How do I properly escape and unescape a multiline string that contains newline literals?

Viewed 25340

I'm working on a Visual Studio Code extension. The extension is supposed to act on the text that is currently selected in the editor window and send it to an external command (lein-cljfmt in my case, but I think that's unrelated to my question). When the external command is done processing the text I want to replace the current editor selector with the result returned from the command line tool.

Before sending the string I escape it like this:

contents
    .replace(/\\/g, '\\\\')
    .replace(/"/g, '\\"')
    .replace(/\n/g, '\\n');

The result in being unescaped like:

contents
    .replace(/\\n/g, '\n')
    .replace(/\\"/g, '"')
    .replace(/\\\\/g, '\\');

This works in all but one case: when the selection that is being processed contains a string literal that contains a newline literal, the unescaping will instead turn this into a linebreak, thus breaking the code in the editor.

This is an example of a snippet that breaks my escaping:

(defn join
  [a b]
  (str a "\n" b)) 

I tried quite some regexp black magic like

.replace(/(?!\B"[^"]*)\\n(?![^"]*"\B)/g, '\n')

by now, but couldn't find a solution that does not have edge cases. Is there a way to do this that I am missing? I also wonder if there is a VSCode extension API that could handle that as it seems to be a common scenario to me.

1 Answers
Related