]> code.delx.au - gnu-emacs/blobdiff - lisp/comint.el
Initial revision
[gnu-emacs] / lisp / comint.el
index 8b18dedd30cf3aa8259c5c109eec12f6d73b654e..3da9fd1d8a972e205c5a97e014b3014b0e2a4a3d 100644 (file)
@@ -1,6 +1,6 @@
 ;;; comint.el --- general command interpreter in a window stuff
 
-;; Copyright (C) 1988, 90, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 90, 92, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu> then
 ;;     Simon Marshall <simon@gnu.ai.mit.edu>
@@ -657,7 +657,7 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
        (default-directory
          (if (file-accessible-directory-p default-directory)
              default-directory
-           "/")))
+           (char-to-string directory-sep-char))))
     (apply 'start-process name buffer command switches)))
 \f
 ;; Input history processing in a buffer
@@ -935,7 +935,7 @@ If N is negative, search backwards for the -Nth previous match."
   (comint-previous-matching-input-from-input (- arg)))
 
 
-(defun comint-replace-by-expanded-history (&optional silent)
+(defun comint-replace-by-expanded-history (&optional silent start)
   "Expand input command history references before point.
 Expansion is dependent on the value of `comint-input-autoexpand'.
 
@@ -949,6 +949,10 @@ it cannot expand absolute input line number references.
 If the optional argument SILENT is non-nil, never complain
 even if history reference seems erroneous.
 
+If the optional argument START is non-nil, that specifies the
+start of the text to scan for history references, rather
+than the logical beginning of line.
+
 See `comint-magic-space' and `comint-replace-by-expanded-history-before-point'.
 
 Returns t if successful."
@@ -959,17 +963,20 @@ Returns t if successful."
                           (looking-at comint-prompt-regexp)))
       ;; Looks like there might be history references in the command.
       (let ((previous-modified-tick (buffer-modified-tick)))
-       (message "Expanding history references...")
-       (comint-replace-by-expanded-history-before-point silent)
+       (comint-replace-by-expanded-history-before-point silent start)
        (/= previous-modified-tick (buffer-modified-tick)))))
 
 
