1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-25 07:28:20 +00:00

* lisp/eshell: Make backslash a no-op in front of normal chars

Fixes: debbugs:8531

* lisp/eshell/esh-arg.el (eshell-parse-argument-hook): Update comment.
(eshell-parse-backslash): Return escaped character after backslash
if it is special.  Otherwise, if the backslash is not in a quoted
string, ignore the backslash and return the character after; if
the backslash is in a quoted string, return the backslash and the
character after.

* test/automated/eshell.el (eshell-test/escape-nonspecial)
(eshell-test/escape-nonspecial-unicode)
(eshell-test/escape-nonspecial-quoted)
(eshell-test/escape-special-quoted): Add tests for new
`eshell-parse-backslash' behavior.
This commit is contained in:
Samer Masterson 2015-04-08 22:31:51 -04:00 committed by Stefan Monnier
parent 3d78c5578c
commit c44f5b046b
2 changed files with 52 additions and 28 deletions

View File

@ -89,7 +89,7 @@ yield the values intended."
(goto-char (match-end 0))
(eshell-finish-arg)))))
;; backslash before a special character means escape it
;; parse backslash and the character after
'eshell-parse-backslash
;; text beginning with ' is a literally quoted
@ -305,34 +305,27 @@ If the character is itself a backslash, it needs no escaping."
(string ?\\ char)))))
(defun eshell-parse-backslash ()
"Parse a single backslash (\) character, which might mean escape.
It only means escape if the character immediately following is a
special character that is not itself a backslash."
"Parse a single backslash (\\) character and the character after.
If the character after the backslash is special, always ignore
the backslash and return the escaped character.
Otherwise, if the backslash is not in quoted string, the
backslash is ignored and the character after is returned. If the
backslash is in a quoted string, the backslash and the character
after are both returned."
(when (eq (char-after) ?\\)
(if (eshell-looking-at-backslash-return (point))
(throw 'eshell-incomplete ?\\)
(if (and (not (eq (char-after (1+ (point))) ?\\))
(if eshell-current-quoted
(memq (char-after (1+ (point)))
eshell-special-chars-inside-quoting)
(memq (char-after (1+ (point)))
eshell-special-chars-outside-quoting)))
(progn
(forward-char 2)
(list 'eshell-escape-arg
(char-to-string (char-before))))
;; allow \\<RET> to mean a literal "\" character followed by a
;; normal return, rather than a backslash followed by a line
;; continuation (i.e., "\\ + \n" rather than "\ + \\n"). This
;; is necessary because backslashes in Eshell are not special
;; unless they either precede something special, or precede a
;; backslash that precedes something special. (Mainly this is
;; done to make using backslash on Windows systems more
;; natural-feeling).
(if (eshell-looking-at-backslash-return (1+ (point)))
(forward-char))
(forward-char)
"\\"))))
(when (eshell-looking-at-backslash-return (point))
(throw 'eshell-incomplete ?\\))
(forward-char 2) ; Move one char past the backslash.
;; If the char is in a quote, backslash only has special meaning
;; if it is escaping a special char.
(if eshell-current-quoted
(if (memq (char-before) eshell-special-chars-inside-quoting)
(list 'eshell-escape-arg (char-to-string (char-before)))
(concat "\\" (char-to-string (char-before))))
(if (memq (char-before) eshell-special-chars-outside-quoting)
(list 'eshell-escape-arg (char-to-string (char-before)))
(char-to-string (char-before))))))
(defun eshell-parse-literal-quote ()
"Parse a literally quoted string. Nothing has special meaning!"

View File

@ -166,6 +166,37 @@ e.g. \"{(+ 1 2)} 3\" => 3"
(eshell-command-result-p "+ 1 2; + $_ 4"
"3\n6\n")))
(ert-deftest eshell-test/escape-nonspecial ()
"Test that \"\\c\" and \"c\" are equivalent when \"c\" is not a
special character."
(with-temp-eshell
(eshell-command-result-p "echo he\\llo"
"hello\n")))
(ert-deftest eshell-test/escape-nonspecial-unicode ()
"Test that \"\\c\" and \"c\" are equivalent when \"c\" is a
unicode character (unicode characters are nonspecial by
definition)."
(with-temp-eshell
(eshell-command-result-p "echo Vid\\éos"
"Vidéos\n")))
(ert-deftest eshell-test/escape-nonspecial-quoted ()
"Test that the backslash is preserved for escaped nonspecial
chars"
(with-temp-eshell
(eshell-command-result-p "echo \"h\\i\""
;; Backslashes are doubled for regexp.
"h\\\\i\n")))
(ert-deftest eshell-test/escape-special-quoted ()
"Test that the backslash is not preserved for escaped special
chars"
(with-temp-eshell
(eshell-command-result-p "echo \"h\\\\i\""
;; Backslashes are doubled for regexp.
"h\\\\i\n")))
(ert-deftest eshell-test/command-running-p ()
"Modeline should show no command running"
(with-temp-eshell