(Fconstrain_to_field): Make sure we don't violate the
[bpt/emacs.git] / lisp / shell.el
index 1b8c9da..13d1d9a 100644 (file)
@@ -3,7 +3,7 @@
 ;; Copyright (C) 1988, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu> then
-;;     Simon Marshall <simon@gnu.ai.mit.edu>
+;;     Simon Marshall <simon@gnu.org>
 ;; Maintainer: FSF
 ;; Keywords: processes
 
@@ -29,7 +29,7 @@
 ;; Please send me bug reports, bug fixes, and extensions, so that I can
 ;; merge them into the master source.
 ;;     - Olin Shivers (shivers@cs.cmu.edu)
-;;     - Simon Marshall (simon@gnu.ai.mit.edu)
+;;     - Simon Marshall (simon@gnu.org)
 
 ;; This file defines a a shell-in-a-buffer package (shell mode) built
 ;; on top of comint mode.  This is actually cmushell with things
 ;;============================================================================
 ;; Comint Mode Commands: (common to shell and all comint-derived modes)
 ;;
-;; m-p     comint-previous-input           Cycle backwards in input history
-;; m-n     comint-next-input               Cycle forwards
+;; m-p    comint-previous-input           Cycle backwards in input history
+;; m-n    comint-next-input               Cycle forwards
 ;; m-r     comint-previous-matching-input  Previous input matching a regexp
 ;; m-s     comint-next-matching-input      Next input that matches
-;; m-c-l   comint-show-output              Show last batch of process output
+;; m-c-l   comint-show-output             Show last batch of process output
 ;; return  comint-send-input
-;; c-d     comint-delchar-or-maybe-eof     Delete char unless at end of buff.
+;; c-d    comint-delchar-or-maybe-eof     Delete char unless at end of buff.
 ;; c-c c-a comint-bol                      Beginning of line; skip prompt
-;; c-c c-u comint-kill-input               ^u
-;; c-c c-w backward-kill-word              ^w
-;; c-c c-c comint-interrupt-subjob         ^c
-;; c-c c-z comint-stop-subjob              ^z
-;; c-c c-\ comint-quit-subjob              ^\
-;; c-c c-o comint-kill-output              Delete last batch of process output
-;; c-c c-r comint-show-output              Show last batch of process output
-;; c-c c-h comint-dynamic-list-input-ring  List input history
+;; c-c c-u comint-kill-input              ^u
+;; c-c c-w backward-kill-word             ^w
+;; c-c c-c comint-interrupt-subjob        ^c
+;; c-c c-z comint-stop-subjob             ^z
+;; c-c c-\ comint-quit-subjob             ^\
+;; c-c c-o comint-kill-output             Delete last batch of process output
+;; c-c c-r comint-show-output             Show last batch of process output
+;; c-c c-l comint-dynamic-list-input-ring  List input history
 ;;         send-invisible                  Read line w/o echo & send to proc
-;;         comint-continue-subjob          Useful if you accidentally suspend
+;;         comint-continue-subjob         Useful if you accidentally suspend
 ;;                                             top-level job
 ;; comint-mode-hook is the comint mode hook.
 
@@ -91,8 +91,8 @@
 ;;                                     List completions in help buffer
 ;; 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-toggle             Turn dir tracking on/off
+;;        dirs                         Resync the buffer's dir stack
+;;        dirtrack-mode                Turn dir tracking on/off
 ;;         comint-strip-ctrl-m         Remove trailing ^Ms from output
 ;;
 ;; The shell mode hook is shell-mode-hook
   :group 'shell)
 
 ;;;###autoload
