;;; shell-toggle.el --- Toggle to and from the *shell* buffer ;;; Version 1.0 - 97-11-25 ;;; Copyright (C) 1997 Mikael Sjödin (mic@docs.uu.se) ;;; ;;; Author: Mikael Sjödin -- mic@docs.uu.se ;;; ;;; This file is NOT part of GNU Emacs. ;;; You may however 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. ;;; ;;; The file 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. ;;; ---------------------------------------------------------------------- ;;; Description: ;;; ;;; Provides the command shell-toggle (and shell-toggle-cd which is the same as ;;; calling shell-toggle with a prefix argument) which toggles between the ;;; *shell* buffer and whatever buffer you are editing. ;;; ;;; This is done in a "fancy" way. Features are: ;;; o Starts a shell if non is existing. ;;; o Minimum distortion of your window configuration. ;;; o When done in the shell buffer you are returned to the same window ;;; configuration you had before you toggled to the shell. ;;; o If you desire, you automagically get a "cd" command in the shell to the ;;; directory where your current file exists. Just add a prefix argument, ;;; type C-u M-f1. (Or bind the command shell-toggle-cd to a key) ;;; o You can convinently choose if you want to have the shell in another ;;; window or in the whole frame. Just hit M-f1 again to get the whole frame ;;; version. ;;; ;;; Bugs: ;;; o In Emacs 20 shell-toggle "fails" first invokation, just invoke ;;; shell-toggle again. ;;; ---------------------------------------------------------------------- ;;; Installation: ;;; ;;; o Place this file in a directory in your 'load-path. ;;; o Put the following in your .emacs file: ;;; (autoload 'shell-toggle "shell-toggle" ;;; "Toggles between the *shell* buffer and whatever buffer you are editing." ;;; t) ;;; (global-set-key [M-f1] 'shell-toggle) ;;; (global-set-key [C-f1] 'shell-toggle-cd) ;;; o Restart your Emacs. To use shell-toggle just hit M-f1 or C-f1 ;;; ;;; (No user options exists.) ;;; ---------------------------------------------------------------------- ;;; BUGS: ;;; o In Emacs 20 shell-toggle "fails" first time it is invoked. Just hit F1 ;;; again :( ;;; ====================================================================== ;;; Commands: (defun shell-toggle-cd () "Calls `shell-toggle' with a prefix argument. Se command `shell-toggle'" (interactive) (shell-toggle t)) (defun shell-toggle (make-cd) "Toggles between the *shell* buffer and whatever buffer you are editing. With a prefix ARG also insert a \"cd DIR\" command into the shell, where DIR is the directory of the current buffer. Call twice in a row to get a full screen window for the *shell* buffer. When called in the *shell* buffer returns you to the buffer you were editing before caling the first time." (interactive "P") ;; Try to descide on one of three possibilities: ;; If not in shell-buffer, switch to it. ;; If in shell-buffer and called twice in a row, delete other windows ;; If in shell-buffer and not called twice in a row, return to state before ;; going to the shell-buffer (if (eq major-mode 'shell-mode) (if (and (eq last-command 'shell-toggle) (not (eq (count-windows) 1))) (delete-other-windows) (shell-toggle-buffer-return-from-shell)) (shell-toggle-buffer-goto-shell make-cd))) ;;; ====================================================================== ;;; Internal functions and declarations (defvar shell-toggle-pre-shell-win-conf nil "Contains the window configuration before the *shell* buffer was selected") (defun shell-toggle-buffer-return-from-shell () "Restores the window configuration used before switching the *shell* buffer. If no configuration has been stored, just burry the *shell* buffer." (if (window-configuration-p shell-toggle-pre-shell-win-conf) (progn (set-window-configuration shell-toggle-pre-shell-win-conf) (setq shell-toggle-pre-shell-win-conf nil) (bury-buffer (get-buffer "*shell*"))) (bury-buffer)) ) (defun shell-toggle-buffer-goto-shell (make-cd) "Switches other window to the *shell* buffer. If no *shell* buffer exists start a new shell and switch to it in other window. If argument MAKE-CD is non-nil, insert a \"cd DIR\" command into the shell, where DIR is the directory of the current buffer. Stores the window cofiguration before creating and/or switching window." (setq shell-toggle-pre-shell-win-conf (current-window-configuration)) (let ((shell-buffer (get-buffer "*shell*")) (cd-command (or (and make-cd (buffer-file-name) (file-name-directory (buffer-file-name)) (concat "cd " (file-name-directory (buffer-file-name)))) (and make-cd list-buffers-directory (concat "cd " list-buffers-directory))))) ;; Switch to an existin shell if one exists, otherwise switch to another ;; window and start a new shell (if shell-buffer (switch-to-buffer-other-window shell-buffer) (shell-toggle-buffer-switch-to-other-window) (shell)) (if cd-command (insert cd-command)))) (defun shell-toggle-buffer-switch-to-other-window () "Switches to other window. If the current window is the only window in the current frame, create a new window and switch to it." (let ((this-window (selected-window))) (other-window 1) ;; If we did not switch window then we only have one window and need to ;; create a new one. (if (eq this-window (selected-window)) (progn (split-window-vertically) (other-window 1))))) (provide 'shell-toggle)