summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2010-11-12 09:13:48 -0500
committerStefan Monnier <monnier@iro.umontreal.ca>2010-11-12 09:13:48 -0500
commit78835dd0546b7c724e82826b7a0897f9497e6ad4 (patch)
tree17e967d613846857eeb031b13d0a283e4c5e9581
parentebff325e4317a1ff8d6a86976a2dc9f78697b21a (diff)
downloademacs-78835dd0546b7c724e82826b7a0897f9497e6ad4.tar.gz
emacs-78835dd0546b7c724e82826b7a0897f9497e6ad4.tar.bz2
emacs-78835dd0546b7c724e82826b7a0897f9497e6ad4.zip
* lisp/shell.el (shell-dir-cookie-re): New custom variable.
(shell-dir-cookie-watcher): New function.
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/ChangeLog3
-rw-r--r--lisp/shell.el29
3 files changed, 35 insertions, 2 deletions
diff --git a/etc/NEWS b/etc/NEWS
index aab6cf98eb0..4ab97b32b16 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -289,6 +289,9 @@ set `x-select-enable-clipboard' to nil.
* Changes in Specialized Modes and Packages in Emacs 24.1
+** shell-mode can track your cwd by reading it from your prompt.
+Just set shell-dir-cookie-re to an appropriate regexp.
+
** Modula-2 mode provides auto-indentation.
** latex-electric-env-pair-mode keeps \begin..\end matched on the fly.
@@ -529,8 +532,6 @@ system or session bus.
** pcase.el provides the ML-style pattern matching macro `pcase'.
-** smie.el is a package providing a simple generic indentation engine.
-
** secrets.el is an implementation of the Secret Service API, an
interface to password managers like GNOME Keyring or KDE Wallet. The
Secret Service API requires D-Bus for communication. The command
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index d7388d5b4f8..822af9becc3 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,8 @@
2010-11-12 Stefan Monnier <monnier@iro.umontreal.ca>
+ * shell.el (shell-dir-cookie-re): New custom variable.
+ (shell-dir-cookie-watcher): New function.
+
* vc/vc.el (vc-deduce-backend): Use default-directory in shell-mode
and compilation-mode (bug#7350).
diff --git a/lisp/shell.el b/lisp/shell.el
index 75040305528..7771c0d1c4f 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -472,6 +472,10 @@ buffer."
(when (string-equal shell "bash")
(add-hook 'comint-output-filter-functions
'shell-filter-ctrl-a-ctrl-b nil t)))
+ (when shell-dir-cookie-re
+ ;; Watch for magic cookies in the output to track the current dir.
+ (add-hook 'comint-output-filter-functions
+ 'shell-dir-cookie-watcher nil t))
(comint-read-input-ring t)))
(defun shell-filter-ctrl-a-ctrl-b (string)
@@ -619,6 +623,31 @@ Otherwise, one argument `-i' is passed to the shell.
;; replace it with a process filter that watches for and strips out
;; these messages.
+(defcustom shell-dir-cookie-re nil
+ "Regexp matching your prompt, including some part of the current directory.
+If your prompt includes the current directory or the last few elements of it,
+set this to a pattern that matches your prompt and whose subgroup 1 matches
+the directory part of it.
+This is used by `shell-dir-cookie-watcher' to try and use this info
+to track your current directory. It can be used instead of or in addition
+to `dirtrack-mode'."
+ :type '(choice (const nil) regexp))
+
+(defun shell-dir-cookie-watcher (text)
+ ;; This is fragile: the TEXT could be split into several chunks and we'd
+ ;; miss it. Oh well. It's a best effort anyway. I'd expect that it's
+ ;; rather unusual to have the prompt split into several packets, but
+ ;; I'm sure Murphy will prove me wrong.
+ (when (and shell-dir-cookie-re (string-match shell-dir-cookie-re text))
+ (let ((dir (match-string 1 text)))
+ (cond
+ ((file-name-absolute-p dir) (shell-cd dir))
+ ;; Let's try and see if it seems to be up or down from where we were.
+ ((string-match "\\`\\(.*\\)\\(?:/.*\\)?\n\\(.*/\\)\\1\\(?:/.*\\)?\\'"
+ (setq text (concat dir "\n" default-directory)))
+ (shell-cd (concat (match-string 2 text) dir)))))))
+
+
(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.