aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/shell.el
diff options
context:
space:
mode:
authorStefan Monnier2006-05-17 21:57:25 +0000
committerStefan Monnier2006-05-17 21:57:25 +0000
commit05327ca9724287cc3da4c625f180da5ab11be998 (patch)
tree07e8dcb823794a9374a544b3cb88ce08aaa2e964 /lisp/shell.el
parent2d38f869f6f2aafd1fc3ddc605d79eda2fa207ae (diff)
downloademacs-05327ca9724287cc3da4c625f180da5ab11be998.tar.gz
emacs-05327ca9724287cc3da4c625f180da5ab11be998.zip
(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.
Diffstat (limited to 'lisp/shell.el')
-rw-r--r--lisp/shell.el163
1 files changed, 80 insertions, 83 deletions
diff --git a/lisp/shell.el b/lisp/shell.el
index 71b5862feb6..bfa9565e8d4 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -150,7 +150,7 @@ This is a fine thing to set in your `.emacs' file."
150 :group 'shell) 150 :group 'shell)
151 151
152(defcustom shell-completion-fignore nil 152(defcustom shell-completion-fignore nil
153 "*List of suffixes to be disregarded during file/command completion. 153 "List of suffixes to be disregarded during file/command completion.
154This variable is used to initialize `comint-completion-fignore' in the shell 154This variable is used to initialize `comint-completion-fignore' in the shell
155buffer. The default is nil, for compatibility with most shells. 155buffer. The default is nil, for compatibility with most shells.
156Some people like (\"~\" \"#\" \"%\"). 156Some people like (\"~\" \"#\" \"%\").
@@ -199,19 +199,19 @@ shell buffer.
199This is a fine thing to set in your `.emacs' file.") 199This is a fine thing to set in your `.emacs' file.")
200 200
201(defcustom shell-command-regexp "[^;&|\n]+" 201(defcustom shell-command-regexp "[^;&|\n]+"
202 "*Regexp to match a single command within a pipeline. 202 "Regexp to match a single command within a pipeline.
203This is used for directory tracking and does not do a perfect job." 203This is used for directory tracking and does not do a perfect job."
204 :type 'regexp 204 :type 'regexp
205 :group 'shell) 205 :group 'shell)
206 206
207(defcustom shell-command-separator-regexp "[;&|\n \t]*" 207(defcustom shell-command-separator-regexp "[;&|\n \t]*"
208 "*Regexp to match a single command within a pipeline. 208 "Regexp to match a single command within a pipeline.
209This is used for directory tracking and does not do a perfect job." 209This is used for directory tracking and does not do a perfect job."
210 :type 'regexp 210 :type 'regexp
211 :group 'shell) 211 :group 'shell)
212 212
213(defcustom shell-completion-execonly t 213(defcustom shell-completion-execonly t
214 "*If non-nil, use executable files only for completion candidates. 214 "If non-nil, use executable files only for completion candidates.
215This mirrors the optional behavior of tcsh. 215This mirrors the optional behavior of tcsh.
216 216
217Detecting executability of files may slow command completion considerably." 217Detecting executability of files may slow command completion considerably."
@@ -219,35 +219,35 @@ Detecting executability of files may slow command completion considerably."
219 :group 'shell) 219 :group 'shell)
220 220
221(defcustom shell-popd-regexp "popd" 221(defcustom shell-popd-regexp "popd"
222 "*Regexp to match subshell commands equivalent to popd." 222 "Regexp to match subshell commands equivalent to popd."
223 :type 'regexp 223 :type 'regexp
224 :group 'shell-directories) 224 :group 'shell-directories)
225 225
226(defcustom shell-pushd-regexp "pushd" 226(defcustom shell-pushd-regexp "pushd"
227 "*Regexp to match subshell commands equivalent to pushd." 227 "Regexp to match subshell commands equivalent to pushd."
228 :type 'regexp 228 :type 'regexp
229 :group 'shell-directories) 229 :group 'shell-directories)
230 230
231(defcustom shell-pushd-tohome nil 231(defcustom shell-pushd-tohome nil
232 "*If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd). 232 "If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd).
233This mirrors the optional behavior of tcsh." 233This mirrors the optional behavior of tcsh."
234 :type 'boolean 234 :type 'boolean
235 :group 'shell-directories) 235 :group 'shell-directories)
236 236
237(defcustom shell-pushd-dextract nil 237(defcustom shell-pushd-dextract nil
238 "*If non-nil, make \"pushd +n\" pop the nth dir to the stack top. 238 "If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
239This mirrors the optional behavior of tcsh." 239This mirrors the optional behavior of tcsh."
240 :type 'boolean 240 :type 'boolean
241 :group 'shell-directories) 241 :group 'shell-directories)
242 242
243(defcustom shell-pushd-dunique nil 243(defcustom shell-pushd-dunique nil
244 "*If non-nil, make pushd only add unique directories to the stack. 244 "If non-nil, make pushd only add unique directories to the stack.
245This mirrors the optional behavior of tcsh." 245This mirrors the optional behavior of tcsh."
246 :type 'boolean 246 :type 'boolean
247 :group 'shell-directories) 247 :group 'shell-directories)
248 248
249(defcustom shell-cd-regexp "cd" 249(defcustom shell-cd-regexp "cd"
250 "*Regexp to match subshell commands equivalent to cd." 250 "Regexp to match subshell commands equivalent to cd."
251 :type 'regexp 251 :type 'regexp
252 :group 'shell-directories) 252 :group 'shell-directories)
253 253
@@ -256,19 +256,19 @@ This mirrors the optional behavior of tcsh."
256 ; NetWare allows the five chars between upper and lower alphabetics. 256 ; NetWare allows the five chars between upper and lower alphabetics.
257 "[]a-zA-Z^_`\\[\\\\]:" 257 "[]a-zA-Z^_`\\[\\\\]:"
258 nil) 258 nil)
259 "*If non-nil, is regexp used to track drive changes." 259 "If non-nil, is regexp used to track drive changes."
260 :type '(choice regexp 260 :type '(choice regexp
261 (const nil)) 261 (const nil))
262 :group 'shell-directories) 262 :group 'shell-directories)
263 263
264(defcustom shell-dirtrack-verbose t 264(defcustom shell-dirtrack-verbose t
265 "*If non-nil, show the directory stack following directory change. 265 "If non-nil, show the directory stack following directory change.
266This is effective only if directory tracking is enabled." 266This is effective only if directory tracking is enabled."
267 :type 'boolean 267 :type 'boolean
268 :group 'shell-directories) 268 :group 'shell-directories)
269 269
270(defcustom explicit-shell-file-name nil 270(defcustom explicit-shell-file-name nil
271 "*If non-nil, is file name to use for explicitly requested inferior shell." 271 "If non-nil, is file name to use for explicitly requested inferior shell."
272 :type '(choice (const :tag "None" nil) file) 272 :type '(choice (const :tag "None" nil) file)
273 :group 'shell) 273 :group 'shell)
274 274
@@ -278,7 +278,7 @@ This is effective only if directory tracking is enabled."
278 ;; than us about what terminal modes to use. 278 ;; than us about what terminal modes to use.
279 '("-i" "-T") 279 '("-i" "-T")
280 '("-i")) 280 '("-i"))
281 "*Args passed to inferior shell by M-x shell, if the shell is csh. 281 "Args passed to inferior shell by \\[shell], if the shell is csh.
282Value is a list of strings, which may be nil." 282Value is a list of strings, which may be nil."
283 :type '(repeat (string :tag "Argument")) 283 :type '(repeat (string :tag "Argument"))
284 :group 'shell) 284 :group 'shell)
@@ -296,13 +296,13 @@ Value is a list of strings, which may be nil."
296 (shell-command-to-string (concat prog " --noediting")))) 296 (shell-command-to-string (concat prog " --noediting"))))
297 '("-i") 297 '("-i")
298 '("--noediting" "-i"))) 298 '("--noediting" "-i")))
299 "*Args passed to inferior shell by M-x shell, if the shell is bash. 299 "Args passed to inferior shell by \\[shell], if the shell is bash.
300Value is a list of strings, which may be nil." 300Value is a list of strings, which may be nil."
301 :type '(repeat (string :tag "Argument")) 301 :type '(repeat (string :tag "Argument"))
302 :group 'shell) 302 :group 'shell)
303 303
304(defcustom shell-input-autoexpand 'history 304(defcustom shell-input-autoexpand 'history
305 "*If non-nil, expand input command history references on completion. 305 "If non-nil, expand input command history references on completion.
306This mirrors the optional behavior of tcsh (its autoexpand and histlit). 306This mirrors the optional behavior of tcsh (its autoexpand and histlit).
307 307
308If the value is `input', then the expansion is seen on input. 308If the value is `input', then the expansion is seen on input.
@@ -433,9 +433,7 @@ buffer."
433 (setq shell-dirstack nil) 433 (setq shell-dirstack nil)
434 (make-local-variable 'shell-last-dir) 434 (make-local-variable 'shell-last-dir)
435 (setq shell-last-dir nil) 435 (setq shell-last-dir nil)
436 (make-local-variable 'shell-dirtrackp) 436 (shell-dirtrack-mode 1)
437 (setq shell-dirtrackp t)
438 (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
439 (setq comint-input-autoexpand shell-input-autoexpand) 437 (setq comint-input-autoexpand shell-input-autoexpand)
440 ;; This is not really correct, since the shell buffer does not really 438 ;; This is not really correct, since the shell buffer does not really
441 ;; edit this directory. But it is useful in the buffer list and menus. 439 ;; edit this directory. But it is useful in the buffer list and menus.
@@ -558,48 +556,48 @@ Otherwise, one argument `-i' is passed to the shell.
558 (shell-mode))) 556 (shell-mode)))
559 buffer) 557 buffer)
560 558
561;;; Don't do this when shell.el is loaded, only while dumping. 559;; Don't do this when shell.el is loaded, only while dumping.
562;;;###autoload (add-hook 'same-window-buffer-names "*shell*") 560;;;###autoload (add-hook 'same-window-buffer-names "*shell*")
563 561
564;;; Directory tracking 562;;; Directory tracking
565;;; 563;;
566;;; This code provides the shell mode input sentinel 564;; This code provides the shell mode input sentinel
567;;; SHELL-DIRECTORY-TRACKER 565;; SHELL-DIRECTORY-TRACKER
568;;; that tracks cd, pushd, and popd commands issued to the shell, and 566;; that tracks cd, pushd, and popd commands issued to the shell, and
569;;; changes the current directory of the shell buffer accordingly. 567;; changes the current directory of the shell buffer accordingly.
570;;; 568;;
571;;; This is basically a fragile hack, although it's more accurate than 569;; This is basically a fragile hack, although it's more accurate than
572;;; the version in Emacs 18's shell.el. It has the following failings: 570;; the version in Emacs 18's shell.el. It has the following failings:
573;;; 1. It doesn't know about the cdpath shell variable. 571;; 1. It doesn't know about the cdpath shell variable.
574;;; 2. It cannot infallibly deal with command sequences, though it does well 572;; 2. It cannot infallibly deal with command sequences, though it does well
575;;; with these and with ignoring commands forked in another shell with ()s. 573;; with these and with ignoring commands forked in another shell with ()s.
576;;; 3. More generally, any complex command is going to throw it. Otherwise, 574;; 3. More generally, any complex command is going to throw it. Otherwise,
577;;; you'd have to build an entire shell interpreter in Emacs Lisp. Failing 575;; you'd have to build an entire shell interpreter in Emacs Lisp. Failing
578;;; that, there's no way to catch shell commands where cd's are buried 576;; that, there's no way to catch shell commands where cd's are buried
579;;; inside conditional expressions, aliases, and so forth. 577;; inside conditional expressions, aliases, and so forth.
580;;; 578;;
581;;; The whole approach is a crock. Shell aliases mess it up. File sourcing 579;; The whole approach is a crock. Shell aliases mess it up. File sourcing
582;;; messes it up. You run other processes under the shell; these each have 580;; messes it up. You run other processes under the shell; these each have
583;;; separate working directories, and some have commands for manipulating 581;; separate working directories, and some have commands for manipulating
584;;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have 582;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have
585;;; commands that do *not* affect the current w.d. at all, but look like they 583;; commands that do *not* affect the current w.d. at all, but look like they
586;;; do (e.g., the cd command in ftp). In shells that allow you job 584;; do (e.g., the cd command in ftp). In shells that allow you job
587;;; control, you can switch between jobs, all having different w.d.'s. So 585;; control, you can switch between jobs, all having different w.d.'s. So
588;;; simply saying %3 can shift your w.d.. 586;; simply saying %3 can shift your w.d..
589;;; 587;;
590;;; The solution is to relax, not stress out about it, and settle for 588;; The solution is to relax, not stress out about it, and settle for
591;;; a hack that works pretty well in typical circumstances. Remember 589;; a hack that works pretty well in typical circumstances. Remember
592;;; that a half-assed solution is more in keeping with the spirit of Unix, 590;; that a half-assed solution is more in keeping with the spirit of Unix,
593;;; anyway. Blech. 591;; anyway. Blech.
594;;; 592;;
595;;; One good hack not implemented here for users of programmable shells 593;; One good hack not implemented here for users of programmable shells
596;;; is to program up the shell w.d. manipulation commands to output 594;; is to program up the shell w.d. manipulation commands to output
597;;; a coded command sequence to the tty. Something like 595;; a coded command sequence to the tty. Something like
598;;; ESC | <cwd> | 596;; ESC | <cwd> |
599;;; where <cwd> is the new current working directory. Then trash the 597;; where <cwd> is the new current working directory. Then trash the
600;;; directory tracking machinery currently used in this package, and 598;; directory tracking machinery currently used in this package, and
601;;; replace it with a process filter that watches for and strips out 599;; replace it with a process filter that watches for and strips out
602;;; these messages. 600;; these messages.
603 601
604(defun shell-directory-tracker (str) 602(defun shell-directory-tracker (str)
605 "Tracks cd, pushd and popd commands issued to the shell. 603 "Tracks cd, pushd and popd commands issued to the shell.
@@ -607,8 +605,8 @@ This function is called on each input passed to the shell.
607It watches for cd, pushd and popd commands and sets the buffer's 605It watches for cd, pushd and popd commands and sets the buffer's
608default directory to track these commands. 606default directory to track these commands.
609 607
610You may toggle this tracking on and off with M-x dirtrack-mode. 608You may toggle this tracking on and off with \\[dirtrack-mode].
611If Emacs gets confused, you can resync with the shell with M-x dirs. 609If Emacs gets confused, you can resync with the shell with \\[dirs].
612 610
613See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp', 611See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp',
614and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract', 612and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract',
@@ -677,7 +675,7 @@ Environment variables are expanded, see function `substitute-in-file-name'."
677 (setq string (replace-match "" nil nil string))))) 675 (setq string (replace-match "" nil nil string)))))
678 string))) 676 string)))
679 677
680;;; popd [+n] 678;; popd [+n]
681(defun shell-process-popd (arg) 679(defun shell-process-popd (arg)
682 (let ((num (or (shell-extract-num arg) 0))) 680 (let ((num (or (shell-extract-num arg) 0)))
683 (cond ((and num (= num 0) shell-dirstack) 681 (cond ((and num (= num 0) shell-dirstack)
@@ -703,7 +701,7 @@ Environment variables are expanded, see function `substitute-in-file-name'."
703 ;; For relative name we assume default-directory already has the prefix. 701 ;; For relative name we assume default-directory already has the prefix.
704 (expand-file-name dir)))) 702 (expand-file-name dir))))
705 703
706;;; cd [dir] 704;; cd [dir]
707(defun shell-process-cd (arg) 705(defun shell-process-cd (arg)
708 (let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix 706 (let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix
709 "~")) 707 "~"))
@@ -713,7 +711,7 @@ Environment variables are expanded, see function `substitute-in-file-name'."
713 (shell-cd new-dir) 711 (shell-cd new-dir)
714 (shell-dirstack-message))) 712 (shell-dirstack-message)))
715 713
716;;; pushd [+n | dir] 714;; pushd [+n | dir]
717(defun shell-process-pushd (arg) 715(defun shell-process-pushd (arg)
718 (let ((num (shell-extract-num arg))) 716 (let ((num (shell-extract-num arg)))
719 (cond ((zerop (length arg)) 717 (cond ((zerop (length arg))
@@ -762,26 +760,25 @@ Environment variables are expanded, see function `substitute-in-file-name'."
762 (and (string-match "^\\+[1-9][0-9]*$" str) 760 (and (string-match "^\\+[1-9][0-9]*$" str)
763 (string-to-number str))) 761 (string-to-number str)))
764 762
765 763(defvaralias 'shell-dirtrack-mode 'shell-dirtrackp)
766(defun shell-dirtrack-mode () 764(define-minor-mode shell-dirtrack-mode
767 "Turn directory tracking on and off in a shell buffer." 765 "Turn directory tracking on and off in a shell buffer."
768 (interactive) 766 nil nil nil
769 (if (setq shell-dirtrackp (not shell-dirtrackp)) 767 (setq list-buffers-directory (if shell-dirtrack-mode default-directory))
770 (setq list-buffers-directory default-directory) 768 (if shell-dirtrack-mode
771 (setq list-buffers-directory nil)) 769 (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
772 (message "Directory tracking %s" (if shell-dirtrackp "ON" "OFF"))) 770 (remove-hook 'comint-input-filter-functions 'shell-directory-tracker t)))
773 771
774;;; For your typing convenience: 772;; For your typing convenience:
775(defalias 'shell-dirtrack-toggle 'shell-dirtrack-mode) 773(defalias 'shell-dirtrack-toggle 'shell-dirtrack-mode) ;??Convenience??
776(defalias 'dirtrack-toggle 'shell-dirtrack-mode) 774(defalias 'dirtrack-toggle 'shell-dirtrack-mode)
777(defalias 'dirtrack-mode 'shell-dirtrack-mode) 775(defalias 'dirtrack-mode 'shell-dirtrack-mode)
778 776
779(defun shell-cd (dir) 777(defun shell-cd (dir)
780 "Do normal `cd' to DIR, and set `list-buffers-directory'." 778 "Do normal `cd' to DIR, and set `list-buffers-directory'."
779 (cd dir)
781 (if shell-dirtrackp 780 (if shell-dirtrackp
782 (setq list-buffers-directory (file-name-as-directory 781 (setq list-buffers-directory default-directory)))
783 (expand-file-name dir))))
784 (cd dir))
785 782
786(defun shell-resync-dirs () 783(defun shell-resync-dirs ()
787 "Resync the buffer's idea of the current directory stack. 784 "Resync the buffer's idea of the current directory stack.
@@ -841,15 +838,15 @@ command again."
841 (shell-dirstack-message)) 838 (shell-dirstack-message))
842 (error (message "Couldn't cd"))))))) 839 (error (message "Couldn't cd")))))))
843 840
844;;; For your typing convenience: 841;; For your typing convenience:
845(defalias 'dirs 'shell-resync-dirs) 842(defalias 'dirs 'shell-resync-dirs)
846 843
847 844
848;;; Show the current dirstack on the message line. 845;; Show the current dirstack on the message line.
849;;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo". 846;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo".
850;;; (This isn't necessary if the dirlisting is generated with a simple "dirs".) 847;; (This isn't necessary if the dirlisting is generated with a simple "dirs".)
851;;; All the commands that mung the buffer's dirstack finish by calling 848;; All the commands that mung the buffer's dirstack finish by calling
852;;; this guy. 849;; this guy.
853(defun shell-dirstack-message () 850(defun shell-dirstack-message ()
854 (when shell-dirtrack-verbose 851 (when shell-dirtrack-verbose
855 (let* ((msg "") 852 (let* ((msg "")
@@ -1076,5 +1073,5 @@ Returns t if successful."
1076 1073
1077(provide 'shell) 1074(provide 'shell)
1078 1075
1079;;; arch-tag: bcb5f12a-c1f4-4aea-a809-2504bd5bd797 1076;; arch-tag: bcb5f12a-c1f4-4aea-a809-2504bd5bd797
1080;;; shell.el ends here 1077;;; shell.el ends here