;;; shell.el --- specialized comint.el for running the shell.
-;;; Copyright (C) 1988, 1993 Free Software Foundation, Inc.
+
+;; Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu>
-;; Adapted-by: Simon Marshall <s.marshall@dcs.hull.ac.uk>
+;; Maintainer: Simon Marshall <s.marshall@dcs.hull.ac.uk>
;; Keywords: processes
-;;; This file is part of GNU Emacs.
+;; This file is part of GNU Emacs.
-;;; 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.
+;; 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.
-;;; GNU Emacs is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;;; GNU General Public License for more details.
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
;;; Commentary:
;;; m-c-b shell-backward-command Backward a shell command
;;; dirs Resync the buffer's dir stack
;;; dirtrack-toggle Turn dir tracking on/off
+;;; shell-strip-ctrl-m Remove trailing ^Ms from output
;;;
;;; The shell mode hook is shell-mode-hook
;;; comint-prompt-regexp is initialised to shell-prompt-pattern, for backwards
This is a fine thing to set in your `.emacs' file.")
+(defvar shell-completion-fignore nil
+ "*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 (\"~\" \"#\" \"%\").
+
+This is a fine thing to set in your `.emacs' file.")
+
(defvar shell-delimiter-argument-list '(?\| ?& ?< ?> ?\( ?\) ?\;)
"List of characters to recognise as separate arguments.
This variable is used to initialize `comint-delimiter-argument-list' in the
(define-key shell-mode-map "\t" 'comint-dynamic-complete)
(define-key shell-mode-map "\M-?"
'comint-dynamic-list-filename-completions)
- ;; Undefine the general completion first.
- (define-key shell-mode-map [menu-bar completion complete] nil)
- (define-key shell-mode-map [menu-bar completion expand-directory]
- '("Expand Directory Reference" . shell-replace-by-expanded-directory))
- (define-key shell-mode-map [menu-bar completion complete-env-variable]
- '("Complete Env. Variable Name" .
- shell-dynamic-complete-environment-variable))
- (define-key shell-mode-map [menu-bar completion complete-command]
- '("Complete Command Name" . shell-dynamic-complete-command))
- ;; Redefine (requires a new key) so that it is at the top.
- (define-key shell-mode-map [menu-bar completion complete-shell]
- '("Complete Before Point" . comint-dynamic-complete))
- ))
+ (define-key-after (lookup-key shell-mode-map [menu-bar completion])
+ [complete-env-variable] '("Complete Env. Variable Name" .
+ shell-dynamic-complete-environment-variable)
+ 'complete-file)
+ (define-key-after (lookup-key shell-mode-map [menu-bar completion])
+ [expand-directory] '("Expand Directory Reference" .
+ shell-replace-by-expanded-directory)
+ 'complete-expand)))
(defvar shell-mode-hook '()
"*Hook for customising Shell mode.")
Return before end of process output copies the current line (except
for the prompt) to the end of the buffer and sends it.
M-x send-invisible reads a line of text without echoing it, and sends it to
- the shell. This is useful for entering passwords.
+ the shell. This is useful for entering passwords. Or, add the function
+ `comint-watch-for-password-prompt' to `comint-output-filter-functions'.
If you accidentally suspend your process, use \\[comint-continue-subjob]
to continue it.
\\{shell-mode-map}
Customization: Entry to this mode runs the hooks on `comint-mode-hook' and
`shell-mode-hook' (in that order). Before each input, the hooks on
-`comint-input-sentinel-functions' are run. After each shell output, the hooks
-on `comint-output-sentinel-functions' are run.
+`comint-input-filter-functions' are run. After each shell output, the hooks
+on `comint-output-filter-functions' are run.
Variables `shell-cd-regexp', `shell-pushd-regexp' and `shell-popd-regexp'
are used to match their respective commands, while `shell-pushd-tohome',
`shell-pushd-dextract' and `shell-pushd-dunique' control the behavior of the
relevant command.
-Variables `comint-completion-autolist', `comint-completion-addsuffix' and
-`comint-completion-recexact' control the behavior of file name, command name
-and variable name completion. Variable `shell-completion-execonly' controls
-the behavior of command name completion.
+Variables `comint-completion-autolist', `comint-completion-addsuffix',
+`comint-completion-recexact' and `comint-completion-fignore' control the
+behavior of file name, command name and variable name completion. Variable
+`shell-completion-execonly' controls the behavior of command name completion.
+Variable `shell-completion-fignore' is used to initialise the value of
+`comint-completion-fignore'.
Variables `comint-input-ring-file-name' and `comint-input-autoexpand' control
the initialisation of the input ring history, and history expansion.
-Variables `comint-output-sentinel-functions', a hook, and
-`comint-scroll-to-bottom-on-input',and `comint-scroll-to-bottom-on-output'
+Variables `comint-output-filter-functions', a hook, and
+`comint-scroll-to-bottom-on-input' and `comint-scroll-to-bottom-on-output'
control whether input and output cause the window to scroll to the end of the
buffer."
(interactive)
(setq mode-name "Shell")
(use-local-map shell-mode-map)
(setq comint-prompt-regexp shell-prompt-pattern)
+ (setq comint-completion-fignore shell-completion-fignore)
(setq comint-delimiter-argument-list shell-delimiter-argument-list)
(setq comint-dynamic-complete-functions shell-dynamic-complete-functions)
(make-local-variable 'paragraph-start)
(setq shell-last-dir nil)
(make-local-variable 'shell-dirtrackp)
(setq shell-dirtrackp t)
- (add-hook 'comint-output-sentinel-functions 'shell-directory-tracker)
+ (add-hook 'comint-input-filter-functions 'shell-directory-tracker)
(setq comint-input-autoexpand shell-input-autoexpand)
;; shell-dependent assignments.
(let ((shell (car (process-command (get-buffer-process (current-buffer))))))
(shell-process-cd (substitute-in-file-name arg1))))
(setq start (progn (string-match "[;\\s ]*" str end) ; skip again
(match-end 0)))))
- (error (message "Couldn't cd")))))
+ (error "Couldn't cd"))))
;;; popd [+n]
(defun shell-process-popd (arg)
(setq shell-dirstack (cdr ds))
(shell-dirstack-message)))
(t
- (error (message "Couldn't popd."))))))
+ (error "Couldn't popd")))))
;; Return DIR prefixed with comint-file-name-prefix as appropriate.
(defsubst shell-prefixed-directory-name (dir)
(defun shell-dynamic-complete-as-command ()
"Dynamically complete at point as a command.
See `shell-dynamic-complete-filename'. Returns t if successful."
- (let* ((completion-ignore-case nil)
- (success t)
- (filename (or (comint-match-partial-filename) ""))
+ (let* ((filename (or (comint-match-partial-filename) ""))
(pathnondir (file-name-nondirectory filename))
(paths (cdr (reverse exec-path)))
(cwd (file-name-as-directory (expand-file-name default-directory)))
(ignored-extensions
- (mapconcat (function (lambda (x) (concat (regexp-quote x) "$")))
- completion-ignored-extensions "\\|"))
+ (and comint-completion-fignore
+ (mapconcat (function (lambda (x) (concat (regexp-quote x) "$")))
+ comint-completion-fignore "\\|")))
(path "") (comps-in-path ()) (file "") (filepath "") (completions ()))
;; Go thru each path in the search path, finding completions.
(while paths
(setq file (car comps-in-path)
filepath (concat path file))
(if (and (not (member file completions))
- (not (string-match ignored-extensions file))
+ (not (and ignored-extensions
+ (string-match ignored-extensions file)))
(or (string-equal path cwd)
(not (file-directory-p filepath)))
(or (null shell-completion-execonly)
(setq comps-in-path (cdr comps-in-path)))
(setq paths (cdr paths)))
;; OK, we've got a list of completions.
- (cond ((null completions)
- (message "No completions of %s" filename)
- (setq success nil))
- ((= 1 (length completions)) ; Gotcha!
- (let ((completion (car completions)))
- (if (string-equal completion pathnondir)
- (message "Sole completion")
- (insert (substring (directory-file-name completion)
- (length pathnondir)))
- (message "Completed"))
- (if comint-completion-addsuffix
- (insert (if (file-directory-p completion) "/" " ")))))
- (t ; There's no unique completion.
- (let ((completion
- (try-completion pathnondir (mapcar (function (lambda (x)
- (list x)))
- completions))))
- ;; Insert the longest substring.
- (insert (substring (directory-file-name completion)
- (length pathnondir)))
- (cond ((and comint-completion-recexact comint-completion-addsuffix
- (string-equal pathnondir completion)
- (member completion completions))
- ;; It's not unique, but user wants shortest match.
- (insert (if (file-directory-p completion) "/" " "))
- (message "Completed shortest"))
- ((or comint-completion-autolist
- (string-equal pathnondir completion))
- ;; It's not unique, list possible completions.
- (comint-dynamic-list-completions completions))
- (t
- (message "Partially completed"))))))
- success))
+ (let ((success (let ((comint-completion-addsuffix nil))
+ (comint-dynamic-simple-complete pathnondir completions))))
+ (if (and (memq success '(sole shortest)) comint-completion-addsuffix
+ (not (file-directory-p (comint-match-partial-filename))))
+ (insert " "))
+ success)))
(defun shell-match-partial-variable ()
(interactive)
(if (comint-match-partial-filename)
(save-excursion
- (message "Expanding directory references...")
(goto-char (match-beginning 0))
(let ((stack (cons default-directory shell-dirstack))
(index (cond ((looking-at "=-/?")
(message "Directory item: %d" index)
t))))))
\f
+(defun shell-strip-ctrl-m (&optional string)
+ "Strip trailing `^M' characters from the current output group.
+
+This function could be in the list `comint-output-filter-functions' or bound to
+a key."
+ (interactive)
+ (let ((pmark (process-mark (get-buffer-process (current-buffer))))
+ (ctrl-m (concat (char-to-string 13) "$")))
+ (save-excursion
+ (goto-char
+ (if (interactive-p) comint-last-input-end comint-last-output-start))
+ (while (re-search-forward ctrl-m pmark t)
+ (replace-match "" t t)))))
+\f
(provide 'shell)
;;; shell.el ends here