From: Arseny Slobodjuck
Subject: special chars in string constant
Date: 
Message-ID: <3a531a97.1536809@news.vtc.ru>
Hi!

How can I insert a special char, say, #\Escape or #\Backspace into the
character constant as in that C string : "123\n456" ? I didn't found
it in CLTL2.

From: Kent M Pitman
Subject: Re: special chars in string constant
Date: 
Message-ID: <sfwd7e4n3am.fsf@world.std.com>
····@crosswinds.net (Arseny Slobodjuck) writes:

> How can I insert a special char, say, #\Escape or #\Backspace into the
> character constant as in that C string : "123\n456" ? I didn't found
> it in CLTL2.

Ordinarily, I would say it's bad style to do this if what you're trying to
do is carriage control, since many kinds of systems don't respond to these
characters.  That's why CL really has no "easy" way to do it.

However, in those cases where you need it, you want to create a context
where you can compute the value of the string and then have that value be
promoted to a constant.  There are several "obvious" ways to do this:

1.  Compute the value at read time in the middle of an expression.

    (defun write-literal-junk ()
      (write-string #.(format nil "123~C456" #\Linefeed)))

2.  Compute the value as a literal constant in code.

    (defun write-literal-junk ()
      (write-string (load-time-value (format nil "123~C456" #\Linefeed))))

3.  Compute the value as a parameter (using DEFVAR or DEFPARAMETER)
    or a named constant (using DEFCONSTANT) and refer to it in code.

    (defconstant +junk+ (format nil "123~C456" #\Linefeed))
    (defun write-literal-junk ()
      (write-string +junk+))

4.  Use the value literally with \ followed by the character.
    (defun write-literal-junk ()
      ;; I used ^J here but I mean the literal linefeed character, 
      ;; not that two-character sequence.
      (write-string "123\^J456")) 


I'd recommend using [1] if you're sure it's really a one-time thing and if the
relevant values going into the literalness are known at compile-time.
[2] is useful if you don't know some value until load time; e.g.,
instead of #\Linefeed it's *foo* where *foo* doesn't get its value until a
load has occurred and you know what environment you're running in.  This might
happen for code that is sometimes supposed to output CRLF pairs and sometimes
just LF (though in that case make sure you use ~A and not ~C).  
[3] is useful if you're doing something like an implementation of ANSI
display graphics and you just want to put things like "<ESC>A"  and "<ESC>C"
into strings to use in multiple places.
[4] is mostly something I observe for generality's sake--that the CL mechanism
of quoting is actually MORE general, not less general, than in other languages.
Any character can be included literally this way--not just a certain 
pre-defined set.  The problem is that many such may be unreadable, and that's
why I usually stylistically prefer [1]-[3], so that it's clear what's going
on.  When you have a non-printable in your code, it can screw up the look
of the code or it can make it hard to tell if you've screwed up the content.
The CL way of making such situations clear is more cumbersome than in other
languages, but I think it doesn't come up enough that it's a major impediment,
and often it makes things more clear even if more verbose.

Incidentally, be very wary of translating \n as #\Newline.  \n in most
systems seems to mean "linefeed", not "newline", in CL "newline" in CL
might be either "return" or "linefeed".

Note, too, that a lot of people just use calls to write-line rather than
write-string to mask the need for \n in many cases where it's needed in other
languages.  That doesn't make it work when then newline is embedded, of course.
But in that case, you can use FORMAT.  The main reason for the above tricks
with FORMAT is for situations where you want to do very fast I/O that does
not involve FORMAT at runtime.  If you're just doing "casual" programming,
I wouldn't do any of the three things above.  I'd just do:

 (defun write-literal-junk ()
   (format t "123~C456" #\Linefeed))

and worry about optimizing it only if it turned out to be a 
performance bottleneck.  I think some compilers will already optimize this
into the appropriate write-string anyway; if your compiler doesn't, I'd
send a bug report.  I'd like to see all compilers optimize the easy cases
of FORMAT so that people wouldn't have to fear using it as an expressional
device.
From: Arseny Slobodjuck
Subject: Re: special chars in string constant
Date: 
Message-ID: <3a543955.118362095@news.vtc.ru>
On Wed, 3 Jan 2001 14:00:49 GMT, Kent M Pitman <······@world.std.com>
wrote:

Thank you  for such a big answer !

>> How can I insert a special char, say, #\Escape or #\Backspace into the
>> character constant as in that C string : "123\n456" ? I didn't found
>> it in CLTL2.
>
>Ordinarily, I would say it's bad style to do this if what you're trying to
>do is carriage control, since many kinds of systems don't respond to these
>characters.  That's why CL really has no "easy" way to do it.
Ok, now I'm understand why. Actually newline is not what I want, but I
don't remember other C escapes exactly.

>1.  Compute the value at read time in the middle of an expression.
Tthanks, the #. macro is new to me though exec speed is not my target
at this time.
>2.  Compute the value as a literal constant in code.
>3.  Compute the value as a parameter (using DEFVAR or DEFPARAMETER)
>    or a named constant (using DEFCONSTANT) and refer to it in code.
>4.  Use the value literally with \ followed by the character.
I didn't knew it too. But with such strings code became really ugly.

>[3] is useful if you're doing something like an implementation of ANSI
>display graphics and you just want to put things like "<ESC>A"  and "<ESC>C"
>into strings to use in multiple places.
Actually it is what I doing. I think, ansi terminal is a simpliest way
to make textmode GUI  for some small lisp program. Besides it let me
work remotely through telnet. I think in that case  #\Escape not going
to make compatibility problems. I used to think that I missed
something in documentation with this constants, but now I see that I
was not. 

I'm going to consider to make set of functions like attrib-invert,
attrib-normal and so on and using #. and format inside it. 
From: Steven M. Haflich
Subject: Re: special chars in string constant
Date: 
Message-ID: <3A543D40.467DB51D@pacbell.net>
Arseny Slobodjuck wrote:
> 
> I'm going to consider to make set of functions like attrib-invert,
> attrib-normal and so on and using #. and format inside it.

You should at least consider another alternative:

You could also define your own readtable with a different dispatch
function on the double-quote character that provides whatever
backslash escapes you like.  This is quite easy to implement once
you learn the necessary readtable functions.

The previous respondents are correct that these escapes don't
belong in the standard CL language because they are fundamentally
platform dependent, and the character/string model of CL is
defined at a higher, more abstract level -- I'm not saying this
was necessarily a good thing --- but for many platform-specific
purposes you might find it convenient to use a string syntax
that "does the right thing" on your platforms of interest.
From: Arseny Slobodjuck
Subject: Re: special chars in string constant
Date: 
Message-ID: <3a543f29.119854892@news.vtc.ru>
On Thu, 04 Jan 2001 01:07:12 -0800, "Steven M. Haflich"
<·······@pacbell.net> wrote:

>> I'm going to consider to make set of functions like attrib-invert,
>> attrib-normal and so on and using #. and format inside it.
>
>You should at least consider another alternative:
>
>You could also define your own readtable with a different dispatch
>function on the double-quote character that provides whatever
>backslash escapes you like.  This is quite easy to implement once
>you learn the necessary readtable functions.

Thank you, I'll try to dig it.
From: Arseny Slobodjuck
Subject: Re: special chars in string constant
Date: 
Message-ID: <3a550af3.279622@news.vtc.ru>
On Thu, 04 Jan 2001 01:07:12 -0800, "Steven M. Haflich"
<·······@pacbell.net> wrote:

>> I'm going to consider to make set of functions like attrib-invert,
>> attrib-normal and so on and using #. and format inside it.
>
>You should at least consider another alternative:
> you might find it convenient to use a string syntax
> that "does the right thing" on your platforms of interest.

Yes, it does! Thanks! Custom string syntax - that's all I need.

(defun read-esc-string(stream char)
 (declare (ignore char))
 (let ((str ""))
  (loop with chr = nil and chresc = nil and sttesc = nil
        do  (setf chr  (read-char stream t))
            (setf chresc  (char= chr #\\))
        until (and (not sttesc) (char= chr #\"))
        if sttesc
             do
               (setf sttesc nil)
               (setf str (concatenate 'string str (string
                  (cond 
                      ((char= chr #\!) #\Escape)
                      (t chr)))))
        else
             do  (unless chresc (setf str (concatenate 'string str
(string chr))))
                 (setf sttesc chresc)) str))

(set-macro-character #\" #'read-esc-string)


(format t "\![7m\"basketball\"\![m")
From: Paolo Amoroso
Subject: Re: special chars in string constant
Date: 
Message-ID: <9GtUOuqsFM6NP8nuoI5=QJ2ZaMSV@4ax.com>
On Thu, 04 Jan 2001 08:50:57 GMT, ····@crosswinds.net (Arseny Slobodjuck)
wrote:

> Actually it is what I doing. I think, ansi terminal is a simpliest way
> to make textmode GUI  for some small lisp program. Besides it let me

If you work mostly with CLISP, you might consider using the functions and
macros in the SCREEN package (see impnotes.html).


Paolo
-- 
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/
From: Christopher J. Vogt
Subject: Re: special chars in string constant
Date: 
Message-ID: <3A53405D.EB1708D9@computer.org>
Arseny Slobodjuck wrote:
> 
> Hi!
> 
> How can I insert a special char, say, #\Escape or #\Backspace into the
> character constant as in that C string : "123\n456" ? I didn't found
> it in CLTL2.

I think this is an editor question.  In emacs you can preface a character with 
^Q (control Q) to get it inserted into the editor buffer.  So if I wanted a string with #\escape in it I'd *type*: "^Q^[" which would display in the editor
buffer as "^[" and is just one charcter in length i.e.
* (length "^[")
* 1
From: Hrvoje Niksic
Subject: Re: special chars in string constant
Date: 
Message-ID: <sxs4rzgr6db.fsf@florida.arsdigita.de>
"Christopher J. Vogt" <····@computer.org> writes:

> Arseny Slobodjuck wrote:
> > 
> > Hi!
> > 
> > How can I insert a special char, say, #\Escape or #\Backspace into the
> > character constant as in that C string : "123\n456" ? I didn't found
> > it in CLTL2.
> 
> I think this is an editor question.  In emacs you can preface a character with 
> ^Q (control Q) to get it inserted into the editor buffer.

This can be unwanted and in some cases outright dangerous.  For
instance, inserting a literal NUL character (ASCII 000) in your string
can seriously damage utilities that ought to work on the source file.
CVS is such an example.
From: Arseny Slobodjuck
Subject: Re: special chars in string constant
Date: 
Message-ID: <3a543986.118411156@news.vtc.ru>
On 03 Jan 2001 19:36:46 +0000, Erik Naggum <····@naggum.net> wrote:

>* Arseny Slobodjuck
>| How can I insert a special char, say, #\Escape or #\Backspace into the
>| character constant as in that C string : "123\n456" ? I didn't found
>| it in CLTL2.
>

>(concatenate 'string "123" (string #\newline) "456")
>(format nil ··@{~A~}" "123" #\newline "456")
>
>  #.x uses the read-time evaluator
>  (load-time-value x) uses the load-time evaluator
>  x uses the normal interpreter- or compile-time evaluator
>
Thank you.

>  If you were a fearless pragmatist with no concern for language design,
>  you would just go ahead and write your own string reader that interprets
>  \ followed by something other than " and \ as something more or less
>  magic.  This is not hard, but it _is_ the way of Perl and other evil.

Yes, I'm a fearless pragmatist. But I very respect to lisp design and
want to do all things lispy. I want to send simple ANSI escape
sequences to terminal. It would be very nice to include some of that
sequences right in strings instead of writing #\Escape in #'format
parameter list, because last case hurts readability. 
From: Ola Rinta-Koski
Subject: Re: special chars in string constant
Date: 
Message-ID: <ne7lmsrf9vs.fsf@karakara.hut.fi>
>····@crosswinds.net (Arseny Slobodjuck)
> Yes, I'm a fearless pragmatist. But I very respect to lisp design and
> want to do all things lispy. I want to send simple ANSI escape
> sequences to terminal. It would be very nice to include some of that
> sequences right in strings instead of writing #\Escape in #'format
> parameter list, because last case hurts readability.

  You'll want to abstract away the actual strings anyway and use them
  only in one place in your code. E.g. (ansi-gotoxy 0 0) instead of
  (format t "~CF;0;0" #\Escape) wherever you need it (the actual control
  code is something different, but that's the idea).
-- 
*** Ola Rinta-Koski  Espoo, FINLAND
***
There's a vas deferens between the epididymis and the ampulla.
From: Kent M Pitman
Subject: Re: special chars in string constant
Date: 
Message-ID: <sfwk88aitvl.fsf@world.std.com>
Ola Rinta-Koski <···@karakara.hut.fi> writes:

>   You'll want to abstract away the actual strings anyway and use them
>   only in one place in your code. E.g. (ansi-gotoxy 0 0) instead of
>   (format t "~CF;0;0" #\Escape) wherever you need it (the actual control
>   code is something different, but that's the idea).

At the least, yes.

If possible, a second layer of abstraction atop that which doesn't presuppose
an ansi model is also desirable:

 (defclass ansi-control () ())

 (defmethod move-cursor (x y) (ansi-gotoxy 0 0))
 ...

 (defvar *cursor-control* (make-instance 'ansi-control))

e.g., you could imagine:

 (defclass minds-eye-array-control ()
   ((screen-array :initform (make-array '(24 80))
                  :accessor screen-array
                  :initarg :screen-array)
    (xpos :initform 0 :accessor xpos :initform :xpos)
    (ypos :initform 0 :accessor ypos :initform :ypos)))

 (defmethod move-cursor (x y)
   (setf (xpos *cursor-control*) x)
   (setf (ypos *cursor-control*) y))
 ...

 (let ((*cursor-control* (make-instance 'minds-eye-array-control))) ...)

or some such thing.  Just thinking aloud.
From: Rob Warnock
Subject: Re: special chars in string constant
Date: 
Message-ID: <933lse$krhmv$1@fido.engr.sgi.com>
Kent M Pitman  <······@world.std.com> wrote:
+---------------
| Ola Rinta-Koski <···@karakara.hut.fi> writes:
| >   You'll want to abstract away the actual strings anyway and use them
| >   only in one place in your code. E.g. (ansi-gotoxy 0 0) instead of
| >   (format t "~CF;0;0" #\Escape) wherever you need it (the actual control
| >   code is something different, but that's the idea).
| 
| At the least, yes.
| If possible, a second layer of abstraction atop that which doesn't presuppose
| an ansi model is also desirable:
|  (defclass ansi-control () ())
|  (defmethod move-cursor (x y) (ansi-gotoxy 0 0))
+---------------

And then you're well on your way to inventing a Common Lisp binding for
the "curses" library (which in turn uses the "termcap" database for *lots*
of terminals [not just ANSI], commonly supplied on Unix & other operating
systems), though be sure to check with the documentation for the version
of Lisp you're using to see whether such as thing might already exist,
such as the SCREEN package in CLISP:

	<URL:http://clisp.sourceforge.net/impnotes.html#screen>
	...
	(screen:make-window) ==> window-stream
	(screen:with-window . body)
	...
	(screen:clear-window window-stream)
	(screen:set-window-cursor-position window-stream line column)
	...

And while you're reading, watch out for anything else your implementation
might do special with the built-in *TERMINAL-IO* stream, such as CLISP's
LISP:WITH-KEYBOARD form:

	<URL:http://clisp.sourceforge.net/impnotes.html#streams>
	<URL:http://clisp.sourceforge.net/impnotes.html#screen>


-Rob

-----
Rob Warnock, 31-2-510		····@sgi.com
SGI Network Engineering		http://reality.sgi.com/rpw3/
1600 Amphitheatre Pkwy.		Phone: 650-933-1673
Mountain View, CA  94043	PP-ASEL-IA
From: Arseny Slobodjuck
Subject: Re: special chars in string constant
Date: 
Message-ID: <3a556f69.29989682@news.vtc.ru>
On 5 Jan 2001 05:25:34 GMT, ····@rigden.engr.sgi.com (Rob Warnock)
wrote:

>Kent M Pitman  <······@world.std.com> wrote:
>+---------------
>| Ola Rinta-Koski <···@karakara.hut.fi> writes:
>| >   You'll want to abstract away the actual strings anyway and use them
>| >   only in one place in your code. E.g. (ansi-gotoxy 0 0) instead of
>| >   (format t "~CF;0;0" #\Escape) wherever you need it (the actual control
>| >   code is something different, but that's the idea).
>| 
>| At the least, yes.
>| If possible, a second layer of abstraction atop that which doesn't presuppose
>| an ansi model is also desirable:
>|  (defclass ansi-control () ())
>|  (defmethod move-cursor (x y) (ansi-gotoxy 0 0))
>+---------------
>
>And then you're well on your way to inventing a Common Lisp binding for
>the "curses" library (which in turn uses the "termcap" database for *lots*
>of terminals [not just ANSI], commonly supplied on Unix & other operating
>systems), though be sure to check with the documentation for the version
>of Lisp you're using to see whether such as thing might already exist,
>such as the SCREEN package in CLISP:

Please before reading following text note that I'm novice in lisp,
know almost nothing about ansi(or not ansi)-terminals and curses
library.

I'm "using" CLISP under Windows NT and CMUCL in FreeBSD, so I need
compatibility at least between them both. And screen package in CLISP
is not supported in win32 (whereas this is possible, I think). I saw
in CMUCL docs that there is a whole set of interface packages for
X-windows. I wonder why not to create such a library which will be
lisp-implementation- independent (while not such powerful as built-in
system).