summaryrefslogtreecommitdiff
path: root/lisp/shell.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/shell.el')
-rw-r--r--lisp/shell.el122
1 files changed, 93 insertions, 29 deletions
diff --git a/lisp/shell.el b/lisp/shell.el
index dc1198b7bac..43ad58774b8 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -249,7 +249,7 @@ This mirrors the optional behavior of tcsh."
(defcustom shell-chdrive-regexp
(if (memq system-type '(ms-dos windows-nt))
; NetWare allows the five chars between upper and lower alphabetics.
- "[]a-zA-Z^_`\\[\\\\]:"
+ "[]a-zA-Z^_`[\\]:"
nil)
"If non-nil, is regexp used to track drive changes."
:type '(choice regexp
@@ -334,6 +334,7 @@ Thus, this does not include the shell's current directory.")
(define-key map "\t" 'completion-at-point)
(define-key map (kbd "M-RET") 'shell-resync-dirs)
(define-key map "\M-?" 'comint-dynamic-list-filename-completions)
+ (define-key map (kbd "C-x n d") 'shell-narrow-to-prompt)
(define-key map [menu-bar completion]
(cons "Complete"
(copy-keymap (lookup-key comint-mode-map [menu-bar completion]))))
@@ -374,7 +375,7 @@ Thus, this does not include the shell's current directory.")
"\\|\\$\\(?:\\([[:alpha:]][[:alnum:]]*\\)"
"\\|{\\(?1:[^{}]+\\)}\\)"
(when (memq system-type '(ms-dos windows-nt))
- "\\|%\\(?1:[^\\\\/]*\\)%")
+ "\\|%\\(?1:[^\\/]*\\)%")
(when comint-file-name-quote-list
"\\|\\\\\\(.\\)")))
(qupos nil)
@@ -460,9 +461,12 @@ Thus, this does not include the shell's current directory.")
This is the value of `pcomplete-command-completion-function' for
Shell buffers. It implements `shell-completion-execonly' for
`pcomplete' completion."
- (pcomplete-here (pcomplete-entries nil
- (if shell-completion-execonly
- 'file-executable-p))))
+ (if (pcomplete-match "/")
+ (pcomplete-here (pcomplete-entries nil
+ (if shell-completion-execonly
+ 'file-executable-p)))
+ (pcomplete-here
+ (nth 2 (shell--command-completion-data)))))
(defun shell-completion-vars ()
"Setup completion vars for `shell-mode' and `read-shell-command'."
@@ -619,7 +623,12 @@ buffer."
;; Bypass a bug in certain versions of bash.
(when (string-equal shell "bash")
(add-hook 'comint-preoutput-filter-functions
- #'shell-filter-ctrl-a-ctrl-b nil t)))
+ #'shell-filter-ctrl-a-ctrl-b nil t))
+
+ ;; Skip extended history for zsh.
+ (when (string-equal shell "zsh")
+ (setq-local comint-input-ring-file-prefix
+ ": [[:digit:]]+:[[:digit:]]+;")))
(comint-read-input-ring t)))
(defun shell-apply-ansi-color (beg end face)
@@ -985,9 +994,6 @@ this feature; see the function `dirtrack-mode'."
(add-hook 'comint-input-filter-functions #'shell-directory-tracker nil t)
(remove-hook 'comint-input-filter-functions #'shell-directory-tracker t)))
-(define-obsolete-function-alias 'shell-dirtrack-toggle #'shell-dirtrack-mode
- "23.1")
-
(defun shell-cd (dir)
"Do normal `cd' to DIR, and set `list-buffers-directory'."
(cd dir)
@@ -1033,25 +1039,41 @@ command again."
(accept-process-output proc)
(goto-char pt)))
(goto-char pmark) (delete-char 1) ; remove the extra newline
- ;; That's the dirlist. grab it & parse it.
- (let* ((dl (buffer-substring (match-beginning 2) (1- (match-end 2))))
- (dl-len (length dl))
- (ds '()) ; new dir stack
- (i 0))
- (while (< i dl-len)
- ;; regexp = optional whitespace, (non-whitespace), optional whitespace
- (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
- (setq ds (cons (concat comint-file-name-prefix
- (substring dl (match-beginning 1)
- (match-end 1)))
- ds))
- (setq i (match-end 0)))
- (let ((ds (nreverse ds)))
- (with-demoted-errors "Couldn't cd: %s"
- (shell-cd (car ds))
- (setq shell-dirstack (cdr ds)
- shell-last-dir (car shell-dirstack))
- (shell-dirstack-message)))))
+ ;; That's the dirlist. Grab it & parse it.
+ (let* ((dls (buffer-substring-no-properties
+ (match-beginning 0) (1- (match-end 0))))
+ (dlsl nil)
+ (pos 0)
+ (ds nil))
+ ;; Split the dirlist into whitespace and non-whitespace chunks.
+ ;; dlsl will be a reversed list of tokens.
+ (while (string-match "\\(\\S-+\\|\\s-+\\)" dls pos)
+ (push (match-string 1 dls) dlsl)
+ (setq pos (match-end 1)))
+
+ ;; Prepend trailing entries until they form an existing directory,
+ ;; whitespace and all. Discard the next whitespace and repeat.
+ (while dlsl
+ (let ((newelt "")
+ tem1 tem2)
+ (while newelt
+ ;; We need tem1 because we don't want to prepend
+ ;; `comint-file-name-prefix' repeatedly into newelt via tem2.
+ (setq tem1 (pop dlsl)
+ tem2 (concat comint-file-name-prefix tem1 newelt))
+ (cond ((file-directory-p tem2)
+ (push tem2 ds)
+ (when (string= " " (car dlsl))
+ (pop dlsl))
+ (setq newelt nil))
+ (t
+ (setq newelt (concat tem1 newelt)))))))
+
+ (with-demoted-errors "Couldn't cd: %s"
+ (shell-cd (car ds))
+ (setq shell-dirstack (cdr ds)
+ shell-last-dir (car shell-dirstack))
+ (shell-dirstack-message))))
(if started-at-pmark (goto-char (marker-position pmark)))))
;; For your typing convenience:
@@ -1187,7 +1209,7 @@ Returns t if successful."
(cwd (file-name-as-directory (expand-file-name default-directory)))
(ignored-extensions
(and comint-completion-fignore
- (mapconcat (function (lambda (x) (concat (regexp-quote x) "\\'")))
+ (mapconcat (lambda (x) (concat (regexp-quote x) "\\'"))
comint-completion-fignore "\\|")))
(dir "") (comps-in-dir ())
(file "") (abs-file-name "") (completions ()))
@@ -1345,6 +1367,48 @@ Returns t if successful."
(let ((f (shell-c-a-p-replace-by-expanded-directory)))
(if f (funcall f))))
+(defun shell--prompt-begin-position ()
+ ;; We need this convoluted function because `looking-at-p' does not work on
+ ;; multiline regexps _and_ `re-search-backward' skips the current line.
+ (save-excursion
+ (let ((old-point (point)))
+ (max
+ (save-excursion
+ ;; Right result if not on prompt.
+ (call-interactively #'comint-previous-prompt)
+ (re-search-backward comint-prompt-regexp)
+ (point))
+ (save-excursion
+ ;; Right result if on first char after prompt.
+ (re-search-backward comint-prompt-regexp)
+ (point))
+ (save-excursion
+ ;; Right result if on prompt.
+ (call-interactively #'comint-next-prompt)
+ (re-search-backward comint-prompt-regexp)
+ (if (<= (point) old-point)
+ (point)
+ (point-min)))))))
+
+(defun shell--prompt-end-position ()
+ (save-excursion
+ (goto-char (shell--prompt-begin-position))
+ (comint-next-prompt 1)
+ (point)))
+
+(defun shell-narrow-to-prompt ()
+ "Narrow buffer to the command line (and any following command output) at point."
+ (interactive)
+ (let ((begin (shell--prompt-begin-position)))
+ (narrow-to-region
+ begin
+ (save-excursion
+ (goto-char (shell--prompt-end-position))
+ (call-interactively #'comint-next-prompt)
+ (if (= begin (shell--prompt-begin-position))
+ (point-max)
+ (shell--prompt-begin-position))))))
+
(provide 'shell)
;;; shell.el ends here