9
(mystery-function "a neat\nstring\"")
=> "\"a neat \\nstring\\\""

This question was asked on freenode#emacs by user dropdrive. How could I write (or use) a function that takes a string literal and returns the string literal that, when read, would return the original string? That is,

(let ((s (any-string)))
  (should (equal s (read (mystery-function s)))))

Note that this let-form is a bit misleading – the session at the very top of this question should be used for testing. Sorry for any confusion!

Sean Allred
  • 6,861
  • 16
  • 85
  • I don't understand your purpose: in particular, `"\"a neat \\nstring\\\""` cannot be `read`, while the output of `(prin1-to-string "a neat\nstring\"")` can (even with "expanded" newline characters)... – T. Verron Dec 07 '14 at 18:02
  • @T.Verron The purpose, I would believe, would be to use the function to insert literal strings for other languages that use escape sequences. I am not the original asker though so I don't know the original intent, but this is how I would use it. – Sean Allred Dec 07 '14 at 18:05

2 Answers2

19

You're looking for prin1-to-string. Also, set print-escape-newlines to a true value to get the "\n" behavior you specified.

I.e.:

(let ((print-escape-newlines t))
  (prin1-to-string "foo\nbar"))
=> "\"foo\\nbar\""
Jorgen Schäfer
  • 3,899
  • 2
  • 17
  • 19
  • +1, but what about `\r`, `\t`, etc.? Sorry that I didn't formulate the question completely – I didn't think there'd be a ready-made solution for `\n` that didn't account for the other sequences :( – Sean Allred Dec 07 '14 at 17:16
  • 1
    Only `\n` and `\f` are affected by `print-escape-newlines` (now I have no idea why `\f` is a newline, but here we are). I'm afraid you are out of luck for the others, as the other `print-escape-*` variables do not affect them. – Jorgen Schäfer Dec 07 '14 at 17:20
  • 3
    Also note, you can use the %S in `format` or `message` and it will print like `prin1` – Jordon Biondo Dec 07 '14 at 22:42
8

This is not exactly the purpose it was invented for, but seems to be useful:

(require 'json)
(json-encode-string "a neat\nstring\" with tab\t and feed \f, also vertical tab \v")
"\"a neat\\nstring\\\" with tab\\t and feed \\f, also vertical tab \\u000b\""
wvxvw
  • 11,222
  • 2
  • 30
  • 55