home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / misc / popper.el < prev    next >
Encoding:
Text File  |  1992-05-11  |  20.2 KB  |  554 lines

  1. ;;; -*-Emacs-Lisp-*-
  2. ;;; %Header
  3. ;;; Shrink-wrapped temporary windows for GNU Emacs V2.11
  4. ;;; Copyright (C) 1990, 1991, 1992 Chris McConnell, ccm@cs.cmu.edu.
  5. ;;; Thanks to Ken Laprade for suggestions and patches.
  6.  
  7. ;;; This file is part of GNU Emacs.
  8.  
  9. ;;; GNU Emacs is distributed in the hope that it will be useful,
  10. ;;; but WITHOUT ANY WARRANTY.  No author or distributor
  11. ;;; accepts responsibility to anyone for the consequences of using it
  12. ;;; or for whether it serves any particular purpose or works at all,
  13. ;;; unless he says so in writing.  Refer to the GNU Emacs General Public
  14. ;;; License for full details.
  15.  
  16. ;;; Everyone is granted permission to copy, modify and redistribute
  17. ;;; GNU Emacs, but only under the conditions described in the
  18. ;;; GNU Emacs General Public License.   A copy of this license is
  19. ;;; supposed to have been given to you along with GNU Emacs so you
  20. ;;; can know your rights and responsibilities.  It should be in a
  21. ;;; file named COPYING.  Among other things, the copyright notice
  22. ;;; and this notice must be preserved on all copies.
  23.  
  24. ;;; DESCRIPTION: This module provides a single shrink-wrapped window
  25. ;;; for displaying temporary text called the popper window.  At any
  26. ;;; time there is only one popper window on the screen.  If there is
  27. ;;; an entry for the buffer being displayed on popper-min-heights, the
  28. ;;; size of the window will be from that entry.  If the buffer is
  29. ;;; empty, the size of the window will be popper-empty-min.  Otherwise
  30. ;;; its size will be the minimum of the number of lines of text being
  31. ;;; displayed and half the number of lines in the currently selected
  32. ;;; window when the popper window was created.  It will work with any
  33. ;;; function that uses temporary windows or that has been wrapped with
  34. ;;; popper-wrap.  The window can be scrolled or buried from any other
  35. ;;; window.
  36. ;;;
  37. ;;; When a buffer is displayed using the function
  38. ;;; with-output-to-temp-buffer, the text will be displayed in the
  39. ;;; popper window if the name of the buffer is in popper-pop-buffers
  40. ;;; or popper-pop-buffers is set to T and the name is not in
  41. ;;; popper-no-pop-buffers.  Many kinds of completion and help
  42. ;;; information are displayed this way.  In general any buffer with
  43. ;;; *'s around its name will be a temporary buffer.  Some commands
  44. ;;; like shell-command do not use with-output-to-temp-buffer even
  45. ;;; though you might like to have their output be temporary.  For
  46. ;;; commands like this, you can define a wrapper like this using the
  47. ;;; function popper-wrap.
  48. ;;;
  49. ;;; The default binding for C-x o is changed so that when a buffer is
  50. ;;; displayed in a popper window, it will be skipped if it is in
  51. ;;; popper-buffers-to-skip or popper-buffers-to-skip is T and it is
  52. ;;; not in popper-buffers-no-skip.
  53.  
  54. ;;; USAGE: Load this file, preferably after byte-compiling it.  If you
  55. ;;; do not define key bindings using popper-load-hook, the bindings
  56. ;;; will be:
  57. ;;; 
  58. ;;;  C-z 1   popper-bury-output
  59. ;;;  C-z v   popper-scroll-output
  60. ;;;  C-z g   popper-grow-output
  61. ;;;  C-z b   popper-switch
  62. ;;;  C-x o   popper-other-window (C-u to select popper window)
  63.  
  64. ;;; See %%User variables below for possible options.  Here is a sample
  65. ;;; load hook for your .emacs:
  66. ;;;
  67. ;;; (setq popper-load-hook 
  68. ;;;      '(lambda ()
  69. ;;;        ;; Define key bindings
  70. ;;;        (define-key global-map "\C-c1" 'popper-bury-output)
  71. ;;;        (define-key global-map "\C-cv" 'popper-scroll-output)
  72. ;;;        (define-key global-map "\C-cg" 'popper-grow-output)
  73. ;;;        (define-key global-map "\C-cb" 'popper-switch)
  74. ;;;        ;; Make *Manual windows default to 10 lines
  75. ;;;        (setq popper-min-heights
  76. ;;;              (cons (cons "^\\*Manual" 10) popper-min-heights)
  77. ;;;              ;; Don't skip over *Buffer List*
  78. ;;;              popper-buffers-no-skip (cons "*Buffer List*" 
  79. ;;;                                             popper-buffers-no-skip))))
  80. ;;; This is an example that will not work in your .emacs
  81. ;;;        ;; Make command's output buffer a popper window even though
  82. ;;;        ;; it does not use with-output-to-temp-buffer
  83. ;;;        (popper-wrap 'command "*Command Output*")))
  84. ;;; (require 'popper)
  85.  
  86. ;;; WARNING: This package redefines the function split-window and
  87. ;;; pop-to-buffer so that the popper window is buried before calling
  88. ;;; the old definition.
  89.  
  90. ;;;%Globals
  91. ;;;%%User variables
  92. (defvar popper-load-hook nil
  93.   "List of functions to run when the popper module is loaded.")
  94.  
  95. ;;;
  96. (defvar popper-pop-buffers t
  97.   "*List of buffers to put in the shrink-wrapped pop-up window.  
  98. If it is T, all temporary buffers will be put in the pop-up window.")
  99.  
  100. (defvar popper-no-pop-buffers nil
  101.   "*If popper-pop-buffers is T, these buffers will not be put into the
  102. pop-up window.")
  103.  
  104. (defvar popper-buffers-to-skip popper-pop-buffers
  105.   "*\\[popper-other-window] will skip over these buffers when they are
  106. used in a temporary window.  If it is T, all popper windows will be
  107. skipped except those in popper-buffers-no-skip.")
  108.  
  109. (defvar popper-buffers-no-skip nil
  110.   "*\\[popper-other-window] will not skip these buffers when they are
  111. used in a popper window if popper-buffers-to-skip is T.")
  112.  
  113. ;;; By default, this is set to 2 so that a window can be one line big.
  114. ;;; The number of lines in the popper window plus the mode line will
  115. ;;; never be less than this value.  (In fact no window will be less
  116. ;;; than this value.)
  117. (setq window-min-height 2)
  118.  
  119. ;;;
  120. (defvar popper-empty-min '(50) 
  121.   "*Minimum number of lines to display for an empty popper buffer.  If
  122. it is a list, it is an integer percentage 0-100 of the available space.")
  123.  
  124. ;;;
  125. (defvar popper-min-heights '(("^\\*compilation\\*" . (50)))
  126.   "*List of cons where each the car is a regular expression pattern to
  127. match a buffer name and the cdr is the minimum number of lines to
  128. allow when popping buffers that match the regular expression.  If the
  129. number is a list, it is interpreted as the percentage of available
  130. space 0-100 to use for the window.")
  131.  
  132. (defvar popper-mode-line-text nil
  133.   "*Minor mode text for mode line of popper buffers.  If nil, it will
  134. be set to a short help message on first use of popper.")
  135.  
  136. ;;;%%Internal variables
  137. (defvar popper-output-buffers nil
  138.   "LIFO list of buffers displayed in the popper window.")
  139. (defvar popper-last-output-window nil
  140.   "The window that last popped up an output window.")
  141.  
  142. (defvar popper-buffer nil
  143.   "Indicates buffer is a popper for minor-mode-alist.")
  144. (make-variable-buffer-local 'popper-buffer)
  145. (or (assq 'popper-buffer minor-mode-alist)
  146.     (setq minor-mode-alist
  147.       (cons '(popper-buffer popper-mode-line-text) minor-mode-alist)))
  148.  
  149. ;;;%Utils
  150. ;;; This should be in emacs, but it isn't.
  151. (defun popper-mem (item list &optional elt=)
  152.   "Test to see if ITEM is equal to an item in LIST.
  153. Option comparison function ELT= defaults to equal."
  154.   (let ((elt= (or elt= (function equal)))
  155.     (done nil))
  156.     (while (and list (not done))
  157.       (if (funcall elt= item (car list))
  158.       (setq done list)
  159.       (setq list (cdr list))))
  160.     done))
  161.  
  162. ;;;
  163. (defun popper-select (&optional window)
  164.   "Select WINDOW and its buffer.  WINDOW defaults to selected-window."
  165.   (setq window (or window (selected-window)))
  166.   (select-window window)
  167.   (set-buffer (window-buffer window)))
  168.  
  169. ;;;
  170. (defun popper-first-buffer ()
  171.   "Remove killed buffers and return the first buffer on
  172. popper-output-buffers."
  173.   (while (and popper-output-buffers
  174.           (null (buffer-name (car popper-output-buffers))))
  175.     (setq popper-output-buffers (cdr popper-output-buffers)))
  176.    (let ((buffers popper-output-buffers))
  177.      (while (cdr buffers)
  178.        (if (buffer-name (car (cdr buffers)))
  179.        (setq buffers (cdr buffers))
  180.        (rplacd buffers (cdr (cdr buffers))))))
  181.    (car popper-output-buffers))
  182.  
  183. ;;;
  184. (defun popper-output-buffer ()
  185.   "Return the buffer being displayed in the popper window."
  186.   (popper-first-buffer)
  187.   (if (not (eq (selected-window) (next-window)))
  188.       (let ((buffers popper-output-buffers)
  189.         (done nil))
  190.     (while (and buffers (not done))
  191.       (let* ((buffer (car buffers))
  192.          (window (if (buffer-name buffer) (get-buffer-window buffer))))
  193.         (if window 
  194.         (setq done buffer)
  195.         (save-excursion
  196.           (set-buffer (car buffers)) (setq popper-buffer nil))
  197.         (setq buffers (cdr buffers)))))
  198.     (if done (setq popper-output-buffers buffers))
  199.     done)))
  200.  
  201. ;;;
  202. (defun popper-parent ()
  203.   "Return the parent of the popper window."
  204.   (let ((output (popper-output-buffer)))
  205.     (if output (next-window (get-buffer-window output) 'no))))
  206.  
  207. ;;;
  208. (defun popper-window-heights (window)
  209.   "Return a list of the heights of all of the windows following WINDOW."
  210.   (let ((heights nil))
  211.     (select-window window)
  212.     (while (progn 
  213.          (select-window (next-window (selected-window) 'no))
  214.          (not (eq (selected-window) window)))
  215.       (setq heights (cons (window-height (selected-window)) heights)))
  216.     (reverse heights)))
  217.  
  218. ;;;
  219. (defun popper-min-height ()
  220.   "Return the minimum height to use for the buffer in the current
  221. window.  This is either an entry from popper-min-heights,
  222. popper-empty-min if the buffer is empty or window-min-height."
  223.   (let ((buffer (buffer-name))
  224.     (pat popper-min-heights)
  225.     min)
  226.     (while pat
  227.       (if (string-match (car (car pat)) buffer)
  228.       (setq min (cdr (car pat))
  229.         pat nil)
  230.     (setq pat (cdr pat))))
  231.     (if (not min)
  232.     (setq min
  233.           (if (= (point-min) (point-max))
  234.           popper-empty-min
  235.           window-min-height)))
  236.     (if (consp min)
  237.     ;; Floating percentage
  238.     (/ (* (+ (window-height) (window-height (next-window)))
  239.           (car min))
  240.        100)
  241.     min)))
  242.  
  243. ;;;
  244. (defun popper-show-output (&optional buffer size)
  245.   "Bring the output window up showing optional BUFFER in window of
  246. SIZE.  If SIZE is not specified, then shrink the window.  Finally
  247. select the original window."
  248.   (let* ((window (selected-window))
  249.      (old-buffer (window-buffer window))
  250.      (buffer (get-buffer-create
  251.           (or buffer (popper-first-buffer) 
  252.               (error "No popper buffers"))))
  253.      start parent
  254.      (min-height (+ window-min-height (or size window-min-height))))
  255.     (setq popper-last-output-window window)
  256.     (if (eq buffer old-buffer)
  257.     (popper-shrink-window)
  258.     (if (eq window (minibuffer-window)) 
  259.         (let* ((parent (popper-parent)))
  260.           (popper-bury-output t)
  261.           (select-window (setq window (or parent (previous-window)))))
  262.         (if (not (eq old-buffer (popper-output-buffer)))
  263.         (popper-bury-output t)))
  264.     (if (< (window-height window) min-height)
  265.         (enlarge-window (- min-height (window-height window))))
  266.     (setq start (window-start window))
  267.     (split-window nil size)
  268.     (set-window-buffer window buffer)
  269.     (set-buffer buffer)
  270.     (setq popper-buffer t)
  271.     (or popper-mode-line-text
  272.         (setq popper-mode-line-text
  273.           (list (format " %s bury, %s scroll" 
  274.                 (where-is-internal 'popper-bury-output nil t)
  275.                 (where-is-internal 'popper-scroll-output nil t)))))
  276.     (setq popper-output-buffers
  277.           (cons buffer (delq buffer popper-output-buffers)))
  278.     (if (not size) (popper-shrink-window))
  279.     (setq parent (next-window window 'no))
  280.     (popper-select parent)
  281.     ;; Move the window so that top lines get covered unless it would
  282.     ;; cover point in which case point is at top of window
  283.     (save-excursion
  284.       (set-window-start parent start)
  285.       (move-to-window-line (window-height window))
  286.       (set-window-start parent (point)))
  287.     (let ((point (save-excursion (beginning-of-line) (point))))
  288.       (if (not (pos-visible-in-window-p point))
  289.           (set-window-start (selected-window) point)))
  290.     (if (eq popper-last-output-window (minibuffer-window))
  291.         (select-window (minibuffer-window)))
  292.     (set-buffer old-buffer))))
  293.  
  294. ;;;
  295. (defun popper-shrink-window ()
  296.   "Shrink the current window if larger than its buffer unless it has
  297. an entry in popper-min-heights or it is empty in which case
  298. popper-empty-min is used."
  299.   (let* ((window (selected-window))
  300.      (window-lines (1- (window-height window))))
  301.     (set-buffer (window-buffer window))
  302.     (let ((buffer-read-only nil)
  303.       (buffer-modified-p (buffer-modified-p)))
  304.       (save-excursion
  305.     ;; Delete trailing blank lines
  306.     (goto-char (point-max))
  307.     (skip-chars-backward "\n")
  308.     (if (< (point) (point-max)) (delete-region (1+ (point)) (point-max)))
  309.     (goto-char (point-min))
  310.     ;; Delete leading blank lines
  311.     (if (looking-at "\n+") (replace-match ""))
  312.     (set-buffer-modified-p buffer-modified-p)))
  313.     (enlarge-window (- (max (1+ (save-excursion 
  314.                   (goto-char (point-min))
  315.                   (vertical-motion window-lines)))
  316.                 (1- (popper-min-height)))
  317.                window-lines))))
  318.  
  319. ;;;
  320. (defun popper-show (buffer)
  321.   "Function to display BUFFER in a popper window if it is in
  322. popper-pop-buffers or popper-pop-buffers is T and it is not in
  323. popper-no-pop-buffers."
  324.   (let ((name (if (bufferp buffer) (buffer-name buffer) buffer)))
  325.     (if (eq popper-pop-buffers t)
  326.     (if (not (popper-mem name popper-no-pop-buffers))
  327.         (popper-show-output buffer)
  328.         (display-buffer buffer))
  329.     (if (popper-mem name popper-pop-buffers)
  330.         (popper-show-output buffer)
  331.         (display-buffer buffer))))
  332.   (setq minibuffer-scroll-window (get-buffer-window buffer)))
  333.  
  334. ;;;%Commands
  335. (defun popper-bury-output (&optional no-error)
  336.   "Bury the popper output signalling an error if not there unless
  337. optional NO-ERROR is T."
  338.   (interactive)
  339.   (let ((buffer (popper-output-buffer)))
  340.     (if buffer
  341.     (let* ((old (current-buffer))
  342.            (old-window (selected-window))
  343.            (output (get-buffer-window buffer))
  344.            (start (window-height output))
  345.            (parent (next-window output 'no))
  346.            (height (window-height output))
  347.            (heights (popper-window-heights output)))
  348.       (bury-buffer buffer)
  349.       (delete-window output)
  350.       (popper-select parent)
  351.       (while heights
  352.         (enlarge-window (- (+ height (car heights)) (window-height)))
  353.         (if start
  354.         (condition-case () (scroll-down start) (error nil)))
  355.         (select-window (next-window (selected-window) 'no))
  356.         (setq height 0 start nil)
  357.         (setq heights (cdr heights)))
  358.       (set-buffer old)
  359.       (if (not (eq old-window output))
  360.           (select-window old-window)))
  361.     (if (not no-error) (popper-show-output)))))
  362.  
  363. ;;;
  364. (defun popper-scroll-output (&optional n)
  365.   "Scroll text of the popper window upward ARG lines ; or near full
  366. screen if no ARG.  When calling from a program, supply a number as
  367. argument or nil.  If the output window is not being displayed, it will
  368. be brought up."
  369.   (interactive "P")
  370.   (let ((buffer (popper-output-buffer)))
  371.     (if buffer
  372.     (let ((window (selected-window)))
  373.       (unwind-protect
  374.            (progn (select-window (get-buffer-window buffer))
  375.               (condition-case ()
  376.               (scroll-up n)
  377.             (error
  378.              (if (or (null n) (and (numberp n) (> n 0)))
  379.                  (goto-char (point-min))
  380.                  (goto-char (point-max))))))
  381.         (select-window window)))
  382.     (popper-show-output))))
  383.  
  384. ;;;
  385. (defun popper-grow-output (&optional n)
  386.   "Grow the popper window by ARG (default 1) lines.  If the popper
  387. window is not being shown, it will be brought up."
  388.   (interactive "p")
  389.   (let ((buffer (popper-output-buffer)))
  390.     (if buffer
  391.     (let ((old-buffer (current-buffer))
  392.           (window (selected-window)))
  393.       (select-window (get-buffer-window buffer))
  394.       (enlarge-window n)
  395.       (popper-select (next-window (selected-window) 'no))
  396.       (save-excursion
  397.         (if (< n 0)
  398.         (condition-case () (scroll-up n) (error nil))
  399.         (move-to-window-line n)
  400.         (set-window-start (selected-window) (point))))
  401.       (select-window window)
  402.       (set-buffer old-buffer))
  403.     (popper-show-output))))
  404.  
  405. ;;;
  406. (defun popper-switch (buffer)
  407.   "Switch the popper window to BUFFER."
  408.   (interactive
  409.    (list (read-buffer
  410.       "Popper buffer " 
  411.       (car (if (popper-output-buffer)
  412.            (cdr popper-output-buffers)
  413.            popper-output-buffers))
  414.       t)))
  415.   (if buffer (popper-show buffer)))
  416.      
  417. ;;;%Redefinitions
  418. ;;;***Redefine split-window to bury popper window first***
  419. (defvar popper-split-window (symbol-function 'split-window) 
  420.   "Original definition of split-window.")
  421. (defun split-window (&optional window size hor-flag)
  422.   "Split WINDOW, putting SIZE lines in the first of the pair.
  423. WINDOW defaults to selected one and SIZE to half its size.
  424. If optional third arg HOR-FLAG is non-nil, split side by side
  425. and put SIZE columns in the first of the pair."
  426.   (let ((parent (popper-parent)))
  427.     (if (eq parent (selected-window))
  428.     (let* ((pop-size (window-height
  429.               (get-buffer-window (popper-output-buffer))))
  430.            (size (if size (+ size pop-size))))
  431.       (popper-bury-output)
  432.       (prog1
  433.           (funcall popper-split-window window size hor-flag)
  434.         (popper-show-output nil pop-size)))
  435.     (funcall popper-split-window window size hor-flag))))
  436.  
  437. ;;; ***Redefine pop-to-buffer to skip output windows***
  438. (defvar popper-pop-to-buffer (symbol-function 'pop-to-buffer)
  439.   "Original pop to buffer function.")
  440. (defun pop-to-buffer (buffer &optional other-window)
  441.   "Select buffer BUFFER in some window, preferably a different one.
  442. If pop-up-windows is non-nil, windows can be split to do this.
  443. If second arg OTHER-WINDOW is non-nil, insist on finding another
  444. window even if BUFFER is already visible in the selected window."
  445.   (let ((parent (popper-parent)))
  446.     (if (and parent 
  447.          (not (eq (get-buffer buffer) (popper-output-buffer))))
  448.     (progn
  449.       (popper-bury-output)
  450.       (funcall popper-pop-to-buffer buffer other-window)
  451.       (select-window parent)
  452.       (popper-show-output)
  453.       (sit-for 0)            ;Allow display update
  454.       (funcall popper-pop-to-buffer buffer))
  455.     (funcall popper-pop-to-buffer buffer other-window))))
  456.  
  457. ;;;***Redefine other-window to skip popper buffers***
  458. (defun popper-other-window (arg)
  459.   "Select the arg'th other window.  If arg is a C-u prefix, the popper
  460. window will be selected.  Otherwise, windows that contain buffers in
  461. popper-buffers-to-skip will be skipped or if popper-buffers-to-skip is
  462. T those that are not in popper-buffers-no-skip."
  463.   (interactive "P")
  464.   (if (consp arg) 
  465.       (let* ((buffer (popper-output-buffer))
  466.          (window (and buffer (get-buffer-window buffer))))
  467.     (if window (select-window window)))
  468.       (setq arg (if (eq arg '-) -1 (or arg 1)))
  469.       (other-window arg)
  470.       (if (eq popper-buffers-to-skip t)
  471.       (if (and (not (popper-mem (buffer-name (current-buffer))
  472.                     popper-buffers-no-skip))
  473.            (eq (popper-output-buffer) (current-buffer)))
  474.           (other-window arg))
  475.       (if (popper-mem (buffer-name (current-buffer))
  476.               popper-buffers-to-skip)
  477.           (other-window arg)))))
  478. (define-key ctl-x-map "o" 'popper-other-window)
  479.  
  480. ;;; %Wrappers
  481. (defun popper-unwrap (function)
  482.   "Remove the popper wrapper for NAME."
  483.   (let ((var (car (read-from-string (format "popper-%s" function)))))
  484.     (if (boundp var)
  485.     (progn (fset function (symbol-value var))
  486.            (makunbound var)))))
  487.  
  488. ;;;
  489. (defun popper-wrap (function buffer)
  490.   "Define a wrapper on FUNCTION so that BUFFER will be a pop up window."
  491.   (popper-unwrap function)
  492.   (let* ((var (car (read-from-string (format "popper-%s" function))))
  493.      (defn (symbol-function function))
  494.      arg-spec doc int)
  495.     (set var defn)
  496.     (if (consp defn)
  497.     (setq arg-spec (elt defn 1)
  498.           doc (elt defn 2)
  499.           int (elt defn 3))
  500.     (setq arg-spec (aref defn 0)
  501.           doc (and (> (length defn) 4) (aref defn 4))
  502.           int (and (> (length defn) 5) (list 'interactive (aref defn 5)))))
  503.     (fset function 
  504.       (append 
  505.        (list 'lambda arg-spec)
  506.        (if (numberp doc) (list (documentation function)))
  507.        (if (stringp doc) (list doc))
  508.        (if (eq (car int) 'interactive) (list int))
  509.        (list 
  510.         (list
  511.          'let '((shown nil))
  512.          (list 'save-window-excursion 
  513.            (cons 'funcall 
  514.              (cons 
  515.               var
  516.               (let ((args nil))
  517.                 (while arg-spec
  518.                   (if (not (eq (car arg-spec) '&optional))
  519.                   (setq args (cons (car arg-spec)
  520.                            args)))
  521.                   (setq arg-spec (cdr arg-spec)))
  522.                 (reverse args))))
  523.            (list 'setq 'shown (list 'get-buffer-window buffer)))
  524.          (list 'if 'shown
  525.            (list 'funcall 'temp-buffer-show-hook buffer))))))
  526.     (if (not (eq popper-pop-buffers t))
  527.     (let ((elt popper-pop-buffers))
  528.       (while (consp elt)
  529.         (if (string= (car elt) buffer) 
  530.         (setq elt t)
  531.         (setq elt (cdr elt))))
  532.       (if (not elt)
  533.           (setq popper-pop-buffers (cons buffer popper-pop-buffers)))))))
  534.  
  535. ;;; 
  536. (popper-wrap 'shell-command "*Shell Command Output*")
  537. (popper-wrap 'shell-command-on-region "*Shell Command Output*")
  538.  
  539. ;;;
  540. (setq temp-buffer-show-hook 'popper-show)
  541. (run-hooks 'popper-load-hook)
  542.  
  543. ;;; Default key bindings
  544. (if (not (where-is-internal 'popper-bury-output nil t))
  545.     (progn
  546.       (if (not (keymapp (lookup-key global-map "\C-z")))
  547.       (define-key global-map "\C-z" (make-keymap)))
  548.       (define-key global-map "\C-z1" 'popper-bury-output)
  549.       (define-key global-map "\C-zv" 'popper-scroll-output)
  550.       (define-key global-map "\C-zg" 'popper-grow-output)
  551.       (define-key global-map "\C-zb" 'popper-switch)))
  552.  
  553. (provide 'popper)
  554.