kayvan@mrspoc.transact.com (Kayvan Sylvan) (09/08/89)
I was just looking at the CMU Shell and comint sources for the purpose of
adding a hook to the directory tracker that would allow a "synchronization" to
occur upon input of the "pwd" command.
I got tired of having my Emacs lose track of what directory my shell buffer is
in. I figured it would be easy but it does not seem so. Emacs would have to
read the output from the shell when pwd was invoked and then do a cd to that
directory.
Anyone have any insight on this?
---Kayvan
Kayvan Sylvan @ Transact Software, Inc. -*- Los Altos, CA (415) 961-6112
Internet: kayvan@Transact.COM -*- UUCP: ...!{apple,pyramid,mips}!mrspoc!kayvanpeck@SUN.COM (Jeff Peck) (09/08/89)
Here are diffs for 3 additions to cmushell/comint
1. allow customized comint-input-send function
(i needed this for a "psh" shell mode)
2. give arbitrary names to cmushell buffers (with arg)
3. handle: pushd +2 and resync directories
Enjoy!
*** comint.el.~1~ Tue Jun 27 14:32:53 1989
--- comint.el Fri Jun 30 18:08:33 1989
***************
*** 94,99 ****
--- 94,100 ----
;;; comint-get-old-input - function Hooks for specific
;;; comint-input-sentinel - function process-in-a-buffer
;;; comint-input-filter - function modes.
+ ;;; comint-input-send - function
(defvar comint-prompt-regexp "^"
"Regexp to recognise prompts in the inferior process.
Defaults to \"^\", the null string at BOL.
***************
*** 129,134 ****
--- 130,141 ----
Only inputs answering true to this function are saved on the input
history list. Default is to save anything that isn't all whitespace")
+ (defvar comint-input-send (function comint-send-string)
+ "Function to actually send to PROCESS the STRING.
+ usually this is just 'comint-send-string, but if your mode needs to
+ massage the input string, this is your hook.
+ comint-send-string just uses process-send-string and also sends a newline.")
+
(defvar comint-mode-hook '()
"Called upon entry into comint-mode")
***************
*** 177,182 ****
--- 184,190 ----
(make-variable-buffer-local 'comint-get-old-input)
(make-variable-buffer-local 'comint-input-sentinel)
(make-variable-buffer-local 'comint-input-filter)
+ (make-variable-buffer-local 'comint-input-send)
(run-hooks 'comint-mode-hook)
;Do this after the hook so the user can mung INPUT-RING-SIZE w/his hook.
;The test is so we don't lose history if we run comint-mode twice in
***************
*** 477,482 ****
--- 485,496 ----
(if p (goto-char p)
(error "No match"))))
+ (defun comint-send-string (proc string)
+ "Called by comint-send-input via the variable comint-input-send.
+ This is uses process-send-string to send the input and a newline."
+ (process-send-string proc string)
+ (process-send-string proc "\n"))
+
(defun comint-send-input ()
"Send input to process. After the process output mark, sends all text
from the process mark to point as input to the process. Before the
***************
*** 486,491 ****
--- 500,507 ----
case, value of variable comint-input-sentinel is called on the input before
sending it. The input is entered into the input history ring, if value of
variable comint-input-filter returns T when called on the input.
+ The sending is actually done by funcalling the local value of comint-input-send.
+ This is usually uses process-send-string to send the input and a newline.
comint-get-old-input, comint-input-sentinel, and comint-input-filter are chosen
according to the command interpreter running in the buffer. E.g.,
***************
*** 519,526 ****
(insert ?\n)
(if (funcall comint-input-filter input) (ring-insert input-ring input))
(funcall comint-input-sentinel input)
! (process-send-string proc input)
! (process-send-string proc "\n")
(set-marker (process-mark proc) (point))
(set-marker comint-last-input-end (point))))))
--- 535,543 ----
(insert ?\n)
(if (funcall comint-input-filter input) (ring-insert input-ring input))
(funcall comint-input-sentinel input)
! (funcall comint-input-send proc input)
! ;;(process-send-string proc input)
! ;;(process-send-string proc "\n")
(set-marker (process-mark proc) (point))
(set-marker comint-last-input-end (point))))))
*** cmushell.el.~1~ Tue Jun 27 14:31:03 1989
--- cmushell.el Wed Aug 23 18:10:15 1989
***************
*** 50,56 ****
;;; Maybe I should ensure the process mark is in the window when I send
;;; text to the process? Switch selectable?
! (require 'comint)
(provide 'cmushell)
;; YOUR .EMACS FILE
--- 50,57 ----
;;; Maybe I should ensure the process mark is in the window when I send
;;; text to the process? Switch selectable?
! (require 'comint "local/comint/comint")
! (require 'cl)
(provide 'cmushell)
;; YOUR .EMACS FILE
***************
*** 270,275 ****
--- 271,279 ----
(interactive)
(comint-mode)
(setq comint-prompt-regexp inferior-lisp-prompt)
+ (setq comint-get-old-input (function lisp-get-old-input))
+ (setq comint-input-filter (function lisp-input-filter))
+ (setq comint-input-sentinel 'ignore)
(setq major-mode 'cmulisp-mode)
(setq mode-name "CMU Lisp")
(setq mode-line-process '(": %s"))
***************
*** 277,285 ****
(lisp-mode-variables) ; This is right for 18.49
(lisp-mode-variables t)) ; This is right for 18.50
(use-local-map cmulisp-mode-map) ;c-c k for "kompile" file
- (setq comint-get-old-input (function lisp-get-old-input))
- (setq comint-input-filter (function lisp-input-filter))
- (setq comint-input-sentinel 'ignore)
(run-hooks 'cmulisp-mode-hook))
(defun lisp-get-old-input ()
--- 281,286 ----
***************
*** 529,539 ****
(run-hooks 'cmushell-mode-hook))
! (defun cmushell ()
! "Run an inferior shell, with I/O through buffer *cmushell*.
If buffer exists but shell process is not running, make new shell.
If buffer exists and shell process is running,
! just switch to buffer *cmushell*.
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.
--- 530,540 ----
(run-hooks 'cmushell-mode-hook))
! (defun cmushell (&optional bname)
! "Run an inferior shell, with I/O through buffer *NAME* (\"*cmushell*\").
If buffer exists but shell process is not running, make new shell.
If buffer exists and shell process is running,
! just switch to buffer *NAME*.
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.
***************
*** 551,571 ****
\(Type \\[describe-mode] in the shell buffer for a list of commands.)"
(interactive)
! (cond ((not (comint-check-proc "*cmushell*"))
! (let* ((prog (or explicit-shell-file-name
! (getenv "ESHELL")
! (getenv "SHELL")
! "/bin/sh"))
! (name (file-name-nondirectory prog))
! (startfile (concat "~/.emacs_" name))
! (xargs-name (intern-soft (concat "explicit-" name "-args"))))
! (set-buffer (apply 'make-comint "cmushell" prog
! (if (file-exists-p startfile) startfile)
! (if (and xargs-name (boundp xargs-name))
! (symbol-value xargs-name)
! '("-i"))))
! (cmushell-mode))))
! (switch-to-buffer "*cmushell*"))
;;; Directory tracking
--- 552,574 ----
\(Type \\[describe-mode] in the shell buffer for a list of commands.)"
(interactive)
! (unless bname (setq bname "cmushell"))
! (let ((bufname (concat "*" bname "*")))
! (cond ((not (comint-check-proc bufname))
! (let* ((prog (or explicit-shell-file-name
! (getenv "ESHELL")
! (getenv "SHELL")
! "/bin/sh"))
! (name (file-name-nondirectory prog))
! (startfile (concat "~/.emacs_" name))
! (xargs-name (intern-soft (concat "explicit-" name "-args"))))
! (set-buffer (apply 'make-comint bname prog
! (if (file-exists-p startfile) startfile)
! (if (and xargs-name (boundp xargs-name))
! (symbol-value xargs-name)
! '("-i"))))
! (cmushell-mode))))
! (switch-to-buffer bufname)))
;;; Directory tracking
***************
*** 651,667 ****
;; The command came with an argument. If pushd, push
;; the current directory (DEFAULT-DIRECTORY) on the stack.
;; In either case, cd to the argument.
! (let ((dir (progn (string-match "[^ \t\;]*" str i) ; match dir
! (expand-file-name
! (substitute-in-file-name
! (substring str i (match-end 0)))))))
(cond ((file-directory-p dir)
(if (not cd-p) ; push the current directory
! (setq shell-directory-stack
! (cons default-directory
! shell-directory-stack)))
! (cd dir)))))))))
;;; Interfacing to client packages (and converting them)
;;;============================================================================
--- 654,706 ----
;; The command came with an argument. If pushd, push
;; the current directory (DEFAULT-DIRECTORY) on the stack.
;; In either case, cd to the argument.
! (let* ((arg (progn (string-match "[^ \t\;]*" str i) ; match dir
! (substring str i (match-end 0))))
! (dir (expand-file-name (substitute-in-file-name arg))))
(cond ((file-directory-p dir)
(if (not cd-p) ; push the current directory
! (push default-directory shell-directory-stack))
! (cd dir))
! ((string-match "+\\([0-9]+\\)" arg 0)
! (setq arg (car (read-from-string arg (match-beginning 1) (match-end 1))))
! (when (<= arg (length shell-directory-stack))
! (do ((l (list default-directory))
! (i (1- arg) (1- i)))
! ((<= i 0)
! (setq shell-directory-stack (append shell-directory-stack (reverse l)))
! (cd (setq default-directory (pop shell-directory-stack)))
! )
! (push (pop shell-directory-stack) l)
! ))))))))))
+ (defun csh-directory-sync ()
+ "Re synchronizes comints internal shell-directory-stack with the csh version."
+ (interactive)
+ (save-excursion
+ (goto-char (point-max))
+ (process-send-string (get-buffer-process (current-buffer)) "dirs\n")
+ (shell-dir-sync
+ (buffer-substring (progn (forward-line -1) (comint-bol nil) (point))
+ (progn (end-of-line) (point))))
+ (message "%s" default-directory)
+ ))
+
+ (defun csh-dir-sync (dirs)
+ (do* ((dirname "[ \t]*\\([^ \t\;]*\\)[ \t]*")
+ (l nil)
+ (beg0 (string-match dirname dirs 0) (string-match dirname dirs end0))
+ (end0 (match-end 0) (match-end 0)))
+ ((= beg0 end0)
+ (setq l (reverse l))
+ (setq shell-directory-stack (cdr l))
+ (setq default-directory (car l))
+ )
+ (setq l (cons (expand-file-name
+ (substitute-in-file-name
+ (substring dirs (match-beginning 1) (match-end 1)))) l))
+ ))
+
+
;;; Interfacing to client packages (and converting them)
;;;============================================================================