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.
"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))))
(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)
(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))
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."
;;; 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)
(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))
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)