(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
:group 'shell
:type '(choice (const nil) regexp))
+
+(defun shell-completion-vars ()
+ "Setup completion vars for `shell-mode' and `read-shell-command'."
+ (set (make-local-variable 'comint-completion-fignore)
+ shell-completion-fignore)
+ (set (make-local-variable 'comint-delimiter-argument-list)
+ shell-delimiter-argument-list)
+ (set (make-local-variable 'comint-file-name-chars) shell-file-name-chars)
+ (set (make-local-variable 'comint-file-name-quote-list)
+ shell-file-name-quote-list)
+ (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)
+ (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.
+ (add-hook 'completion-at-point-functions 'comint-completion-at-point nil t))
+
(put 'shell-mode 'mode-class 'special)
(define-derived-mode shell-mode comint-mode "Shell"
control whether input and output cause the window to scroll to the end of the
buffer."
(setq comint-prompt-regexp shell-prompt-pattern)
- (setq comint-completion-fignore shell-completion-fignore)
- (setq comint-delimiter-argument-list shell-delimiter-argument-list)
- (setq comint-file-name-chars shell-file-name-chars)
- (setq comint-file-name-quote-list shell-file-name-quote-list)
- (set (make-local-variable 'comint-dynamic-complete-functions)
- shell-dynamic-complete-functions)
+ (shell-completion-vars)
(set (make-local-variable 'paragraph-separate) "\\'")
- (make-local-variable 'paragraph-start)
- (setq paragraph-start comint-prompt-regexp)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults '(shell-font-lock-keywords t))
- (make-local-variable 'shell-dirstack)
- (setq shell-dirstack nil)
- (make-local-variable 'shell-last-dir)
- (setq shell-last-dir nil)
- (setq comint-input-autoexpand shell-input-autoexpand)
+ (set (make-local-variable 'paragraph-start) comint-prompt-regexp)
+ (set (make-local-variable 'font-lock-defaults) '(shell-font-lock-keywords t))
+ (set (make-local-variable 'shell-dirstack) nil)
+ (set (make-local-variable 'shell-last-dir) nil)
(shell-dirtrack-mode 1)
;; This is not really correct, since the shell buffer does not really
;; edit this directory. But it is useful in the buffer list and menus.
(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)
(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 ()