[comp.emacs] GNU shell name completion

denny@mcmi.UUCP (09/18/87)

This is an updated version of the code I previously distributed via
mail request only.  It has been running at several sites, and I feel
that it is now ready for general distribution.

For those of you who have inquired about command name completion:
Having just gone through a change of jobs and cities (I know...
excuses, excuses), I haven't had much time to work on it.  Soon is
the best that I can say.

Please send enhancement suggestions and bug reports directly to me.

Denny	ihnp4!ohgua!ugn!mcmi!denny



The diffs below are based on the 18.47 distribution.

------------------------------------------------------------------
*** shell.el.org	Tue Aug 18 12:02:30 1987
--- shell.el	Tue Aug 18 13:59:56 1987
***************
*** 43,48
  (defvar explicit-shell-file-name nil
    "*If non-nil, is file name to use for explicitly requested inferior shell.")
  
  ;In loaddefs.el now.
  ;(defconst shell-prompt-pattern
  ;  "^[^#$%>]*[#$%>] *"

--- 43,54 -----
  (defvar explicit-shell-file-name nil
    "*If non-nil, is file name to use for explicitly requested inferior shell.")
  
+ (defvar shell-completions-window nil
+   "If non-nil, completion window requires cleaning up.")
+ 
+ (defvar shell-token-pattern "[ \t\n()<>&|;]"
+   "*Regexp used by shell name completion to mark path name boundries.")
+ 
  ;In loaddefs.el now.
  ;(defconst shell-prompt-pattern
  ;  "^[^#$%>]*[#$%>] *"
***************
*** 90,95
      nil
    (setq shell-mode-map (make-sparse-keymap))
    (define-key shell-mode-map "\C-m" 'shell-send-input)
    (define-key shell-mode-map "\C-c\C-d" 'shell-send-eof)
    (define-key shell-mode-map "\C-c\C-u" 'kill-shell-input)
    (define-key shell-mode-map "\C-c\C-w" 'backward-kill-word)

--- 96,102 -----
      nil
    (setq shell-mode-map (make-sparse-keymap))
    (define-key shell-mode-map "\C-m" 'shell-send-input)
+   (define-key shell-mode-map "\C-i" 'shell-file-name-completion)
    (define-key shell-mode-map "\C-c\C-d" 'shell-send-eof)
    (define-key shell-mode-map "\C-c\C-u" 'kill-shell-input)
    (define-key shell-mode-map "\C-c\C-w" 'backward-kill-word)
***************
*** 98,104
    (define-key shell-mode-map "\C-c\C-\\" 'quit-shell-subjob)
    (define-key shell-mode-map "\C-c\C-o" 'kill-output-from-shell)
    (define-key shell-mode-map "\C-c\C-r" 'show-output-from-shell)
!   (define-key shell-mode-map "\C-c\C-y" 'copy-last-shell-input))
  
  (defvar explicit-csh-args
    (if (eq system-type 'hpux)

--- 105,115 -----
    (define-key shell-mode-map "\C-c\C-\\" 'quit-shell-subjob)
    (define-key shell-mode-map "\C-c\C-o" 'kill-output-from-shell)
    (define-key shell-mode-map "\C-c\C-r" 'show-output-from-shell)
!   (define-key shell-mode-map "\C-c\C-y" 'copy-last-shell-input)
!   (define-key shell-mode-map "\C-c\C-k" 'kill-all-output-from-shell)
!   (define-key shell-mode-map "\C-c\C-n" 'shell-next-command)
!   (define-key shell-mode-map "\C-c\C-p" 'shell-prev-command))
! 
  
  (defvar explicit-csh-args
    (if (eq system-type 'hpux)
***************
*** 194,199
  by matching the regexp that is the value of shell-prompt-pattern if possible.
  This regexp should start with \"^\"."
    (interactive)
    (end-of-line)
      (if (eobp)
  	(progn

--- 205,211 -----
  by matching the regexp that is the value of shell-prompt-pattern if possible.
  This regexp should start with \"^\"."
    (interactive)
+   (shell-completion-cleanup)
    (end-of-line)
      (if (eobp)
  	(progn
***************
*** 280,285
    (interactive)
    (process-send-eof))
  
  (defun kill-output-from-shell ()
    "Kill all output from shell since last input."
    (interactive)

--- 292,359 -----
    (interactive)
    (process-send-eof))
  
+ 
+ (defun shell-file-name-completion ()
+   "Preform file name completion in shell mode"
+   (interactive)
+   (let ((shell-expand-string nil)
+ 	(shell-expand-begin nil)
+ 	(shell-expand-end nil)
+ 	(shell-expand-dir nil)
+ 	(shell-expand-file nil)
+ 	(shell-expand-completion nil))
+ 
+     ;; look back
+     (re-search-backward shell-token-pattern nil t)
+     (forward-char)
+     (setq shell-expand-begin (point))
+     ;; look ahead
+     (if (re-search-forward shell-token-pattern nil 0) (backward-char))
+     (setq shell-expand-end (point))
+ 
+     ;; the name requiring expansion
+     (setq shell-expand-string
+ 	  (buffer-substring shell-expand-begin shell-expand-end))
+     ;; directory part of name
+     (setq shell-expand-dir
+ 	  (or (file-name-directory shell-expand-string) default-directory))
+     ;; file part of name
+     (setq shell-expand-file
+ 	  (file-name-nondirectory shell-expand-string))
+     
+     ;; do the expansion
+     (setq shell-expand-completion
+ 	  (file-name-completion shell-expand-file shell-expand-dir))
+     ;; display the results
+     (if (eq shell-expand-completion t) (message "Sole completion")
+       (if (eq shell-expand-completion nil) (message "No match")
+ 	(if (equal shell-expand-completion shell-expand-file)
+ 	    (progn
+ 	      (if shell-completions-window nil
+ 		(setq shell-completions-window
+ 		      (current-window-configuration)))
+ 	      (message "Making completion list...")
+ 	      (with-output-to-temp-buffer " *Completions*"
+ 		(display-completion-list
+ 		 (sort (file-name-all-completions
+ 			shell-expand-completion shell-expand-dir)
+ 		       'string-lessp)))
+ 	      (message ""))
+ 	  ;; put in the expansion
+ 	  (search-backward shell-expand-file)
+ 	  (replace-match shell-expand-completion t t))))))
+   
+ 
+ (defun shell-completion-cleanup ()
+   "Clean up windows after shell file name completion."
+   (interactive)
+   (if shell-completions-window
+       (save-excursion
+ 	(set-window-configuration shell-completions-window)
+ 	(setq shell-completions-window nil))))
+ 
+ 
+ 
  (defun kill-output-from-shell ()
    "Kill all output from shell since last input."
    (interactive)
***************
*** 289,294
    (insert "*** output flushed ***\n")
    (goto-char (point-max)))
  
  (defun show-output-from-shell ()
    "Display start of this batch of shell output at top of window.
  Also put cursor there."

--- 363,388 -----
    (insert "*** output flushed ***\n")
    (goto-char (point-max)))
  
+ (defun kill-all-output-from-shell ()
+   "Kill shell buffer above current prompt."
+   (interactive)
+   (goto-char (point-max))
+   (re-search-backward shell-prompt-pattern nil t)
+   (kill-region (point-min) (point))
+   (goto-char (point-max)))
+ 
+ (defun shell-next-command ()
+   "Search for the next command in a shell."
+   (interactive)
+   (re-search-forward shell-prompt-pattern nil t))
+ 
+ (defun shell-prev-command ()
+   "Search for the previous command in a shell."
+   (interactive)
+   (beginning-of-line)
+   (re-search-backward shell-prompt-pattern nil t)
+   (re-search-forward shell-prompt-pattern nil t))
+ 
  (defun show-output-from-shell ()
    "Display start of this batch of shell output at top of window.
  Also put cursor there."
***************
*** 325,330
  (defun kill-shell-input ()
    "Kill all text since last stuff output by the shell or its subjobs."
    (interactive)
    (kill-region (process-mark (get-buffer-process (current-buffer)))
  	       (point)))
  

--- 419,425 -----
  (defun kill-shell-input ()
    "Kill all text since last stuff output by the shell or its subjobs."
    (interactive)
+   (shell-completion-cleanup)
    (kill-region (process-mark (get-buffer-process (current-buffer)))
  	       (point)))