Function: shell-directory-tracker

shell-directory-tracker is a byte-compiled function defined in shell.el.gz.

Signature

(shell-directory-tracker STR)

Documentation

Tracks cd, pushd and popd commands issued to the shell.

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 shell-dirtrack-mode (shell-dirtrack-mode). If Emacs gets confused, you can resync with the shell with M-x dirs (dirs).
(The dirtrack package provides an alternative implementation of this
feature - see the function dirtrack-mode(var)/dirtrack-mode(fun).)

See variables shell-cd-regexp, shell-chdrive-regexp, shell-pushd-regexp,
and shell-popd-regexp, while shell-pushd-tohome, shell-pushd-dextract,
and shell-pushd-dunique control the behavior of the relevant command.

Environment variables are expanded, see function substitute-in-file-name.

Source Code

;; Defined in /usr/src/emacs/lisp/shell.el.gz
(defun shell-directory-tracker (str)
  "Tracks cd, pushd and popd commands issued to the shell.
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 \\[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',
and `shell-pushd-dunique' control the behavior of the relevant command.

Environment variables are expanded, see function `substitute-in-file-name'."
  (if shell-dirtrack-mode
      ;; We fail gracefully if we think the command will fail in the shell.
;;;      (with-demoted-errors "Directory tracker failure: %s"
      ;; This fails so often that it seems better to just ignore errors (?).
      ;; Eg even: foo=/tmp; cd $foo is beyond us (bug#17159).
      (ignore-errors
        (let ((start (progn (string-match
			       (concat "^" shell-command-separator-regexp)
			       str) ; skip whitespace
			      (match-end 0)))
		(case-fold-search)
		end cmd arg1 cmd-subst-fn)
	    (while (string-match shell-command-regexp str start)
	      (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)))
              (if shell-has-auto-cd
                  (setq cmd-subst-fn (comint-substitute-in-file-name cmd)))
	      (cond ((string-match (concat "\\`\\(" shell-popd-regexp
					   "\\)\\($\\|[ \t]\\)")
				   cmd)
		     (shell-process-popd (comint-substitute-in-file-name arg1)))
		    ((string-match (concat "\\`\\(" shell-pushd-regexp
					   "\\)\\($\\|[ \t]\\)")
				   cmd)
		     (shell-process-pushd (comint-substitute-in-file-name arg1)))
		    ((string-match (concat "\\`\\(" shell-cd-regexp
					   "\\)\\($\\|[ \t]\\)")
				   cmd)
		     (shell-process-cd (comint-substitute-in-file-name arg1)))
		    ((and shell-chdrive-regexp
			  (string-match (concat "\\`\\(" shell-chdrive-regexp
						"\\)\\($\\|[ \t]\\)")
					cmd))
		     (shell-process-cd (comint-substitute-in-file-name cmd)))
                    ((and shell-has-auto-cd (file-directory-p cmd-subst-fn))
                     (shell-process-cd cmd-subst-fn)))
	      (setq start (progn (string-match shell-command-separator-regexp
					       str end)
				 ;; skip again
				 (match-end 0))))))))