-(defvar shell-prompt-pattern "^[^#$%>\n]*[#$%>] *"
+(defcustom shell-prompt-pattern "^[^#$%>\n]*[#$%>] *"
   "Regexp to match prompts in the inferior shell.
 Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well.
 This variable is used to initialise `comint-prompt-regexp' in the 
@@ -131,7 +131,9 @@ The pattern should probably not match more than one line.  If it does,
 Shell mode may become confused trying to distinguish prompt from input
 on lines which don't start with a prompt.
 
-This is a fine thing to set in your `.emacs' file.")
+This is a fine thing to set in your `.emacs' file."
+  :type 'regexp
+  :group 'shell)
 
 (defcustom shell-completion-fignore nil
   "*List of suffixes to be disregarded during file/command completion.
@@ -152,7 +154,7 @@ This is a fine thing to set in your `.emacs' file.")
 
 (defvar shell-file-name-chars
   (if (memq system-type '(ms-dos windows-nt))
-      "~/A-Za-z0-9_^$!#%&{}@`'.()-"
+      "~/A-Za-z0-9_^$!#%&{}@`'.,:()-"
     "~/A-Za-z0-9+@:_.$#%,={}-")
   "String of characters valid in a file name.
 This variable is used to initialize `comint-file-name-chars' in the
@@ -163,7 +165,7 @@ This is a fine thing to set in your `.emacs' file.")
 (defvar shell-file-name-quote-list
   (if (memq system-type '(ms-dos windows-nt))
       nil
-    (append shell-delimiter-argument-list '(?\  ?\* ?\! ?\" ?\' ?\`)))
+    (append shell-delimiter-argument-list '(?\  ?\* ?\! ?\" ?\' ?\` ?\#)))
   "List of characters to quote when in a file name.
 This variable is used to initialize `comint-file-name-quote-list' in the
 shell buffer.  The value may depend on the operating system or shell.
@@ -239,6 +241,12 @@ This mirrors the optional behavior of tcsh."
                 (const nil))
   :group 'shell-directories)
 
+(defcustom shell-dirtrack-verbose t
+  "*If non-nil, show the directory stack following directory change.
+This is effective only if directory tracking is enabled."
+  :type 'boolean
+  :group 'shell-directories)
+
 (defcustom explicit-shell-file-name nil
   "*If non-nil, is file name to use for explicitly requested inferior shell."
   :type '(choice (const :tag "None" nil) file)
@@ -266,8 +274,11 @@ into the buffer's input ring.  See also `comint-magic-space' and
 
 This variable supplies a default for `comint-input-autoexpand',
 for Shell mode only."
-  :type '(choice (const nil) (const input) (const history))
-  :type 'shell)
+  :type '(choice (const :tag "off" nil)
+                (const input)
+                (const history)
+                (const :tag "on" t))
+  :group 'shell)
 
 (defvar shell-dirstack nil
   "List of directories saved by pushd in this buffer's shell.
@@ -342,7 +353,7 @@ 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-toggle] turns directory tracking on and off.
+\\[dirtrack-mode] turns directory tracking on and off.
 
 \\{shell-mode-map}
 Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
@@ -513,7 +524,7 @@ 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 M-x dirtrack-toggle.
+You may toggle this tracking on and off with M-x dirtrack-mode.
 If emacs gets confused, you can resync with the shell with M-x dirs.
 
 See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp',
@@ -531,6 +542,8 @@ Environment variables are expanded, see function `substitute-in-file-name'."
              (setq end (match-end 0)
                    cmd (comint-arguments (substring str start end) 0 0)
                    arg1 (comint-arguments (substring str start end) 1 1))
+             (if arg1
+                 (setq arg1 (shell-unquote-argument arg1)))
              (cond ((string-match (concat "\\`\\(" shell-popd-regexp
                                           "\\)\\($\\|[ \t]\\)")
                                   cmd)
@@ -552,6 +565,25 @@ Environment variables are expanded, see function `substitute-in-file-name'."
                                 (match-end 0)))))
        (error "Couldn't cd"))))
 
+(defun shell-unquote-argument (string)
+  "Remove all kinds of shell quoting from STRING."
+  (save-match-data
+    (let ((idx 0) next inside)
+      (while (and (< idx (length string))
+                 (setq next (string-match "[\\'`\"]" string next)))
+       (cond ((= (aref string next) ?\\)
+              (setq string (replace-match "" nil nil string))
+              (setq next (1+ next)))
+             ((and inside (= (aref string next) inside))
+              (setq string (replace-match "" nil nil string))
+              (setq inside nil))
+             (inside
+              (setq next (1+ next)))
+             (t
+              (setq inside (aref string next))
+              (setq string (replace-match "" nil nil string)))))
+      string)))
+
 ;;; popd [+n]
 (defun shell-process-popd (arg)
   (let ((num (or (shell-extract-num arg) 0)))
@@ -638,7 +670,7 @@ Environment variables are expanded, see function `substitute-in-file-name'."
        (string-to-int str)))
 
 
-(defun shell-dirtrack-toggle ()
+(defun shell-dirtrack-mode ()
   "Turn directory tracking on and off in a shell buffer."
   (interactive)
   (if (setq shell-dirtrackp (not shell-dirtrackp))
@@ -647,7 +679,9 @@ Environment variables are expanded, see function `substitute-in-file-name'."
   (message "Directory tracking %s" (if shell-dirtrackp "ON" "OFF")))
 
 ;;; For your typing convenience:
-(defalias 'dirtrack-toggle 'shell-dirtrack-toggle)
+(defalias 'shell-dirtrack-toggle 'shell-dirtrack-mode)
+(defalias 'dirtrack-toggle 'shell-dirtrack-mode)
+(defalias 'dirtrack-mode 'shell-dirtrack-mode)
 
 (defun shell-cd (dir)
   "Do normal `cd' to DIR, and set `list-buffers-directory'."
@@ -713,24 +747,26 @@ command again."
 ;;; All the commands that mung the buffer's dirstack finish by calling
 ;;; this guy.
 (defun shell-dirstack-message ()
-  (let* ((msg "")
-        (ds (cons default-directory shell-dirstack))
-        (home (expand-file-name (concat comint-file-name-prefix "~/")))
-        (homelen (length home)))
-    (while ds
-      (let ((dir (car ds)))
-       (and (>= (length dir) homelen) (string= home (substring dir 0 homelen))
-           (setq dir (concat "~/" (substring dir homelen))))
-       ;; Strip off comint-file-name-prefix if present.
-       (and comint-file-name-prefix
-            (>= (length dir) (length comint-file-name-prefix))
-            (string= comint-file-name-prefix
-                     (substring dir 0 (length comint-file-name-prefix)))
-            (setq dir (substring dir (length comint-file-name-prefix)))
-            (setcar ds dir))
-       (setq msg (concat msg (directory-file-name dir) " "))
-       (setq ds (cdr ds))))
-    (message "%s" msg)))
+  (when shell-dirtrack-verbose
+    (let* ((msg "")
+          (ds (cons default-directory shell-dirstack))
+          (home (expand-file-name (concat comint-file-name-prefix "~/")))
+          (homelen (length home)))
+      (while ds
+       (let ((dir (car ds)))
+         (and (>= (length dir) homelen)
+              (string= home (substring dir 0 homelen))
+              (setq dir (concat "~/" (substring dir homelen))))
+         ;; Strip off comint-file-name-prefix if present.
+         (and comint-file-name-prefix
+              (>= (length dir) (length comint-file-name-prefix))
+              (string= comint-file-name-prefix
+                       (substring dir 0 (length comint-file-name-prefix)))
+              (setq dir (substring dir (length comint-file-name-prefix)))
+              (setcar ds dir))
+         (setq msg (concat msg (directory-file-name dir) " "))
+         (setq ds (cdr ds))))
+      (message "%s" msg))))
 \f
 ;; This was mostly copied from shell-resync-dirs.
 (defun shell-snarf-envar (var)
@@ -756,7 +792,7 @@ command again."
   "Copy the environment variable VARIABLE from the subshell to Emacs.
 This command reads the value of the specified environment variable
 in the shell, and sets the same environment variable in Emacs
-\(what `getenv' in Emacvs would return) to that value.
+\(what `getenv' in Emacs would return) to that value.
 That value will affect any new subprocesses that you subsequently start
 from Emacs."
   (interactive (list (read-envvar-name "\