Bug fix for vc-dispatcher split.
[bpt/emacs.git] / lisp / shell.el
index 6c09654..67050c9 100644 (file)
@@ -1,7 +1,7 @@
 ;;; 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>
@@ -88,7 +88,7 @@
 ;; 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
@@ -186,7 +186,7 @@ This is a fine thing to set in your `.emacs' file.")
     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.
@@ -258,7 +258,9 @@ This mirrors the optional behavior of tcsh."
 
 (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)
 
@@ -393,7 +395,9 @@ While directory tracking is enabled, the shell's working directory is displayed
 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
@@ -542,15 +546,16 @@ Otherwise, one argument `-i' is passed to the shell.
   (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).
@@ -620,8 +625,10 @@ This function is called on each input passed to the shell.
 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',
@@ -777,17 +784,17 @@ Environment variables are expanded, see function `substitute-in-file-name'."
 
 (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'."
@@ -807,51 +814,54 @@ new directory stack -- you lose.  If this happens, just do the
 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)
@@ -955,7 +965,8 @@ Returns t if successful."
             (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)))))
 
 
@@ -999,6 +1010,19 @@ See `shell-dynamic-complete-filename'.  Returns t if successful."
          (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."
@@ -1012,7 +1036,6 @@ See `shell-dynamic-complete-filename'.  Returns t if successful."
        (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 \"$\".
@@ -1030,7 +1053,8 @@ Returns non-nil if successful."
   (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)))))