2

How to programmatically insert a text verbatim?

The following function inserts ocumentclass and not \documentclass.

(defun foo () (interactive)
(insert "\documentclass"))

Of course one can use

 (defun foo () (interactive)
    (insert "\\documentclass"))

to correctly insert \documentclass. But I am wondering if there is a way to directly insert a text verbatim without modifying it at all (e.g. without changing its special characters).

Drew
  • 75,699
  • 9
  • 109
  • 225
Name
  • 7,689
  • 4
  • 38
  • 84
  • Probably related to http://emacs.stackexchange.com/questions/4198/how-can-i-turn-a-string-into-its-literal-representation, while there is no a complete answer. – xuchunyang Oct 18 '15 at 08:04
  • @xuchunyang The solutions given in that question seem to not help here. Thank you anway. – Name Oct 18 '15 at 08:22
  • 3
    There's no such thing as raw strings in elisp. If the reader encounters a "\d" for instance, it turns it into a control character. Therefore, your question isn't solvable. – wasamasa Oct 18 '15 at 08:25
  • If you want to **programmatically** insert a text, it depends on where you get the text from. If it's a literal string in an emacs-lisp source file, as already said, you have to quote the backslash. But if you get it from a database or from a file, it will insert it literally. For example, in a shell: `echo -n '\doc' > /tmp/doc.txt`. In emacs: `(insert-file-content "/tmp/doc.txt")` will insert `\doc`, as stored in the text file. – duthen Sep 19 '22 at 09:31

2 Answers2

11

You may be misinterpreting what's going on. The insert function inserts its argument verbatim. The problem is that the string you've included in your program is not \documentclass but ␡ocumentclass where ␡ is ASCII character number 127 (which is unprintable).

The string literal "\documentclass" represents the string ␡ocumentclass. Notice how two things happen: the literal has additional quotes at the beginning and at the end, and backslash+character in the literal¹ is transformed into a single character in the string. Why? The quotes delimit the string literal, so that the computer knows that you meant to write a string and not whatever code the text could represent. At the very least, there needs to be a way to include a quote character in a string. Emacs Lisp, like most programming languages, uses the backslash to escape the next character: the string literal "foo\"bar" represents the string foo"bar — the second quote doesn't end the literal because it's preceded by a backslash. Backslash followed by a non-alphanumeric character always quotes the next character: the backslash character is removed and the next character is included in the string. Backslash followed by some alphanumeric characters allows you to specify characters that it might not be easy to include in source code, such as control characters.

Once again, this is happening when your code is parsed. If you write "\documentclass", there is no way to get back to what you typed, because it's stored in exactly the same way as if you'd typed ␡ocumentclass. If you write "\math", it's stored exactly in the same way as if you'd typed "math".

Some languages have alternate syntaxes for string literals with a multi-character delimiter and no interpretation of anything but the end delimiter inside the string literal. Emacs Lisp doesn't, it keeps things simple. So just type "\\documentclass" to get the string \documentclass.

¹ Sometimes backslash plus a sequence of characters.

  • 1
    Common Lisp lets you redefine the reader syntax using the full power of the language. But Emacs Lisp is not Common Lisp - and perhaps it shouldn't be. I *do*, however, sometimes wish for a different syntax for regexps, which often get filled with lots of double (and quadruple) backslashes. – Harald Hanche-Olsen Oct 19 '15 at 16:59
  • @HaraldHanche-Olsen Try the `rx` library. – Gilles 'SO- stop being evil' Oct 19 '15 at 23:08
  • I am aware of that, but I find it too verbose. (I am hard to satisfy, I guess.) It seems like a step in the right direction, but going too far rather than too short. But then I have never used it in anger, so I really should suspend judgement. – Harald Hanche-Olsen Oct 20 '15 at 11:52
-3

Generally it is not possible, as elisp interprets all strings, and there doesn't seem to a way to prevent it doing so.

However in this particular example it is possible -- as elisp interprets \d as DEL char (ascii code: 127). So, assuming you string won't contain DEL chars by itself, one can search and replace it in emacs string representation. Generally it is possible to fight \a, \b, \d, \e, \f, \r, \v, \x cases:

enter image description here

(SE text field can't render this code without modifications)

Using this defun:

(defun foo () (interactive)
(insert (sheild-all-possible-letters "\documentclass")))

Inserts \documentclass.

Edit:

Here's a way to see how emacs sees the string:

(defun how-emacs-sees-string (string)
  (interactive "s")

  (setq tempBuffer (generate-new-buffer-name "temp"))
  (switch-to-buffer tempBuffer)
  (insert string)
  )

(how-emacs-sees-string "
a: \a
b: \b
c: \c
d: \d
e: \e
f: \f
g: \g
h: \h
i: \i
j: \j
k: \k
l: \l
m: \m
n: \n
o: \o
p: \p
q: \q
r: \r
s: \s
t: \t
v: \v
w: \w
x: \x
y: \y
z: \z
")
Adobe
  • 1,859
  • 13
  • 27