From 327b688dc548bb336d6a547d34530ad47fa8553b Mon Sep 17 00:00:00 2001
From: Travis Heppe <heppe@google.com>
Date: Wed, 22 Jan 2014 00:14:57 -0800
Subject: [PATCH] [vim] Fix unescaping of escaped strings for search and
 replace

Add unit tests.
---
 keymap/vim.js    | 22 ++++++++++++++++++++--
 test/vim_test.js | 21 +++++++++++++++++++++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/keymap/vim.js b/keymap/vim.js
index a08c5c2f7..21c74c4cf 100644
--- a/keymap/vim.js
+++ b/keymap/vim.js
@@ -2750,10 +2750,28 @@
         if (!escapeNextChar && c == '/') {
           slashes.push(i);
         }
-        escapeNextChar = (c == '\\');
+        escapeNextChar = !escapeNextChar && (c == '\\');
       }
       return slashes;
     }
+
+    function unescapeString(str) {
+      var escapeNextChar = false;
+      var out = [];
+      for (var i = 0; i < str.length; i++) {
+        var c = str.charAt(i);
+        var next = str.charAt(i+1);
+        var slashComesNext = (next == '\\') || (next == '/');
+        if (c !== '\\' || escapeNextChar || !slashComesNext) {
+          out.push(c);
+          escapeNextChar = false;
+        } else {
+          escapeNextChar = true;
+        }
+      }
+      return out.join('');
+    }
+
     /**
      * Extract the regular expression from the query and return a Regexp object.
      * Returns null if the query is blank.
@@ -3278,7 +3296,7 @@
         var count;
         var confirm = false; // Whether to confirm each replace.
         if (slashes[1]) {
-          replacePart = argString.substring(slashes[1] + 1, slashes[2]);
+          replacePart = unescapeString(argString.substring(slashes[1] + 1, slashes[2]));
         }
         if (slashes[2]) {
           // After the 3rd slash, we can have flags followed by a space followed
diff --git a/test/vim_test.js b/test/vim_test.js
index d39753c10..dd88bbf8c 100644
--- a/test/vim_test.js
+++ b/test/vim_test.js
@@ -2264,6 +2264,8 @@ testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) {
   helpers.doEx('sort! d');
   eq('a3\nb2\nc1\nz\ny', cm.getValue());
 }, { value: 'a3\nz\nc1\ny\nb2'});
+
+
 testVim('ex_substitute_same_line', function(cm, vim, helpers) {
   cm.setCursor(1, 0);
   helpers.doEx('s/one/two');
@@ -2299,6 +2301,25 @@ testVim('ex_substitute_empty_query', function(cm, vim, helpers) {
   helpers.doEx('s//b');
   eq('abb ab2 ab3', cm.getValue());
 }, { value: 'a11 a12 a13' });
+testVim('ex_substitute_slash_regex', function(cm, vim, helpers) {
+  cm.setCursor(1, 0);
+  helpers.doEx('%s/\\//|');
+  eq('one|two \n three|four', cm.getValue());
+}, { value: 'one/two \n three/four'});
+testVim('ex_substitute_backslashslash_regex', function(cm, vim, helpers) {
+  cm.setCursor(1, 0);
+  helpers.doEx('%s/\\\\/,');
+  eq('one,two \n three,four', cm.getValue());
+}, { value: 'one\\two \n three\\four'});
+testVim('ex_substitute_slash_replacement', function(cm, vim, helpers) {
+  cm.setCursor(1, 0);
+  helpers.doEx('%s/,/\\/');
+  eq('one/two \n three/four', cm.getValue());
+}, { value: 'one,two \n three,four'});
+testVim('ex_substitute_backslash_replacement', function(cm, vim, helpers) {
+  helpers.doEx('%s/,/\\\\/g');
+  eq('one\\two \n three\\four', cm.getValue());
+}, { value: 'one,two \n three,four'});
 testVim('ex_substitute_count', function(cm, vim, helpers) {
   cm.setCursor(1, 0);
   helpers.doEx('s/\\d/0/i 2');
-- 
GitLab