merge trunk
[bpt/emacs.git] / lisp / shell.el
CommitLineData
1cd7adc6 1;;; shell.el --- specialized comint.el for running the shell
5109bfb0 2
95df8112 3;; Copyright (C) 1988, 1993-1997, 2000-2011 Free Software Foundation, Inc.
6d74b528 4
1cd7adc6 5;; Author: Olin Shivers <shivers@cs.cmu.edu>
5762abec 6;; Simon Marshall <simon@gnu.org>
b71f9bdb 7;; Maintainer: FSF <emacs-devel@gnu.org>
d7b4d18f 8;; Keywords: processes
630cc463 9
5109bfb0 10;; This file is part of GNU Emacs.
c88ab9ce 11
eb3fa2cf 12;; GNU Emacs is free software: you can redistribute it and/or modify
5109bfb0 13;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
c88ab9ce 16
5109bfb0
KH
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
c88ab9ce 21
5109bfb0 22;; You should have received a copy of the GNU General Public License
eb3fa2cf 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
be9b65ac 24
630cc463
ER
25;;; Commentary:
26
4696802b
JB
27;; This file defines a shell-in-a-buffer package (shell mode) built on
28;; top of comint mode. This is actually cmushell with things renamed
29;; to replace its counterpart in Emacs 18. cmushell is more
b578f267 30;; featureful, robust, and uniform than the Emacs 18 version.
be9b65ac 31
b578f267 32;; Since this mode is built on top of the general command-interpreter-in-
84728570 33;; a-buffer mode (comint mode), it shares a common base functionality,
b578f267
EN
34;; and a common set of bindings, with all modes derived from comint mode.
35;; This makes these modes easier to use.
be9b65ac 36
b578f267
EN
37;; For documentation on the functionality provided by comint mode, and
38;; the hooks available for customising it, see the file comint.el.
39;; For further information on shell mode, see the comments below.
be9b65ac 40
b578f267 41;; Needs fixin:
84728570 42;; When sending text from a source file to a subprocess, the process-mark can
b578f267
EN
43;; move off the window, so you can lose sight of the process interactions.
44;; Maybe I should ensure the process mark is in the window when I send
45;; text to the process? Switch selectable?
be9b65ac 46
a9ec2adb
JB
47;; YOUR .EMACS FILE
48;;=============================================================================
49;; Some suggestions for your .emacs file.
50;;
0b3c9cf1
SM
51;; ;; Define M-# to run some strange command:
52;; (eval-after-load "shell"
53;; '(define-key shell-mode-map "\M-#" 'shells-dynamic-spell))
84728570 54
b578f267
EN
55;; Brief Command Documentation:
56;;============================================================================
57;; Comint Mode Commands: (common to shell and all comint-derived modes)
58;;
a9e73449
RS
59;; m-p comint-previous-input Cycle backwards in input history
60;; m-n comint-next-input Cycle forwards
b578f267
EN
61;; m-r comint-previous-matching-input Previous input matching a regexp
62;; m-s comint-next-matching-input Next input that matches
a9e73449 63;; m-c-l comint-show-output Show last batch of process output
b578f267 64;; return comint-send-input
a9e73449 65;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff.
b578f267 66;; c-c c-a comint-bol Beginning of line; skip prompt
a9e73449
RS
67;; c-c c-u comint-kill-input ^u
68;; c-c c-w backward-kill-word ^w
69;; c-c c-c comint-interrupt-subjob ^c
70;; c-c c-z comint-stop-subjob ^z
71;; c-c c-\ comint-quit-subjob ^\
3226d6ca 72;; c-c c-o comint-delete-output Delete last batch of process output
a9e73449 73;; c-c c-r comint-show-output Show last batch of process output
94c34f7a 74;; c-c c-l comint-dynamic-list-input-ring List input history
b578f267 75;; send-invisible Read line w/o echo & send to proc
a9e73449 76;; comint-continue-subjob Useful if you accidentally suspend
b578f267
EN
77;; top-level job
78;; comint-mode-hook is the comint mode hook.
79
80;; Shell Mode Commands:
81;; shell Fires up the shell process
82;; tab comint-dynamic-complete Complete filename/command/history
83;; m-? comint-dynamic-list-filename-completions
84;; List completions in help buffer
85;; m-c-f shell-forward-command Forward a shell command
86;; m-c-b shell-backward-command Backward a shell command
a9e73449 87;; dirs Resync the buffer's dir stack
a034393c 88;; shell-dirtrack-mode Turn dir tracking on/off
b578f267
EN
89;; comint-strip-ctrl-m Remove trailing ^Ms from output
90;;
91;; The shell mode hook is shell-mode-hook
92;; comint-prompt-regexp is initialised to shell-prompt-pattern, for backwards
93;; compatibility.
a9ec2adb 94
b578f267 95;; Read the rest of this file for more information.
84728570 96
630cc463
ER
97;;; Code:
98
99(require 'comint)
100
b578f267
EN
101;;; Customization and Buffer Variables
102
ed366e87 103(defgroup shell nil
edf959f9 104 "Running shell from within Emacs buffers."
ed366e87
RS
105 :group 'processes
106 :group 'unix)
107
108(defgroup shell-directories nil
edf959f9 109 "Directory support in shell mode."
ed366e87
RS
110 :group 'shell)
111
112(defgroup shell-faces nil
edf959f9 113 "Faces in shell buffers."
ed366e87
RS
114 :group 'shell)
115
c88ab9ce 116;;;###autoload
1e8780b1 117(defcustom shell-dumb-shell-regexp (purecopy "cmd\\(proxy\\)?\\.exe")
f5058b96
EZ
118 "Regexp to match shells that don't save their command history, and
119don't handle the backslash as a quote character. For shells that
120match this regexp, Emacs will write out the command history when the
121shell finishes, and won't remove backslashes when it unquotes shell
122arguments."
4dced927
AI
123 :type 'regexp
124 :group 'shell)
125
fad22e2e 126(defcustom shell-prompt-pattern "^[^#$%>\n]*[#$%>] *"
a9ec2adb 127 "Regexp to match prompts in the inferior shell.
ac75ef20 128Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well.
2df2f980 129This variable is used to initialize `comint-prompt-regexp' in the
a9ec2adb
JB
130shell buffer.
131
e03035e3
LT
132If `comint-use-prompt-regexp' is nil, then this variable is only used
133to determine paragraph boundaries. See Info node `Shell Prompts' for
134how Shell mode treats paragraphs.
28bc09d6 135
ac75ef20 136The pattern should probably not match more than one line. If it does,
221ca406 137Shell mode may become confused trying to distinguish prompt from input
ac75ef20
JB
138on lines which don't start with a prompt.
139
fad22e2e
RS
140This is a fine thing to set in your `.emacs' file."
141 :type 'regexp
142 :group 'shell)
a9ec2adb 143
ed366e87 144(defcustom shell-completion-fignore nil
05327ca9 145 "List of suffixes to be disregarded during file/command completion.
e11284d5
RS
146This variable is used to initialize `comint-completion-fignore' in the shell
147buffer. The default is nil, for compatibility with most shells.
148Some people like (\"~\" \"#\" \"%\").
149
ed366e87
RS
150This is a fine thing to set in your `.emacs' file."
151 :type '(repeat (string :tag "Suffix"))
152 :group 'shell)
e11284d5 153
56eb1060 154(defvar shell-delimiter-argument-list '(?\| ?& ?< ?> ?\( ?\) ?\;)
2df2f980 155 "List of characters to recognize as separate arguments.
56eb1060 156This variable is used to initialize `comint-delimiter-argument-list' in the
39d1a2ce
SM
157shell buffer. The value may depend on the operating system or shell.
158
159This is a fine thing to set in your `.emacs' file.")
160
76f63ea0 161(defvar shell-file-name-chars
c60ee5e7 162 (if (memq system-type '(ms-dos windows-nt cygwin))
4aed0379 163 "~/A-Za-z0-9_^$!#%&{}@`'.,:()-"
f0d5dc24 164 "[]~/A-Za-z0-9+@:_.$#%,={}-")
76f63ea0
RS
165 "String of characters valid in a file name.
166This variable is used to initialize `comint-file-name-chars' in the
39d1a2ce 167shell buffer. The value may depend on the operating system or shell.
d76b71af
RS
168
169This is a fine thing to set in your `.emacs' file.")
170
7b4c6503 171(defvar shell-file-name-quote-list
39d1a2ce
SM
172 (if (memq system-type '(ms-dos windows-nt))
173 nil
3ca5dc5b 174 (append shell-delimiter-argument-list '(?\s ?$ ?\* ?\! ?\" ?\' ?\` ?\# ?\\)))
7b4c6503
SM
175 "List of characters to quote when in a file name.
176This variable is used to initialize `comint-file-name-quote-list' in the
39d1a2ce 177shell buffer. The value may depend on the operating system or shell.
7b4c6503
SM
178
179This is a fine thing to set in your `.emacs' file.")
180
988a4d60
RS
181(defvar shell-dynamic-complete-functions
182 '(comint-replace-by-expanded-history
183 shell-dynamic-complete-environment-variable
184 shell-dynamic-complete-command
185 shell-replace-by-expanded-directory
49e3189d
CY
186 shell-dynamic-complete-filename
187 comint-dynamic-complete-filename)
988a4d60 188 "List of functions called to perform completion.
2df2f980 189This variable is used to initialize `comint-dynamic-complete-functions' in the
988a4d60
RS
190shell buffer.
191
192This is a fine thing to set in your `.emacs' file.")
193
ed366e87 194(defcustom shell-command-regexp "[^;&|\n]+"
05327ca9 195 "Regexp to match a single command within a pipeline.
ed366e87
RS
196This is used for directory tracking and does not do a perfect job."
197 :type 'regexp
198 :group 'shell)
d76b71af 199
6ed020c8 200(defcustom shell-command-separator-regexp "[;&|\n \t]*"
05327ca9 201 "Regexp to match a single command within a pipeline.
6ed020c8
JB
202This is used for directory tracking and does not do a perfect job."
203 :type 'regexp
204 :group 'shell)
205
ed366e87 206(defcustom shell-completion-execonly t
05327ca9 207 "If non-nil, use executable files only for completion candidates.
5394cb44 208This mirrors the optional behavior of tcsh.
d76b71af 209
ed366e87
RS
210Detecting executability of files may slow command completion considerably."
211 :type 'boolean
212 :group 'shell)
d76b71af 213
ed366e87 214(defcustom shell-popd-regexp "popd"
05327ca9 215 "Regexp to match subshell commands equivalent to popd."
ed366e87
RS
216 :type 'regexp
217 :group 'shell-directories)
be9b65ac 218
ed366e87 219(defcustom shell-pushd-regexp "pushd"
05327ca9 220 "Regexp to match subshell commands equivalent to pushd."
ed366e87
RS
221 :type 'regexp
222 :group 'shell-directories)
be9b65ac 223
ed366e87 224(defcustom shell-pushd-tohome nil
05327ca9 225 "If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd).
ed366e87
RS
226This mirrors the optional behavior of tcsh."
227 :type 'boolean
228 :group 'shell-directories)
d76b71af 229
ed366e87 230(defcustom shell-pushd-dextract nil
05327ca9 231 "If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
ed366e87
RS
232This mirrors the optional behavior of tcsh."
233 :type 'boolean
234 :group 'shell-directories)
d76b71af 235
ed366e87 236(defcustom shell-pushd-dunique nil
05327ca9 237 "If non-nil, make pushd only add unique directories to the stack.
ed366e87
RS
238This mirrors the optional behavior of tcsh."
239 :type 'boolean
240 :group 'shell-directories)
d76b71af 241
ed366e87 242(defcustom shell-cd-regexp "cd"
05327ca9 243 "Regexp to match subshell commands equivalent to cd."
ed366e87
RS
244 :type 'regexp
245 :group 'shell-directories)
be9b65ac 246
ed366e87 247(defcustom shell-chdrive-regexp
84728570 248 (if (memq system-type '(ms-dos windows-nt))
32d01212
RS
249 ; NetWare allows the five chars between upper and lower alphabetics.
250 "[]a-zA-Z^_`\\[\\\\]:"
251 nil)
05327ca9 252 "If non-nil, is regexp used to track drive changes."
233f3fb8
RS
253 :type '(choice regexp
254 (const nil))
ed366e87 255 :group 'shell-directories)
32d01212 256
8a6387ed 257(defcustom shell-dirtrack-verbose t
05327ca9 258 "If non-nil, show the directory stack following directory change.
a034393c 259This is effective only if directory tracking is enabled.
c004e539
GM
260The `dirtrack' package provides an alternative implementation of this feature -
261see the function `dirtrack-mode'."
8a6387ed
SM
262 :type 'boolean
263 :group 'shell-directories)
264
ed366e87 265(defcustom explicit-shell-file-name nil
05327ca9 266 "If non-nil, is file name to use for explicitly requested inferior shell."
ed366e87
RS
267 :type '(choice (const :tag "None" nil) file)
268 :group 'shell)
be9b65ac 269
400b0022
KS
270;; Note: There are no explicit references to the variable `explicit-csh-args'.
271;; It is used implicitly by M-x shell when the shell is `csh'.
ed366e87 272(defcustom explicit-csh-args
be9b65ac
DL
273 (if (eq system-type 'hpux)
274 ;; -T persuades HP's csh not to think it is smarter
275 ;; than us about what terminal modes to use.
276 '("-i" "-T")
277 '("-i"))
05327ca9 278 "Args passed to inferior shell by \\[shell], if the shell is csh.
ed366e87
RS
279Value is a list of strings, which may be nil."
280 :type '(repeat (string :tag "Argument"))
281 :group 'shell)
be9b65ac 282
400b0022
KS
283;; Note: There are no explicit references to the variable `explicit-bash-args'.
284;; It is used implicitly by M-x shell when the interactive shell is `bash'.
6674676b 285(defcustom explicit-bash-args
969a0631
KS
286 (let* ((prog (or (and (boundp 'explicit-shell-file-name) explicit-shell-file-name)
287 (getenv "ESHELL") shell-file-name))
288 (name (file-name-nondirectory prog)))
491bf4bc
RS
289 ;; Tell bash not to use readline, except for bash 1.x which
290 ;; doesn't grook --noediting. Bash 1.x has -nolineediting, but
291 ;; process-send-eof cannot terminate bash if we use it.
969a0631
KS
292 (if (and (not purify-flag)
293 (equal name "bash")
294 (file-executable-p prog)
295 (string-match "bad option"
88b7c0e4
KS
296 (shell-command-to-string
297 (concat (shell-quote-argument prog)
298 " --noediting"))))
969a0631
KS
299 '("-i")
300 '("--noediting" "-i")))
05327ca9 301 "Args passed to inferior shell by \\[shell], if the shell is bash.
6674676b
AS
302Value is a list of strings, which may be nil."
303 :type '(repeat (string :tag "Argument"))
304 :group 'shell)
305
ed366e87 306(defcustom shell-input-autoexpand 'history
05327ca9 307 "If non-nil, expand input command history references on completion.
4f99443b
RS
308This mirrors the optional behavior of tcsh (its autoexpand and histlit).
309
310If the value is `input', then the expansion is seen on input.
311If the value is `history', then the expansion is only when inserting
312into the buffer's input ring. See also `comint-magic-space' and
313`comint-dynamic-complete'.
314
315This variable supplies a default for `comint-input-autoexpand',
ed366e87 316for Shell mode only."
6f0984e5
AS
317 :type '(choice (const :tag "off" nil)
318 (const input)
319 (const history)
320 (const :tag "on" t))
362ae0b3 321 :group 'shell)
4f99443b 322
be9b65ac 323(defvar shell-dirstack nil
c88ab9ce
ER
324 "List of directories saved by pushd in this buffer's shell.
325Thus, this does not include the shell's current directory.")
be9b65ac 326
b493a9b2
RS
327(defvar shell-dirtrackp t
328 "Non-nil in a shell buffer means directory tracking is enabled.")
329
fa8f1b25
ER
330(defvar shell-last-dir nil
331 "Keep track of last directory for ksh `cd -' command.")
332
c63e83a4 333(defvar shell-dirstack-query nil
4dea1735 334 "Command used by `shell-resync-dirs' to query the shell.")
be9b65ac 335
a0310a6c
DN
336(defvar shell-mode-map
337 (let ((map (nconc (make-sparse-keymap) comint-mode-map)))
338 (define-key map "\C-c\C-f" 'shell-forward-command)
339 (define-key map "\C-c\C-b" 'shell-backward-command)
340 (define-key map "\t" 'comint-dynamic-complete)
341 (define-key map (kbd "M-RET") 'shell-resync-dirs)
342 (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
343 (define-key map [menu-bar completion]
344 (cons "Complete"
345 (copy-keymap (lookup-key comint-mode-map [menu-bar completion]))))
346 (define-key-after (lookup-key map [menu-bar completion])
347 [complete-env-variable] '("Complete Env. Variable Name" .
348 shell-dynamic-complete-environment-variable)
349 'complete-file)
350 (define-key-after (lookup-key map [menu-bar completion])
351 [expand-directory] '("Expand Directory Reference" .
352 shell-replace-by-expanded-directory)
353 'complete-expand)
354 map))
be9b65ac 355
ed366e87 356(defcustom shell-mode-hook '()
5a0c3f56 357 "Hook for customizing Shell mode."
ed366e87
RS
358 :type 'hook
359 :group 'shell)
be9b65ac 360
5945a1f7 361(defvar shell-font-lock-keywords
cb6e07b1 362 '(("[ \t]\\([+-][^ \t\n]+\\)" 1 font-lock-comment-face)
473fbd89
SM
363 ("^[^ \t\n]+:.*" . font-lock-string-face)
364 ("^\\[[1-9][0-9]*\\]" . font-lock-string-face))
5945a1f7 365 "Additional expressions to highlight in Shell mode.")
84728570 366
be9b65ac 367;;; Basic Procedures
be9b65ac 368
e96d4147
GM
369(defcustom shell-dir-cookie-re nil
370 "Regexp matching your prompt, including some part of the current directory.
371If your prompt includes the current directory or the last few elements of it,
372set this to a pattern that matches your prompt and whose subgroup 1 matches
373the directory part of it.
374This is used by `shell-dir-cookie-watcher' to try and use this info
375to track your current directory. It can be used instead of or in addition
376to `dirtrack-mode'."
377 :group 'shell
378 :type '(choice (const nil) regexp))
379
e9904b59
RS
380(put 'shell-mode 'mode-class 'special)
381
9f299ecb 382(define-derived-mode shell-mode comint-mode "Shell"
933907e9 383 "Major mode for interacting with an inferior shell.\\<shell-mode-map>
8079b590
SM
384\\[comint-send-input] after the end of the process' output sends the text from
385 the end of process to the end of the current line.
386\\[comint-send-input] before end of process output copies the current line minus the prompt to
387 the end of the buffer and sends it (\\[comint-copy-old-input] just copies the current line).
e9933cb1 388\\[send-invisible] reads a line of text without echoing it, and sends it to
56783585
RS
389 the shell. This is useful for entering passwords. Or, add the function
390 `comint-watch-for-password-prompt' to `comint-output-filter-functions'.
be9b65ac 391
e9933cb1
SM
392If you want to make multiple shell buffers, rename the `*shell*' buffer
393using \\[rename-buffer] or \\[rename-uniquely] and start a new shell.
394
8079b590 395If you want to make shell buffers limited in length, add the function
4841acc4 396`comint-truncate-buffer' to `comint-output-filter-functions'.
8079b590 397
be9b65ac
DL
398If you accidentally suspend your process, use \\[comint-continue-subjob]
399to continue it.
400
e9933cb1
SM
401`cd', `pushd' and `popd' commands given to the shell are watched by Emacs to
402keep this buffer's default directory the same as the shell's working directory.
0b3c9cf1
SM
403While directory tracking is enabled, the shell's working directory is displayed
404by \\[list-buffers] or \\[mouse-buffer-menu] in the `File' field.
84728570 405\\[dirs] queries the shell and resyncs Emacs' idea of what the current
be9b65ac 406 directory stack is.
a034393c
GM
407\\[shell-dirtrack-mode] turns directory tracking on and off.
408\(The `dirtrack' package provides an alternative implementation of this
c004e539 409feature - see the function `dirtrack-mode'.)
be9b65ac
DL
410
411\\{shell-mode-map}
24fdffaa 412Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
988a4d60 413`shell-mode-hook' (in that order). Before each input, the hooks on
ba02c167
RS
414`comint-input-filter-functions' are run. After each shell output, the hooks
415on `comint-output-filter-functions' are run.
be9b65ac 416
84728570
SS
417Variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp'
418and `shell-popd-regexp' are used to match their respective commands,
419while `shell-pushd-tohome', `shell-pushd-dextract' and `shell-pushd-dunique'
32d01212 420control the behavior of the relevant command.
d76b71af 421
e11284d5
RS
422Variables `comint-completion-autolist', `comint-completion-addsuffix',
423`comint-completion-recexact' and `comint-completion-fignore' control the
424behavior of file name, command name and variable name completion. Variable
425`shell-completion-execonly' controls the behavior of command name completion.
2df2f980 426Variable `shell-completion-fignore' is used to initialize the value of
e11284d5 427`comint-completion-fignore'.
d76b71af
RS
428
429Variables `comint-input-ring-file-name' and `comint-input-autoexpand' control
ab646e49 430the initialization of the input ring history, and history expansion.
d76b71af 431
ba02c167 432Variables `comint-output-filter-functions', a hook, and
e11284d5 433`comint-scroll-to-bottom-on-input' and `comint-scroll-to-bottom-on-output'
988a4d60
RS
434control whether input and output cause the window to scroll to the end of the
435buffer."
d76b71af 436 (setq comint-prompt-regexp shell-prompt-pattern)
e11284d5 437 (setq comint-completion-fignore shell-completion-fignore)
d76b71af 438 (setq comint-delimiter-argument-list shell-delimiter-argument-list)
76f63ea0 439 (setq comint-file-name-chars shell-file-name-chars)
7b4c6503 440 (setq comint-file-name-quote-list shell-file-name-quote-list)
898cfc1d
SM
441 (set (make-local-variable 'comint-dynamic-complete-functions)
442 shell-dynamic-complete-functions)
e03035e3 443 (set (make-local-variable 'paragraph-separate) "\\'")
d76b71af
RS
444 (make-local-variable 'paragraph-start)
445 (setq paragraph-start comint-prompt-regexp)
c156572f
SM
446 (make-local-variable 'font-lock-defaults)
447 (setq font-lock-defaults '(shell-font-lock-keywords t))
be9b65ac 448 (make-local-variable 'shell-dirstack)
a9ec2adb 449 (setq shell-dirstack nil)
fdcc1ef7 450 (make-local-variable 'shell-last-dir)
fa8f1b25 451 (setq shell-last-dir nil)
4f99443b 452 (setq comint-input-autoexpand shell-input-autoexpand)
11ee8d90 453 (shell-dirtrack-mode 1)
5d9719e6
RS
454 ;; This is not really correct, since the shell buffer does not really
455 ;; edit this directory. But it is useful in the buffer list and menus.
5d9719e6 456 (setq list-buffers-directory (expand-file-name default-directory))
d76b71af 457 ;; shell-dependent assignments.
6ba0fd3e 458 (when (ring-empty-p comint-input-ring)
ee8107c0
RS
459 (let ((shell (file-name-nondirectory (car
460 (process-command (get-buffer-process (current-buffer)))))))
461 (setq comint-input-ring-file-name
462 (or (getenv "HISTFILE")
463 (cond ((string-equal shell "bash") "~/.bash_history")
464 ((string-equal shell "ksh") "~/.sh_history")
465 (t "~/.history"))))
466 (if (or (equal comint-input-ring-file-name "")
467 (equal (file-truename comint-input-ring-file-name)
468 (file-truename "/dev/null")))
469 (setq comint-input-ring-file-name nil))
470 ;; Arrange to write out the input ring on exit, if the shell doesn't
471 ;; do this itself.
472 (if (and comint-input-ring-file-name
473 (string-match shell-dumb-shell-regexp shell))
474 (set-process-sentinel (get-buffer-process (current-buffer))
475 #'shell-write-history-on-exit))
476 (setq shell-dirstack-query
477 (cond ((string-equal shell "sh") "pwd")
478 ((string-equal shell "ksh") "echo $PWD ~-")
3811bec8
LK
479 (t "dirs")))
480 ;; Bypass a bug in certain versions of bash.
481 (when (string-equal shell "bash")
482 (add-hook 'comint-output-filter-functions
483 'shell-filter-ctrl-a-ctrl-b nil t)))
78835dd0
SM
484 (when shell-dir-cookie-re
485 ;; Watch for magic cookies in the output to track the current dir.
486 (add-hook 'comint-output-filter-functions
487 'shell-dir-cookie-watcher nil t))
ee8107c0 488 (comint-read-input-ring t)))
4dced927 489
3811bec8
LK
490(defun shell-filter-ctrl-a-ctrl-b (string)
491 "Remove `^A' and `^B' characters from comint output.
492
493Bash uses these characters as internal quoting characters in its
494prompt. Due to a bug in some bash versions (including 2.03,
4952.04, and 2.05b), they may erroneously show up when bash is
496started with the `--noediting' option and Select Graphic
497Rendition (SGR) control sequences (formerly known as ANSI escape
498sequences) are used to color the prompt.
499
500This function can be put on `comint-output-filter-functions'.
501The argument STRING is ignored."
502 (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
503 (save-excursion
cc6e650e
JL
504 (goto-char (or (and (markerp comint-last-output-start)
505 (marker-position comint-last-output-start))
506 (point-min)))
3811bec8
LK
507 (while (re-search-forward "[\C-a\C-b]" pmark t)
508 (replace-match "")))))
509
4dced927
AI
510(defun shell-write-history-on-exit (process event)
511 "Called when the shell process is stopped.
512
513Writes the input history to a history file
84728570 514`comint-input-ring-file-name' using `comint-write-input-ring'
4dced927
AI
515and inserts a short message in the shell buffer.
516
517This function is a sentinel watching the shell interpreter process.
518Sentinels will always get the two parameters PROCESS and EVENT."
519 ;; Write history.
520 (comint-write-input-ring)
84728570
SS
521 (let ((buf (process-buffer process)))
522 (when (buffer-live-p buf)
523 (with-current-buffer buf
524 (insert (format "\nProcess %s %s\n" process event))))))
525
c88ab9ce 526;;;###autoload
fd1035aa
MB
527(defun shell (&optional buffer)
528 "Run an inferior shell, with I/O through BUFFER (which defaults to `*shell*').
529Interactively, a prefix arg means to prompt for BUFFER.
66a100be
MA
530If `default-directory' is a remote file name, it is also prompted
531to change if called with a prefix arg.
532
fd1035aa
MB
533If BUFFER exists but shell process is not running, make new shell.
534If BUFFER exists and shell process is running, just switch to BUFFER.
24fdffaa 535Program used comes from variable `explicit-shell-file-name',
a9ec2adb 536 or (if that is nil) from the ESHELL environment variable,
c3342e8e 537 or (if that is nil) from `shell-file-name'.
ec1d7c6e 538If a file `~/.emacs_SHELLNAME' exists, or `~/.emacs.d/init_SHELLNAME.sh',
71af6fc4
RS
539it is given as initial input (but this may be lost, due to a timing
540error, if the shell discards input when it starts up).
fbc270e7
RS
541The buffer is put in Shell mode, giving commands for sending input
542and controlling the subjobs of the shell. See `shell-mode'.
543See also the variable `shell-prompt-pattern'.
be9b65ac 544
ebe4d555
RS
545To specify a coding system for converting non-ASCII characters
546in the input and output to the shell, use \\[universal-coding-system-argument]
547before \\[shell]. You can also specify this with \\[set-buffer-process-coding-system]
548in the shell buffer, after you start the shell.
549The default comes from `process-coding-system-alist' and
550`default-process-coding-system'.
551
a9ec2adb 552The shell file name (sans directories) is used to make a symbol name
62c9fad7 553such as `explicit-csh-args'. If that symbol is a variable,
be9b65ac
DL
554its value is used as a list of arguments when invoking the shell.
555Otherwise, one argument `-i' is passed to the shell.
556
557\(Type \\[describe-mode] in the shell buffer for a list of commands.)"
fd1035aa
MB
558 (interactive
559 (list
560 (and current-prefix-arg
d9af6951
AS
561 (prog1
562 (read-buffer "Shell buffer: "
563 (generate-new-buffer-name "*shell*"))
564 (if (file-remote-p default-directory)
565 ;; It must be possible to declare a local default-directory.
8f5f1e68
SM
566 ;; FIXME: This can't be right: it changes the default-directory
567 ;; of the current-buffer rather than of the *shell* buffer.
d9af6951
AS
568 (setq default-directory
569 (expand-file-name
570 (read-file-name
571 "Default directory: " default-directory default-directory
572 t nil 'file-directory-p))))))))
925f8c70 573 (require 'ansi-color)
8f5f1e68
SM
574 (setq buffer (if (or buffer (not (derived-mode-p 'shell-mode))
575 (comint-check-proc (current-buffer)))
576 (get-buffer-create (or buffer "*shell*"))
577 ;; If the current buffer is a dead shell buffer, use it.
578 (current-buffer)))
5a45735a
SM
579 ;; Pop to buffer, so that the buffer's window will be correctly set
580 ;; when we call comint (so that comint sets the COLUMNS env var properly).
581 (pop-to-buffer buffer)
582 (unless (comint-check-proc buffer)
583 (let* ((prog (or explicit-shell-file-name
584 (getenv "ESHELL") shell-file-name))
585 (name (file-name-nondirectory prog))
586 (startfile (concat "~/.emacs_" name))
587 (xargs-name (intern-soft (concat "explicit-" name "-args"))))
ec1d7c6e 588 (unless (file-exists-p startfile)
f7c94f43 589 (setq startfile (concat user-emacs-directory "init_" name ".sh")))
5a45735a
SM
590 (apply 'make-comint-in-buffer "shell" buffer prog
591 (if (file-exists-p startfile) startfile)
592 (if (and xargs-name (boundp xargs-name))
593 (symbol-value xargs-name)
594 '("-i")))
595 (shell-mode)))
596 buffer)
519bfec4 597
05327ca9 598;; Don't do this when shell.el is loaded, only while dumping.
ca0a881a 599;;;###autoload (add-hook 'same-window-buffer-names (purecopy "*shell*"))
84728570 600
be9b65ac 601;;; Directory tracking
05327ca9
SM
602;;
603;; This code provides the shell mode input sentinel
604;; SHELL-DIRECTORY-TRACKER
605;; that tracks cd, pushd, and popd commands issued to the shell, and
606;; changes the current directory of the shell buffer accordingly.
607;;
608;; This is basically a fragile hack, although it's more accurate than
609;; the version in Emacs 18's shell.el. It has the following failings:
610;; 1. It doesn't know about the cdpath shell variable.
611;; 2. It cannot infallibly deal with command sequences, though it does well
612;; with these and with ignoring commands forked in another shell with ()s.
613;; 3. More generally, any complex command is going to throw it. Otherwise,
614;; you'd have to build an entire shell interpreter in Emacs Lisp. Failing
615;; that, there's no way to catch shell commands where cd's are buried
616;; inside conditional expressions, aliases, and so forth.
617;;
618;; The whole approach is a crock. Shell aliases mess it up. File sourcing
619;; messes it up. You run other processes under the shell; these each have
620;; separate working directories, and some have commands for manipulating
621;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have
622;; commands that do *not* affect the current w.d. at all, but look like they
623;; do (e.g., the cd command in ftp). In shells that allow you job
624;; control, you can switch between jobs, all having different w.d.'s. So
625;; simply saying %3 can shift your w.d..
626;;
627;; The solution is to relax, not stress out about it, and settle for
628;; a hack that works pretty well in typical circumstances. Remember
629;; that a half-assed solution is more in keeping with the spirit of Unix,
630;; anyway. Blech.
631;;
632;; One good hack not implemented here for users of programmable shells
633;; is to program up the shell w.d. manipulation commands to output
634;; a coded command sequence to the tty. Something like
635;; ESC | <cwd> |
636;; where <cwd> is the new current working directory. Then trash the
637;; directory tracking machinery currently used in this package, and
638;; replace it with a process filter that watches for and strips out
639;; these messages.
be9b65ac 640
78835dd0
SM
641(defun shell-dir-cookie-watcher (text)
642 ;; This is fragile: the TEXT could be split into several chunks and we'd
643 ;; miss it. Oh well. It's a best effort anyway. I'd expect that it's
644 ;; rather unusual to have the prompt split into several packets, but
645 ;; I'm sure Murphy will prove me wrong.
646 (when (and shell-dir-cookie-re (string-match shell-dir-cookie-re text))
647 (let ((dir (match-string 1 text)))
648 (cond
649 ((file-name-absolute-p dir) (shell-cd dir))
650 ;; Let's try and see if it seems to be up or down from where we were.
651 ((string-match "\\`\\(.*\\)\\(?:/.*\\)?\n\\(.*/\\)\\1\\(?:/.*\\)?\\'"
652 (setq text (concat dir "\n" default-directory)))
653 (shell-cd (concat (match-string 2 text) dir)))))))
78835dd0 654
be9b65ac
DL
655(defun shell-directory-tracker (str)
656 "Tracks cd, pushd and popd commands issued to the shell.
657This function is called on each input passed to the shell.
658It watches for cd, pushd and popd commands and sets the buffer's
659default directory to track these commands.
660
a034393c 661You may toggle this tracking on and off with \\[shell-dirtrack-mode].
05327ca9 662If Emacs gets confused, you can resync with the shell with \\[dirs].
c004e539
GM
663\(The `dirtrack' package provides an alternative implementation of this
664feature - see the function `dirtrack-mode'.)
be9b65ac 665
32d01212 666See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp',
84728570 667and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract',
32d01212 668and `shell-pushd-dunique' control the behavior of the relevant command.
d76b71af 669
24fdffaa 670Environment variables are expanded, see function `substitute-in-file-name'."
d76b71af
RS
671 (if shell-dirtrackp
672 ;; We fail gracefully if we think the command will fail in the shell.
673 (condition-case chdir-failure
6ed020c8
JB
674 (let ((start (progn (string-match
675 (concat "^" shell-command-separator-regexp)
676 str) ; skip whitespace
d76b71af
RS
677 (match-end 0)))
678 end cmd arg1)
679 (while (string-match shell-command-regexp str start)
680 (setq end (match-end 0)
681 cmd (comint-arguments (substring str start end) 0 0)
682 arg1 (comint-arguments (substring str start end) 1 1))
5f49d5e8
KH
683 (if arg1
684 (setq arg1 (shell-unquote-argument arg1)))
54021695
KH
685 (cond ((string-match (concat "\\`\\(" shell-popd-regexp
686 "\\)\\($\\|[ \t]\\)")
687 cmd)
32d01212 688 (shell-process-popd (comint-substitute-in-file-name arg1)))
54021695
KH
689 ((string-match (concat "\\`\\(" shell-pushd-regexp
690 "\\)\\($\\|[ \t]\\)")
691 cmd)
32d01212 692 (shell-process-pushd (comint-substitute-in-file-name arg1)))
54021695
KH
693 ((string-match (concat "\\`\\(" shell-cd-regexp
694 "\\)\\($\\|[ \t]\\)")
695 cmd)
32d01212
RS
696 (shell-process-cd (comint-substitute-in-file-name arg1)))
697 ((and shell-chdrive-regexp
698 (string-match (concat "\\`\\(" shell-chdrive-regexp
699 "\\)\\($\\|[ \t]\\)")
700 cmd))
701 (shell-process-cd (comint-substitute-in-file-name cmd))))
6ed020c8
JB
702 (setq start (progn (string-match shell-command-separator-regexp
703 str end)
704 ;; skip again
d76b71af 705 (match-end 0)))))
ba02c167 706 (error "Couldn't cd"))))
d76b71af 707
5f49d5e8
KH
708(defun shell-unquote-argument (string)
709 "Remove all kinds of shell quoting from STRING."
710 (save-match-data
f5058b96
EZ
711 (let ((idx 0) next inside
712 (quote-chars
713 (if (string-match shell-dumb-shell-regexp
714 (file-name-nondirectory
715 (car (process-command (get-buffer-process (current-buffer))))))
716 "['`\"]"
717 "[\\'`\"]")))
5f49d5e8 718 (while (and (< idx (length string))
f5058b96 719 (setq next (string-match quote-chars string next)))
5f49d5e8
KH
720 (cond ((= (aref string next) ?\\)
721 (setq string (replace-match "" nil nil string))
722 (setq next (1+ next)))
723 ((and inside (= (aref string next) inside))
724 (setq string (replace-match "" nil nil string))
725 (setq inside nil))
726 (inside
727 (setq next (1+ next)))
728 (t
729 (setq inside (aref string next))
730 (setq string (replace-match "" nil nil string)))))
731 string)))
732
05327ca9 733;; popd [+n]
be9b65ac 734(defun shell-process-popd (arg)
d76b71af
RS
735 (let ((num (or (shell-extract-num arg) 0)))
736 (cond ((and num (= num 0) shell-dirstack)
f8aefe82 737 (shell-cd (shell-prefixed-directory-name (car shell-dirstack)))
d76b71af
RS
738 (setq shell-dirstack (cdr shell-dirstack))
739 (shell-dirstack-message))
740 ((and num (> num 0) (<= num (length shell-dirstack)))
741 (let* ((ds (cons nil shell-dirstack))
742 (cell (nthcdr (1- num) ds)))
743 (rplacd cell (cdr (cdr cell)))
744 (setq shell-dirstack (cdr ds))
745 (shell-dirstack-message)))
746 (t
ba02c167 747 (error "Couldn't popd")))))
be9b65ac 748
3db9a4eb 749;; Return DIR prefixed with comint-file-name-prefix as appropriate.
4a02b552
RS
750(defun shell-prefixed-directory-name (dir)
751 (if (= (length comint-file-name-prefix) 0)
752 dir
753 (if (file-name-absolute-p dir)
754 ;; The name is absolute, so prepend the prefix.
755 (concat comint-file-name-prefix dir)
0b3c9cf1 756 ;; For relative name we assume default-directory already has the prefix.
4a02b552 757 (expand-file-name dir))))
3db9a4eb 758
05327ca9 759;; cd [dir]
be9b65ac 760(defun shell-process-cd (arg)
3db9a4eb
RM
761 (let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix
762 "~"))
d76b71af 763 ((string-equal "-" arg) shell-last-dir)
3db9a4eb 764 (t (shell-prefixed-directory-name arg)))))
d76b71af 765 (setq shell-last-dir default-directory)
0b3c9cf1 766 (shell-cd new-dir)
d76b71af 767 (shell-dirstack-message)))
be9b65ac 768
05327ca9 769;; pushd [+n | dir]
be9b65ac 770(defun shell-process-pushd (arg)
d76b71af
RS
771 (let ((num (shell-extract-num arg)))
772 (cond ((zerop (length arg))
773 ;; no arg -- swap pwd and car of stack unless shell-pushd-tohome
774 (cond (shell-pushd-tohome
3db9a4eb 775 (shell-process-pushd (concat comint-file-name-prefix "~")))
d76b71af
RS
776 (shell-dirstack
777 (let ((old default-directory))
0b3c9cf1 778 (shell-cd (car shell-dirstack))
221ca406 779 (setq shell-dirstack (cons old (cdr shell-dirstack)))
d76b71af
RS
780 (shell-dirstack-message)))
781 (t
782 (message "Directory stack empty."))))
783 ((numberp num)
784 ;; pushd +n
785 (cond ((> num (length shell-dirstack))
786 (message "Directory stack not that deep."))
787 ((= num 0)
1cd7adc6 788 (error (message "Couldn't cd")))
d76b71af
RS
789 (shell-pushd-dextract
790 (let ((dir (nth (1- num) shell-dirstack)))
791 (shell-process-popd arg)
792 (shell-process-pushd default-directory)
0b3c9cf1 793 (shell-cd dir)
d76b71af
RS
794 (shell-dirstack-message)))
795 (t
796 (let* ((ds (cons default-directory shell-dirstack))
797 (dslen (length ds))
798 (front (nthcdr num ds))
799 (back (reverse (nthcdr (- dslen num) (reverse ds))))
800 (new-ds (append front back)))
0b3c9cf1 801 (shell-cd (car new-ds))
d76b71af
RS
802 (setq shell-dirstack (cdr new-ds))
803 (shell-dirstack-message)))))
804 (t
805 ;; pushd <dir>
806 (let ((old-wd default-directory))
0b3c9cf1 807 (shell-cd (shell-prefixed-directory-name arg))
d76b71af
RS
808 (if (or (null shell-pushd-dunique)
809 (not (member old-wd shell-dirstack)))
810 (setq shell-dirstack (cons old-wd shell-dirstack)))
811 (shell-dirstack-message))))))
be9b65ac
DL
812
813;; If STR is of the form +n, for n>0, return n. Otherwise, nil.
814(defun shell-extract-num (str)
815 (and (string-match "^\\+[1-9][0-9]*$" str)
027a4b6b 816 (string-to-number str)))
be9b65ac 817
05327ca9
SM
818(defvaralias 'shell-dirtrack-mode 'shell-dirtrackp)
819(define-minor-mode shell-dirtrack-mode
c004e539
GM
820 "Turn directory tracking on and off in a shell buffer.
821The `dirtrack' package provides an alternative implementation of this
822feature - see the function `dirtrack-mode'."
05327ca9
SM
823 nil nil nil
824 (setq list-buffers-directory (if shell-dirtrack-mode default-directory))
825 (if shell-dirtrack-mode
826 (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
827 (remove-hook 'comint-input-filter-functions 'shell-directory-tracker t)))
828
a034393c
GM
829(define-obsolete-function-alias 'shell-dirtrack-toggle 'shell-dirtrack-mode
830 "23.1")
be9b65ac 831
0b3c9cf1
SM
832(defun shell-cd (dir)
833 "Do normal `cd' to DIR, and set `list-buffers-directory'."
05327ca9 834 (cd dir)
b7e97ed5 835 (if shell-dirtrackp
05327ca9 836 (setq list-buffers-directory default-directory)))
be9b65ac
DL
837
838(defun shell-resync-dirs ()
839 "Resync the buffer's idea of the current directory stack.
84728570 840This command queries the shell with the command bound to
24fdffaa 841`shell-dirstack-query' (default \"dirs\"), reads the next
be9b65ac
DL
842line output and parses it to form the new directory stack.
843DON'T issue this command unless the buffer is at a shell prompt.
844Also, note that if some other subprocess decides to do output
845immediately after the query, its output will be taken as the
ab646e49 846new directory stack -- you lose. If this happens, just do the
be9b65ac
DL
847command again."
848 (interactive)
849 (let* ((proc (get-buffer-process (current-buffer)))
45a4af63
GM
850 (pmark (process-mark proc))
851 (started-at-pmark (= (point) (marker-position pmark))))
852 (save-excursion
853 (goto-char pmark)
854 ;; If the process echoes commands, don't insert a fake command in
855 ;; the buffer or it will appear twice.
856 (unless comint-process-echoes
857 (insert shell-dirstack-query) (insert "\n"))
858 (sit-for 0) ; force redisplay
859 (comint-send-string proc shell-dirstack-query)
860 (comint-send-string proc "\n")
861 (set-marker pmark (point))
862 (let ((pt (point))
863 (regexp
864 (concat
865 (if comint-process-echoes
866 ;; Skip command echo if the process echoes
867 (concat "\\(" (regexp-quote shell-dirstack-query) "\n\\)")
868 "\\(\\)")
869 "\\(.+\n\\)")))
870 ;; This extra newline prevents the user's pending input from spoofing us.
871 (insert "\n") (backward-char 1)
872 ;; Wait for one line.
873 (while (not (looking-at regexp))
874 (accept-process-output proc)
875 (goto-char pt)))
876 (goto-char pmark) (delete-char 1) ; remove the extra newline
877 ;; That's the dirlist. grab it & parse it.
878 (let* ((dl (buffer-substring (match-beginning 2) (1- (match-end 2))))
879 (dl-len (length dl))
880 (ds '()) ; new dir stack
881 (i 0))
882 (while (< i dl-len)
883 ;; regexp = optional whitespace, (non-whitespace), optional whitespace
884 (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
885 (setq ds (cons (concat comint-file-name-prefix
886 (substring dl (match-beginning 1)
887 (match-end 1)))
888 ds))
889 (setq i (match-end 0)))
890 (let ((ds (nreverse ds)))
891 (condition-case nil
892 (progn (shell-cd (car ds))
893 (setq shell-dirstack (cdr ds)
894 shell-last-dir (car shell-dirstack))
895 (shell-dirstack-message))
896 (error (message "Couldn't cd"))))))
897 (if started-at-pmark (goto-char (marker-position pmark)))))
be9b65ac 898
05327ca9 899;; For your typing convenience:
31e1d920 900(defalias 'dirs 'shell-resync-dirs)
be9b65ac
DL
901
902
05327ca9
SM
903;; Show the current dirstack on the message line.
904;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo".
905;; (This isn't necessary if the dirlisting is generated with a simple "dirs".)
906;; All the commands that mung the buffer's dirstack finish by calling
907;; this guy.
be9b65ac 908(defun shell-dirstack-message ()
8a6387ed
SM
909 (when shell-dirtrack-verbose
910 (let* ((msg "")
911 (ds (cons default-directory shell-dirstack))
912 (home (expand-file-name (concat comint-file-name-prefix "~/")))
913 (homelen (length home)))
914 (while ds
915 (let ((dir (car ds)))
916 (and (>= (length dir) homelen)
917 (string= home (substring dir 0 homelen))
918 (setq dir (concat "~/" (substring dir homelen))))
919 ;; Strip off comint-file-name-prefix if present.
920 (and comint-file-name-prefix
921 (>= (length dir) (length comint-file-name-prefix))
922 (string= comint-file-name-prefix
923 (substring dir 0 (length comint-file-name-prefix)))
924 (setq dir (substring dir (length comint-file-name-prefix)))
925 (setcar ds dir))
926 (setq msg (concat msg (directory-file-name dir) " "))
927 (setq ds (cdr ds))))
928 (message "%s" msg))))
84728570 929
c64d8c55
RS
930;; This was mostly copied from shell-resync-dirs.
931(defun shell-snarf-envar (var)
932 "Return as a string the shell's value of environment variable VAR."
933 (let* ((cmd (format "printenv '%s'\n" var))
934 (proc (get-buffer-process (current-buffer)))
935 (pmark (process-mark proc)))
936 (goto-char pmark)
937 (insert cmd)
938 (sit-for 0) ; force redisplay
939 (comint-send-string proc cmd)
940 (set-marker pmark (point))
941 (let ((pt (point))) ; wait for 1 line
942 ;; This extra newline prevents the user's pending input from spoofing us.
943 (insert "\n") (backward-char 1)
944 (while (not (looking-at ".+\n"))
945 (accept-process-output proc)
946 (goto-char pt)))
947 (goto-char pmark) (delete-char 1) ; remove the extra newline
948 (buffer-substring (match-beginning 0) (1- (match-end 0)))))
949
950(defun shell-copy-environment-variable (variable)
951 "Copy the environment variable VARIABLE from the subshell to Emacs.
952This command reads the value of the specified environment variable
953in the shell, and sets the same environment variable in Emacs
a9e73449 954\(what `getenv' in Emacs would return) to that value.
c64d8c55
RS
955That value will affect any new subprocesses that you subsequently start
956from Emacs."
957 (interactive (list (read-envvar-name "\
958Copy Shell environment variable to Emacs: ")))
959 (setenv variable (shell-snarf-envar variable)))
84728570 960
d76b71af
RS
961(defun shell-forward-command (&optional arg)
962 "Move forward across ARG shell command(s). Does not cross lines.
963See `shell-command-regexp'."
964 (interactive "p")
5ed619e0 965 (let ((limit (line-end-position)))
19134c18 966 (if (re-search-forward (concat shell-command-regexp "\\([;&|][\t ]*\\)+")
d76b71af 967 limit 'move arg)
b0f86743 968 (skip-syntax-backward " "))))
d76b71af
RS
969
970
971(defun shell-backward-command (&optional arg)
972 "Move backward across ARG shell command(s). Does not cross lines.
973See `shell-command-regexp'."
974 (interactive "p")
975 (let ((limit (save-excursion (comint-bol nil) (point))))
28bc09d6
MB
976 (when (> limit (point))
977 (setq limit (line-beginning-position)))
b0f86743 978 (skip-syntax-backward " " limit)
d76b71af 979 (if (re-search-backward
19134c18 980 (format "[;&|]+[\t ]*\\(%s\\)" shell-command-regexp) limit 'move arg)
d76b71af 981 (progn (goto-char (match-beginning 1))
b0f86743 982 (skip-chars-forward ";&|")))))
d76b71af 983
d76b71af
RS
984(defun shell-dynamic-complete-command ()
985 "Dynamically complete the command at point.
986This function is similar to `comint-dynamic-complete-filename', except that it
5113b294 987searches `exec-path' (minus the trailing Emacs library path) for completion
d76b71af
RS
988candidates. Note that this may not be the same as the shell's idea of the
989path.
990
991Completion is dependent on the value of `shell-completion-execonly', plus
988a4d60
RS
992those that effect file completion. See `shell-dynamic-complete-as-command'.
993
994Returns t if successful."
d76b71af 995 (interactive)
988a4d60
RS
996 (let ((filename (comint-match-partial-filename)))
997 (if (and filename
998 (save-match-data (not (string-match "[~/]" filename)))
999 (eq (match-beginning 0)
1000 (save-excursion (shell-backward-command 1) (point))))
c35be7ec
JL
1001 (prog2 (unless (window-minibuffer-p (selected-window))
1002 (message "Completing command name..."))
988a4d60
RS
1003 (shell-dynamic-complete-as-command)))))
1004
1005
1006(defun shell-dynamic-complete-as-command ()
1007 "Dynamically complete at point as a command.
1008See `shell-dynamic-complete-filename'. Returns t if successful."
56783585 1009 (let* ((filename (or (comint-match-partial-filename) ""))
f0d5dc24
RS
1010 (filenondir (file-name-nondirectory filename))
1011 (path-dirs (cdr (reverse exec-path)))
d76b71af
RS
1012 (cwd (file-name-as-directory (expand-file-name default-directory)))
1013 (ignored-extensions
a867a90a
RS
1014 (and comint-completion-fignore
1015 (mapconcat (function (lambda (x) (concat (regexp-quote x) "$")))
1016 comint-completion-fignore "\\|")))
2df2f980 1017 (dir "") (comps-in-dir ())
f0d5dc24
RS
1018 (file "") (abs-file-name "") (completions ()))
1019 ;; Go thru each dir in the search path, finding completions.
1020 (while path-dirs
1021 (setq dir (file-name-as-directory (comint-directory (or (car path-dirs) ".")))
1022 comps-in-dir (and (file-accessible-directory-p dir)
1023 (file-name-all-completions filenondir dir)))
d76b71af 1024 ;; Go thru each completion found, to see whether it should be used.
f0d5dc24
RS
1025 (while comps-in-dir
1026 (setq file (car comps-in-dir)
1027 abs-file-name (concat dir file))
d76b71af 1028 (if (and (not (member file completions))
7b2db0a0
KH
1029 (not (and ignored-extensions
1030 (string-match ignored-extensions file)))
f0d5dc24
RS
1031 (or (string-equal dir cwd)
1032 (not (file-directory-p abs-file-name)))
d76b71af 1033 (or (null shell-completion-execonly)
f0d5dc24 1034 (file-executable-p abs-file-name)))
d76b71af 1035 (setq completions (cons file completions)))
f0d5dc24
RS
1036 (setq comps-in-dir (cdr comps-in-dir)))
1037 (setq path-dirs (cdr path-dirs)))
d76b71af 1038 ;; OK, we've got a list of completions.
56783585 1039 (let ((success (let ((comint-completion-addsuffix nil))
f0d5dc24 1040 (comint-dynamic-simple-complete filenondir completions))))
56783585
RS
1041 (if (and (memq success '(sole shortest)) comint-completion-addsuffix
1042 (not (file-directory-p (comint-match-partial-filename))))
1043 (insert " "))
1044 success)))
988a4d60 1045
a086d081
CY
1046(defun shell-dynamic-complete-filename ()
1047 "Dynamically complete the filename at point.
1048This completes only if point is at a suitable position for a
1049filename argument."
1050 (interactive)
1051 (let ((opoint (point))
1052 (beg (comint-line-beginning-position)))
1053 (when (save-excursion
1054 (goto-char (if (re-search-backward "[;|&]" beg t)
1055 (match-end 0)
1056 beg))
1057 (re-search-forward "[^ \t][ \t]" opoint t))
1058 (comint-dynamic-complete-as-filename))))
988a4d60
RS
1059
1060(defun shell-match-partial-variable ()
da6a48c9 1061 "Return the shell variable at point, or nil if none is found."
988a4d60
RS
1062 (save-excursion
1063 (let ((limit (point)))
1064 (if (re-search-backward "[^A-Za-z0-9_{}]" nil 'move)
1065 (or (looking-at "\\$") (forward-char 1)))
1066 ;; Anchor the search forwards.
1067 (if (or (eolp) (looking-at "[^A-Za-z0-9_{}$]"))
1068 nil
1069 (re-search-forward "\\$?{?[A-Za-z0-9_]*}?" limit)
1070 (buffer-substring (match-beginning 0) (match-end 0))))))
a9ec2adb 1071
988a4d60
RS
1072(defun shell-dynamic-complete-environment-variable ()
1073 "Dynamically complete the environment variable at point.
1074Completes if after a variable, i.e., if it starts with a \"$\".
1075See `shell-dynamic-complete-as-environment-variable'.
1076
1077This function is similar to `comint-dynamic-complete-filename', except that it
1078searches `process-environment' for completion candidates. Note that this may
1079not be the same as the interpreter's idea of variable names. The main problem
1080with this type of completion is that `process-environment' is the environment
1081which Emacs started with. Emacs does not track changes to the environment made
1082by the interpreter. Perhaps it would be more accurate if this function was
1083called `shell-dynamic-complete-process-environment-variable'.
1084
1085Returns non-nil if successful."
1086 (interactive)
1087 (let ((variable (shell-match-partial-variable)))
1088 (if (and variable (string-match "^\\$" variable))
c35be7ec
JL
1089 (prog2 (unless (window-minibuffer-p (selected-window))
1090 (message "Completing variable name..."))
988a4d60
RS
1091 (shell-dynamic-complete-as-environment-variable)))))
1092
1093
1094(defun shell-dynamic-complete-as-environment-variable ()
1095 "Dynamically complete at point as an environment variable.
1096Used by `shell-dynamic-complete-environment-variable'.
1097Uses `comint-dynamic-simple-complete'."
1098 (let* ((var (or (shell-match-partial-variable) ""))
1099 (variable (substring var (or (string-match "[^$({]\\|$" var) 0)))
1100 (variables (mapcar (function (lambda (x)
1101 (substring x 0 (string-match "=" x))))
1102 process-environment))
1103 (addsuffix comint-completion-addsuffix)
1104 (comint-completion-addsuffix nil)
1105 (success (comint-dynamic-simple-complete variable variables)))
1106 (if (memq success '(sole shortest))
1107 (let* ((var (shell-match-partial-variable))
1108 (variable (substring var (string-match "[^$({]" var)))
1109 (protection (cond ((string-match "{" var) "}")
1110 ((string-match "(" var) ")")
1111 (t "")))
1112 (suffix (cond ((null addsuffix) "")
1113 ((file-directory-p
1114 (comint-directory (getenv variable))) "/")
1115 (t " "))))
1116 (insert protection suffix)))
1117 success))
1118
1119
1120(defun shell-replace-by-expanded-directory ()
1121 "Expand directory stack reference before point.
1122Directory stack references are of the form \"=digit\" or \"=-\".
1123See `default-directory' and `shell-dirstack'.
1124
1125Returns t if successful."
1126 (interactive)
1127 (if (comint-match-partial-filename)
1128 (save-excursion
988a4d60
RS
1129 (goto-char (match-beginning 0))
1130 (let ((stack (cons default-directory shell-dirstack))
1131 (index (cond ((looking-at "=-/?")
1132 (length shell-dirstack))
1b93984e 1133 ((looking-at "=\\([0-9]+\\)/?")
988a4d60
RS
1134 (string-to-number
1135 (buffer-substring
1136 (match-beginning 1) (match-end 1)))))))
1137 (cond ((null index)
1138 nil)
1139 ((>= index (length stack))
1cd7adc6 1140 (error "Directory stack not that deep"))
988a4d60
RS
1141 (t
1142 (replace-match (file-name-as-directory (nth index stack)) t t)
1143 (message "Directory item: %d" index)
1144 t))))))
84728570 1145
c88ab9ce
ER
1146(provide 'shell)
1147
1148;;; shell.el ends here