]> code.delx.au - gnu-emacs/blobdiff - lisp/shell.el
(mouse-set-font): Don't error if no selection.
[gnu-emacs] / lisp / shell.el
index 3a6a9c0381892136bd474ba3a27273806efc4e5e..2cc0e5481ef98c2d4127f9f56be99bac70fd987c 100644 (file)
@@ -1,25 +1,26 @@
 ;;; 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:
 
@@ -93,6 +94,7 @@
 ;;; 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
@@ -153,6 +155,14 @@ on lines which don't start with a prompt.
 
 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
@@ -249,19 +259,14 @@ Thus, this does not include the shell's current directory.")
        (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.")
@@ -278,7 +283,8 @@ Return after the end of the process' output sends the text from the
 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.
@@ -292,24 +298,26 @@ M-x dirtrack-toggle turns directory tracking on and off.
 \\{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)
@@ -318,6 +326,7 @@ buffer."
   (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)
@@ -327,7 +336,7 @@ buffer."
   (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))))))
@@ -450,7 +459,7 @@ Environment variables are expanded, see function `substitute-in-file-name'."
                     (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)
@@ -466,7 +475,7 @@ Environment variables are expanded, see function `substitute-in-file-name'."
             (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)
@@ -670,15 +679,14 @@ Returns t if successful."
 (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
@@ -690,7 +698,8 @@ See `shell-dynamic-complete-filename'.  Returns t if successful."
        (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)
@@ -699,39 +708,12 @@ See `shell-dynamic-complete-filename'.  Returns t if successful."
        (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 ()
@@ -803,7 +785,6 @@ Returns t if successful."
   (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 "=-/?")
@@ -821,6 +802,20 @@ Returns t if successful."
                 (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