123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- (eval-when-compile
- (require 'comint)
- (require 'shell))
- (defgroup dirtrack nil
- "Directory tracking by watching the prompt."
- :prefix "dirtrack-"
- :group 'shell)
- (defcustom dirtrack-list (list "^emacs \\([a-zA-Z]:.*\\)>" 1)
- "List for directory tracking.
- First item is a regexp that describes where to find the path in a prompt.
- Second is a number, the regexp group to match."
- :group 'dirtrack
- :type '(sexp (regexp :tag "Prompt Expression")
- (integer :tag "Regexp Group"))
- :version "24.1")
- (make-variable-buffer-local 'dirtrack-list)
- (defcustom dirtrack-debug nil
- "If non-nil, the function `dirtrack' will report debugging info."
- :group 'dirtrack
- :type 'boolean)
- (defcustom dirtrack-debug-buffer "*Directory Tracking Log*"
- "Buffer in which to write directory tracking debug information."
- :group 'dirtrack
- :type 'string)
- (defcustom dirtrack-directory-function
- (if (memq system-type '(ms-dos windows-nt cygwin))
- 'dirtrack-windows-directory-function
- 'file-name-as-directory)
- "Function to apply to the prompt directory for comparison purposes."
- :group 'dirtrack
- :type 'function)
- (defcustom dirtrack-canonicalize-function
- (if (memq system-type '(ms-dos windows-nt cygwin))
- 'downcase 'identity)
- "Function to apply to the default directory for comparison purposes."
- :group 'dirtrack
- :type 'function)
- (defcustom dirtrack-directory-change-hook nil
- "Hook that is called when a directory change is made."
- :group 'dirtrack
- :type 'hook)
- (defun dirtrack-windows-directory-function (dir)
- "Return a canonical directory for comparison purposes.
- Such a directory is all lowercase, has forward-slashes as delimiters,
- and ends with a forward slash."
- (file-name-as-directory (downcase (subst-char-in-string ?\\ ?/ dir))))
- (defun dirtrack-cygwin-directory-function (dir)
- "Return a canonical directory taken from a Cygwin path for comparison purposes."
- (if (string-match "/cygdrive/\\([A-Z]\\)\\(.*\\)" dir)
- (concat (match-string 1 dir) ":" (match-string 2 dir))
- dir))
- (define-minor-mode dirtrack-mode
- "Toggle directory tracking in shell buffers (Dirtrack mode).
- With a prefix argument ARG, enable Dirtrack mode if ARG is
- positive, and disable it otherwise. If called from Lisp, enable
- the mode if ARG is omitted or nil.
- This method requires that your shell prompt contain the current
- working directory at all times, and that you set the variable
- `dirtrack-list' to match the prompt.
- This is an alternative to `shell-dirtrack-mode', which works by
- tracking `cd' and similar commands which change the shell working
- directory."
- nil nil nil
- (if dirtrack-mode
- (add-hook 'comint-preoutput-filter-functions 'dirtrack nil t)
- (remove-hook 'comint-preoutput-filter-functions 'dirtrack t)))
- (define-obsolete-function-alias 'dirtrack-toggle 'dirtrack-mode "23.1")
- (define-obsolete-variable-alias 'dirtrackp 'dirtrack-mode "23.1")
- (define-minor-mode dirtrack-debug-mode
- "Toggle Dirtrack debugging.
- With a prefix argument ARG, enable Dirtrack debugging if ARG is
- positive, and disable it otherwise. If called from Lisp, enable
- the mode if ARG is omitted or nil."
- nil nil nil
- (if dirtrack-debug-mode
- (display-buffer (get-buffer-create dirtrack-debug-buffer))))
- (define-obsolete-function-alias 'dirtrack-debug-toggle 'dirtrack-debug-mode
- "23.1")
- (define-obsolete-variable-alias 'dirtrack-debug 'dirtrack-debug-mode "23.1")
- (defun dirtrack-debug-message (msg1 msg2)
- "Insert strings at the end of `dirtrack-debug-buffer'."
- (when dirtrack-debug-mode
- (with-current-buffer (get-buffer-create dirtrack-debug-buffer)
- (goto-char (point-max))
- (insert msg1 msg2 "\n"))))
- (defun dirtrack (input)
- "Determine the current directory from the process output for a prompt.
- This filter function is used by `dirtrack-mode'. It looks for
- the prompt specified by `dirtrack-list', and calls
- `shell-process-cd' if the directory seems to have changed away
- from `default-directory'."
- (when (and dirtrack-mode
- (not (eq (point) (point-min))))
- (save-excursion
- (if (not (string-match (nth 0 dirtrack-list) input))
-
- (dirtrack-debug-message
- "Input failed to match `dirtrack-list': " input)
- (let ((prompt-path (match-string (nth 1 dirtrack-list) input))
- temp)
- (cond
-
- ((string-equal prompt-path "")
- (dirtrack-debug-message "Prompt match gives empty string: " input))
-
-
- ((file-name-absolute-p prompt-path)
-
- (let ((orig-prompt-path (funcall dirtrack-directory-function
- prompt-path))
- (current-dir (funcall dirtrack-canonicalize-function
- default-directory)))
- (setq prompt-path (shell-prefixed-directory-name orig-prompt-path))
-
- (if (or (string-equal current-dir prompt-path)
- (string-equal (expand-file-name current-dir)
- (expand-file-name prompt-path)))
- (dirtrack-debug-message "Not changing directory: " current-dir)
-
-
- (if (file-accessible-directory-p prompt-path)
-
-
- (progn
- (shell-process-cd orig-prompt-path)
- (run-hooks 'dirtrack-directory-change-hook)
- (dirtrack-debug-message "Changing directory to "
- prompt-path))
- (dirtrack-debug-message "Not changing to non-existent directory: "
- prompt-path)))))
-
-
- ((string-match "\\`\\(.*\\)\\(?:/.*\\)?\n\\(.*/\\)\\1\\(?:/.*\\)?\\'"
- (setq temp
- (concat prompt-path "\n" default-directory)))
- (shell-process-cd (concat (match-string 2 temp)
- prompt-path))
- (run-hooks 'dirtrack-directory-change-hook)))))))
- input)
- (provide 'dirtrack)
|