Subject: Re: readable syntax for control characters in strings
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 1996/11/01
Newsgroups: comp.lang.lisp
Message-ID: <55cha7$39s@tokyo.engr.sgi.com>

Erik Naggum  <erik@naggum.no> wrote:
+---------------
| given that a syntax familiar to Emacs Lisp (and C) users is unavailable...
|     #.(format nil "foo~Cbar" #\Newline)
|     #.(concatenate 'string "foo" '(#\Newline) "bar")
+---------------

You realize, I assume, that this particular example can already be
done easily in CL, like so:

	#.(format nil "foo~%bar")

And (if you don't mind tabs being expanded) for "foo\tbar\nbaz\tgorp\n\f"
you can use:


	#.(format nil "foo~9,8Tbar~%baz~9,8Tgorp~%~|")

So back to the general case...

+---------------
| how would one accomplish the same goal: to embed a (named) control
| character in a literal string in source code that is likely to travel
| across all sorts of information-losing channels?   ...
| I feel I must have overlooked something or think in the wrong terms.
+---------------

I suspect the latter. Look, Lisp is a language for building languages,
right? So design a "language" for expressing the kind of strings you
want, and build a mechanism for translating that into Lisp.

Oh? You say you already *have* the language you want, namely, good old
familiar C strings?  Fine!  Then simply write a function that takes C
strings as input (in the form of "control strings") and gives you Lisp
strings as output. Something like this:

	(cstr->string "First line:\\ttext\\nSecond line:\\tmore text\\007\\n")
	==> "First line:    text
	    Second line:    more text(*ding!*)
	    "                        [i.e. ^G ]

(Unfortunately, if you want the use "backslash" as your escape character,
you'd have to double them everywhere [as shown] to get them into your
control string. And if you want to use C strings in "format" calls, you
probably don't want to use "~", either. How about "%" or "^" or "&"?)

Then if you wanted to use these inside "format", perhaps to print lines
with fields prefixed by the tab character and suffixed by (say) <cntl-A>,
you could do something like this (let "c2s" be an alias for "cstr->string"):

	(format nil #.(c2s "\\tfield1=~A\\001\\tfield2=~A\\001~%") 123 456)
	==> "	field1=123	field2=456
	    "
a.k.a.  ==> "^Ifield1=123^A^Ifield2=456^A^J"

By the way, with some work (well, probably quite a bit more!), a similar
hack would enable one to rewrite C "printf" control strings into "format"
control strings (at least, for those things that map):

	(pf2fmt "foo = %8.8x, bar = %d\\n")
	==> "foo = ~8,'0X, bar = ~D~%"

so you could say:

	(format nil #.(pf2fmt "foo = 0x%8.8x, bar = %d\\n") 123456 789)
	==> "foo = 0x0001e240, bar = 789
	    "

+---------------
| (incidentally, my actual problem case involves lots of escape sequences for
| a form printer now written in Emacs Lisp with the `cl' package.  it is
| trivially portable to Common Lisp except for the string literals.)
+---------------

So write yourself a "c2s" function, and with a little editing to double
the backslashes and wrap #.(c2s ...) around the strings, you're home.


-Rob

-----
Rob Warnock, 7L-551		rpw3@sgi.com
Silicon Graphics, Inc.		http://reality.sgi.com/rpw3/
2011 N. Shoreline Blvd.		Phone: 415-933-1673  FAX: 415-933-0979
Mountain View, CA  94043	PP-ASEL-IA