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!kayvan
peck@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) ;;;============================================================================