;;; shell.el --- specialized comint.el for running the shell
-;; Copyright (C) 1988, 1993, 1994, 1995, 1996, 1997, 2000,
-;; 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1993, 1994, 1995, 1996, 1997, 2000, 2001,
+;; 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu>
;; Simon Marshall <simon@gnu.org>
-;; Maintainer: FSF
+;; Maintainer: FSF <emacs-devel@gnu.org>
;; Keywords: processes
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
-;; Please send me bug reports, bug fixes, and extensions, so that I can
-;; merge them into the master source.
-;; - Olin Shivers (shivers@cs.cmu.edu)
-;; - Simon Marshall (simon@gnu.org)
-
;; This file defines a shell-in-a-buffer package (shell mode) built on
;; top of comint mode. This is actually cmushell with things renamed
;; to replace its counterpart in Emacs 18. cmushell is more
;; m-c-f shell-forward-command Forward a shell command
;; m-c-b shell-backward-command Backward a shell command
;; dirs Resync the buffer's dir stack
-;; dirtrack-mode Turn dir tracking on/off
+;; shell-dirtrack-mode Turn dir tracking on/off
;; comint-strip-ctrl-m Remove trailing ^Ms from output
;;
;; The shell mode hook is shell-mode-hook
:group 'shell)
(defcustom shell-completion-fignore nil
- "*List of suffixes to be disregarded during file/command completion.
+ "List of suffixes to be disregarded during file/command completion.
This variable is used to initialize `comint-completion-fignore' in the shell
buffer. The default is nil, for compatibility with most shells.
Some people like (\"~\" \"#\" \"%\").
shell-dynamic-complete-environment-variable
shell-dynamic-complete-command
shell-replace-by-expanded-directory
+ shell-dynamic-complete-filename
comint-dynamic-complete-filename)
"List of functions called to perform completion.
This variable is used to initialize `comint-dynamic-complete-functions' in the
This is a fine thing to set in your `.emacs' file.")
(defcustom shell-command-regexp "[^;&|\n]+"
- "*Regexp to match a single command within a pipeline.
+ "Regexp to match a single command within a pipeline.
This is used for directory tracking and does not do a perfect job."
:type 'regexp
:group 'shell)
(defcustom shell-command-separator-regexp "[;&|\n \t]*"
- "*Regexp to match a single command within a pipeline.
+ "Regexp to match a single command within a pipeline.
This is used for directory tracking and does not do a perfect job."
:type 'regexp
:group 'shell)
(defcustom shell-completion-execonly t
- "*If non-nil, use executable files only for completion candidates.
+ "If non-nil, use executable files only for completion candidates.
This mirrors the optional behavior of tcsh.
Detecting executability of files may slow command completion considerably."
:group 'shell)
(defcustom shell-popd-regexp "popd"
- "*Regexp to match subshell commands equivalent to popd."
+ "Regexp to match subshell commands equivalent to popd."
:type 'regexp
:group 'shell-directories)
(defcustom shell-pushd-regexp "pushd"
- "*Regexp to match subshell commands equivalent to pushd."
+ "Regexp to match subshell commands equivalent to pushd."
:type 'regexp
:group 'shell-directories)
(defcustom shell-pushd-tohome nil
- "*If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd).
+ "If non-nil, make pushd with no arg behave as \"pushd ~\" (like cd).
This mirrors the optional behavior of tcsh."
:type 'boolean
:group 'shell-directories)
(defcustom shell-pushd-dextract nil
- "*If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
+ "If non-nil, make \"pushd +n\" pop the nth dir to the stack top.
This mirrors the optional behavior of tcsh."
:type 'boolean
:group 'shell-directories)
(defcustom shell-pushd-dunique nil
- "*If non-nil, make pushd only add unique directories to the stack.
+ "If non-nil, make pushd only add unique directories to the stack.
This mirrors the optional behavior of tcsh."
:type 'boolean
:group 'shell-directories)
(defcustom shell-cd-regexp "cd"
- "*Regexp to match subshell commands equivalent to cd."
+ "Regexp to match subshell commands equivalent to cd."
:type 'regexp
:group 'shell-directories)
; NetWare allows the five chars between upper and lower alphabetics.
"[]a-zA-Z^_`\\[\\\\]:"
nil)
- "*If non-nil, is regexp used to track drive changes."
+ "If non-nil, is regexp used to track drive changes."
:type '(choice regexp
(const nil))
:group 'shell-directories)
(defcustom shell-dirtrack-verbose t
- "*If non-nil, show the directory stack following directory change.
-This is effective only if directory tracking is enabled."
+ "If non-nil, show the directory stack following directory change.
+This is effective only if directory tracking is enabled.
+The `dirtrack' package provides an alternative implementation of this feature -
+see the function `dirtrack-mode'."
:type 'boolean
:group 'shell-directories)
(defcustom explicit-shell-file-name nil
- "*If non-nil, is file name to use for explicitly requested inferior shell."
+ "If non-nil, is file name to use for explicitly requested inferior shell."
:type '(choice (const :tag "None" nil) file)
:group 'shell)
+;; Note: There are no explicit references to the variable `explicit-csh-args'.
+;; It is used implicitly by M-x shell when the shell is `csh'.
(defcustom explicit-csh-args
(if (eq system-type 'hpux)
;; -T persuades HP's csh not to think it is smarter
;; than us about what terminal modes to use.
'("-i" "-T")
'("-i"))
- "*Args passed to inferior shell by M-x shell, if the shell is csh.
+ "Args passed to inferior shell by \\[shell], if the shell is csh.
Value is a list of strings, which may be nil."
:type '(repeat (string :tag "Argument"))
:group 'shell)
+;; Note: There are no explicit references to the variable `explicit-bash-args'.
+;; It is used implicitly by M-x shell when the interactive shell is `bash'.
(defcustom explicit-bash-args
- ;; Tell bash not to use readline, except for bash 1.x which doesn't grook --noediting.
- ;; Bash 1.x has -nolineediting, but process-send-eof cannot terminate bash if we use it.
(let* ((prog (or (and (boundp 'explicit-shell-file-name) explicit-shell-file-name)
(getenv "ESHELL") shell-file-name))
(name (file-name-nondirectory prog)))
+ ;; Tell bash not to use readline, except for bash 1.x which
+ ;; doesn't grook --noediting. Bash 1.x has -nolineediting, but
+ ;; process-send-eof cannot terminate bash if we use it.
(if (and (not purify-flag)
(equal name "bash")
(file-executable-p prog)
(string-match "bad option"
- (shell-command-to-string (concat prog " --noediting"))))
+ (shell-command-to-string
+ (concat (shell-quote-argument prog)
+ " --noediting"))))
'("-i")
'("--noediting" "-i")))
- "*Args passed to inferior shell by M-x shell, if the shell is bash.
+ "Args passed to inferior shell by \\[shell], if the shell is bash.
Value is a list of strings, which may be nil."
:type '(repeat (string :tag "Argument"))
:group 'shell)
(defcustom shell-input-autoexpand 'history
- "*If non-nil, expand input command history references on completion.
+ "If non-nil, expand input command history references on completion.
This mirrors the optional behavior of tcsh (its autoexpand and histlit).
If the value is `input', then the expansion is seen on input.
"Keep track of last directory for ksh `cd -' command.")
(defvar shell-dirstack-query nil
- "Command used by `shell-resync-dir' to query the shell.")
+ "Command used by `shell-resync-dirs' to query the shell.")
(defvar shell-mode-map nil)
(cond ((not shell-mode-map)
(put 'shell-mode 'mode-class 'special)
(define-derived-mode shell-mode comint-mode "Shell"
- "Major mode for interacting with an inferior shell.
+ "Major mode for interacting with an inferior shell.\\<shell-mode-map>
\\[comint-send-input] after the end of the process' output sends the text from
the end of process to the end of the current line.
\\[comint-send-input] before end of process output copies the current line minus the prompt to
by \\[list-buffers] or \\[mouse-buffer-menu] in the `File' field.
\\[dirs] queries the shell and resyncs Emacs' idea of what the current
directory stack is.
-\\[dirtrack-mode] turns directory tracking on and off.
+\\[shell-dirtrack-mode] turns directory tracking on and off.
+\(The `dirtrack' package provides an alternative implementation of this
+feature - see the function `dirtrack-mode'.)
\\{shell-mode-map}
Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
(setq comint-delimiter-argument-list shell-delimiter-argument-list)
(setq comint-file-name-chars shell-file-name-chars)
(setq comint-file-name-quote-list shell-file-name-quote-list)
- (setq comint-dynamic-complete-functions shell-dynamic-complete-functions)
+ (set (make-local-variable 'comint-dynamic-complete-functions)
+ shell-dynamic-complete-functions)
(set (make-local-variable 'paragraph-separate) "\\'")
(make-local-variable 'paragraph-start)
(setq paragraph-start comint-prompt-regexp)
(setq shell-dirstack nil)
(make-local-variable 'shell-last-dir)
(setq shell-last-dir nil)
- (make-local-variable 'shell-dirtrackp)
- (setq shell-dirtrackp t)
- (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
(setq comint-input-autoexpand shell-input-autoexpand)
;; This is not really correct, since the shell buffer does not really
;; edit this directory. But it is useful in the buffer list and menus.
(make-local-variable 'list-buffers-directory)
+ (shell-dirtrack-mode 1)
(setq list-buffers-directory (expand-file-name default-directory))
;; shell-dependent assignments.
(when (ring-empty-p comint-input-ring)
The argument STRING is ignored."
(let ((pmark (process-mark (get-buffer-process (current-buffer)))))
(save-excursion
- (goto-char (or comint-last-output-start (point-min)))
+ (goto-char (or (and (markerp comint-last-output-start)
+ (marker-position comint-last-output-start))
+ (point-min)))
(while (re-search-forward "[\C-a\C-b]" pmark t)
(replace-match "")))))
(defun shell (&optional buffer)
"Run an inferior shell, with I/O through BUFFER (which defaults to `*shell*').
Interactively, a prefix arg means to prompt for BUFFER.
+If `default-directory' is a remote file name, it is also prompted
+to change if called with a prefix arg.
+
If BUFFER exists but shell process is not running, make new shell.
If BUFFER exists and shell process is running, just switch to BUFFER.
Program used comes from variable `explicit-shell-file-name',
or (if that is nil) from the ESHELL environment variable,
- or else from SHELL if there is no ESHELL.
-If a file `~/.emacs_SHELLNAME' exists, it is given as initial input
- (Note that this may lose due to a timing error if the shell
- discards input when it starts up.)
+ or (if that is nil) from `shell-file-name'.
+If a file `~/.emacs_SHELLNAME' exists, or `~/.emacs.d/init_SHELLNAME.sh',
+it is given as initial input (but this may be lost, due to a timing
+error, if the shell discards input when it starts up).
The buffer is put in Shell mode, giving commands for sending input
and controlling the subjobs of the shell. See `shell-mode'.
See also the variable `shell-prompt-pattern'.
(interactive
(list
(and current-prefix-arg
- (read-buffer "Shell buffer: "
- (generate-new-buffer-name "*shell*")))))
+ (prog1
+ (read-buffer "Shell buffer: "
+ (generate-new-buffer-name "*shell*"))
+ (if (file-remote-p default-directory)
+ ;; It must be possible to declare a local default-directory.
+ (setq default-directory
+ (expand-file-name
+ (read-file-name
+ "Default directory: " default-directory default-directory
+ t nil 'file-directory-p))))))))
(setq buffer (get-buffer-create (or buffer "*shell*")))
;; Pop to buffer, so that the buffer's window will be correctly set
;; when we call comint (so that comint sets the COLUMNS env var properly).
(name (file-name-nondirectory prog))
(startfile (concat "~/.emacs_" name))
(xargs-name (intern-soft (concat "explicit-" name "-args"))))
- (if (not (file-exists-p startfile))
- (setq startfile (concat "~/.emacs.d/.emacs_" name)))
+ (unless (file-exists-p startfile)
+ (setq startfile (concat user-emacs-directory "init_" name ".sh")))
(apply 'make-comint-in-buffer "shell" buffer prog
(if (file-exists-p startfile) startfile)
(if (and xargs-name (boundp xargs-name))
(shell-mode)))
buffer)
-;;; Don't do this when shell.el is loaded, only while dumping.
+;; Don't do this when shell.el is loaded, only while dumping.
;;;###autoload (add-hook 'same-window-buffer-names "*shell*")
;;; Directory tracking
-;;;
-;;; This code provides the shell mode input sentinel
-;;; SHELL-DIRECTORY-TRACKER
-;;; that tracks cd, pushd, and popd commands issued to the shell, and
-;;; changes the current directory of the shell buffer accordingly.
-;;;
-;;; This is basically a fragile hack, although it's more accurate than
-;;; the version in Emacs 18's shell.el. It has the following failings:
-;;; 1. It doesn't know about the cdpath shell variable.
-;;; 2. It cannot infallibly deal with command sequences, though it does well
-;;; with these and with ignoring commands forked in another shell with ()s.
-;;; 3. More generally, any complex command is going to throw it. Otherwise,
-;;; you'd have to build an entire shell interpreter in emacs lisp. Failing
-;;; that, there's no way to catch shell commands where cd's are buried
-;;; inside conditional expressions, aliases, and so forth.
-;;;
-;;; The whole approach is a crock. Shell aliases mess it up. File sourcing
-;;; messes it up. You run other processes under the shell; these each have
-;;; separate working directories, and some have commands for manipulating
-;;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have
-;;; commands that do *not* affect the current w.d. at all, but look like they
-;;; do (e.g., the cd command in ftp). In shells that allow you job
-;;; control, you can switch between jobs, all having different w.d.'s. So
-;;; simply saying %3 can shift your w.d..
-;;;
-;;; The solution is to relax, not stress out about it, and settle for
-;;; a hack that works pretty well in typical circumstances. Remember
-;;; that a half-assed solution is more in keeping with the spirit of Unix,
-;;; anyway. Blech.
-;;;
-;;; One good hack not implemented here for users of programmable shells
-;;; is to program up the shell w.d. manipulation commands to output
-;;; a coded command sequence to the tty. Something like
-;;; ESC | <cwd> |
-;;; where <cwd> is the new current working directory. Then trash the
-;;; directory tracking machinery currently used in this package, and
-;;; replace it with a process filter that watches for and strips out
-;;; these messages.
+;;
+;; This code provides the shell mode input sentinel
+;; SHELL-DIRECTORY-TRACKER
+;; that tracks cd, pushd, and popd commands issued to the shell, and
+;; changes the current directory of the shell buffer accordingly.
+;;
+;; This is basically a fragile hack, although it's more accurate than
+;; the version in Emacs 18's shell.el. It has the following failings:
+;; 1. It doesn't know about the cdpath shell variable.
+;; 2. It cannot infallibly deal with command sequences, though it does well
+;; with these and with ignoring commands forked in another shell with ()s.
+;; 3. More generally, any complex command is going to throw it. Otherwise,
+;; you'd have to build an entire shell interpreter in Emacs Lisp. Failing
+;; that, there's no way to catch shell commands where cd's are buried
+;; inside conditional expressions, aliases, and so forth.
+;;
+;; The whole approach is a crock. Shell aliases mess it up. File sourcing
+;; messes it up. You run other processes under the shell; these each have
+;; separate working directories, and some have commands for manipulating
+;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have
+;; commands that do *not* affect the current w.d. at all, but look like they
+;; do (e.g., the cd command in ftp). In shells that allow you job
+;; control, you can switch between jobs, all having different w.d.'s. So
+;; simply saying %3 can shift your w.d..
+;;
+;; The solution is to relax, not stress out about it, and settle for
+;; a hack that works pretty well in typical circumstances. Remember
+;; that a half-assed solution is more in keeping with the spirit of Unix,
+;; anyway. Blech.
+;;
+;; One good hack not implemented here for users of programmable shells
+;; is to program up the shell w.d. manipulation commands to output
+;; a coded command sequence to the tty. Something like
+;; ESC | <cwd> |
+;; where <cwd> is the new current working directory. Then trash the
+;; directory tracking machinery currently used in this package, and
+;; replace it with a process filter that watches for and strips out
+;; these messages.
(defun shell-directory-tracker (str)
"Tracks cd, pushd and popd commands issued to the shell.
It watches for cd, pushd and popd commands and sets the buffer's
default directory to track these commands.
-You may toggle this tracking on and off with M-x dirtrack-mode.
-If emacs gets confused, you can resync with the shell with M-x dirs.
+You may toggle this tracking on and off with \\[shell-dirtrack-mode].
+If Emacs gets confused, you can resync with the shell with \\[dirs].
+\(The `dirtrack' package provides an alternative implementation of this
+feature - see the function `dirtrack-mode'.)
See variables `shell-cd-regexp', `shell-chdrive-regexp', `shell-pushd-regexp',
and `shell-popd-regexp', while `shell-pushd-tohome', `shell-pushd-dextract',
(setq string (replace-match "" nil nil string)))))
string)))
-;;; popd [+n]
+;; popd [+n]
(defun shell-process-popd (arg)
(let ((num (or (shell-extract-num arg) 0)))
(cond ((and num (= num 0) shell-dirstack)
;; For relative name we assume default-directory already has the prefix.
(expand-file-name dir))))
-;;; cd [dir]
+;; cd [dir]
(defun shell-process-cd (arg)
(let ((new-dir (cond ((zerop (length arg)) (concat comint-file-name-prefix
"~"))
(shell-cd new-dir)
(shell-dirstack-message)))
-;;; pushd [+n | dir]
+;; pushd [+n | dir]
(defun shell-process-pushd (arg)
(let ((num (shell-extract-num arg)))
(cond ((zerop (length arg))
(and (string-match "^\\+[1-9][0-9]*$" str)
(string-to-number str)))
+(defvaralias 'shell-dirtrack-mode 'shell-dirtrackp)
+(define-minor-mode shell-dirtrack-mode
+ "Turn directory tracking on and off in a shell buffer.
+The `dirtrack' package provides an alternative implementation of this
+feature - see the function `dirtrack-mode'."
+ nil nil nil
+ (setq list-buffers-directory (if shell-dirtrack-mode default-directory))
+ (if shell-dirtrack-mode
+ (add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t)
+ (remove-hook 'comint-input-filter-functions 'shell-directory-tracker t)))
-(defun shell-dirtrack-mode ()
- "Turn directory tracking on and off in a shell buffer."
- (interactive)
- (if (setq shell-dirtrackp (not shell-dirtrackp))
- (setq list-buffers-directory default-directory)
- (setq list-buffers-directory nil))
- (message "Directory tracking %s" (if shell-dirtrackp "ON" "OFF")))
-
-;;; For your typing convenience:
-(defalias 'shell-dirtrack-toggle 'shell-dirtrack-mode)
-(defalias 'dirtrack-toggle 'shell-dirtrack-mode)
-(defalias 'dirtrack-mode 'shell-dirtrack-mode)
+(define-obsolete-function-alias 'shell-dirtrack-toggle 'shell-dirtrack-mode
+ "23.1")
(defun shell-cd (dir)
"Do normal `cd' to DIR, and set `list-buffers-directory'."
+ (cd dir)
(if shell-dirtrackp
- (setq list-buffers-directory (file-name-as-directory
- (expand-file-name dir))))
- (cd dir))
+ (setq list-buffers-directory default-directory)))
(defun shell-resync-dirs ()
"Resync the buffer's idea of the current directory stack.
command again."
(interactive)
(let* ((proc (get-buffer-process (current-buffer)))
- (pmark (process-mark proc)))
- (goto-char pmark)
- ;; If the process echoes commands, don't insert a fake command in
- ;; the buffer or it will appear twice.
- (unless comint-process-echoes
- (insert shell-dirstack-query) (insert "\n"))
- (sit-for 0) ; force redisplay
- (comint-send-string proc shell-dirstack-query)
- (comint-send-string proc "\n")
- (set-marker pmark (point))
- (let ((pt (point))
- (regexp
- (concat
- (if comint-process-echoes
- ;; Skip command echo if the process echoes
- (concat "\\(" (regexp-quote shell-dirstack-query) "\n\\)")
- "\\(\\)")
- "\\(.+\n\\)")))
- ;; This extra newline prevents the user's pending input from spoofing us.
- (insert "\n") (backward-char 1)
- ;; Wait for one line.
- (while (not (looking-at regexp))
- (accept-process-output proc)
- (goto-char pt)))
- (goto-char pmark) (delete-char 1) ; remove the extra newline
- ;; That's the dirlist. grab it & parse it.
- (let* ((dl (buffer-substring (match-beginning 2) (1- (match-end 2))))
- (dl-len (length dl))
- (ds '()) ; new dir stack
- (i 0))
- (while (< i dl-len)
- ;; regexp = optional whitespace, (non-whitespace), optional whitespace
- (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
- (setq ds (cons (concat comint-file-name-prefix
- (substring dl (match-beginning 1)
- (match-end 1)))
- ds))
- (setq i (match-end 0)))
- (let ((ds (nreverse ds)))
- (condition-case nil
- (progn (shell-cd (car ds))
- (setq shell-dirstack (cdr ds)
- shell-last-dir (car shell-dirstack))
- (shell-dirstack-message))
- (error (message "Couldn't cd")))))))
-
-;;; For your typing convenience:
+ (pmark (process-mark proc))
+ (started-at-pmark (= (point) (marker-position pmark))))
+ (save-excursion
+ (goto-char pmark)
+ ;; If the process echoes commands, don't insert a fake command in
+ ;; the buffer or it will appear twice.
+ (unless comint-process-echoes
+ (insert shell-dirstack-query) (insert "\n"))
+ (sit-for 0) ; force redisplay
+ (comint-send-string proc shell-dirstack-query)
+ (comint-send-string proc "\n")
+ (set-marker pmark (point))
+ (let ((pt (point))
+ (regexp
+ (concat
+ (if comint-process-echoes
+ ;; Skip command echo if the process echoes
+ (concat "\\(" (regexp-quote shell-dirstack-query) "\n\\)")
+ "\\(\\)")
+ "\\(.+\n\\)")))
+ ;; This extra newline prevents the user's pending input from spoofing us.
+ (insert "\n") (backward-char 1)
+ ;; Wait for one line.
+ (while (not (looking-at regexp))
+ (accept-process-output proc)
+ (goto-char pt)))
+ (goto-char pmark) (delete-char 1) ; remove the extra newline
+ ;; That's the dirlist. grab it & parse it.
+ (let* ((dl (buffer-substring (match-beginning 2) (1- (match-end 2))))
+ (dl-len (length dl))
+ (ds '()) ; new dir stack
+ (i 0))
+ (while (< i dl-len)
+ ;; regexp = optional whitespace, (non-whitespace), optional whitespace
+ (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
+ (setq ds (cons (concat comint-file-name-prefix
+ (substring dl (match-beginning 1)
+ (match-end 1)))
+ ds))
+ (setq i (match-end 0)))
+ (let ((ds (nreverse ds)))
+ (condition-case nil
+ (progn (shell-cd (car ds))
+ (setq shell-dirstack (cdr ds)
+ shell-last-dir (car shell-dirstack))
+ (shell-dirstack-message))
+ (error (message "Couldn't cd"))))))
+ (if started-at-pmark (goto-char (marker-position pmark)))))
+
+;; For your typing convenience:
(defalias 'dirs 'shell-resync-dirs)
-;;; Show the current dirstack on the message line.
-;;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo".
-;;; (This isn't necessary if the dirlisting is generated with a simple "dirs".)
-;;; All the commands that mung the buffer's dirstack finish by calling
-;;; this guy.
+;; Show the current dirstack on the message line.
+;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo".
+;; (This isn't necessary if the dirlisting is generated with a simple "dirs".)
+;; All the commands that mung the buffer's dirstack finish by calling
+;; this guy.
(defun shell-dirstack-message ()
(when shell-dirtrack-verbose
(let* ((msg "")
(defun shell-dynamic-complete-command ()
"Dynamically complete the command at point.
This function is similar to `comint-dynamic-complete-filename', except that it
-searches `exec-path' (minus the trailing emacs library path) for completion
+searches `exec-path' (minus the trailing Emacs library path) for completion
candidates. Note that this may not be the same as the shell's idea of the
path.
(save-match-data (not (string-match "[~/]" filename)))
(eq (match-beginning 0)
(save-excursion (shell-backward-command 1) (point))))
- (prog2 (message "Completing command name...")
+ (prog2 (unless (window-minibuffer-p (selected-window))
+ (message "Completing command name..."))
(shell-dynamic-complete-as-command)))))
(insert " "))
success)))
+(defun shell-dynamic-complete-filename ()
+ "Dynamically complete the filename at point.
+This completes only if point is at a suitable position for a
+filename argument."
+ (interactive)
+ (let ((opoint (point))
+ (beg (comint-line-beginning-position)))
+ (when (save-excursion
+ (goto-char (if (re-search-backward "[;|&]" beg t)
+ (match-end 0)
+ beg))
+ (re-search-forward "[^ \t][ \t]" opoint t))
+ (comint-dynamic-complete-as-filename))))
(defun shell-match-partial-variable ()
"Return the shell variable at point, or nil if none is found."
(re-search-forward "\\$?{?[A-Za-z0-9_]*}?" limit)
(buffer-substring (match-beginning 0) (match-end 0))))))
-
(defun shell-dynamic-complete-environment-variable ()
"Dynamically complete the environment variable at point.
Completes if after a variable, i.e., if it starts with a \"$\".
(interactive)
(let ((variable (shell-match-partial-variable)))
(if (and variable (string-match "^\\$" variable))
- (prog2 (message "Completing variable name...")
+ (prog2 (unless (window-minibuffer-p (selected-window))
+ (message "Completing variable name..."))
(shell-dynamic-complete-as-environment-variable)))))
(provide 'shell)
-;;; arch-tag: bcb5f12a-c1f4-4aea-a809-2504bd5bd797
+;; arch-tag: bcb5f12a-c1f4-4aea-a809-2504bd5bd797
;;; shell.el ends here