;;; -*- Mode: Emacs-Lisp -*- ;;; ilisp-out.el -- ;;; ILISP output, including a popper replacement. ;;; ;;; This file is part of ILISP. ;;; Please refer to the file COPYING for copyrights and licensing ;;; information. ;;; Please refer to the file ACKNOWLEGDEMENTS for an (incomplete) list ;;; of present and past contributors. ;;; ;;; $Id: ilisp-out.el,v 1.5 2002-06-03 23:37:02 wbd Exp $ ;;; Old history log. ;;; ;;; 2000-03-02: Martin Atzmueller: general rewrite to support ;;; a general interface for multiple different output-frames. (defvar ilisp-*icon-file* "/pictures/ilisp-icon.bmp") (defun ilisp-find-ilisp-icon () (if (and ilisp-*icon-file* (file-exists-p (concat ilisp-*directory* ilisp-*icon-file*))) (concat ilisp-*directory* ilisp-*icon-file*) t)) (defun ilisp-make-output-frame (name) (when (and window-system ilisp-*use-frame-for-output*) (let ((new-frame (make-frame `((name . ,name) (minibuffer . nil) (visibility . nil) (unsplittable . t) (menu-bar-lines . 0) ;; Use of icon-type is currently disabled due to a bug ;; in at least Emacs 21.1 running on Windows. ;; (icon-type . ,(ilisp-find-ilisp-icon)) ))) ) (when (eq +ilisp-emacs-version-id+ 'xemacs) (set-frame-properties new-frame '(default-toolbar-visible-p nil default-gutter-visible-p nil menubar-visible-p nil has-modeline-p t)) ) new-frame))) (defvar ilisp-display-output-function 'ilisp-display-output-default "The name of a function to display all ilisp output. The function gets a single argument, a string.") (defvar ilisp-*last-ilisp-output-sink* nil "Last buffer displayed. This is needed for 'ilisp-scroll-output', and 'ilisp-bury-output'") ;;; ilisp-output-sink -- ;;; Datastructure for a output sink that points to its ;;; output-{buffers|frames|windows} (defstruct ilisp-output-sink (buffer nil) (frame nil) (frame-name nil) (mode nil) (modeline nil) (set-modeline-p nil) (major-mode-def nil) (window-min-height nil) (window-max-height nil) (frame-min-height nil) (frame-min-width nil)) ;;; general ilisp-output (defvar ilisp-output-mode nil "If T, then we are in the ilisp-output minor mode.") ;; Minor mode (just to get a pretty mode line). (defvar ilisp-output-mode-line nil) (make-variable-buffer-local 'ilisp-output-mode) (or (assq 'ilisp-output-mode minor-mode-alist) (setq minor-mode-alist (cons '(ilisp-output-mode ilisp-output-mode-line) minor-mode-alist))) ;;; ilisp-output ;;; ilisp-output is the default for all commands (defvar ilisp-output nil "Output for general ILISP-output") (setq ilisp-output (make-ilisp-output-sink :buffer " *Output*" :major-mode-def 'lisp-mode ; The major mode for the ; typeout window. :frame nil ;; Cached frame for ILISP output. If no window system is ;; 'running' then the value of this is nil. :frame-name "ILISP Output" :modeline 'ilisp-output-mode-line :set-modeline-p t :mode 'ilisp-output-mode :window-min-height 2 ; The minimum height of the ; typeout window :window-max-height 25 ; The maximum height of the ; typeout window :frame-min-height 5 ; Rows :frame-min-width 70 ; Columns )) ;;; arglist-output (defvar ilisp-arglist-output nil "Output sink for Arglist messages.") (if ilisp-*use-frame-for-arglist-output-p* (progn ;; if seperate output for arglist enabled, then use it! (setq ilisp-arglist-output (make-ilisp-output-sink :buffer " *Arglist-Output*" :major-mode-def 'lisp-mode ; The major mode for the ; typeout window. :frame nil ;; Cached frame for ILISP output. If no window system is ;; 'running' then the value of this is nil. :frame-name "ILISP Arglist Output" :modeline nil :set-modeline-p nil :mode 'ilisp-output-mode :window-min-height 2 ; The minimum height of the ; typeout window :window-max-height 25 ; The maximum height of the ; typeout window :frame-min-height 5 ; Rows :frame-min-width 70 ; Columns )) (defvar ilisp-arglist-output-mode nil "If T, then we are in the ilisp-arglist-output minor mode.") (make-variable-buffer-local 'ilisp-arglist-output-mode) (or (assq 'ilisp-arglist-output-mode minor-mode-alist) (setq minor-mode-alist (cons '(ilisp-arglist-output-mode ilisp-arglist-output-mode-line) minor-mode-alist)))) ;; Otherwise use default (setq ilisp-arglist-output ilisp-output)) ;;; ilisp-*command-to-ilisp-output-sink-table* -- ;;; Actually implemented as an a-list. (defvar ilisp-*command-to-ilisp-output-sink-table* () "An association table between 'commands and 'output sinks. It is used to determine where the output of a 'command' should go.") ;;; Accessor functions for ;;; 'ilisp-*command-to-ilisp-output-sink-table*'. (defun* ilisp-get-sink-for-command (command &optional (default ilisp-output)) (let ((result (assoc* command ilisp-*command-to-ilisp-output-sink-table* :test #'eq))) (if result (rest result) default))) (defun* ilisp-set-sink-for-command (command output-sink) (setf ilisp-*command-to-ilisp-output-sink-table* (acons command output-sink ilisp-*command-to-ilisp-output-sink-table*))) (ilisp-set-sink-for-command 'arglist-lisp ilisp-arglist-output) (ilisp-set-sink-for-command 'ilisp-arglist-message-lisp-space ilisp-arglist-output) ;;; Output buffer functions. (defun ilisp-output-buffer (ilisp-output-sink &optional create-p) "Displays the sink's buffer. Sets the corresponding modeline if the 'set-modeline-p' slot is T for sink." (let ((buffer (if create-p (get-buffer-create (ilisp-output-sink-buffer ilisp-output-sink)) (get-buffer (ilisp-output-sink-buffer ilisp-output-sink)))) (modeline (ilisp-output-sink-modeline ilisp-output-sink)) (set-modeline-p (ilisp-output-sink-set-modeline-p ilisp-output-sink)) ) (setq ilisp-*last-ilisp-output-sink* ilisp-output-sink) ;; save ilisp-output-sink for scrolling and burying (unless (and (boundp modeline) (symbol-value modeline)) (when set-modeline-p (setf (symbol-value modeline) (list (format " %s bury, %s scroll" (ilisp-where-is 'ilisp-bury-output) (ilisp-where-is 'ilisp-scroll-output)))))) buffer)) (defun ilisp-output-window (ilisp-output-sink) "Gets the Output-Window for sink's buffer." (let ((buffer (get-buffer (ilisp-output-sink-buffer ilisp-output-sink)))) (when buffer (get-buffer-window buffer t)))) ;;; Popper replacement ;;; ilisp-bury-output -- ;;; ;;; 19991220 Marco Antoniotti ;;; Changed the function to take care of the output frame. (defun* ilisp-bury-output (&optional (pilisp-output-sink nil)) "Delete the typeout window, with sink's buffer, if any" (interactive) (let* ((ilisp-output-sink (or pilisp-output-sink ilisp-*last-ilisp-output-sink*)) (buffer (ilisp-output-buffer ilisp-output-sink)) (window (and buffer (get-buffer-window buffer t))) (frame (ilisp-output-sink-frame ilisp-output-sink))) (when buffer (with-current-buffer buffer (erase-buffer)) (bury-buffer buffer)) (if frame (when (not (eql this-command 'ilisp-arglist-message-lisp-space)) (ilisp-delete-message-frame ilisp-output-sink)) (when window (ilisp-delete-window window))))) (defun ilisp-delete-window (window) "Delete a window with minimal redisplay." (let ((height (window-height window)) (lower-window (ilisp-find-lower-window window))) (delete-window window) (when (and lower-window (not (eq lower-window window))) (let ((old-window (selected-window))) (save-excursion (select-window lower-window) (set-buffer (window-buffer)) (goto-char (window-start)) (vertical-motion (- height)) (set-window-start lower-window (point))) (select-window old-window))))) (defun ilisp-scroll-output (&optional lines) "Scroll the typeout-window, if any." (interactive "P") (let* ((ilisp-output-sink ilisp-*last-ilisp-output-sink*) (buffer (ilisp-output-buffer ilisp-output-sink)) (window (and buffer (get-buffer-window buffer t))) (old-window (selected-window))) (when window (unwind-protect (progn (select-window window) (set-buffer buffer) ;; 19990806 Martin Atzmueller ;; (scroll-up lines) (let ((scroll-in-place nil)) (scroll-up lines))) (select-window old-window))))) (defun ilisp-grow-output (&optional n) "Grow the typeout window by ARG (default 1) lines." (interactive "p") (let* ((buffer (ilisp-output-buffer ilisp-output)) (window (and buffer (get-buffer-window buffer t))) (old-window (selected-window))) (when window (unwind-protect (progn (select-window window) (enlarge-window n)) (when (ilisp-window-live-p old-window) (select-window old-window)))))) (defun ilisp-trim-blank-lines () ;; Delete leading blank lines (goto-char (point-min)) (when (looking-at "\n+") (replace-match "")) ;; Delete trailing blank lines (goto-char (point-max)) (skip-chars-backward "\n") (when (< (point) (point-max)) (delete-region (1+ (point)) (point-max)))) (defun ilisp-write-string-to-buffer (ilisp-output-sink string) (let ((buffer (ilisp-output-buffer ilisp-output-sink t))) (save-excursion (set-buffer buffer) (let ((buffer-read-only nil)) ;; Maybe an option to keep the old output? (erase-buffer)) ;; New: select mode for the output buffer. (unless (eq major-mode (ilisp-output-sink-major-mode-def ilisp-output-sink)) (funcall (ilisp-output-sink-major-mode-def ilisp-output-sink))) (setf (symbol-value (ilisp-output-sink-mode ilisp-output-sink)) t) (let ((buffer-read-only nil)) (princ string buffer) (ilisp-trim-blank-lines) (goto-char (point-min)))))) (defun ilisp-desired-height (ilisp-output-sink windowp) (let ((height (cond ((not windowp) (ilisp-needed-buffer-height (ilisp-output-sink-buffer ilisp-output-sink))) (windowp (ilisp-needed-window-height (get-buffer-window (ilisp-output-sink-buffer ilisp-output-sink) t)))))) (max window-min-height (min (ilisp-output-sink-window-max-height ilisp-output-sink) (max (ilisp-output-sink-window-min-height ilisp-output-sink) height))))) ;; A first guess at the height needed to display this buffer. (defun ilisp-needed-buffer-height (buffer) (save-excursion (set-buffer buffer) (1+ (count-lines (point-min) (point-max))))) ;; The height this window must be to display its entire buffer. (defun ilisp-needed-window-height (window) (save-window-excursion (select-window window) (save-excursion (set-buffer (window-buffer)) ;; 19990806 Marti Atzmueller ;; Changed 2 to 3 just below. (+ 3 (save-excursion (goto-char (point-min)) ;; Any upper bound on the height of an emacs window will ;; do here. How about 1000. (vertical-motion 1000)))))) (defun ilisp-shrink-wrap-window (window ilisp-output-sink) (let ((previously-selected-window (selected-window)) (buffer (window-buffer window))) (select-window window) (let* ((current-height (window-height window)) (desired-height (ilisp-desired-height ilisp-output-sink t)) (delta (- desired-height current-height))) (enlarge-window delta) (set-buffer buffer) (goto-char (point-min)) ;; Now repair damage to the window below us, if it still exists. (let ((lower-window (ilisp-find-lower-window window))) (when lower-window (select-window lower-window) (let ((old-point (point))) (goto-char (window-start)) (vertical-motion delta) (set-window-start lower-window (point)) (goto-char old-point) (when (not (pos-visible-in-window-p old-point)) (recenter 0))))) ;; If there was no lower window, then we ought to preserve ;; the start of the window above us, if any. (when (ilisp-window-live-p previously-selected-window) (select-window previously-selected-window))))) ;;; ilisp-shrink-wrap-window-and-frame -- ;;; I need this one to change the also the frame size. (defun ilisp-shrink-wrap-window-and-frame (window ilisp-output-sink) (let ((previously-selected-window (selected-window)) (buffer (window-buffer window)) (frame (window-frame window))) (select-window window) (let* ((current-height (window-height window)) (desired-height (ilisp-desired-height ilisp-output-sink t)) (delta (- desired-height current-height)) (frame-desired-height (max (ilisp-output-sink-frame-min-height ilisp-output-sink) desired-height))) (set-buffer buffer) (goto-char (point-min)) ;; Now repair damage to the window below us, if it still exists. ;; ;; 19991220 Marco Antoniotti ;; This is probably useless, since the '*ilisp-message-frame*' ;; only has a single window. (let ((lower-window (ilisp-find-lower-window window))) (when lower-window (select-window lower-window) (let ((old-point (point))) (goto-char (window-start)) (vertical-motion delta) (set-window-start lower-window (point)) (goto-char old-point) (unless (pos-visible-in-window-p old-point) (recenter 0))))) ;; If there was no lower window, then we ought to preserve ;; the start of the window above us, if any. (when (ilisp-window-live-p previously-selected-window) (select-window previously-selected-window)) ;; Finally shrink the frame. (set-frame-size frame (ilisp-output-sink-frame-min-width ilisp-output-sink) frame-desired-height)))) (defun ilisp-window-live-p (window) (window-live-p window)) ;;; This old implementation ignores windows in other frames, ;;; which makes a lot of trouble if the ILISP buffer is shown in ;;; a single dedicated window in a frame. ;;(defun ilisp-window-live-p (window) ;; (let* ((initial-window (selected-window)) ;; (win initial-window) ;; (found nil)) ;; (while win ;; (cond ((eq window win) ;; (setq found t ;; win nil)) ;; (t ;; (setq win (next-window win 'no)) ;; (if (eq win initial-window) ;; (setq win nil))))) ;; found)) ;; XEmacs change -- window-edges is gone in 19.12+ so use ;; next-vertical-window instead. (defun ilisp-find-lower-window (window) "Find the window directly below us, if any. This is probably the window from which enlarge-window would steal lines." (if (or (not (string-match "XEmacs" emacs-version)) (and (= emacs-major-version 19) (< emacs-minor-version 12))) (let* ((bottom (nth 3 (window-edges window))) (window* nil) (win window)) (while (not (eq (setq win (next-window win 'no)) window)) (if (and (= (nth 1 (window-edges win)) bottom) (null window*)) (setq window* win))) window*) (next-vertical-window window))) ;;; ilisp-find-top-left-most-window -- ;;; ;;; Notes: ;;; 19980101 ;;; XEmacs change -- There is now a primitive to do this. ;;; ;;; 19991219 Marco Antoniotti ;;; It would seem that also Emacs 20.xx has a built in function for ;;; doing this (either frame-first-window or frame-top-window at least ;;; as of 20.4). However, I leave it as it is just for safety and ;;; history. The only changes I make are to make it a DEFUN* with an ;;; optional parameter and to change the way the local variable ;;; 'window*' is bound. (defun* ilisp-find-top-left-most-window (&optional (frame (selected-frame))) "Return the leftmost topmost window on the current screen." (if (or (not (string-match "XEmacs" emacs-version)) (and (= emacs-major-version 19) (< emacs-minor-version 12))) (frame-first-window frame) (frame-highest-window frame 0))) ; (defun* ilisp-find-top-left-most-window (&optional (frame (selected-frame))) ; "Return the leftmost topmost window on the current screen." ; (if (or (not (string-match "XEmacs" emacs-version)) ; (and (= emacs-major-version 19) ; (< emacs-minor-version 12))) ; (let* ((window* (frame-selected-window frame)) ; ;; (window* (selected-window)) ; (edges* (window-edges window*)) ; (win nil) ; (edges nil) ; (start-window window*)) ; (message ">>> window* %s %s %s." window* start-window frame) ; (while (not (eq (setq win (next-window win 'no)) ; start-window)) ; (message ">>>>>> win %s." win) ; (setq edges (window-edges win)) ; (if (or (< (car (cdr edges)) (car (cdr edges*))) ; top ; (and (= (car (cdr edges)) (car (cdr edges*))) ; (< (car edges) (car edges*)))) ; left ; (setq window* win ; edges* edges))) ; (message ">>> about to return window*.") ; window*) ; (frame-highest-window frame 0))) ;; This causes the typeout window to be created by splitting or using the ;; top-left-most window on the current screen. That is different behavior ;; from the popper, which always split the current window. (defun ilisp-window-to-use-for-typeout () (let ((window (ilisp-find-top-left-most-window))) (while (window-dedicated-p window) (setq window (next-window window nil 'visible))) window)) (defun ilisp-display-buffer-in-typeout-window (ilisp-output-sink) "Display buffer in a window at the top of the screen." (let* ((buffer (ilisp-output-sink-buffer ilisp-output-sink)) (window (get-buffer-window buffer t))) ;; If buffer already has a window, keep it. (if (null window) ;; Otherwise, find a window to split. (let* ((top-window (ilisp-window-to-use-for-typeout)) (new-window nil) (previously-selected-window (selected-window)) (desired-height (ilisp-desired-height ilisp-output-sink nil))) ;; The new window is always the lower one. (select-window top-window) ;; Always minimize redisplay (except in emacs 18). (let ((split-window-keep-point nil)) ;; If the top window is not big enough to split, commandeer it ;; entirely. (if (> desired-height (- (window-height) window-min-height)) (setq new-window top-window) (setq new-window (split-window-vertically desired-height)))) (set-window-buffer top-window buffer) ;; The height is already correct, unless there was line wrapping. ;; Account for that here. (ilisp-shrink-wrap-window top-window ilisp-output-sink) ;; Restore selected window. (if (eq previously-selected-window top-window) (select-window new-window) (select-window previously-selected-window))) ;; Simply shrink-wrap an existing window. (ilisp-shrink-wrap-window window ilisp-output-sink)))) ;;; ilisp-get-message-frame -- ;;; ;;; 19991219 Marco Antoniotti ;;; Utility function. If we get the error it is because the function ;;; has been called in an improper context. ;;; This should not really happen, since this function is called only ;;; within 'ilisp-display-buffer-in-typeout-frame', which is called ;;; only when a window system is running. (defun ilisp-get-message-frame (ilisp-output-sink) (let* ((frame (ilisp-output-sink-frame ilisp-output-sink)) (f (or (and frame (frame-live-p frame) frame) (setf (ilisp-output-sink-frame ilisp-output-sink) (ilisp-make-output-frame (ilisp-output-sink-frame-name ilisp-output-sink)))))) (if f f (error "ILISP: cannot build the ILISP output frame.")))) (defun ilisp-delete-message-frame (ilisp-output-sink) (let ((frame (ilisp-output-sink-frame ilisp-output-sink))) (when frame (when (frame-live-p frame) (delete-frame frame)) (setf (ilisp-output-sink-frame ilisp-output-sink) nil)))) (defun ilisp-display-buffer-in-typeout-area (ilisp-output-sink) (let ((buffer (ilisp-output-sink-buffer ilisp-output-sink))) (cond ((and window-system ilisp-*use-frame-for-output*) (message "See ILISP Message Frame.") (ilisp-display-buffer-in-typeout-frame ilisp-output-sink)) (t (message "See above.") (ilisp-display-buffer-in-typeout-window ilisp-output-sink))))) (defun ilisp-display-buffer-in-typeout-frame (ilisp-output-sink) "Display buffer in a special ILISP frame." (let* ((output-frame (ilisp-get-message-frame ilisp-output-sink)) (buffer (ilisp-output-sink-buffer ilisp-output-sink)) (buffer-window (get-buffer-window buffer)) (previous-output-window (selected-window))) (if (null buffer-window) ;; No window is associated to the buffer. (unwind-protect (let* ((output-frame-window (ilisp-find-top-left-most-window output-frame)) (desired-height (ilisp-desired-height ilisp-output-sink nil))) (select-window output-frame-window) (set-window-buffer output-frame-window buffer) (ilisp-shrink-wrap-window-and-frame output-frame-window ilisp-output-sink) (unless (frame-visible-p output-frame) (make-frame-visible output-frame)) (raise-frame output-frame)) (progn (select-window previous-output-window) (select-frame (window-frame (selected-window))))) ;; else (progn (ilisp-shrink-wrap-window-and-frame buffer-window ilisp-output-sink) ;; Let's try to display the buffer window in the output frame. (unless (and (eq (window-frame buffer-window) output-frame) (not (frame-visible-p output-frame))) (make-frame-visible output-frame)) (raise-frame output-frame))))) ;;; lisp-display-output - general output function (defun lisp-display-output (output) "Displays OUTPUT in the appropriate place. This calls the function given by the value of ILISP-DISPLAY-OUTPUT-FUNCTION in order to do the real work." (when output ;; Bugcheck (unless (stringp output) (error "ILISP: not a string in lisp-display-output")) (when (ilisp-value 'comint-errorp t) (setq output (funcall (ilisp-value 'ilisp-error-filter) output))) (let ((ilisp-output-sink (ilisp-get-sink-for-command this-command ilisp-output))) (funcall ilisp-display-output-function output ilisp-output-sink)))) ;;; Various functions to which to bind ilisp-display-output-function. ;;; ilisp-display-output-default -- ;;; This function does what ilisp used to do, except that we use the ;;; new "popper". ;;; ;;; Notes: ;;; 2000-01-22 Martin Atzmueller: force prompt in inferior-lisp-buffer ;;; after an error. ;;; 19990806 Martin Atzmueller ;;; Added check for COMINT-ERRORP. (defun ilisp-force-output-after-error (ilisp-output-sink) "Force the ilisp buffer to display the prompt." "Display output in the ilisp buffer" (let ((buffer (current-buffer)) (window (selected-window))) ;; we want _exactly_ one prompt ;; this means this function has only to be performed once. ;; so check for ilisp-last-message! (if ilisp-last-message (unwind-protect (progn (lisp-pop-to-buffer (ilisp-buffer) ilisp-output-sink) (if (not (eq (current-buffer) buffer)) (setq ilisp-last-buffer buffer)) (comint-insert (concat (if ilisp-last-message (concat ";;; " ilisp-last-message "\n")) "\n" ilisp-last-prompt)) (setq ilisp-last-message nil)) (if (window-point window) (progn (select-window window) (set-buffer buffer))))))) (defun ilisp-display-output-default (output ilisp-output-sink) "Displays 'output' depending on the value of 'lisp-no-popper'. Dispatch on the value of 'lisp-no-popper': 'lisp-no-popper' = nil: displays 'output' in a typeout window. 'lisp-no-popper' = t: displays 'output' in the ilisp buffer otherwise: displays one-line 'output' in the echo area, multiline output in the ilisp buffer." (cond ((null lisp-no-popper) (ilisp-display-output-in-typeout-window output ilisp-output-sink)) ((eq lisp-no-popper t) (ilisp-display-output-in-lisp-listener output ilisp-output-sink)) (t (ilisp-display-output-adaptively output ilisp-output-sink))) (when (or (ilisp-value 'comint-errorp t) (string-match (ilisp-value 'ilisp-error-regexp t) output)) ;; display error-msg too, if not already in lisp-listener (unless (eq lisp-no-popper t) (ilisp-display-output-in-lisp-listener output ilisp-output-sink)) ;; force output, e.g. for (ilisp-force-output-after-error ilisp-output-sink))) ;; This is the display function I like to use. ;; Another trick which might be useful is to dispatch on the value ;; this-command here, to make output from different ilisp commands ;; go to different places. (defun ilisp-display-output-adaptively (output ilisp-output-sink) "Display one-liners in the echo area, others in the typeout window" (cond ((or (string-match "\n" output) (> (length output) (window-width (minibuffer-window)))) (ilisp-display-output-in-typeout-window output ilisp-output-sink)) (t (ilisp-display-output-in-echo-area output ilisp-output-sink)))) (defun ilisp-display-output-in-typeout-window (output ilisp-output-sink) "Display output in a shrink-wrapped window at the top of the screen." (let ((old-buffer (current-buffer)) (old-window (selected-window)) (buffer (ilisp-output-buffer ilisp-output-sink t))) (ilisp-write-string-to-buffer ilisp-output-sink output) (ilisp-display-buffer-in-typeout-area ilisp-output-sink) ;; Martin Atzmueller 2000-01-27 ;; this-command trick: ;; if this-command is ilisp-message-lisp-space, switch back! (if (and (eql this-command 'ilisp-arglist-message-lisp-space) ilisp-*arglist-message-switch-back-p* (not (member (buffer-name old-buffer) special-display-buffer-names))) (progn (raise-frame (window-frame old-window)) (switch-to-buffer old-buffer))))) (defun ilisp-display-output-in-echo-area (output ilisp-output-sink) "Display output as a message in the echo area." ;; First clear any existing typeout so as to not confuse the user. (or (eq (selected-window) (get-buffer-window (ilisp-output-sink-buffer ilisp-output-sink) t)) (ilisp-bury-output ilisp-output-sink)) ;; v5.7: Patch suggested by hunter@work.nlm.nih.gov (Larry Hunter) ;; If output contains '%', 'message' loses. ;; (message (ilisp-quote-%s output)) ;; An alternative here could be '(princ output)', as suggested by ;; Christopher Hoover ;; (princ output) ;; v5.7b: Patch suggested by fujieda@jaist.ac.jp (Kazuhiro Fujieda) ;; Best one for FSF Emacs 19.2[89]. (message "%s" output)) ;;; ilisp-quote-%s -- ;;; Patch suggested by hunter@work.nlm.nih.gov (Larry Hunter) (defun ilisp-quote-%s (string) "Quote all the occurences of ?% in STRING in an ELisp fashion." (mapconcat '(lambda (char) (if (char-equal char ?%) "%%" (char-to-string char))) string "")) (defun ilisp-display-output-in-temp-buffer (output) (with-output-to-temp-buffer ilisp-output-buffer (princ output))) (defun ilisp-display-output-in-lisp-listener (output ilisp-output-sink) "Display output in the ilisp buffer" (let ((buffer (current-buffer)) (window (selected-window))) (unwind-protect (progn (lisp-pop-to-buffer (ilisp-buffer) ilisp-output-sink) (unless (eq (current-buffer) buffer) (setq ilisp-last-buffer buffer)) (comint-insert (concat (when ilisp-last-message (concat ";;; " ilisp-last-message "\n")) (comint-remove-whitespace output) "\n" ilisp-last-prompt)) (setq ilisp-last-message nil)) (when (window-point window) (select-window window) (set-buffer buffer))))) (defun lisp-pop-to-buffer (pbuffer &optional ilisp-output-sink set-input-focus-p) "Like pop-to-buffer, but select a screen that buffer was shown in. ilisp-output-sink is the last ilisp-output-sink visited/active or nil if this is not relevant." (let* ((buffer (or pbuffer (when ilisp-output-sink (ilisp-output-sink-buffer ilisp-output-sink)))) (window (if ilisp-epoch-running (epoch::get-buffer-window buffer) (get-buffer-window buffer t))) (frame (when window (window-frame window)))) (cond ((not window) (when ilisp-output-sink (ilisp-bury-output ilisp-output-sink)) ; is this neccessary? (pop-to-buffer buffer)) (set-input-focus-p (if (fboundp 'select-frame-set-input-focus) (select-frame-set-input-focus frame) (raise-frame frame) (select-frame frame) (focus-frame frame)) (select-window window)) (t (when (or (memq (frame-visible-p frame) '(nil icon)) (when (fboundp 'frame-iconified-p) (frame-iconified-p frame))) (raise-frame frame) (raise-frame (selected-frame))) (select-frame frame) (select-window window))) (set-buffer buffer))) (defun switch-to-lisp (eob-p &optional ilisp-only) "If in an ILISP buffer, switch to the last non-ILISP buffer visited. Otherwise, switch to the current ILISP buffer. With argument, positions cursor at end of buffer. If you don't want to split windows, set pop-up-windows to NIL." (interactive "P") (if (and (not ilisp-only) ilisp-last-buffer (memq major-mode ilisp-modes)) (lisp-pop-to-buffer ilisp-last-buffer nil t) (unless (memq major-mode ilisp-modes) (setq ilisp-last-buffer (current-buffer))) (lisp-pop-to-buffer (ilisp-buffer) nil t) (when eob-p (goto-char (point-max))))) ;;; end of file -- ilisp-out.el --