# HG changeset patch # User Stefan Monnier # Date 1147903045 0 # Node ID a69f2db3d3ae959d2495872d21b57a44465f3980 # Parent 8fd6ecfbe6ea8fa5fbaaf98456621a24cf1e9c18 (shell-dirtrack-mode): Make it into a proper minor mode, so we can explicitly enable/disable rather than toggle. (shell-mode): Use it. (shell-cd): Don't try to reproduce what `cd' does. diff -r 8fd6ecfbe6ea -r a69f2db3d3ae lisp/ChangeLog --- a/lisp/ChangeLog Wed May 17 21:25:59 2006 +0000 +++ b/lisp/ChangeLog Wed May 17 21:57:25 2006 +0000 @@ -1,6 +1,14 @@ +2006-05-17 Stefan Monnier + + * shell.el (shell-dirtrack-mode): Make it into a proper minor mode, so + we can explicitly enable/disable rather than toggle. + (shell-mode): Use it. + (shell-cd): Don't try to reproduce what `cd' does. + 2006-05-17 Kim F. Storm - * ido.el (ido-read-internal): Use only nondirectory part of default item. + * ido.el (ido-read-internal): Use only nondirectory part of + default item. 2006-05-17 Thien-Thi Nguyen diff -r 8fd6ecfbe6ea -r a69f2db3d3ae lisp/shell.el --- a/lisp/shell.el Wed May 17 21:25:59 2006 +0000 +++ b/lisp/shell.el Wed May 17 21:57:25 2006 +0000 @@ -150,7 +150,7 @@ :group 'shell) (defcustom shell-completion-fignore nil - "*List of suffixes to be disregarded during file/command completion. + "List of suffixes to be disregarded during file/command completion. This variable is used to initialize `comint-completion-fignore' in the shell buffer. The default is nil, for compatibility with most shells. Some people like (\"~\" \"#\" \"%\"). @@ -199,19 +199,19 @@ This is a fine thing to set in your `.emacs' file.") (defcustom shell-command-regexp "[^;&|\n]+" - "*Regexp to match a single command within a pipeline. + "Regexp to match a single command within a pipeline. This is used for directory tracking and does not do a perfect job." :type 'regexp :group 'shell) (defcustom shell-command-separator-regexp "[;&|\n \t]*" - "*Regexp to match a single command within a pipeline. + "Regexp to match a single command within a pipeline. This is used for directory tracking and does not do a perfect job." :type 'regexp :group 'shell) (defcustom shell-completion-execonly t - "*If non-nil, use executable files only for completion candidates. + "If non-nil, use executable files only for completion candidates. This mirrors the optional behavior of tcsh. Detecting executability of files may slow command completion considerably." @@ -219,35 +219,35 @@ :group 'shell) (defcustom shell-popd-regexp "popd" - "*Regexp to match subshell commands equivalent to popd." + "Regexp to match subshell commands equivalent to popd." :type 'regexp :group 'shell-directories) (defcustom shell-pushd-regexp "pushd" - "*Regexp to match subshell commands equivalent to pushd." + "Regexp to match subshell commands equivalent to pushd." :type 'regexp :group 'shell-directories) (defcustom shell-pushd-tohome nil - "*If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd). + "If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd). This mirrors the optional behavior of tcsh." :type 'boolean :group 'shell-directories) (defcustom shell-pushd-dextract nil - "*If non-nil, make \"pushd +n\" pop the nth dir to the stack top. + "If non-nil, make \"pushd +n\" pop the nth dir to the stack top. This mirrors the optional behavior of tcsh." :type 'boolean :group 'shell-directories) (defcustom shell-pushd-dunique nil - "*If non-nil, make pushd only add unique directories to the stack. + "If non-nil, make pushd only add unique directories to the stack. This mirrors the optional behavior of tcsh." :type 'boolean :group 'shell-directories) (defcustom shell-cd-regexp "cd" - "*Regexp to match subshell commands equivalent to cd." + "Regexp to match subshell commands equivalent to cd." :type 'regexp :group 'shell-directories) @@ -256,19 +256,19 @@ ; NetWare allows the five chars between upper and lower alphabetics. "[]a-zA-Z^_`\\[\\\\]:" nil) - "*If non-nil, is regexp used to track drive changes." + "If non-nil, is regexp used to track drive changes." :type '(choice regexp (const nil)) :group 'shell-directories) (defcustom shell-dirtrack-verbose t - "*If non-nil, show the directory stack following directory change. + "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." + "If non-nil, is file name to use for explicitly requested inferior shell." :type '(choice (const :tag "None" nil) file) :group 'shell) @@ -278,7 +278,7 @@ ;; than us about what terminal modes to use. '("-i" "-T") '("-i")) - "*Args passed to inferior shell by M-x shell, if the shell is csh. + "Args passed to inferior shell by \\[shell], if the shell is csh. Value is a list of strings, which may be nil." :type '(repeat (string :tag "Argument")) :group 'shell) @@ -296,13 +296,13 @@ (shell-command-to-string (concat prog " --noediting")))) '("-i") '("--noediting" "-i"))) - "*Args passed to inferior shell by M-x shell, if the shell is bash. + "Args passed to inferior shell by \\[shell], if the shell is bash. Value is a list of strings, which may be nil." :type '(repeat (string :tag "Argument")) :group 'shell) (defcustom shell-input-autoexpand 'history - "*If non-nil, expand input command history references on completion. + "If non-nil, expand input command history references on completion. This mirrors the optional behavior of tcsh (its autoexpand and histlit). If the value is `input', then the expansion is seen on input. @@ -433,9 +433,7 @@ (setq shell-dirstack nil) (make-local-variable 'shell-last-dir) (setq shell-last-dir nil) - (make-local-variable 'shell-dirtrackp) - (setq shell-dirtrackp t) - (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t) + (shell-dirtrack-mode 1) (setq comint-input-autoexpand shell-input-autoexpand) ;; This is not really correct, since the shell buffer does not really ;; edit this directory. But it is useful in the buffer list and menus. @@ -558,48 +556,48 @@ (shell-mode))) buffer) -;;; Don't do this when shell.el is loaded, only while dumping. +;; Don't do this when shell.el is loaded, only while dumping. ;;;###autoload (add-hook 'same-window-buffer-names "*shell*") ;;; Directory tracking -;;; -;;; This code provides the shell mode input sentinel -;;; SHELL-DIRECTORY-TRACKER -;;; that tracks cd, pushd, and popd commands issued to the shell, and -;;; changes the current directory of the shell buffer accordingly. -;;; -;;; This is basically a fragile hack, although it's more accurate than -;;; the version in Emacs 18's shell.el. It has the following failings: -;;; 1. It doesn't know about the cdpath shell variable. -;;; 2. It cannot infallibly deal with command sequences, though it does well -;;; with these and with ignoring commands forked in another shell with ()s. -;;; 3. More generally, any complex command is going to throw it. Otherwise, -;;; you'd have to build an entire shell interpreter in Emacs Lisp. Failing -;;; that, there's no way to catch shell commands where cd's are buried -;;; inside conditional expressions, aliases, and so forth. -;;; -;;; The whole approach is a crock. Shell aliases mess it up. File sourcing -;;; messes it up. You run other processes under the shell; these each have -;;; separate working directories, and some have commands for manipulating -;;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have -;;; commands that do *not* affect the current w.d. at all, but look like they -;;; do (e.g., the cd command in ftp). In shells that allow you job -;;; control, you can switch between jobs, all having different w.d.'s. So -;;; simply saying %3 can shift your w.d.. -;;; -;;; The solution is to relax, not stress out about it, and settle for -;;; a hack that works pretty well in typical circumstances. Remember -;;; that a half-assed solution is more in keeping with the spirit of Unix, -;;; anyway. Blech. -;;; -;;; One good hack not implemented here for users of programmable shells -;;; is to program up the shell w.d. manipulation commands to output -;;; a coded command sequence to the tty. Something like -;;; ESC | | -;;; where is the new current working directory. Then trash the -;;; directory tracking machinery currently used in this package, and -;;; replace it with a process filter that watches for and strips out -;;; these messages. +;; +;; This code provides the shell mode input sentinel +;; SHELL-DIRECTORY-TRACKER +;; that tracks cd, pushd, and popd commands issued to the shell, and +;; changes the current directory of the shell buffer accordingly. +;; +;; This is basically a fragile hack, although it's more accurate than +;; the version in Emacs 18's shell.el. It has the following failings: +;; 1. It doesn't know about the cdpath shell variable. +;; 2. It cannot infallibly deal with command sequences, though it does well +;; with these and with ignoring commands forked in another shell with ()s. +;; 3. More generally, any complex command is going to throw it. Otherwise, +;; you'd have to build an entire shell interpreter in Emacs Lisp. Failing +;; that, there's no way to catch shell commands where cd's are buried +;; inside conditional expressions, aliases, and so forth. +;; +;; The whole approach is a crock. Shell aliases mess it up. File sourcing +;; messes it up. You run other processes under the shell; these each have +;; separate working directories, and some have commands for manipulating +;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have +;; commands that do *not* affect the current w.d. at all, but look like they +;; do (e.g., the cd command in ftp). In shells that allow you job +;; control, you can switch between jobs, all having different w.d.'s. So +;; simply saying %3 can shift your w.d.. +;; +;; The solution is to relax, not stress out about it, and settle for +;; a hack that works pretty well in typical circumstances. Remember +;; that a half-assed solution is more in keeping with the spirit of Unix, +;; anyway. Blech. +;; +;; One good hack not implemented here for users of programmable shells +;; is to program up the shell w.d. manipulation commands to output +;; a coded command sequence to the tty. Something like +;; ESC | | +;; where is the new current working directory. Then trash the +;; directory tracking machinery currently used in this package, and +;; replace it with a process filter that watches for and strips out +;; these messages. (defun shell-directory-tracker (str) "Tracks cd, pushd and popd commands issued to the shell. @@ -607,8 +605,8 @@ 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-mode. -If Emacs gets confused, you can resync with the shell with M-x dirs. +You may toggle this tracking on and off with \\[dirtrack-mode]. +If Emacs gets confused, you can resync with the shell with \\[dirs]. See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp', and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract', @@ -677,7 +675,7 @@ (setq string (replace-match "" nil nil string))))) string))) -;;; popd [+n] +;; popd [+n] (defun shell-process-popd (arg) (let ((num (or (shell-extract-num arg) 0))) (cond ((and num (= num 0) shell-dirstack) @@ -703,7 +701,7 @@ ;; For relative name we assume default-directory already has the prefix. (expand-file-name dir)))) -;;; cd [dir] +;; cd [dir] (defun shell-process-cd (arg) (let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix "~")) @@ -713,7 +711,7 @@ (shell-cd new-dir) (shell-dirstack-message))) -;;; pushd [+n | dir] +;; pushd [+n | dir] (defun shell-process-pushd (arg) (let ((num (shell-extract-num arg))) (cond ((zerop (length arg)) @@ -762,26 +760,25 @@ (and (string-match "^\\+[1-9][0-9]*$" str) (string-to-number str))) - -(defun shell-dirtrack-mode () +(defvaralias 'shell-dirtrack-mode 'shell-dirtrackp) +(define-minor-mode shell-dirtrack-mode "Turn directory tracking on and off in a shell buffer." - (interactive) - (if (setq shell-dirtrackp (not shell-dirtrackp)) - (setq list-buffers-directory default-directory) - (setq list-buffers-directory nil)) - (message "Directory tracking %s" (if shell-dirtrackp "ON" "OFF"))) + 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) +;; For your typing convenience: +(defalias 'shell-dirtrack-toggle 'shell-dirtrack-mode) ;??Convenience?? (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'." + (cd dir) (if shell-dirtrackp - (setq list-buffers-directory (file-name-as-directory - (expand-file-name dir)))) - (cd dir)) + (setq list-buffers-directory default-directory))) (defun shell-resync-dirs () "Resync the buffer's idea of the current directory stack. @@ -841,15 +838,15 @@ (shell-dirstack-message)) (error (message "Couldn't cd"))))))) -;;; For your typing convenience: +;; For your typing convenience: (defalias 'dirs 'shell-resync-dirs) -;;; Show the current dirstack on the message line. -;;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo". -;;; (This isn't necessary if the dirlisting is generated with a simple "dirs".) -;;; All the commands that mung the buffer's dirstack finish by calling -;;; this guy. +;; Show the current dirstack on the message line. +;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo". +;; (This isn't necessary if the dirlisting is generated with a simple "dirs".) +;; All the commands that mung the buffer's dirstack finish by calling +;; this guy. (defun shell-dirstack-message () (when shell-dirtrack-verbose (let* ((msg "") @@ -1076,5 +1073,5 @@ (provide 'shell) -;;; arch-tag: bcb5f12a-c1f4-4aea-a809-2504bd5bd797 +;; arch-tag: bcb5f12a-c1f4-4aea-a809-2504bd5bd797 ;;; shell.el ends here