Function: shell-dirtrack-mode
shell-dirtrack-mode is an interactive and byte-compiled function
defined in shell.el.gz.
Signature
(shell-dirtrack-mode &optional ARG)
Documentation
Toggle directory tracking in this shell buffer (Shell Dirtrack mode).
This assigns a buffer-local non-nil value to shell-dirtrackp.
The dirtrack package provides an alternative implementation of
this feature; see the function dirtrack-mode(var)/dirtrack-mode(fun). Also see
comint-osc-directory-tracker for an escape-sequence based
solution.
This is a minor mode. If called interactively, toggle the
Shell-Dirtrack mode mode. If the prefix argument is positive, enable
the mode, and if it is zero or negative, disable the mode.
If called from Lisp, toggle the mode if ARG is toggle. Enable the
mode if ARG is nil, omitted, or is a positive number. Disable the mode
if ARG is a negative number.
To check whether the minor mode is enabled in the current buffer,
evaluate the variable shell-dirtrack-mode(var)/shell-dirtrack-mode(fun).
The mode's hook is called both when the mode is enabled and when it is disabled.
Probably introduced at or before Emacs version 22.2.
Key Bindings
Source Code
;; Defined in /usr/src/emacs/lisp/shell.el.gz
;;; 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. 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 | <cwd> |
;; where <cwd> 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.
(define-minor-mode shell-dirtrack-mode
"Toggle directory tracking in this shell buffer (Shell Dirtrack mode).
This assigns a buffer-local non-nil value to `shell-dirtrackp'.
The `dirtrack' package provides an alternative implementation of
this feature; see the function `dirtrack-mode'. Also see
`comint-osc-directory-tracker' for an escape-sequence based
solution."
:lighter nil
:interactive (shell-mode)
(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)))