Only handle ".." and '..' quoting in shell-mode.

* lisp/shell.el (shell--unquote&requote-argument, shell--unquote-argument)
(shell--requote-argument): New functions.
(shell-completion-vars): Use them.
(shell--parse-pcomplete-arguments): Rename from
shell-parse-pcomplete-arguments.
* lisp/comint.el (comint-word): Obey comint-file-name-quote-list.  Simplify.
(comint--unquote&requote-argument): Don't handle ".." and '..' quoting.
Obey comint-file-name-quote-list.

Fixes: debbugs:11466
This commit is contained in:
Stefan Monnier 2012-05-15 12:58:35 -04:00
parent fdb058c228
commit 2473256d7b
3 changed files with 80 additions and 29 deletions

View file

@ -1,5 +1,15 @@
2012-05-15 Stefan Monnier <monnier@iro.umontreal.ca>
Only handle ".." and '..' quoting in shell-mode (bug#11466).
* shell.el (shell--unquote&requote-argument, shell--unquote-argument)
(shell--requote-argument): New functions.
(shell-completion-vars): Use them.
(shell--parse-pcomplete-arguments): Rename from
shell-parse-pcomplete-arguments.
* comint.el (comint-word): Obey comint-file-name-quote-list. Simplify.
(comint--unquote&requote-argument): Don't handle ".." and '..' quoting.
Obey comint-file-name-quote-list.
* emacs-lisp/smie.el (smie-indent--bolp-1): New function.
(smie-indent-keyword): Use it.

View file

@ -2968,19 +2968,20 @@ This is a good thing to set in mode hooks.")
"Return the word of WORD-CHARS at point, or nil if none is found.
Word constituents are considered to be those in WORD-CHARS, which is like the
inside of a \"[...]\" (see `skip-chars-forward'), plus all non-ASCII characters."
;; FIXME: Need to handle "..." and '...' quoting in shell.el!
;; This should be combined with pomplete-parsing somehow.
(save-excursion
(let ((here (point))
giveup)
(while (not giveup)
(let ((startpoint (point)))
(skip-chars-backward (concat "\\\\" word-chars))
;; Fixme: This isn't consistent with Bash, at least -- not
;; all non-ASCII chars should be word constituents.
(if (and (> (- (point) 2) (point-min))
(= (char-after (- (point) 2)) ?\\))
(if (and comint-file-name-quote-list
(eq (char-before (1- (point))) ?\\))
(forward-char -2))
(if (and (> (- (point) 1) (point-min))
(>= (char-after (- (point) 1)) 128))
;; FIXME: This isn't consistent with Bash, at least -- not
;; all non-ASCII chars should be word constituents.
(if (and (not (bobp)) (>= (char-before) 128))
(forward-char -1))
(if (= (point) startpoint)
(setq giveup t))))
@ -3012,14 +3013,14 @@ See `comint-word'."
(defun comint--unquote&requote-argument (qstr &optional upos)
(unless upos (setq upos 0))
(let* ((qpos 0)
(dquotes nil)
(ustrs '())
(re (concat
"[\"']\\|\\\\\\(.\\)"
"\\|\\$\\(?:\\([[:alpha:]][[:alnum:]]*\\)"
"\\|{\\(?2:[^{}]+\\)}\\)"
"\\$\\(?:\\([[:alpha:]][[:alnum:]]*\\)"
"\\|{\\(?1:[^{}]+\\)}\\)"
(when (memq system-type '(ms-dos windows-nt))
"\\|%\\(?2:[^\\\\/]*\\)%")))
"\\|%\\(?1:[^\\\\/]*\\)%")
(when comint-file-name-quote-list
"\\|\\\\\\(.\\)")))
(qupos nil)
(push (lambda (str end)
(push str ustrs)
@ -3030,18 +3031,9 @@ See `comint-word'."
(while (setq match (string-match re qstr qpos))
(funcall push (substring qstr qpos match) match)
(cond
((match-beginning 1) (funcall push (match-string 1 qstr) (match-end 0)))
((match-beginning 2) (funcall push (getenv (match-string 2 qstr))
((match-beginning 2) (funcall push (match-string 2 qstr) (match-end 0)))
((match-beginning 1) (funcall push (getenv (match-string 1 qstr))
(- (match-end 0))))
((eq (aref qstr match) ?\") (setq dquotes (not dquotes)))
((eq (aref qstr match) ?\')
(cond
(dquotes (funcall push "'" (match-end 0)))
((< match (1+ (length qstr)))
(let ((end (string-match "'" qstr (1+ match))))
(funcall push (substring qstr (1+ match) end)
(or end (length qstr)))))
(t nil)))
(t (error "Unexpected case in comint--unquote&requote-argument!")))
(setq qpos (match-end 0)))
(funcall push (substring qstr qpos) (length qstr))
@ -3140,7 +3132,7 @@ Returns t if successful."
See `completion-table-with-quoting' and `comint-requote-function'.")
(defvar comint-requote-function #'comint--requote-argument
"Function to use for completion of quoted data.
See `completion-table-with-quoting' and `comint-requote-function'.")
See `completion-table-with-quoting' and `comint-unquote-function'.")
(defun comint--complete-file-name-data ()
"Return the completion data for file name at point."

View file

@ -372,8 +372,57 @@ Thus, this does not include the shell's current directory.")
;;; Basic Procedures
(defun shell-parse-pcomplete-arguments ()
(defun shell--unquote&requote-argument (qstr &optional upos)
(unless upos (setq upos 0))
(let* ((qpos 0)
(dquotes nil)
(ustrs '())
(re (concat
"[\"']"
"\\|\\$\\(?:\\([[:alpha:]][[:alnum:]]*\\)"
"\\|{\\(?1:[^{}]+\\)}\\)"
(when (memq system-type '(ms-dos windows-nt))
"\\|%\\(?1:[^\\\\/]*\\)%")
(when comint-file-name-quote-list
"\\|\\\\\\(.\\)")))
(qupos nil)
(push (lambda (str end)
(push str ustrs)
(setq upos (- upos (length str)))
(unless (or qupos (> upos 0))
(setq qupos (if (< end 0) (- end) (+ upos end))))))
match)
(while (setq match (string-match re qstr qpos))
(funcall push (substring qstr qpos match) match)
(cond
((match-beginning 2) (funcall push (match-string 2 qstr) (match-end 0)))
((match-beginning 1) (funcall push (getenv (match-string 1 qstr))
(- (match-end 0))))
((eq (aref qstr match) ?\") (setq dquotes (not dquotes)))
((eq (aref qstr match) ?\')
(cond
(dquotes (funcall push "'" (match-end 0)))
((< match (1+ (length qstr)))
(let ((end (string-match "'" qstr (1+ match))))
(funcall push (substring qstr (1+ match) end)
(or end (length qstr)))))
(t nil)))
(t (error "Unexpected case in shell--unquote&requote-argument!")))
(setq qpos (match-end 0)))
(funcall push (substring qstr qpos) (length qstr))
(list (mapconcat #'identity (nreverse ustrs) "")
qupos #'comint-quote-filename)))
(defun shell--unquote-argument (str)
(car (shell--unquote&requote-argument str)))
(defun shell--requote-argument (upos qstr)
;; See `completion-table-with-quoting'.
(let ((res (shell--unquote&requote-argument qstr upos)))
(cons (nth 1 res) (nth 2 res))))
(defun shell--parse-pcomplete-arguments ()
"Parse whitespace separated arguments in the current region."
;; FIXME: share code with shell--unquote&requote-argument.
(let ((begin (save-excursion (shell-backward-command 1) (point)))
(end (point))
begins args)
@ -394,13 +443,13 @@ Thus, this does not include the shell's current directory.")
(cond
((match-beginning 3) ;Backslash escape.
(push (cond
((null pcomplete-arg-quote-list)
((null comint-file-name-quote-list)
(goto-char (match-beginning 3)) "\\")
((= (match-beginning 3) (match-end 3)) "\\")
(t (match-string 3)))
arg))
((match-beginning 2) ;Double quote.
(push (if (null pcomplete-arg-quote-list) (match-string 2)
(push (if (null comint-file-name-quote-list) (match-string 2)
(replace-regexp-in-string
"\\\\\\(.\\)" "\\1" (match-string 2)))
arg))
@ -430,10 +479,10 @@ Shell buffers. It implements `shell-completion-execonly' for
shell-file-name-quote-list)
(set (make-local-variable 'comint-dynamic-complete-functions)
shell-dynamic-complete-functions)
(setq-local comint-unquote-function #'shell--unquote-argument)
(setq-local comint-requote-function #'shell--requote-argument)
(set (make-local-variable 'pcomplete-parse-arguments-function)
#'shell-parse-pcomplete-arguments)
(set (make-local-variable 'pcomplete-arg-quote-list)
comint-file-name-quote-list)
#'shell--parse-pcomplete-arguments)
(set (make-local-variable 'pcomplete-termination-string)
(cond ((not comint-completion-addsuffix) "")
((stringp comint-completion-addsuffix)