6e1b46aeeecc690a6b7e4fbc85a89ecfa8c6f96a
[bpt/emacs.git] / lisp / shell.el
1 ;;; shell.el --- specialized comint.el for running the shell -*- lexical-binding: t -*-
2
3 ;; Copyright (C) 1988, 1993-1997, 2000-2013 Free Software Foundation, Inc.
4
5 ;; Author: Olin Shivers <shivers@cs.cmu.edu>
6 ;; Simon Marshall <simon@gnu.org>
7 ;; Maintainer: FSF <emacs-devel@gnu.org>
8 ;; Keywords: processes
9
10 ;; This file is part of GNU Emacs.
11
12 ;; GNU Emacs is free software: you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation, either version 3 of the License, or
15 ;; (at your option) any later version.
16
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.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24
25 ;;; Commentary:
26
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
30 ;; featureful, robust, and uniform than the Emacs 18 version.
31
32 ;; Since this mode is built on top of the general command-interpreter-in-
33 ;; a-buffer mode (comint mode), it shares a common base functionality,
34 ;; and a common set of bindings, with all modes derived from comint mode.
35 ;; This makes these modes easier to use.
36
37 ;; For documentation on the functionality provided by comint mode, and
38 ;; the hooks available for customizing it, see the file comint.el.
39 ;; For further information on shell mode, see the comments below.
40
41 ;; Needs fixin:
42 ;; When sending text from a source file to a subprocess, the process-mark can
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?
46
47 ;; YOUR .EMACS FILE
48 ;;=============================================================================
49 ;; Some suggestions for your init file.
50 ;;
51 ;; ;; Define M-# to run some strange command:
52 ;; (eval-after-load "shell"
53 ;; '(define-key shell-mode-map "\M-#" 'shells-dynamic-spell))
54
55 ;; Brief Command Documentation:
56 ;;============================================================================
57 ;; Comint Mode Commands: (common to shell and all comint-derived modes)
58 ;;
59 ;; m-p comint-previous-input Cycle backwards in input history
60 ;; m-n comint-next-input Cycle forwards
61 ;; m-r comint-previous-matching-input Previous input matching a regexp
62 ;; m-s comint-next-matching-input Next input that matches
63 ;; m-c-l comint-show-output Show last batch of process output
64 ;; return comint-send-input
65 ;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff.
66 ;; c-c c-a comint-bol Beginning of line; skip prompt
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 ^\
72 ;; c-c c-o comint-delete-output Delete last batch of process output
73 ;; c-c c-r comint-show-output Show last batch of process output
74 ;; c-c c-l comint-dynamic-list-input-ring List input history
75 ;; send-invisible Read line w/o echo & send to proc
76 ;; comint-continue-subjob Useful if you accidentally suspend
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 completion-at-point 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
87 ;; dirs Resync the buffer's dir stack
88 ;; shell-dirtrack-mode Turn dir tracking on/off
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 initialized to shell-prompt-pattern, for backwards
93 ;; compatibility.
94
95 ;; Read the rest of this file for more information.
96
97 ;;; Code:
98
99 (require 'comint)
100 (require 'pcomplete)
101
102 ;;; Customization and Buffer Variables
103
104 (defgroup shell nil
105 "Running shell from within Emacs buffers."
106 :group 'processes
107 :group 'unix)
108
109 (defgroup shell-directories nil
110 "Directory support in shell mode."
111 :group 'shell)
112
113 ;; Unused.
114 ;;; (defgroup shell-faces nil
115 ;;; "Faces in shell buffers."
116 ;;; :group 'shell)
117
118 ;;;###autoload
119 (defcustom shell-dumb-shell-regexp (purecopy "cmd\\(proxy\\)?\\.exe")
120 "Regexp to match shells that don't save their command history, and
121 don't handle the backslash as a quote character. For shells that
122 match this regexp, Emacs will write out the command history when the
123 shell finishes, and won't remove backslashes when it unquotes shell
124 arguments."
125 :type 'regexp
126 :group 'shell)
127
128 (defcustom shell-prompt-pattern "^[^#$%>\n]*[#$%>] *"
129 "Regexp to match prompts in the inferior shell.
130 Defaults to \"^[^#$%>\\n]*[#$%>] *\", which works pretty well.
131 This variable is used to initialize `comint-prompt-regexp' in the
132 shell buffer.
133
134 If `comint-use-prompt-regexp' is nil, then this variable is only used
135 to determine paragraph boundaries. See Info node `Shell Prompts' for
136 how Shell mode treats paragraphs.
137
138 The pattern should probably not match more than one line. If it does,
139 Shell mode may become confused trying to distinguish prompt from input
140 on lines which don't start with a prompt."
141 :type 'regexp
142 :group 'shell)
143
144 (defcustom shell-completion-fignore nil
145 "List of suffixes to be disregarded during file/command completion.
146 This variable is used to initialize `comint-completion-fignore' in the shell
147 buffer. The default is nil, for compatibility with most shells.
148 Some people like (\"~\" \"#\" \"%\")."
149 :type '(repeat (string :tag "Suffix"))
150 :group 'shell)
151
152 (defcustom shell-delimiter-argument-list '(?\| ?& ?< ?> ?\( ?\) ?\;)
153 "List of characters to recognize as separate arguments.
154 This variable is used to initialize `comint-delimiter-argument-list' in the
155 shell buffer. The value may depend on the operating system or shell."
156 :type '(choice (const nil)
157 (repeat :tag "List of characters" character))
158 :group 'shell)
159
160 (defcustom shell-file-name-chars
161 (if (memq system-type '(ms-dos windows-nt cygwin))
162 "~/A-Za-z0-9_^$!#%&{}@`'.,:()-"
163 "[]~/A-Za-z0-9+@:_.$#%,={}-")
164 "String of characters valid in a file name.
165 This variable is used to initialize `comint-file-name-chars' in the
166 shell buffer. The value may depend on the operating system or shell."
167 :type 'string
168 :group 'shell)
169
170 (defcustom shell-file-name-quote-list
171 (if (memq system-type '(ms-dos windows-nt))
172 nil
173 (append shell-delimiter-argument-list '(?\s ?$ ?\* ?\! ?\" ?\' ?\` ?\# ?\\)))
174 "List of characters to quote when in a file name.
175 This variable is used to initialize `comint-file-name-quote-list' in the
176 shell buffer. The value may depend on the operating system or shell."
177 :type '(repeat character)
178 :group 'shell)
179
180 (defcustom shell-dynamic-complete-functions
181 '(comint-c-a-p-replace-by-expanded-history
182 shell-environment-variable-completion
183 shell-command-completion
184 shell-c-a-p-replace-by-expanded-directory
185 pcomplete-completions-at-point
186 shell-filename-completion
187 comint-filename-completion)
188 "List of functions called to perform completion.
189 This variable is used to initialize `comint-dynamic-complete-functions' in the
190 shell buffer."
191 :type '(repeat function)
192 :group 'shell)
193
194 (defcustom shell-command-regexp "[^;&|\n]+"
195 "Regexp to match a single command within a pipeline.
196 This is used for directory tracking and does not do a perfect job."
197 :type 'regexp
198 :group 'shell)
199
200 (defcustom shell-command-separator-regexp "[;&|\n \t]*"
201 "Regexp to match a single command within a pipeline.
202 This is used for directory tracking and does not do a perfect job."
203 :type 'regexp
204 :group 'shell)
205
206 (defcustom shell-completion-execonly t
207 "If non-nil, use executable files only for completion candidates.
208 This mirrors the optional behavior of tcsh.
209
210 Detecting executability of files may slow command completion considerably."
211 :type 'boolean
212 :group 'shell)
213
214 (defcustom shell-popd-regexp "popd"
215 "Regexp to match subshell commands equivalent to popd."
216 :type 'regexp
217 :group 'shell-directories)
218
219 (defcustom shell-pushd-regexp "pushd"
220 "Regexp to match subshell commands equivalent to pushd."
221 :type 'regexp
222 :group 'shell-directories)
223
224 (defcustom shell-pushd-tohome nil
225 "If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd).
226 This mirrors the optional behavior of tcsh."
227 :type 'boolean
228 :group 'shell-directories)
229
230 (defcustom shell-pushd-dextract nil
231 "If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
232 This mirrors the optional behavior of tcsh."
233 :type 'boolean
234 :group 'shell-directories)
235
236 (defcustom shell-pushd-dunique nil
237 "If non-nil, make pushd only add unique directories to the stack.
238 This mirrors the optional behavior of tcsh."
239 :type 'boolean
240 :group 'shell-directories)
241
242 (defcustom shell-cd-regexp "cd"
243 "Regexp to match subshell commands equivalent to cd."
244 :type 'regexp
245 :group 'shell-directories)
246
247 (defcustom shell-chdrive-regexp
248 (if (memq system-type '(ms-dos windows-nt))
249 ; NetWare allows the five chars between upper and lower alphabetics.
250 "[]a-zA-Z^_`\\[\\\\]:"
251 nil)
252 "If non-nil, is regexp used to track drive changes."
253 :type '(choice regexp
254 (const nil))
255 :group 'shell-directories)
256
257 (defcustom shell-dirtrack-verbose t
258 "If non-nil, show the directory stack following directory change.
259 This is effective only if directory tracking is enabled.
260 The `dirtrack' package provides an alternative implementation of this feature -
261 see the function `dirtrack-mode'."
262 :type 'boolean
263 :group 'shell-directories)
264
265 (defcustom explicit-shell-file-name nil
266 "If non-nil, is file name to use for explicitly requested inferior shell."
267 :type '(choice (const :tag "None" nil) file)
268 :group 'shell)
269
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'.
272 (defcustom explicit-csh-args
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"))
278 "Args passed to inferior shell by \\[shell], if the shell is csh.
279 Value is a list of strings, which may be nil."
280 :type '(repeat (string :tag "Argument"))
281 :group 'shell)
282
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'.
285 (defcustom explicit-bash-args
286 ;; Tell bash not to use readline. It's safe to assume --noediting now,
287 ;; as it was introduced in 1996 in Bash version 2.
288 '("--noediting" "-i")
289 "Args passed to inferior shell by \\[shell], if the shell is bash.
290 Value is a list of strings, which may be nil."
291 :type '(repeat (string :tag "Argument"))
292 :group 'shell)
293
294 (defcustom shell-input-autoexpand 'history
295 "If non-nil, expand input command history references on completion.
296 This mirrors the optional behavior of tcsh (its autoexpand and histlit).
297
298 If the value is `input', then the expansion is seen on input.
299 If the value is `history', then the expansion is only when inserting
300 into the buffer's input ring. See also `comint-magic-space' and
301 `comint-dynamic-complete-functions'.
302
303 This variable supplies a default for `comint-input-autoexpand',
304 for Shell mode only."
305 :type '(choice (const :tag "off" nil)
306 (const input)
307 (const history)
308 (const :tag "on" t))
309 :group 'shell)
310
311 (defvar shell-dirstack nil
312 "List of directories saved by pushd in this buffer's shell.
313 Thus, this does not include the shell's current directory.")
314
315 (defvar shell-dirtrackp t
316 "Non-nil in a shell buffer means directory tracking is enabled.")
317
318 (defvar shell-last-dir nil
319 "Keep track of last directory for ksh `cd -' command.")
320
321 (defvar shell-dirstack-query nil
322 "Command used by `shell-resync-dirs' to query the shell.")
323
324 (defvar shell-mode-map
325 (let ((map (nconc (make-sparse-keymap) comint-mode-map)))
326 (define-key map "\C-c\C-f" 'shell-forward-command)
327 (define-key map "\C-c\C-b" 'shell-backward-command)
328 (define-key map "\t" 'completion-at-point)
329 (define-key map (kbd "M-RET") 'shell-resync-dirs)
330 (define-key map "\M-?" 'comint-dynamic-list-filename-completions)
331 (define-key map [menu-bar completion]
332 (cons "Complete"
333 (copy-keymap (lookup-key comint-mode-map [menu-bar completion]))))
334 (define-key-after (lookup-key map [menu-bar completion])
335 [complete-env-variable] '("Complete Env. Variable Name" .
336 shell-dynamic-complete-environment-variable)
337 'complete-file)
338 (define-key-after (lookup-key map [menu-bar completion])
339 [expand-directory] '("Expand Directory Reference" .
340 shell-replace-by-expanded-directory)
341 'complete-expand)
342 map))
343
344 (defcustom shell-mode-hook '()
345 "Hook for customizing Shell mode."
346 :type 'hook
347 :group 'shell)
348
349 (defvar shell-font-lock-keywords
350 '(("[ \t]\\([+-][^ \t\n]+\\)" 1 font-lock-comment-face)
351 ("^[^ \t\n]+:.*" . font-lock-string-face)
352 ("^\\[[1-9][0-9]*\\]" . font-lock-string-face))
353 "Additional expressions to highlight in Shell mode.")
354
355 ;;; Basic Procedures
356
357 (defun shell--unquote&requote-argument (qstr &optional upos)
358 (unless upos (setq upos 0))
359 (let* ((qpos 0)
360 (dquotes nil)
361 (ustrs '())
362 (re (concat
363 "[\"']"
364 "\\|\\$\\(?:\\([[:alpha:]][[:alnum:]]*\\)"
365 "\\|{\\(?1:[^{}]+\\)}\\)"
366 (when (memq system-type '(ms-dos windows-nt))
367 "\\|%\\(?1:[^\\\\/]*\\)%")
368 (when comint-file-name-quote-list
369 "\\|\\\\\\(.\\)")))
370 (qupos nil)
371 (push (lambda (str end)
372 (push str ustrs)
373 (setq upos (- upos (length str)))
374 (unless (or qupos (> upos 0))
375 (setq qupos (if (< end 0) (- end) (+ upos end))))))
376 match)
377 (while (setq match (string-match re qstr qpos))
378 (funcall push (substring qstr qpos match) match)
379 (cond
380 ((match-beginning 2) (funcall push (match-string 2 qstr) (match-end 0)))
381 ((match-beginning 1) (funcall push (getenv (match-string 1 qstr))
382 (- (match-end 0))))
383 ((eq (aref qstr match) ?\") (setq dquotes (not dquotes)))
384 ((eq (aref qstr match) ?\')
385 (cond
386 (dquotes (funcall push "'" (match-end 0)))
387 ((< match (1+ (length qstr)))
388 (let ((end (string-match "'" qstr (1+ match))))
389 (funcall push (substring qstr (1+ match) end)
390 (or end (length qstr)))))
391 (t nil)))
392 (t (error "Unexpected case in shell--unquote&requote-argument!")))
393 (setq qpos (match-end 0)))
394 (funcall push (substring qstr qpos) (length qstr))
395 (list (mapconcat #'identity (nreverse ustrs) "")
396 qupos #'comint-quote-filename)))
397
398 (defun shell--unquote-argument (str)
399 (car (shell--unquote&requote-argument str)))
400 (defun shell--requote-argument (upos qstr)
401 ;; See `completion-table-with-quoting'.
402 (let ((res (shell--unquote&requote-argument qstr upos)))
403 (cons (nth 1 res) (nth 2 res))))
404
405 (defun shell--parse-pcomplete-arguments ()
406 "Parse whitespace separated arguments in the current region."
407 ;; FIXME: share code with shell--unquote&requote-argument.
408 (let ((begin (save-excursion (shell-backward-command 1) (point)))
409 (end (point))
410 begins args)
411 (save-excursion
412 (goto-char begin)
413 (while (< (point) end)
414 (skip-chars-forward " \t\n")
415 (push (point) begins)
416 (let ((arg ()))
417 (while (looking-at
418 (eval-when-compile
419 (concat
420 "\\(?:[^\s\t\n\\\"']+"
421 "\\|'\\([^']*\\)'?"
422 "\\|\"\\(\\(?:[^\"\\]\\|\\\\.\\)*\\)\"?"
423 "\\|\\\\\\(\\(?:.\\|\n\\)?\\)\\)")))
424 (goto-char (match-end 0))
425 (cond
426 ((match-beginning 3) ;Backslash escape.
427 (push (cond
428 ((null comint-file-name-quote-list)
429 (goto-char (match-beginning 3)) "\\")
430 ((= (match-beginning 3) (match-end 3)) "\\")
431 (t (match-string 3)))
432 arg))
433 ((match-beginning 2) ;Double quote.
434 (push (if (null comint-file-name-quote-list) (match-string 2)
435 (replace-regexp-in-string
436 "\\\\\\(.\\)" "\\1" (match-string 2)))
437 arg))
438 ((match-beginning 1) ;Single quote.
439 (push (match-string 1) arg))
440 (t (push (match-string 0) arg))))
441 (push (mapconcat #'identity (nreverse arg) "") args)))
442 (cons (nreverse args) (nreverse begins)))))
443
444 (defun shell-command-completion-function ()
445 "Completion function for shell command names.
446 This is the value of `pcomplete-command-completion-function' for
447 Shell buffers. It implements `shell-completion-execonly' for
448 `pcomplete' completion."
449 (pcomplete-here (pcomplete-entries nil
450 (if shell-completion-execonly
451 'file-executable-p))))
452
453 (defun shell-completion-vars ()
454 "Setup completion vars for `shell-mode' and `read-shell-command'."
455 (set (make-local-variable 'comint-completion-fignore)
456 shell-completion-fignore)
457 (set (make-local-variable 'comint-delimiter-argument-list)
458 shell-delimiter-argument-list)
459 (set (make-local-variable 'comint-file-name-chars) shell-file-name-chars)
460 (set (make-local-variable 'comint-file-name-quote-list)
461 shell-file-name-quote-list)
462 (set (make-local-variable 'comint-dynamic-complete-functions)
463 shell-dynamic-complete-functions)
464 (setq-local comint-unquote-function #'shell--unquote-argument)
465 (setq-local comint-requote-function #'shell--requote-argument)
466 (set (make-local-variable 'pcomplete-parse-arguments-function)
467 #'shell--parse-pcomplete-arguments)
468 (set (make-local-variable 'pcomplete-termination-string)
469 (cond ((not comint-completion-addsuffix) "")
470 ((stringp comint-completion-addsuffix)
471 comint-completion-addsuffix)
472 ((not (consp comint-completion-addsuffix)) " ")
473 (t (cdr comint-completion-addsuffix))))
474 (set (make-local-variable 'pcomplete-command-completion-function)
475 #'shell-command-completion-function)
476 ;; Don't use pcomplete's defaulting mechanism, rely on
477 ;; shell-dynamic-complete-functions instead.
478 (set (make-local-variable 'pcomplete-default-completion-function) #'ignore)
479 (setq comint-input-autoexpand shell-input-autoexpand)
480 ;; Not needed in shell-mode because it's inherited from comint-mode, but
481 ;; placed here for read-shell-command.
482 (add-hook 'completion-at-point-functions 'comint-completion-at-point nil t))
483
484 (put 'shell-mode 'mode-class 'special)
485
486 (define-derived-mode shell-mode comint-mode "Shell"
487 "Major mode for interacting with an inferior shell.\\<shell-mode-map>
488 \\[comint-send-input] after the end of the process' output sends the text from
489 the end of process to the end of the current line.
490 \\[comint-send-input] before end of process output copies the current line minus the prompt to
491 the end of the buffer and sends it (\\[comint-copy-old-input] just copies the current line).
492 \\[send-invisible] reads a line of text without echoing it, and sends it to
493 the shell. This is useful for entering passwords. Or, add the function
494 `comint-watch-for-password-prompt' to `comint-output-filter-functions'.
495
496 If you want to make multiple shell buffers, rename the `*shell*' buffer
497 using \\[rename-buffer] or \\[rename-uniquely] and start a new shell.
498
499 If you want to make shell buffers limited in length, add the function
500 `comint-truncate-buffer' to `comint-output-filter-functions'.
501
502 If you accidentally suspend your process, use \\[comint-continue-subjob]
503 to continue it.
504
505 `cd', `pushd' and `popd' commands given to the shell are watched by Emacs to
506 keep this buffer's default directory the same as the shell's working directory.
507 While directory tracking is enabled, the shell's working directory is displayed
508 by \\[list-buffers] or \\[mouse-buffer-menu] in the `File' field.
509 \\[dirs] queries the shell and resyncs Emacs's idea of what the current
510 directory stack is.
511 \\[shell-dirtrack-mode] turns directory tracking on and off.
512 \(The `dirtrack' package provides an alternative implementation of this
513 feature - see the function `dirtrack-mode'.)
514
515 \\{shell-mode-map}
516 Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
517 `shell-mode-hook' (in that order). Before each input, the hooks on
518 `comint-input-filter-functions' are run. After each shell output, the hooks
519 on `comint-output-filter-functions' are run.
520
521 Variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp'
522 and `shell-popd-regexp' are used to match their respective commands,
523 while `shell-pushd-tohome', `shell-pushd-dextract' and `shell-pushd-dunique'
524 control the behavior of the relevant command.
525
526 Variables `comint-completion-autolist', `comint-completion-addsuffix',
527 `comint-completion-recexact' and `comint-completion-fignore' control the
528 behavior of file name, command name and variable name completion. Variable
529 `shell-completion-execonly' controls the behavior of command name completion.
530 Variable `shell-completion-fignore' is used to initialize the value of
531 `comint-completion-fignore'.
532
533 Variables `comint-input-ring-file-name' and `comint-input-autoexpand' control
534 the initialization of the input ring history, and history expansion.
535
536 Variables `comint-output-filter-functions', a hook, and
537 `comint-scroll-to-bottom-on-input' and `comint-scroll-to-bottom-on-output'
538 control whether input and output cause the window to scroll to the end of the
539 buffer."
540 (setq comint-prompt-regexp shell-prompt-pattern)
541 (shell-completion-vars)
542 (set (make-local-variable 'paragraph-separate) "\\'")
543 (set (make-local-variable 'paragraph-start) comint-prompt-regexp)
544 (set (make-local-variable 'font-lock-defaults) '(shell-font-lock-keywords t))
545 (set (make-local-variable 'shell-dirstack) nil)
546 (set (make-local-variable 'shell-last-dir) nil)
547 (shell-dirtrack-mode 1)
548
549 ;; By default, ansi-color applies faces using overlays. This is
550 ;; very inefficient in Shell buffers (e.g. Bug#10835). We use a
551 ;; custom `ansi-color-apply-face-function' to convert color escape
552 ;; sequences into `font-lock-face' properties.
553 (setq-local ansi-color-apply-face-function #'shell-apply-ansi-color)
554 (shell-reapply-ansi-color)
555
556 ;; This is not really correct, since the shell buffer does not really
557 ;; edit this directory. But it is useful in the buffer list and menus.
558 (setq list-buffers-directory (expand-file-name default-directory))
559 ;; shell-dependent assignments.
560 (when (ring-empty-p comint-input-ring)
561 (let ((shell (file-name-nondirectory (car
562 (process-command (get-buffer-process (current-buffer))))))
563 (hsize (getenv "HISTSIZE")))
564 (and (stringp hsize)
565 (integerp (setq hsize (string-to-number hsize)))
566 (> hsize 0)
567 (set (make-local-variable 'comint-input-ring-size) hsize))
568 (setq comint-input-ring-file-name
569 (or (getenv "HISTFILE")
570 (cond ((string-equal shell "bash") "~/.bash_history")
571 ((string-equal shell "ksh") "~/.sh_history")
572 (t "~/.history"))))
573 (if (or (equal comint-input-ring-file-name "")
574 (equal (file-truename comint-input-ring-file-name)
575 (file-truename "/dev/null")))
576 (setq comint-input-ring-file-name nil))
577 ;; Arrange to write out the input ring on exit, if the shell doesn't
578 ;; do this itself.
579 (if (and comint-input-ring-file-name
580 (string-match shell-dumb-shell-regexp shell))
581 (set-process-sentinel (get-buffer-process (current-buffer))
582 #'shell-write-history-on-exit))
583 (setq shell-dirstack-query
584 (cond ((string-equal shell "sh") "pwd")
585 ((string-equal shell "ksh") "echo $PWD ~-")
586 (t "dirs")))
587 ;; Bypass a bug in certain versions of bash.
588 (when (string-equal shell "bash")
589 (add-hook 'comint-preoutput-filter-functions
590 'shell-filter-ctrl-a-ctrl-b nil t)))
591 (comint-read-input-ring t)))
592
593 (defun shell-apply-ansi-color (beg end face)
594 "Apply FACE as the ansi-color face for the text between BEG and END."
595 (when face
596 (put-text-property beg end 'ansi-color-face face)
597 (put-text-property beg end 'font-lock-face face)))
598
599 (defun shell-reapply-ansi-color ()
600 "Reapply ansi-color faces to the existing contents of the buffer."
601 (save-restriction
602 (widen)
603 (let* ((pos (point-min))
604 (end (or (next-single-property-change pos 'ansi-color-face)
605 (point-max)))
606 face)
607 (while end
608 (if (setq face (get-text-property pos 'ansi-color-face))
609 (put-text-property pos (or end (point-max))
610 'font-lock-face face))
611 (setq pos end
612 end (next-single-property-change pos 'ansi-color-face))))))
613
614 (defun shell-filter-ctrl-a-ctrl-b (string)
615 "Remove `^A' and `^B' characters from comint output.
616
617 Bash uses these characters as internal quoting characters in its
618 prompt. Due to a bug in some bash versions (including 2.03,
619 2.04, and 2.05b), they may erroneously show up when bash is
620 started with the `--noediting' option and Select Graphic
621 Rendition (SGR) control sequences (formerly known as ANSI escape
622 sequences) are used to color the prompt.
623
624 This function can be put on `comint-preoutput-filter-functions'."
625 (if (string-match "[\C-a\C-b]" string)
626 (replace-regexp-in-string "[\C-a\C-b]" "" string t t)
627 string))
628
629 (defun shell-write-history-on-exit (process event)
630 "Called when the shell process is stopped.
631
632 Writes the input history to a history file
633 `comint-input-ring-file-name' using `comint-write-input-ring'
634 and inserts a short message in the shell buffer.
635
636 This function is a sentinel watching the shell interpreter process.
637 Sentinels will always get the two parameters PROCESS and EVENT."
638 ;; Write history.
639 (comint-write-input-ring)
640 (let ((buf (process-buffer process)))
641 (when (buffer-live-p buf)
642 (with-current-buffer buf
643 (insert (format "\nProcess %s %s\n" process event))))))
644
645 ;;;###autoload
646 (defun shell (&optional buffer)
647 "Run an inferior shell, with I/O through BUFFER (which defaults to `*shell*').
648 Interactively, a prefix arg means to prompt for BUFFER.
649 If `default-directory' is a remote file name, it is also prompted
650 to change if called with a prefix arg.
651
652 If BUFFER exists but shell process is not running, make new shell.
653 If BUFFER exists and shell process is running, just switch to BUFFER.
654 Program used comes from variable `explicit-shell-file-name',
655 or (if that is nil) from the ESHELL environment variable,
656 or (if that is nil) from `shell-file-name'.
657 If a file `~/.emacs_SHELLNAME' exists, or `~/.emacs.d/init_SHELLNAME.sh',
658 it is given as initial input (but this may be lost, due to a timing
659 error, if the shell discards input when it starts up).
660 The buffer is put in Shell mode, giving commands for sending input
661 and controlling the subjobs of the shell. See `shell-mode'.
662 See also the variable `shell-prompt-pattern'.
663
664 To specify a coding system for converting non-ASCII characters
665 in the input and output to the shell, use \\[universal-coding-system-argument]
666 before \\[shell]. You can also specify this with \\[set-buffer-process-coding-system]
667 in the shell buffer, after you start the shell.
668 The default comes from `process-coding-system-alist' and
669 `default-process-coding-system'.
670
671 The shell file name (sans directories) is used to make a symbol name
672 such as `explicit-csh-args'. If that symbol is a variable,
673 its value is used as a list of arguments when invoking the shell.
674 Otherwise, one argument `-i' is passed to the shell.
675
676 \(Type \\[describe-mode] in the shell buffer for a list of commands.)"
677 (interactive
678 (list
679 (and current-prefix-arg
680 (prog1
681 (read-buffer "Shell buffer: "
682 ;; If the current buffer is an inactive
683 ;; shell buffer, use it as the default.
684 (if (and (eq major-mode 'shell-mode)
685 (null (get-buffer-process (current-buffer))))
686 (buffer-name)
687 (generate-new-buffer-name "*shell*")))
688 (if (file-remote-p default-directory)
689 ;; It must be possible to declare a local default-directory.
690 ;; FIXME: This can't be right: it changes the default-directory
691 ;; of the current-buffer rather than of the *shell* buffer.
692 (setq default-directory
693 (expand-file-name
694 (read-directory-name
695 "Default directory: " default-directory default-directory
696 t nil))))))))
697 (setq buffer (if (or buffer (not (derived-mode-p 'shell-mode))
698 (comint-check-proc (current-buffer)))
699 (get-buffer-create (or buffer "*shell*"))
700 ;; If the current buffer is a dead shell buffer, use it.
701 (current-buffer)))
702
703 ;; On remote hosts, the local `shell-file-name' might be useless.
704 (if (and (called-interactively-p 'any)
705 (file-remote-p default-directory)
706 (null explicit-shell-file-name)
707 (null (getenv "ESHELL")))
708 (with-current-buffer buffer
709 (set (make-local-variable 'explicit-shell-file-name)
710 (file-remote-p
711 (expand-file-name
712 (read-file-name
713 "Remote shell path: " default-directory shell-file-name
714 t shell-file-name))
715 'localname))))
716
717 ;; The buffer's window must be correctly set when we call comint (so
718 ;; that comint sets the COLUMNS env var properly).
719 (pop-to-buffer-same-window buffer)
720 (unless (comint-check-proc buffer)
721 (let* ((prog (or explicit-shell-file-name
722 (getenv "ESHELL") shell-file-name))
723 (name (file-name-nondirectory prog))
724 (startfile (concat "~/.emacs_" name))
725 (xargs-name (intern-soft (concat "explicit-" name "-args"))))
726 (unless (file-exists-p startfile)
727 (setq startfile (concat user-emacs-directory "init_" name ".sh")))
728 (apply 'make-comint-in-buffer "shell" buffer prog
729 (if (file-exists-p startfile) startfile)
730 (if (and xargs-name (boundp xargs-name))
731 (symbol-value xargs-name)
732 '("-i")))
733 (shell-mode)))
734 buffer)
735
736 ;;; Directory tracking
737 ;;
738 ;; This code provides the shell mode input sentinel
739 ;; SHELL-DIRECTORY-TRACKER
740 ;; that tracks cd, pushd, and popd commands issued to the shell, and
741 ;; changes the current directory of the shell buffer accordingly.
742 ;;
743 ;; This is basically a fragile hack, although it's more accurate than
744 ;; the version in Emacs 18's shell.el. It has the following failings:
745 ;; 1. It doesn't know about the cdpath shell variable.
746 ;; 2. It cannot infallibly deal with command sequences, though it does well
747 ;; with these and with ignoring commands forked in another shell with ()s.
748 ;; 3. More generally, any complex command is going to throw it. Otherwise,
749 ;; you'd have to build an entire shell interpreter in Emacs Lisp. Failing
750 ;; that, there's no way to catch shell commands where cd's are buried
751 ;; inside conditional expressions, aliases, and so forth.
752 ;;
753 ;; The whole approach is a crock. Shell aliases mess it up. File sourcing
754 ;; messes it up. You run other processes under the shell; these each have
755 ;; separate working directories, and some have commands for manipulating
756 ;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have
757 ;; commands that do *not* affect the current w.d. at all, but look like they
758 ;; do (e.g., the cd command in ftp). In shells that allow you job
759 ;; control, you can switch between jobs, all having different w.d.'s. So
760 ;; simply saying %3 can shift your w.d..
761 ;;
762 ;; The solution is to relax, not stress out about it, and settle for
763 ;; a hack that works pretty well in typical circumstances. Remember
764 ;; that a half-assed solution is more in keeping with the spirit of Unix,
765 ;; anyway. Blech.
766 ;;
767 ;; One good hack not implemented here for users of programmable shells
768 ;; is to program up the shell w.d. manipulation commands to output
769 ;; a coded command sequence to the tty. Something like
770 ;; ESC | <cwd> |
771 ;; where <cwd> is the new current working directory. Then trash the
772 ;; directory tracking machinery currently used in this package, and
773 ;; replace it with a process filter that watches for and strips out
774 ;; these messages.
775
776 (defun shell-directory-tracker (str)
777 "Tracks cd, pushd and popd commands issued to the shell.
778 This function is called on each input passed to the shell.
779 It watches for cd, pushd and popd commands and sets the buffer's
780 default directory to track these commands.
781
782 You may toggle this tracking on and off with \\[shell-dirtrack-mode].
783 If Emacs gets confused, you can resync with the shell with \\[dirs].
784 \(The `dirtrack' package provides an alternative implementation of this
785 feature - see the function `dirtrack-mode'.)
786
787 See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp',
788 and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract',
789 and `shell-pushd-dunique' control the behavior of the relevant command.
790
791 Environment variables are expanded, see function `substitute-in-file-name'."
792 (if shell-dirtrackp
793 ;; We fail gracefully if we think the command will fail in the shell.
794 (with-demoted-errors "Couldn't cd: %s"
795 (let ((start (progn (string-match
796 (concat "^" shell-command-separator-regexp)
797 str) ; skip whitespace
798 (match-end 0)))
799 (case-fold-search)
800 end cmd arg1)
801 (while (string-match shell-command-regexp str start)
802 (setq end (match-end 0)
803 cmd (comint-arguments (substring str start end) 0 0)
804 arg1 (comint-arguments (substring str start end) 1 1))
805 (if arg1
806 (setq arg1 (shell-unquote-argument arg1)))
807 (cond ((string-match (concat "\\`\\(" shell-popd-regexp
808 "\\)\\($\\|[ \t]\\)")
809 cmd)
810 (shell-process-popd (comint-substitute-in-file-name arg1)))
811 ((string-match (concat "\\`\\(" shell-pushd-regexp
812 "\\)\\($\\|[ \t]\\)")
813 cmd)
814 (shell-process-pushd (comint-substitute-in-file-name arg1)))
815 ((string-match (concat "\\`\\(" shell-cd-regexp
816 "\\)\\($\\|[ \t]\\)")
817 cmd)
818 (shell-process-cd (comint-substitute-in-file-name arg1)))
819 ((and shell-chdrive-regexp
820 (string-match (concat "\\`\\(" shell-chdrive-regexp
821 "\\)\\($\\|[ \t]\\)")
822 cmd))
823 (shell-process-cd (comint-substitute-in-file-name cmd))))
824 (setq start (progn (string-match shell-command-separator-regexp
825 str end)
826 ;; skip again
827 (match-end 0))))))))
828
829 (defun shell-unquote-argument (string)
830 "Remove all kinds of shell quoting from STRING."
831 (save-match-data
832 (let ((idx 0) next inside
833 (quote-chars
834 (if (string-match shell-dumb-shell-regexp
835 (file-name-nondirectory
836 (car (process-command (get-buffer-process (current-buffer))))))
837 "['`\"]"
838 "[\\'`\"]")))
839 (while (and (< idx (length string))
840 (setq next (string-match quote-chars string next)))
841 (cond ((= (aref string next) ?\\)
842 (setq string (replace-match "" nil nil string))
843 (setq next (1+ next)))
844 ((and inside (= (aref string next) inside))
845 (setq string (replace-match "" nil nil string))
846 (setq inside nil))
847 (inside
848 (setq next (1+ next)))
849 (t
850 (setq inside (aref string next))
851 (setq string (replace-match "" nil nil string)))))
852 string)))
853
854 ;; popd [+n]
855 (defun shell-process-popd (arg)
856 (let ((num (or (shell-extract-num arg) 0)))
857 (cond ((and num (= num 0) shell-dirstack)
858 (shell-cd (shell-prefixed-directory-name (car shell-dirstack)))
859 (setq shell-dirstack (cdr shell-dirstack))
860 (shell-dirstack-message))
861 ((and num (> num 0) (<= num (length shell-dirstack)))
862 (let* ((ds (cons nil shell-dirstack))
863 (cell (nthcdr (1- num) ds)))
864 (rplacd cell (cdr (cdr cell)))
865 (setq shell-dirstack (cdr ds))
866 (shell-dirstack-message)))
867 (t
868 (error "Couldn't popd")))))
869
870 ;; Return DIR prefixed with comint-file-name-prefix as appropriate.
871 (defun shell-prefixed-directory-name (dir)
872 (if (= (length comint-file-name-prefix) 0)
873 dir
874 (if (file-name-absolute-p dir)
875 ;; The name is absolute, so prepend the prefix.
876 (concat comint-file-name-prefix dir)
877 ;; For relative name we assume default-directory already has the prefix.
878 (expand-file-name dir))))
879
880 ;; cd [dir]
881 (defun shell-process-cd (arg)
882 (let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix
883 "~"))
884 ((string-equal "-" arg) shell-last-dir)
885 (t (shell-prefixed-directory-name arg)))))
886 (setq shell-last-dir default-directory)
887 (shell-cd new-dir)
888 (shell-dirstack-message)))
889
890 ;; pushd [+n | dir]
891 (defun shell-process-pushd (arg)
892 (let ((num (shell-extract-num arg)))
893 (cond ((zerop (length arg))
894 ;; no arg -- swap pwd and car of stack unless shell-pushd-tohome
895 (cond (shell-pushd-tohome
896 (shell-process-pushd (concat comint-file-name-prefix "~")))
897 (shell-dirstack
898 (let ((old default-directory))
899 (shell-cd (car shell-dirstack))
900 (setq shell-dirstack (cons old (cdr shell-dirstack)))
901 (shell-dirstack-message)))
902 (t
903 (message "Directory stack empty."))))
904 ((numberp num)
905 ;; pushd +n
906 (cond ((> num (length shell-dirstack))
907 (message "Directory stack not that deep."))
908 ((= num 0)
909 (error "Couldn't cd"))
910 (shell-pushd-dextract
911 (let ((dir (nth (1- num) shell-dirstack)))
912 (shell-process-popd arg)
913 (shell-process-pushd default-directory)
914 (shell-cd dir)
915 (shell-dirstack-message)))
916 (t
917 (let* ((ds (cons default-directory shell-dirstack))
918 (dslen (length ds))
919 (front (nthcdr num ds))
920 (back (reverse (nthcdr (- dslen num) (reverse ds))))
921 (new-ds (append front back)))
922 (shell-cd (car new-ds))
923 (setq shell-dirstack (cdr new-ds))
924 (shell-dirstack-message)))))
925 (t
926 ;; pushd <dir>
927 (let ((old-wd default-directory))
928 (shell-cd (shell-prefixed-directory-name arg))
929 (if (or (null shell-pushd-dunique)
930 (not (member old-wd shell-dirstack)))
931 (setq shell-dirstack (cons old-wd shell-dirstack)))
932 (shell-dirstack-message))))))
933
934 ;; If STR is of the form +n, for n>0, return n. Otherwise, nil.
935 (defun shell-extract-num (str)
936 (and (string-match "^\\+[1-9][0-9]*$" str)
937 (string-to-number str)))
938
939 (defvaralias 'shell-dirtrack-mode 'shell-dirtrackp)
940 (define-minor-mode shell-dirtrack-mode
941 "Toggle directory tracking in this shell buffer (Shell Dirtrack mode).
942 With a prefix argument ARG, enable Shell Dirtrack mode if ARG is
943 positive, and disable it otherwise. If called from Lisp, enable
944 the mode if ARG is omitted or nil.
945
946 The `dirtrack' package provides an alternative implementation of
947 this feature; see the function `dirtrack-mode'."
948 nil nil nil
949 (setq list-buffers-directory (if shell-dirtrack-mode default-directory))
950 (if shell-dirtrack-mode
951 (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
952 (remove-hook 'comint-input-filter-functions 'shell-directory-tracker t)))
953
954 (define-obsolete-function-alias 'shell-dirtrack-toggle 'shell-dirtrack-mode
955 "23.1")
956
957 (defun shell-cd (dir)
958 "Do normal `cd' to DIR, and set `list-buffers-directory'."
959 (cd dir)
960 (if shell-dirtrackp
961 (setq list-buffers-directory default-directory)))
962
963 (defun shell-resync-dirs ()
964 "Resync the buffer's idea of the current directory stack.
965 This command queries the shell with the command bound to
966 `shell-dirstack-query' (default \"dirs\"), reads the next
967 line output and parses it to form the new directory stack.
968 DON'T issue this command unless the buffer is at a shell prompt.
969 Also, note that if some other subprocess decides to do output
970 immediately after the query, its output will be taken as the
971 new directory stack -- you lose. If this happens, just do the
972 command again."
973 (interactive)
974 (let* ((proc (get-buffer-process (current-buffer)))
975 (pmark (process-mark proc))
976 (started-at-pmark (= (point) (marker-position pmark))))
977 (save-excursion
978 (goto-char pmark)
979 ;; If the process echoes commands, don't insert a fake command in
980 ;; the buffer or it will appear twice.
981 (unless comint-process-echoes
982 (insert shell-dirstack-query) (insert "\n"))
983 (sit-for 0) ; force redisplay
984 (comint-send-string proc shell-dirstack-query)
985 (comint-send-string proc "\n")
986 (set-marker pmark (point))
987 (let ((pt (point))
988 (regexp
989 (concat
990 (if comint-process-echoes
991 ;; Skip command echo if the process echoes
992 (concat "\\(" (regexp-quote shell-dirstack-query) "\n\\)")
993 "\\(\\)")
994 "\\(.+\n\\)")))
995 ;; This extra newline prevents the user's pending input from spoofing us.
996 (insert "\n") (backward-char 1)
997 ;; Wait for one line.
998 (while (not (looking-at regexp))
999 (accept-process-output proc)
1000 (goto-char pt)))
1001 (goto-char pmark) (delete-char 1) ; remove the extra newline
1002 ;; That's the dirlist. grab it & parse it.
1003 (let* ((dl (buffer-substring (match-beginning 2) (1- (match-end 2))))
1004 (dl-len (length dl))
1005 (ds '()) ; new dir stack
1006 (i 0))
1007 (while (< i dl-len)
1008 ;; regexp = optional whitespace, (non-whitespace), optional whitespace
1009 (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
1010 (setq ds (cons (concat comint-file-name-prefix
1011 (substring dl (match-beginning 1)
1012 (match-end 1)))
1013 ds))
1014 (setq i (match-end 0)))
1015 (let ((ds (nreverse ds)))
1016 (with-demoted-errors "Couldn't cd: %s"
1017 (shell-cd (car ds))
1018 (setq shell-dirstack (cdr ds)
1019 shell-last-dir (car shell-dirstack))
1020 (shell-dirstack-message)))))
1021 (if started-at-pmark (goto-char (marker-position pmark)))))
1022
1023 ;; For your typing convenience:
1024 (defalias 'dirs 'shell-resync-dirs)
1025
1026
1027 ;; Show the current dirstack on the message line.
1028 ;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo".
1029 ;; (This isn't necessary if the dirlisting is generated with a simple "dirs".)
1030 ;; All the commands that mung the buffer's dirstack finish by calling
1031 ;; this guy.
1032 (defun shell-dirstack-message ()
1033 (when shell-dirtrack-verbose
1034 (let* ((msg "")
1035 (ds (cons default-directory shell-dirstack))
1036 (home (expand-file-name (concat comint-file-name-prefix "~/")))
1037 (homelen (length home)))
1038 (while ds
1039 (let ((dir (car ds)))
1040 (and (>= (length dir) homelen)
1041 (string= home (substring dir 0 homelen))
1042 (setq dir (concat "~/" (substring dir homelen))))
1043 ;; Strip off comint-file-name-prefix if present.
1044 (and comint-file-name-prefix
1045 (>= (length dir) (length comint-file-name-prefix))
1046 (string= comint-file-name-prefix
1047 (substring dir 0 (length comint-file-name-prefix)))
1048 (setq dir (substring dir (length comint-file-name-prefix)))
1049 (setcar ds dir))
1050 (setq msg (concat msg (directory-file-name dir) " "))
1051 (setq ds (cdr ds))))
1052 (message "%s" msg))))
1053
1054 ;; This was mostly copied from shell-resync-dirs.
1055 (defun shell-snarf-envar (var)
1056 "Return as a string the shell's value of environment variable VAR."
1057 (let* ((cmd (format "printenv '%s'\n" var))
1058 (proc (get-buffer-process (current-buffer)))
1059 (pmark (process-mark proc)))
1060 (goto-char pmark)
1061 (insert cmd)
1062 (sit-for 0) ; force redisplay
1063 (comint-send-string proc cmd)
1064 (set-marker pmark (point))
1065 (let ((pt (point))) ; wait for 1 line
1066 ;; This extra newline prevents the user's pending input from spoofing us.
1067 (insert "\n") (backward-char 1)
1068 (while (not (looking-at ".+\n"))
1069 (accept-process-output proc)
1070 (goto-char pt)))
1071 (goto-char pmark) (delete-char 1) ; remove the extra newline
1072 (buffer-substring (match-beginning 0) (1- (match-end 0)))))
1073
1074 (defun shell-copy-environment-variable (variable)
1075 "Copy the environment variable VARIABLE from the subshell to Emacs.
1076 This command reads the value of the specified environment variable
1077 in the shell, and sets the same environment variable in Emacs
1078 \(what `getenv' in Emacs would return) to that value.
1079 That value will affect any new subprocesses that you subsequently start
1080 from Emacs."
1081 (interactive (list (read-envvar-name "\
1082 Copy Shell environment variable to Emacs: ")))
1083 (setenv variable (shell-snarf-envar variable)))
1084
1085 (defun shell-forward-command (&optional arg)
1086 "Move forward across ARG shell command(s). Does not cross lines.
1087 See `shell-command-regexp'."
1088 (interactive "p")
1089 (let ((limit (line-end-position)))
1090 (if (re-search-forward (concat shell-command-regexp "\\([;&|][\t ]*\\)+")
1091 limit 'move arg)
1092 (skip-syntax-backward " "))))
1093
1094
1095 (defun shell-backward-command (&optional arg)
1096 "Move backward across ARG shell command(s). Does not cross lines.
1097 See `shell-command-regexp'."
1098 (interactive "p")
1099 (let ((limit (save-excursion (comint-bol nil) (point))))
1100 (when (> limit (point))
1101 (setq limit (line-beginning-position)))
1102 (skip-syntax-backward " " limit)
1103 (if (re-search-backward
1104 (format "[;&|]+[\t ]*\\(%s\\)" shell-command-regexp) limit 'move arg)
1105 (progn (goto-char (match-beginning 1))
1106 (skip-chars-forward ";&|")))))
1107
1108 (defun shell-dynamic-complete-command ()
1109 "Dynamically complete the command at point.
1110 This function is similar to `comint-dynamic-complete-filename', except that it
1111 searches `exec-path' (minus trailing `exec-directory') for completion
1112 candidates. Note that this may not be the same as the shell's idea of the
1113 path.
1114
1115 Completion is dependent on the value of `shell-completion-execonly',
1116 `shell-completion-fignore', plus those that affect file completion. See Info
1117 node `Shell Options'.
1118
1119 Returns t if successful."
1120 (interactive)
1121 (let ((data (shell-command-completion)))
1122 (if data
1123 (prog2 (unless (window-minibuffer-p)
1124 (message "Completing command name..."))
1125 (apply #'completion-in-region data)))))
1126
1127 (defun shell-command-completion ()
1128 "Return the completion data for the command at point, if any."
1129 (let ((filename (comint-match-partial-filename)))
1130 (if (and filename
1131 (save-match-data (not (string-match "[~/]" filename)))
1132 (eq (match-beginning 0)
1133 (save-excursion (shell-backward-command 1) (point))))
1134 (shell--command-completion-data))))
1135
1136 (defun shell--command-completion-data ()
1137 "Return the completion data for the command at point."
1138 (let* ((filename (or (comint-match-partial-filename) ""))
1139 (start (if (zerop (length filename)) (point) (match-beginning 0)))
1140 (end (if (zerop (length filename)) (point) (match-end 0)))
1141 (filenondir (file-name-nondirectory filename))
1142 ; why cdr? see `shell-dynamic-complete-command'
1143 (path-dirs (append (cdr (reverse exec-path))
1144 (if (memq system-type '(windows-nt ms-dos)) '("."))))
1145 (cwd (file-name-as-directory (expand-file-name default-directory)))
1146 (ignored-extensions
1147 (and comint-completion-fignore
1148 (mapconcat (function (lambda (x) (concat (regexp-quote x) "\\'")))
1149 comint-completion-fignore "\\|")))
1150 (dir "") (comps-in-dir ())
1151 (file "") (abs-file-name "") (completions ()))
1152 ;; Go thru each dir in the search path, finding completions.
1153 (while path-dirs
1154 (setq dir (file-name-as-directory (comint-directory (or (car path-dirs) ".")))
1155 comps-in-dir (and (file-accessible-directory-p dir)
1156 (file-name-all-completions filenondir dir)))
1157 ;; Go thru each completion found, to see whether it should be used.
1158 (while comps-in-dir
1159 (setq file (car comps-in-dir)
1160 abs-file-name (concat dir file))
1161 (if (and (not (member file completions))
1162 (not (and ignored-extensions
1163 (string-match ignored-extensions file)))
1164 (or (string-equal dir cwd)
1165 (not (file-directory-p abs-file-name)))
1166 (or (null shell-completion-execonly)
1167 (file-executable-p abs-file-name)))
1168 (setq completions (cons file completions)))
1169 (setq comps-in-dir (cdr comps-in-dir)))
1170 (setq path-dirs (cdr path-dirs)))
1171 ;; OK, we've got a list of completions.
1172 (list
1173 start end
1174 (lambda (string pred action)
1175 (if (string-match "/" string)
1176 (completion-file-name-table string pred action)
1177 (complete-with-action action completions string pred)))
1178 :exit-function
1179 (lambda (_string finished)
1180 (when (memq finished '(sole finished))
1181 (if (looking-at " ")
1182 (goto-char (match-end 0))
1183 (insert " ")))))))
1184
1185 ;; (defun shell-dynamic-complete-as-command ()
1186 ;; "Dynamically complete at point as a command.
1187 ;; See `shell-dynamic-complete-filename'. Returns t if successful."
1188 ;; (apply #'completion-in-region shell--command-completion-data))
1189
1190 (defun shell-dynamic-complete-filename ()
1191 "Dynamically complete the filename at point.
1192 This completes only if point is at a suitable position for a
1193 filename argument."
1194 (interactive)
1195 (let ((data (shell-filename-completion)))
1196 (if data (apply #'completion-in-region data))))
1197
1198 (defun shell-filename-completion ()
1199 "Return the completion data for file name at point, if any."
1200 (let ((opoint (point))
1201 (beg (comint-line-beginning-position)))
1202 (when (save-excursion
1203 (goto-char (if (re-search-backward "[;|&]" beg t)
1204 (match-end 0)
1205 beg))
1206 (re-search-forward "[^ \t][ \t]" opoint t))
1207 (comint-filename-completion))))
1208
1209 (defun shell-match-partial-variable ()
1210 "Return the shell variable at point, or nil if none is found."
1211 (save-excursion
1212 (if (re-search-backward "[^A-Za-z0-9_{(]" nil 'move)
1213 (or (looking-at "\\$") (forward-char 1)))
1214 (if (or (eolp) (looking-at "[^A-Za-z0-9_{($]"))
1215 nil
1216 (looking-at "\\$?[{(]?[A-Za-z0-9_]*[})]?")
1217 (buffer-substring (match-beginning 0) (match-end 0)))))
1218
1219 (defun shell-dynamic-complete-environment-variable ()
1220 "Dynamically complete the environment variable at point.
1221 Completes if after a variable, i.e., if it starts with a \"$\".
1222
1223 This function is similar to `comint-dynamic-complete-filename', except that it
1224 searches `process-environment' for completion candidates. Note that this may
1225 not be the same as the interpreter's idea of variable names. The main problem
1226 with this type of completion is that `process-environment' is the environment
1227 which Emacs started with. Emacs does not track changes to the environment made
1228 by the interpreter. Perhaps it would be more accurate if this function was
1229 called `shell-dynamic-complete-process-environment-variable'.
1230
1231 Returns non-nil if successful."
1232 (interactive)
1233 (let ((data (shell-environment-variable-completion)))
1234 (if data
1235 (prog2 (unless (window-minibuffer-p)
1236 (message "Completing variable name..."))
1237 (apply #'completion-in-region data)))))
1238
1239
1240 (defun shell-environment-variable-completion ()
1241 "Completion data for an environment variable at point, if any."
1242 (let* ((var (shell-match-partial-variable))
1243 (end (match-end 0)))
1244 (when (and (not (zerop (length var))) (eq (aref var 0) ?$))
1245 (let* ((start
1246 (save-excursion
1247 (goto-char (match-beginning 0))
1248 (looking-at "\\$?[({]*")
1249 (match-end 0)))
1250 (variables (mapcar (lambda (x)
1251 (substring x 0 (string-match "=" x)))
1252 process-environment))
1253 (suffix (pcase (char-before start) (?\{ "}") (?\( ")") (_ ""))))
1254 (list start end variables
1255 :exit-function
1256 (lambda (s finished)
1257 (when (memq finished '(sole finished))
1258 (let ((suf (concat suffix
1259 (if (file-directory-p
1260 (comint-directory (getenv s)))
1261 "/"))))
1262 (if (looking-at (regexp-quote suf))
1263 (goto-char (match-end 0))
1264 (insert suf))))))))))
1265
1266
1267 (defun shell-c-a-p-replace-by-expanded-directory ()
1268 "Expand directory stack reference before point.
1269 For use on `completion-at-point-functions'."
1270 (when (comint-match-partial-filename)
1271 (save-excursion
1272 (goto-char (match-beginning 0))
1273 (let ((stack (cons default-directory shell-dirstack))
1274 (index (cond ((looking-at "=-/?")
1275 (length shell-dirstack))
1276 ((looking-at "=\\([0-9]+\\)/?")
1277 (string-to-number
1278 (buffer-substring
1279 (match-beginning 1) (match-end 1)))))))
1280 (when index
1281 (let ((start (match-beginning 0))
1282 (end (match-end 0))
1283 (replacement (file-name-as-directory (nth index stack))))
1284 (lambda ()
1285 (cond
1286 ((>= index (length stack))
1287 (error "Directory stack not that deep"))
1288 (t
1289 (save-excursion
1290 (goto-char start)
1291 (insert replacement)
1292 (delete-char (- end start)))
1293 (message "Directory item: %d" index)
1294 t)))))))))
1295
1296 (defun shell-replace-by-expanded-directory ()
1297 "Expand directory stack reference before point.
1298 Directory stack references are of the form \"=digit\" or \"=-\".
1299 See `default-directory' and `shell-dirstack'.
1300
1301 Returns t if successful."
1302 (interactive)
1303 (let ((f (shell-c-a-p-replace-by-expanded-directory)))
1304 (if f (funcall f))))
1305
1306 (provide 'shell)
1307
1308 ;;; shell.el ends here