-(defun comint-replace-by-expanded-history-before-point (silent)
+(defun comint-replace-by-expanded-history-before-point (silent &optional start)
   "Expand directory stack reference before point.
-See `comint-replace-by-expanded-history'.  Returns t if successful."
+See `comint-replace-by-expanded-history'.  Returns t if successful.
+
+If the optional argument START is non-nil, that specifies the
+start of the text to scan for history references, rather
+than the logical beginning of line."
   (save-excursion
     (let ((toend (- (save-excursion (end-of-line nil) (point)) (point)))
-         (start (progn (comint-bol nil) (point))))
+         (start (or start (progn (comint-bol nil) (point)))))
       (while (progn
               (skip-chars-forward "^!^"
                                   (save-excursion
@@ -1051,7 +1058,7 @@ See `comint-replace-by-expanded-history'.  Returns t if successful."
                   (replace-match new t t)
                   (message "History item: substituted"))))
              (t
-              (goto-char (match-end 0))))))))
+              (forward-char 1)))))))
 
 
 (defun comint-magic-space (arg)
@@ -1126,7 +1133,15 @@ We assume whitespace separates arguments, except within quotes.
 Also, a run of one or more of a single character
 in `comint-delimiter-argument-list' is a separate argument.
 Argument 0 is the command name."
-  (let ((argpart "[^ \n\t\"'`]+\\|\\(\"[^\"]*\"\\|'[^']*'\\|`[^`]*`\\)")
+  ;; The first line handles ordinary characters and backslash-sequences.
+  ;; The second matches "-quoted strings.
+  ;; The third matches '-quoted strings.
+  ;; The fourth matches `-quoted strings.
+  ;; This seems to fit the syntax of BASH 2.0.
+  (let ((argpart "[^ \n\t\"'`\\]+\\|\\\\[\"'`\\]+\\|\
+\\(\"\\([^\"\\]\\|\\\\.\\)*\"\\|\
+'[^']*'\\|\
+`[^`]*`\\)") 
        (args ()) (pos 0)
        (count 0)
        beg str value quotes)
@@ -1215,14 +1230,14 @@ Similarly for Soar, Scheme, etc."
                          ;; Just whatever's already there
                          intxt
                        ;; Expand and leave it visible in buffer
-                       (comint-replace-by-expanded-history t)
+                       (comint-replace-by-expanded-history t pmark)
                        (buffer-substring pmark (point))))
               (history (if (not (eq comint-input-autoexpand 'history))
                            input
                          ;; This is messy 'cos ultimately the original
                          ;; functions used do insertion, rather than return
                          ;; strings.  We have to expand, then insert back.
-                         (comint-replace-by-expanded-history t)
+                         (comint-replace-by-expanded-history t pmark)
                          (let ((copy (buffer-substring pmark (point)))
                                (start (point)))
                            (insert input)
@@ -1252,7 +1267,7 @@ Similarly for Soar, Scheme, etc."
          (run-hook-with-args 'comint-output-filter-functions "")))))
 
 (defvar comint-preoutput-filter-functions nil 
-  "Functions to call after output is inserted into the buffer.
+  "Functions to call before output is inserted into the buffer.
 These functions get one argument, a string containing the text to be
 inserted.  They return the string as it should be inserted.
 
@@ -1578,27 +1593,40 @@ Sets mark to the value of point when this command is run."
     (comint-skip-prompt)))
 
 (defun comint-interrupt-subjob ()
-  "Interrupt the current subjob."
+  "Interrupt the current subjob.
+This command also kills the pending input
+between the process-mark and point."
   (interactive)
+  (comint-kill-input)
   (interrupt-process nil comint-ptyp))
 
 (defun comint-kill-subjob ()
-  "Send kill signal to the current subjob."
+  "Send kill signal to the current subjob.
+This command also kills the pending input
+between the process-mark and point."
   (interactive)
+  (comint-kill-input)
   (kill-process nil comint-ptyp))
 
 (defun comint-quit-subjob ()
-  "Send quit signal to the current subjob."
+  "Send quit signal to the current subjob.
+This command also kills the pending input
+between the process-mark and point."
   (interactive)
+  (comint-kill-input)
   (quit-process nil comint-ptyp))
 
 (defun comint-stop-subjob ()
   "Stop the current subjob.
+This command also kills the pending input
+between the process-mark and point.
+
 WARNING: if there is no current subjob, you can end up suspending
 the top-level process running in the buffer. If you accidentally do
 this, use \\[comint-continue-subjob] to resume the process. (This
 is not a problem with most shells, since they ignore this signal.)"
   (interactive)
+  (comint-kill-input)
   (stop-process nil comint-ptyp))
 
 (defun comint-continue-subjob ()
@@ -1852,13 +1880,13 @@ See `comint-prompt-regexp'."
       ;; Try to position the proc window so you can see the answer.
       ;; This is bogus code. If you delete the (sit-for 0), it breaks.
       ;; I don't know why. Wizards invited to improve it.
-      (if (not (pos-visible-in-window-p proc-pt proc-win))
-         (let ((opoint (window-point proc-win)))
-           (set-window-point proc-win proc-mark)
-           (sit-for 0)
-           (if (not (pos-visible-in-window-p opoint proc-win))
-               (push-mark opoint)
-             (set-window-point proc-win opoint)))))))
+      (unless (pos-visible-in-window-p proc-pt proc-win)
+       (let ((opoint (window-point proc-win)))
+         (set-window-point proc-win proc-mark)
+         (sit-for 0)
+         (if (not (pos-visible-in-window-p opoint proc-win))
+             (push-mark opoint)
+           (set-window-point proc-win opoint)))))))
 
 \f
 ;; Filename/command/history completion in a buffer
@@ -1919,13 +1947,9 @@ This is used by comint's and shell's completion functions, and by shell's
 directory tracking functions.")
 
 (defvar comint-file-name-chars
-  (cond
-   ((eq system-type 'ms-dos)
-    "~/A-Za-z0-9_^$!#%&{}@`'.()-")
-   ((eq system-type 'windows-nt)
-    "~/A-Za-z0-9_^$!#%&{}@`'.,:()-")
-   (t   
-    "~/A-Za-z0-9+@:_.$#%,={}-"))
+  (if (memq system-type '(ms-dos windows-nt))
+      "~/A-Za-z0-9_^$!#%&{}@`'.,:()-"
+    "~/A-Za-z0-9+@:_.$#%,={}-")
   "String of characters valid in a file name.
 Note that all non-ASCII characters are considered valid in a file name
 regardless of what this variable says.
@@ -1958,12 +1982,12 @@ plus all non-ASCII characters."
                      (eq (preceding-char) ?\\)))
        (backward-char 1))
       ;; Don't go forward over a word-char (this can happen if we're at bob).
-      (if (or (not (bobp)) (looking-at non-word-chars))
-         (forward-char 1))
+      (when (or (not (bobp)) (looking-at non-word-chars))
+       (forward-char 1))
       ;; Set match-data to match the entire string.
-      (if (< (point) here)
-         (progn (store-match-data (list (point) here))
-                (match-string 0))))))
+      (when (< (point) here)
+       (set-match-data (list (point) here))
+       (match-string 0)))))
 
 (defun comint-substitute-in-file-name (filename)
   "Return FILENAME with environment variables substituted.
@@ -2040,13 +2064,10 @@ completions listing is dependent on the value of `comint-completion-autolist'.
 
 Returns t if successful."
   (interactive)
-  (if (comint-match-partial-filename)
-      (let ((directory-sep-char (if (memq system-type '(ms-dos windows-nt))
-                                   ?\\
-                                 ?/)))
-       (prog2 (or (window-minibuffer-p (selected-window))
-                  (message "Completing file name..."))
-           (comint-dynamic-complete-as-filename)))))
+  (when (comint-match-partial-filename)
+    (unless (window-minibuffer-p (selected-window))
+      (message "Completing file name..."))
+    (comint-dynamic-complete-as-filename)))
 
 (defun comint-dynamic-complete-as-filename ()
   "Dynamically complete at point as a filename.
@@ -2059,12 +2080,18 @@ See `comint-dynamic-complete-filename'.  Returns t if successful."
         ;;(file-name-handler-alist nil)
         (minibuffer-p (window-minibuffer-p (selected-window)))
         (success t)
-        (dirsuffix (cond ((not comint-completion-addsuffix) "")
-                         ((not (consp comint-completion-addsuffix)) "/")
-                         (t (car comint-completion-addsuffix))))
-        (filesuffix (cond ((not comint-completion-addsuffix) "")
-                          ((not (consp comint-completion-addsuffix)) " ")
-                          (t (cdr comint-completion-addsuffix))))
+        (dirsuffix (cond ((not comint-completion-addsuffix)
+                          "")
+                         ((not (consp comint-completion-addsuffix))
+                          (char-to-string directory-sep-char))
+                         (t
+                          (car comint-completion-addsuffix))))
+        (filesuffix (cond ((not comint-completion-addsuffix)
+                           "")
+                          ((not (consp comint-completion-addsuffix))
+                           " ")
+                          (t
+                           (cdr comint-completion-addsuffix))))
         (filename (or (comint-match-partial-filename) ""))
         (pathdir (file-name-directory filename))
         (pathnondir (file-name-nondirectory filename))
@@ -2075,7 +2102,8 @@ See `comint-dynamic-complete-filename'.  Returns t if successful."
           (setq success nil))
           ((eq completion t)            ; Means already completed "file".
            (insert filesuffix)
-           (or minibuffer-p (message "Sole completion")))
+           (unless minibuffer-p
+            (message "Sole completion")))
           ((string-equal completion "") ; Means completion on "directory/".
            (comint-dynamic-list-filename-completions))
           (t                            ; Completion string returned.
@@ -2086,19 +2114,22 @@ See `comint-dynamic-complete-filename'.  Returns t if successful."
              (cond ((symbolp (file-name-completion completion directory))
                     ;; We inserted a unique completion.
                    (insert (if (file-directory-p file) dirsuffix filesuffix))
-                    (or minibuffer-p (message "Completed")))
+                    (unless minibuffer-p
+                     (message "Completed")))
                    ((and comint-completion-recexact comint-completion-addsuffix
                          (string-equal pathnondir completion)
                          (file-exists-p file))
                     ;; It's not unique, but user wants shortest match.
                     (insert (if (file-directory-p file) dirsuffix filesuffix))
-                    (or minibuffer-p (message "Completed shortest")))
+                    (unless minibuffer-p
+                     (message "Completed shortest")))
                    ((or comint-completion-autolist
                         (string-equal pathnondir completion))
                     ;; It's not unique, list possible completions.
                     (comint-dynamic-list-filename-completions))
                    (t
-                    (or minibuffer-p (message "Partially completed")))))))
+                    (unless minibuffer-p
+                     (message "Partially completed")))))))
     success))