(eval-when-compile (require 'cl))
(require 'comint)
+(require 'pcomplete)
;;; Customization and Buffer Variables
shell-environment-variable-completion
shell-command-completion
shell-c-a-p-replace-by-expanded-directory
+ pcomplete-completions-at-point
shell-filename-completion
+ ;; Not sure when this one would still be useful. --Stef
comint-filename-completion)
"List of functions called to perform completion.
This variable is used to initialize `comint-dynamic-complete-functions' in the
to track your current directory. It can be used instead of or in addition
to `dirtrack-mode'."
:group 'shell
- :type '(choice (const nil) regexp))
-
-(defvar pcomplete-parse-arguments-function)
+ :type '(choice (const nil) regexp)
+ :version "24.1")
+
+(defun shell-parse-pcomplete-arguments ()
+ "Parse whitespace separated arguments in the current region."
+ (let ((begin (save-excursion (shell-backward-command 1) (point)))
+ (end (point))
+ begins args)
+ (save-excursion
+ (goto-char begin)
+ (while (< (point) end)
+ (skip-chars-forward " \t\n")
+ (push (point) begins)
+ (let ((arg ()))
+ (while (looking-at
+ (eval-when-compile
+ (concat
+ "\\(?:[^\s\t\n\\\"']+"
+ "\\|'\\([^']*\\)'?"
+ "\\|\"\\(\\(?:[^\"\\]\\|\\\\.\\)*\\)\"?"
+ "\\|\\\\\\(\\(?:.\\|\n\\)?\\)\\)")))
+ (goto-char (match-end 0))
+ (cond
+ ((match-beginning 3) ;Backslash escape.
+ (push (if (= (match-beginning 3) (match-end 3))
+ "\\" (match-string 3))
+ arg))
+ ((match-beginning 2) ;Double quote.
+ (push (replace-regexp-in-string
+ "\\\\\\(.\\)" "\\1" (match-string 2))
+ arg))
+ ((match-beginning 1) ;Single quote.
+ (push (match-string 1) arg))
+ (t (push (match-string 0) arg))))
+ (push (mapconcat #'identity (nreverse arg) "") args)))
+ (cons (nreverse args) (nreverse begins)))))
(defun shell-completion-vars ()
"Setup completion vars for `shell-mode' and `read-shell-command'."
(set (make-local-variable 'comint-dynamic-complete-functions)
shell-dynamic-complete-functions)
(set (make-local-variable 'pcomplete-parse-arguments-function)
- ;; FIXME: This function should be moved to shell.el.
- #'pcomplete-parse-comint-arguments)
+ #'shell-parse-pcomplete-arguments)
+ (set (make-local-variable 'pcomplete-arg-quote-list)
+ (append "\\ \t\n\r\"'`$|&;(){}[]<>#" nil))
+ (set (make-local-variable 'pcomplete-termination-string)
+ (cond ((not comint-completion-addsuffix) "")
+ ((stringp comint-completion-addsuffix)
+ comint-completion-addsuffix)
+ ((not (consp comint-completion-addsuffix)) " ")
+ (t (cdr comint-completion-addsuffix))))
+ ;; Don't use pcomplete's defaulting mechanism, rely on
+ ;; shell-dynamic-complete-functions instead.
+ (set (make-local-variable 'pcomplete-default-completion-function) #'ignore)
(setq comint-input-autoexpand shell-input-autoexpand)
;; Not needed in shell-mode because it's inherited from comint-mode, but
;; placed here for read-shell-command.
t shell-file-name))
'localname))))
- ;; Pop to buffer, so that the buffer's window will be correctly set
- ;; when we call comint (so that comint sets the COLUMNS env var properly).
- (pop-to-buffer buffer)
+ ;; The buffer's window must be correctly set when we call comint (so
+ ;; that comint sets the COLUMNS env var properly).
+ (pop-to-buffer-same-window buffer)
(unless (comint-check-proc buffer)
(let* ((prog (or explicit-shell-file-name
(getenv "ESHELL") shell-file-name))
(shell-mode)))
buffer)
-;; Don't do this when shell.el is loaded, only while dumping.
-;;;###autoload (add-hook 'same-window-buffer-names (purecopy "*shell*"))
-
;;; Directory tracking
;;
;; This code provides the shell mode input sentinel
(concat "^" shell-command-separator-regexp)
str) ; skip whitespace
(match-end 0)))
+ (case-fold-search)
end cmd arg1)
(while (string-match shell-command-regexp str start)
(setq end (match-end 0)
(defvaralias 'shell-dirtrack-mode 'shell-dirtrackp)
(define-minor-mode shell-dirtrack-mode
- "Turn directory tracking on and off in a shell buffer.
-The `dirtrack' package provides an alternative implementation of this
-feature - see the function `dirtrack-mode'."
+ "Toggle directory tracking in this shell buffer (Shell Dirtrack mode).
+With a prefix argument ARG, enable Shell Dirtrack mode if ARG is
+positive, and disable it otherwise. If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+The `dirtrack' package provides an alternative implementation of
+this feature; see the function `dirtrack-mode'."
nil nil nil
(setq list-buffers-directory (if shell-dirtrack-mode default-directory))
(if shell-dirtrack-mode
(list
start end
(lambda (string pred action)
- (completion-table-with-terminator
- " " (lambda (string pred action)
- (if (string-match "/" string)
- (completion-file-name-table string pred action)
- (complete-with-action action completions string pred)))
- string pred action)))))
+ (if (string-match "/" string)
+ (completion-file-name-table string pred action)
+ (complete-with-action action completions string pred)))
+ :exit-function
+ (lambda (_string finished)
+ (when (memq finished '(sole finished))
+ (if (looking-at " ")
+ (goto-char (match-end 0))
+ (insert " ")))))))
;; (defun shell-dynamic-complete-as-command ()
;; "Dynamically complete at point as a command.
(substring x 0 (string-match "=" x)))
process-environment))
(suffix (case (char-before start) (?\{ "}") (?\( ")") (t ""))))
- (list
- start end
- (apply-partially
- #'completion-table-with-terminator
- (cons (lambda (comp)
- (concat comp
- suffix
- (if (file-directory-p
- (comint-directory (getenv comp)))
- "/")))
- "\\`a\\`")
- variables))))))
+ (list start end variables
+ :exit-function
+ (lambda (s finished)
+ (when (memq finished '(sole finished))
+ (let ((suf (concat suffix
+ (if (file-directory-p
+ (comint-directory (getenv s)))
+ "/"))))
+ (if (looking-at (regexp-quote suf))
+ (goto-char (match-end 0))
+ (insert suf))))))))))
(defun shell-c-a-p-replace-by-expanded-directory ()