Changeset 4111 for trunk/lisp/dirtrack.el
- Timestamp:
- 07/16/06 08:36:52 (2 years ago)
- Files:
-
- trunk/lisp/dirtrack.el (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/lisp/dirtrack.el
r4037 r4111 30 30 ;; 31 31 ;; This is yet another attempt at a directory-tracking package for 32 ;; Emacs shell-mode. However, this package makes one strong assumption:32 ;; Emacs shell-mode. However, this package makes one strong assumption: 33 33 ;; that you can customize your shell's prompt to contain the 34 ;; current working directory. Most shells do support this, including34 ;; current working directory. Most shells do support this, including 35 35 ;; almost every type of Bourne and C shell on Unix, the native shells on 36 36 ;; Windows95 (COMMAND.COM) and Windows NT (CMD.EXE), and most 3rd party 37 ;; Windows shells. If you cannot do this, or do not wish to, this package37 ;; Windows shells. If you cannot do this, or do not wish to, this package 38 38 ;; will be useless to you. 39 39 ;; … … 46 46 ;; Note that directory tracking is done by matching regular expressions, 47 47 ;; therefore it is *VERY IMPORTANT* for your prompt to be easily 48 ;; distinguishable from other output. If your prompt regexp is too general,48 ;; distinguishable from other output. If your prompt regexp is too general, 49 49 ;; you will see error messages from the dirtrack filter as it attempts to cd 50 50 ;; to non-existent directories. 51 51 ;; 52 ;; 2) Set the variable `dirtrack-list' to an appropriate value. This52 ;; 2) Set the variable `dirtrack-list' to an appropriate value. This 53 53 ;; should be a list of two elements: the first is a regular expression 54 54 ;; which matches your prompt up to and including the pathname part. 55 55 ;; The second is a number which tells which regular expression group to 56 ;; match to extract only the pathname. If you use a multi-line prompt,57 ;; add 't' as a third element. Note that some of the functions in56 ;; match to extract only the pathname. If you use a multi-line prompt, 57 ;; add 't' as a third element. Note that some of the functions in 58 58 ;; 'comint.el' assume a single-line prompt (eg, comint-bol). 59 59 ;; 60 ;; Determining this information may take some experimentation. Setting60 ;; Determining this information may take some experimentation. Setting 61 61 ;; the variable `dirtrack-debug' may help; it causes the directory-tracking 62 ;; filter to log messages to the buffer `dirtrack-debug-buffer'. You can easily62 ;; filter to log messages to the buffer `dirtrack-debug-buffer'. You can easily 63 63 ;; toggle this setting with the `dirtrack-debug-toggle' function. 64 64 ;; … … 66 66 ;; 67 67 ;; (add-hook 'shell-mode-hook 68 ;; (function (lambda () 69 ;; (setq comint-preoutput-filter-functions 70 ;; (append (list 'dirtrack) 71 ;; comint-preoutput-filter-functions))))) 68 ;; (lambda () (add-hook 'comint-preoutput-filter-functions 'dirtrack nil t))) 72 69 ;; 73 70 ;; You may wish to turn ordinary shell tracking off by calling … … 108 105 ;; If you do this, and the shell prompt contains a ~, Emacs will interpret 109 106 ;; this relative to the user which owns the Emacs process, not the user 110 ;; who owns the shell buffer. This may cause dirtrack to behave strangely107 ;; who owns the shell buffer. This may cause dirtrack to behave strangely 111 108 ;; (typically it reports that it is unable to cd to a directory 112 109 ;; with a ~ in it). … … 114 111 ;; The same behavior can occur if you use dirtrack with remote filesystems 115 112 ;; (using telnet, rlogin, etc) as Emacs will be checking the local 116 ;; filesystem, not the remote one. This problem is not specific to dirtrack,113 ;; filesystem, not the remote one. This problem is not specific to dirtrack, 117 114 ;; but also affects file completion, etc. 118 115 … … 133 130 134 131 (defcustom dirtrack-list (list "^emacs \\([a-zA-Z]:.*\\)>" 1) 135 " *List for directory tracking.132 "List for directory tracking. 136 133 First item is a regexp that describes where to find the path in a prompt. 137 134 Second is a number, the regexp group to match. Optional third item is … … 141 138 :type '(sexp (regexp :tag "Prompt Expression") 142 139 (integer :tag "Regexp Group") 143 (boolean :tag "Multiline Prompt") 144 ) 145 ) 140 (boolean :tag "Multiline Prompt"))) 146 141 147 142 (make-variable-buffer-local 'dirtrack-list) 148 143 149 144 (defcustom dirtrack-debug nil 150 "*If non-nil, the function `dirtrack' will report debugging info." 151 :group 'dirtrack 152 :type 'boolean 153 ) 145 "If non-nil, the function `dirtrack' will report debugging info." 146 :group 'dirtrack 147 :type 'boolean) 154 148 155 149 (defcustom dirtrack-debug-buffer "*Directory Tracking Log*" 156 150 "Buffer to write directory tracking debug information." 157 151 :group 'dirtrack 158 :type 'string 159 ) 152 :type 'string) 160 153 161 154 (defcustom dirtrackp t 162 "*If non-nil, directory tracking via `dirtrack' is enabled." 163 :group 'dirtrack 164 :type 'boolean 165 ) 155 "If non-nil, directory tracking via `dirtrack' is enabled." 156 :group 'dirtrack 157 :type 'boolean) 166 158 167 159 (make-variable-buffer-local 'dirtrackp) … … 170 162 (if (memq system-type (list 'ms-dos 'windows-nt 'cygwin)) 171 163 'dirtrack-windows-directory-function 172 'dirtrack-default-directory-function) 173 "*Function to apply to the prompt directory for comparison purposes." 174 :group 'dirtrack 175 :type 'function 176 ) 164 'file-name-as-directory) 165 "Function to apply to the prompt directory for comparison purposes." 166 :group 'dirtrack 167 :type 'function) 177 168 178 169 (defcustom dirtrack-canonicalize-function 179 170 (if (memq system-type (list 'ms-dos 'windows-nt 'cygwin)) 180 171 'downcase 'identity) 181 "*Function to apply to the default directory for comparison purposes." 182 :group 'dirtrack 183 :type 'function 184 ) 172 "Function to apply to the default directory for comparison purposes." 173 :group 'dirtrack 174 :type 'function) 185 175 186 176 (defcustom dirtrack-directory-change-hook nil 187 177 "Hook that is called when a directory change is made." 188 178 :group 'dirtrack 189 :type 'hook 190 ) 179 :type 'hook) 191 180 192 181 … … 195 184 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 196 185 197 (defun dirtrack-default-directory-function (dir)198 "Return a canonical directory for comparison purposes.199 Such a directory ends with a forward slash."200 (let ((directory dir))201 (if (not (char-equal ?/ (string-to-char (substring directory -1))))202 (concat directory "/")203 directory)))204 186 205 187 (defun dirtrack-windows-directory-function (dir) … … 207 189 Such a directory is all lowercase, has forward-slashes as delimiters, 208 190 and ends with a forward slash." 209 (let ((directory dir)) 210 (setq directory (downcase (dirtrack-replace-slash directory t))) 211 (if (not (char-equal ?/ (string-to-char (substring directory -1)))) 212 (concat directory "/") 213 directory))) 191 (file-name-as-directory (downcase (subst-char-in-string ?\\ ?/ dir)))) 214 192 215 193 (defun dirtrack-cygwin-directory-function (dir) … … 219 197 dir)) 220 198 221 (defconst dirtrack-forward-slash (regexp-quote "/"))222 (defconst dirtrack-backward-slash (regexp-quote "\\"))223 224 (defun dirtrack-replace-slash (string &optional opposite)225 "Replace forward slashes with backwards ones.226 If additional argument is non-nil, replace backwards slashes with227 forward ones."228 (let ((orig (if opposite229 dirtrack-backward-slash230 dirtrack-forward-slash))231 (replace (if opposite232 dirtrack-forward-slash233 dirtrack-backward-slash))234 (newstring string)235 )236 (while (string-match orig newstring)237 (setq newstring (replace-match replace nil t newstring)))238 newstring))239 240 199 ;; Copied from shell.el 241 200 (defun dirtrack-toggle () 242 201 "Enable or disable Dirtrack directory tracking in a shell buffer." 243 202 (interactive) 244 (setq dirtrackp (not dirtrackp)) 203 (if (setq dirtrackp (not dirtrackp)) 204 (add-hook 'comint-preoutput-filter-functions 'dirtrack nil t) 205 (remove-hook 'comint-preoutput-filter-functions 'dirtrack t)) 245 206 (message "Directory tracking %s" (if dirtrackp "ON" "OFF"))) 246 207 … … 274 235 275 236 You can enable directory tracking by adding this function to 276 `comint-output-filter-functions'. 277 " 278 (if (null dirtrackp) 237 `comint-output-filter-functions'." 238 (if (or (null dirtrackp) 239 ;; No output? 240 (eq (point) (point-min))) 279 241 nil 280 242 (let (prompt-path 281 matched282 243 (current-dir default-directory) 283 244 (dirtrack-regexp (nth 0 dirtrack-list)) 284 245 (match-num (nth 1 dirtrack-list)) 285 (multi-line (nth 2 dirtrack-list)) 286 ) 287 ;; No output? 288 (if (eq (point) (point-min)) 289 nil 290 (save-excursion 291 (setq matched (string-match dirtrack-regexp input))) 292 ;; No match 293 (if (null matched) 294 (and dirtrack-debug 295 (dirtrack-debug-message 296 (format 297 "Input `%s' failed to match regexp: %s" 298 input dirtrack-regexp))) 299 (setq prompt-path 300 (substring input 301 (match-beginning match-num) (match-end match-num))) 302 ;; Empty string 303 (if (not (> (length prompt-path) 0)) 304 (and dirtrack-debug 305 (dirtrack-debug-message "Match is empty string")) 306 ;; Transform prompts into canonical forms 307 (setq prompt-path (funcall dirtrack-directory-function 308 prompt-path)) 309 (setq current-dir (funcall dirtrack-canonicalize-function 310 current-dir)) 311 (and dirtrack-debug 312 (dirtrack-debug-message 313 (format 314 "Prompt is %s\nCurrent directory is %s" 315 prompt-path current-dir))) 316 ;; Compare them 317 (if (or (string= current-dir prompt-path) 318 (string= current-dir 319 (abbreviate-file-name prompt-path))) 320 (and dirtrack-debug 321 (dirtrack-debug-message 322 (format "Not changing directory"))) 323 ;; It's possible that Emacs will think the directory 324 ;; won't exist (eg, rlogin buffers) 325 (if (file-accessible-directory-p prompt-path) 326 ;; Change directory 327 (and (shell-process-cd prompt-path) 328 (run-hooks 'dirtrack-directory-change-hook) 329 dirtrack-debug 330 (dirtrack-debug-message 331 (format "Changing directory to %s" prompt-path))) 332 (error "Directory %s does not exist" prompt-path))) 333 ))))) 246 ;; Currently unimplemented, it seems. --Stef 247 (multi-line (nth 2 dirtrack-list))) 248 (save-excursion 249 ;; No match 250 (if (null (string-match dirtrack-regexp input)) 251 (and dirtrack-debug 252 (dirtrack-debug-message 253 (format 254 "Input `%s' failed to match `dirtrack-regexp'" input))) 255 (setq prompt-path (match-string match-num input)) 256 ;; Empty string 257 (if (not (> (length prompt-path) 0)) 258 (and dirtrack-debug 259 (dirtrack-debug-message "Match is empty string")) 260 ;; Transform prompts into canonical forms 261 (setq prompt-path (funcall dirtrack-directory-function 262 prompt-path)) 263 (setq current-dir (funcall dirtrack-canonicalize-function 264 current-dir)) 265 (and dirtrack-debug 266 (dirtrack-debug-message 267 (format 268 "Prompt is %s\nCurrent directory is %s" 269 prompt-path current-dir))) 270 ;; Compare them 271 (if (or (string= current-dir prompt-path) 272 (string= current-dir 273 (abbreviate-file-name prompt-path))) 274 (and dirtrack-debug 275 (dirtrack-debug-message 276 (format "Not changing directory"))) 277 ;; It's possible that Emacs will think the directory 278 ;; won't exist (eg, rlogin buffers) 279 (if (file-accessible-directory-p prompt-path) 280 ;; Change directory 281 (and (shell-process-cd prompt-path) 282 (run-hooks 'dirtrack-directory-change-hook) 283 dirtrack-debug 284 (dirtrack-debug-message 285 (format "Changing directory to %s" prompt-path))) 286 (error "Directory %s does not exist" prompt-path))) 287 ))))) 334 288 input) 335 289 336 290 (provide 'dirtrack) 337 291 338 ;; ;arch-tag: 168de071-be88-4937-aff6-2aba9f328d5a292 ;; arch-tag: 168de071-be88-4937-aff6-2aba9f328d5a 339 293 ;;; dirtrack.el ends here
