diff options
Diffstat (limited to 'lisp/shell.el')
-rw-r--r-- | lisp/shell.el | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/lisp/shell.el b/lisp/shell.el index ca86059f9de..cd49d289403 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -345,10 +345,10 @@ undefined commands." "List of directories saved by pushd in this buffer's shell. Thus, this does not include the shell's current directory.") -(defvaralias 'shell-dirtrack-mode 'shell-dirtrackp) - -(defvar shell-dirtrackp t - "Non-nil in a shell buffer means directory tracking is enabled.") +(defvaralias 'shell-dirtrackp 'shell-dirtrack-mode + "Non-nil in a shell buffer means directory tracking is enabled. +Directory tracking (`shell-dirtrack-mode') is automatically enabled +when `shell-mode' is activated.") (defvar shell-last-dir nil "Keep track of last directory for ksh `cd -' command.") @@ -365,6 +365,12 @@ Useful for shells like zsh that has this feature." :group 'shell-directories :version "28.1") +(defcustom shell-get-old-input-include-continuation-lines nil + "Whether `shell-get-old-input' includes \"\\\" lines." + :type 'boolean + :group 'shell + :version "30.1") + (defcustom shell-kill-buffer-on-exit nil "Kill a shell buffer after the shell process terminates." :type 'boolean @@ -505,6 +511,39 @@ Useful for shells like zsh that has this feature." (push (mapconcat #'identity (nreverse arg) "") args))) (cons (nreverse args) (nreverse begins))))) +(defun shell-get-old-input () + "Default for `comint-get-old-input' in `shell-mode'. +If `comint-use-prompt-regexp' is nil, then either +return the current input field (if point is on an input field), or the +current line (if point is on an output field). +If `comint-use-prompt-regexp' is non-nil, then return +the current line, with any initial string matching the regexp +`comint-prompt-regexp' removed. +In either case, if `shell-get-old-input-include-continuation-lines' +is non-nil and the current line ends with a backslash, the next +line is also included and examined for a backslash, ending with a +final line without a backslash." + (let (field-prop bof) + (if (and (not comint-use-prompt-regexp) + ;; Make sure we're in an input rather than output field. + (not (setq field-prop (get-char-property + (setq bof (field-beginning)) 'field)))) + (field-string-no-properties bof) + (comint-bol) + (let ((start (point))) + (cond ((or comint-use-prompt-regexp + (eq field-prop 'output)) + (goto-char (line-end-position)) + (when shell-get-old-input-include-continuation-lines + ;; Include continuation lines as long as the current + ;; line ends with a backslash. + (while (and (not (eobp)) + (= (char-before) ?\\)) + (goto-char (line-end-position 2))))) + (t + (goto-char (field-end)))) + (buffer-substring-no-properties start (point)))))) + ;;;###autoload (defun split-string-shell-command (string) "Split STRING (a shell command) into a list of strings. @@ -555,6 +594,9 @@ Shell buffers. It implements `shell-completion-execonly' for ;; Don't use pcomplete's defaulting mechanism, rely on ;; shell-dynamic-complete-functions instead. (setq-local pcomplete-default-completion-function #'ignore) + ;; Do not expand remote file names. + (setq-local pcomplete-remote-file-ignore + (not (file-remote-p default-directory))) (setq-local 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. @@ -564,6 +606,9 @@ Shell buffers. It implements `shell-completion-execonly' for (defvar sh-shell-file) +(declare-function w32-application-type "w32proc.c" + (program) t) + (define-derived-mode shell-mode comint-mode "Shell" "Major mode for interacting with an inferior shell. \\<shell-mode-map> @@ -641,6 +686,7 @@ command." (setq-local font-lock-defaults '(shell-font-lock-keywords t)) (setq-local shell-dirstack nil) (setq-local shell-last-dir nil) + (setq-local comint-get-old-input #'shell-get-old-input) ;; People expect Shell mode to keep the last line of output at ;; window bottom. (setq-local scroll-conservatively 101) @@ -711,6 +757,11 @@ command." ((string-equal shell "ksh") "echo $PWD ~-") ;; Bypass any aliases. TODO all shells could use this. ((string-equal shell "bash") "command dirs") + ((and (string-equal shell "bash.exe") + (eq system-type 'windows-nt) + (eq (w32-application-type (executable-find "bash.exe")) + 'msys)) + "command pwd -W") ((string-equal shell "zsh") "dirs -l") (t "dirs"))) ;; Bypass a bug in certain versions of bash. @@ -956,6 +1007,21 @@ Make the shell buffer the current buffer, and return it. ;; replace it with a process filter that watches for and strips out ;; these messages. +(define-minor-mode shell-dirtrack-mode + "Toggle directory tracking in this shell buffer (Shell Dirtrack mode). +This assigns a buffer-local non-nil value to `shell-dirtrackp'. + +The `dirtrack' package provides an alternative implementation of +this feature; see the function `dirtrack-mode'. Also see +`comint-osc-directory-tracker' for an escape-sequence based +solution." + :lighter nil + :interactive (shell-mode) + (setq list-buffers-directory (if shell-dirtrack-mode default-directory)) + (if shell-dirtrack-mode + (add-hook 'comint-input-filter-functions #'shell-directory-tracker nil t) + (remove-hook 'comint-input-filter-functions #'shell-directory-tracker t))) + (defun shell-directory-tracker (str) "Tracks cd, pushd and popd commands issued to the shell. This function is called on each input passed to the shell. @@ -972,7 +1038,7 @@ and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract', and `shell-pushd-dunique' control the behavior of the relevant command. Environment variables are expanded, see function `substitute-in-file-name'." - (if shell-dirtrackp + (if shell-dirtrack-mode ;; We fail gracefully if we think the command will fail in the shell. ;;; (with-demoted-errors "Directory tracker failure: %s" ;; This fails so often that it seems better to just ignore errors (?). @@ -1126,23 +1192,10 @@ Environment variables are expanded, see function `substitute-in-file-name'." (and (string-match "^\\+[1-9][0-9]*$" str) (string-to-number str))) -(define-minor-mode shell-dirtrack-mode - "Toggle directory tracking in this shell buffer (Shell Dirtrack mode). - -The `dirtrack' package provides an alternative implementation of -this feature; see the function `dirtrack-mode'. Also see -`comint-osc-directory-tracker' for an escape-sequence based -solution." - :lighter nil - (setq list-buffers-directory (if shell-dirtrack-mode default-directory)) - (if shell-dirtrack-mode - (add-hook 'comint-input-filter-functions #'shell-directory-tracker nil t) - (remove-hook 'comint-input-filter-functions #'shell-directory-tracker t))) - (defun shell-cd (dir) "Do normal `cd' to DIR, and set `list-buffers-directory'." (cd dir) - (if shell-dirtrackp + (if shell-dirtrack-mode (setq list-buffers-directory default-directory))) (defun shell-resync-dirs () @@ -1331,7 +1384,12 @@ Returns t if successful." (while path-dirs (setq dir (file-name-as-directory (comint-directory (or (car path-dirs) "."))) comps-in-dir (and (file-accessible-directory-p dir) - (file-name-all-completions filenondir dir))) + (condition-case nil + (file-name-all-completions filenondir dir) + ;; Systems such as Android sometimes + ;; put inaccessible directories in + ;; PATH. + (permission-denied nil)))) ;; Go thru each completion found, to see whether it should be used. (while comps-in-dir (setq file (car comps-in-dir) |