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