;;; shell.el --- specialized comint.el for running the shell
;; Copyright (C) 1988, 1993, 1994, 1995, 1996, 1997, 2000, 2001,
-;; 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+;; 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu>
;; Simon Marshall <simon@gnu.org>
;; m-c-f shell-forward-command Forward a shell command
;; m-c-b shell-backward-command Backward a shell command
;; dirs Resync the buffer's dir stack
-;; dirtrack-mode Turn dir tracking on/off
+;; shell-dirtrack-mode Turn dir tracking on/off
;; comint-strip-ctrl-m Remove trailing ^Ms from output
;;
;; The shell mode hook is shell-mode-hook
shell-dynamic-complete-environment-variable
shell-dynamic-complete-command
shell-replace-by-expanded-directory
- comint-dynamic-complete-filename)
+ shell-dynamic-complete-filename)
"List of functions called to perform completion.
This variable is used to initialize `comint-dynamic-complete-functions' in the
shell buffer.
(defcustom shell-dirtrack-verbose t
"If non-nil, show the directory stack following directory change.
-This is effective only if directory tracking is enabled."
+This is effective only if directory tracking is enabled.
+The `dirtrack' package provides an alternative implementation of this feature -
+see the function `dirtrack-mode'."
:type 'boolean
:group 'shell-directories)
by \\[list-buffers] or \\[mouse-buffer-menu] in the `File' field.
\\[dirs] queries the shell and resyncs Emacs' idea of what the current
directory stack is.
-\\[dirtrack-mode] turns directory tracking on and off.
+\\[shell-dirtrack-mode] turns directory tracking on and off.
+\(The `dirtrack' package provides an alternative implementation of this
+feature - see the function `dirtrack-mode'.)
\\{shell-mode-map}
Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
(interactive
(list
(and current-prefix-arg
- (read-buffer "Shell buffer: "
- (generate-new-buffer-name "*shell*"))
- (file-remote-p default-directory)
- ;; It must be possible to declare a local default-directory.
- (setq default-directory
- (expand-file-name
- (read-file-name
- "Default directory: " default-directory default-directory
- t nil 'file-directory-p))))))
+ (prog1
+ (read-buffer "Shell buffer: "
+ (generate-new-buffer-name "*shell*"))
+ (if (file-remote-p default-directory)
+ ;; It must be possible to declare a local default-directory.
+ (setq default-directory
+ (expand-file-name
+ (read-file-name
+ "Default directory: " default-directory default-directory
+ t nil 'file-directory-p))))))))
(setq buffer (get-buffer-create (or buffer "*shell*")))
;; 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).
It watches for cd, pushd and popd commands and sets the buffer's
default directory to track these commands.
-You may toggle this tracking on and off with \\[dirtrack-mode].
+You may toggle this tracking on and off with \\[shell-dirtrack-mode].
If Emacs gets confused, you can resync with the shell with \\[dirs].
+\(The `dirtrack' package provides an alternative implementation of this
+feature - see the function `dirtrack-mode'.)
See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp',
and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract',
(defvaralias 'shell-dirtrack-mode 'shell-dirtrackp)
(define-minor-mode shell-dirtrack-mode
- "Turn directory tracking on and off in a shell buffer."
+ "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'."
nil nil 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)))
-;; For your typing convenience:
-(defalias 'shell-dirtrack-toggle 'shell-dirtrack-mode) ;??Convenience??
-(defalias 'dirtrack-toggle 'shell-dirtrack-mode)
-(defalias 'dirtrack-mode 'shell-dirtrack-mode)
+(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'."
command again."
(interactive)
(let* ((proc (get-buffer-process (current-buffer)))
- (pmark (process-mark proc)))
- (goto-char pmark)
- ;; If the process echoes commands, don't insert a fake command in
- ;; the buffer or it will appear twice.
- (unless comint-process-echoes
- (insert shell-dirstack-query) (insert "\n"))
- (sit-for 0) ; force redisplay
- (comint-send-string proc shell-dirstack-query)
- (comint-send-string proc "\n")
- (set-marker pmark (point))
- (let ((pt (point))
- (regexp
- (concat
- (if comint-process-echoes
- ;; Skip command echo if the process echoes
- (concat "\\(" (regexp-quote shell-dirstack-query) "\n\\)")
- "\\(\\)")
- "\\(.+\n\\)")))
- ;; This extra newline prevents the user's pending input from spoofing us.
- (insert "\n") (backward-char 1)
- ;; Wait for one line.
- (while (not (looking-at regexp))
- (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)))
- (condition-case nil
- (progn (shell-cd (car ds))
- (setq shell-dirstack (cdr ds)
- shell-last-dir (car shell-dirstack))
- (shell-dirstack-message))
- (error (message "Couldn't cd")))))))
+ (pmark (process-mark proc))
+ (started-at-pmark (= (point) (marker-position pmark))))
+ (save-excursion
+ (goto-char pmark)
+ ;; If the process echoes commands, don't insert a fake command in
+ ;; the buffer or it will appear twice.
+ (unless comint-process-echoes
+ (insert shell-dirstack-query) (insert "\n"))
+ (sit-for 0) ; force redisplay
+ (comint-send-string proc shell-dirstack-query)
+ (comint-send-string proc "\n")
+ (set-marker pmark (point))
+ (let ((pt (point))
+ (regexp
+ (concat
+ (if comint-process-echoes
+ ;; Skip command echo if the process echoes
+ (concat "\\(" (regexp-quote shell-dirstack-query) "\n\\)")
+ "\\(\\)")
+ "\\(.+\n\\)")))
+ ;; This extra newline prevents the user's pending input from spoofing us.
+ (insert "\n") (backward-char 1)
+ ;; Wait for one line.
+ (while (not (looking-at regexp))
+ (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)))
+ (condition-case nil
+ (progn (shell-cd (car ds))
+ (setq shell-dirstack (cdr ds)
+ shell-last-dir (car shell-dirstack))
+ (shell-dirstack-message))
+ (error (message "Couldn't cd"))))))
+ (if started-at-pmark (goto-char (marker-position pmark)))))
;; For your typing convenience:
(defalias 'dirs 'shell-resync-dirs)
(save-match-data (not (string-match "[~/]" filename)))
(eq (match-beginning 0)
(save-excursion (shell-backward-command 1) (point))))
- (prog2 (message "Completing command name...")
+ (prog2 (unless (window-minibuffer-p (selected-window))
+ (message "Completing command name..."))
(shell-dynamic-complete-as-command)))))
(insert " "))
success)))
+(defun shell-dynamic-complete-filename ()
+ "Dynamically complete the filename at point.
+This completes only if point is at a suitable position for a
+filename argument."
+ (interactive)
+ (let ((opoint (point))
+ (beg (comint-line-beginning-position)))
+ (when (save-excursion
+ (goto-char (if (re-search-backward "[;|&]" beg t)
+ (match-end 0)
+ beg))
+ (re-search-forward "[^ \t][ \t]" opoint t))
+ (comint-dynamic-complete-as-filename))))
(defun shell-match-partial-variable ()
"Return the shell variable at point, or nil if none is found."
(re-search-forward "\\$?{?[A-Za-z0-9_]*}?" limit)
(buffer-substring (match-beginning 0) (match-end 0))))))
-
(defun shell-dynamic-complete-environment-variable ()
"Dynamically complete the environment variable at point.
Completes if after a variable, i.e., if it starts with a \"$\".
(interactive)
(let ((variable (shell-match-partial-variable)))
(if (and variable (string-match "^\\$" variable))
- (prog2 (message "Completing variable name...")
+ (prog2 (unless (window-minibuffer-p (selected-window))
+ (message "Completing variable name..."))
(shell-dynamic-complete-as-environment-variable)))))