julian@uhccux.uhcc.hawaii.edu (Julian Cowley) (01/17/90)
Here is something which I wrote a year back to view buffers
without using view.el. It has been slightly extended in the
year since. I am aware that there might be some discrepancy
between the naming of functions between this and view.el, but I
am too lazy to check. The reason that I wrote a replacment is
that I found view.el too cumbersome, especially with its use of
recursive edit, and I wanted something closer to the standard
`more' functions of Unix. Hope you folks find it useful.
julian@uhccux.uhcc.hawaii.edu
julian@uhccux.bitnet
"I press Execute." -- KT
;;; Simple mode for the viewing the current buffer
;;;
;;; Written by Julian Cowley <julian@uhccux.uhcc.hawaii.edu> Jan. 1989
;;; This program is now in the public domain as of 22 Feb. 1989.
;;;
;;; This is a simple replacement for view-mode that is
;;; intentionally small, doesn't use recursive edit, etc. While
;;; it is really a major mode, view-buffer-mode makes almost no
;;; disturbances to the buffer, and is able to appear/disappear
;;; upon command like minor modes do. In addition, whenever view
;;; buffer mode is active, the word "View" will be present on the
;;; mode line right after the name of the major mode, also
;;; similar to minor modes.
;;;
;;; Suggested key binding: M-#
;;;
;;; (global-set-key "\M-#" 'view-buffer-mode)
;;;
;;; An interesting thing to do is to automatically go into
;;; view-buffer-mode whenever you find a read-only file. You can
;;; do this by putting the following in your .emacs:
;;;
;;; (setq find-file-hooks '((lambda ()
;;; (if buffer-read-only
;;; (view-buffer-mode)))))
;;;
;;; If you want to be able to use C-x C-r (find-file-read-only)
;;; to find a file that you have write access to and go straight
;;; into view mode, you must redefine find-file-read-only so that
;;; it sets the buffer read-only *before* it runs the
;;; find-file-hooks. Put the following redefinition in your
;;; .emacs, or better yet, byte-compile it and place it in a file
;;; that gets loaded upon start up. If you have write access to
;;; the Emacs sources, replace the distribution version in simple.el
;;; with this.
;;;
;;; (defun find-file-read-only (filename)
;;; "Edit file FILENAME but don't save without confirmation.
;;; Like find-file but marks buffer as read-only."
;;; (interactive "fFind file read-only: ")
;;; (let ((find-file-hooks (append '((lambda ()
;;; (setq buffer-read-only t)))
;;; find-file-hooks)))
;;; (find-file filename)))
;;;
;;; Please send comments/suggestions/bugs to me at the above address.
(defvar view-buffer-mode-map nil
"The keymap for View buffer mode.")
(defvar old-local-map nil
"Temporary storage for the buffer's local map while View buffer
mode is in effect.")
(defvar old-buffer-read-only nil
"Temporary storage for the buffer's buffer-read-only variable
while View buffer mode is in effect.")
(make-variable-buffer-local 'viewing-buffer)
(make-variable-buffer-local 'old-local-map)
(make-variable-buffer-local 'old-buffer-read-only)
(or (assq 'viewing-buffer minor-mode-alist)
(nconc minor-mode-alist
'((viewing-buffer " View"))))
(if view-buffer-mode-map
()
(setq view-buffer-mode-map (make-sparse-keymap))
(define-key view-buffer-mode-map " " 'scroll-up)
(define-key view-buffer-mode-map "\r" 'scroll-up-line)
(define-key view-buffer-mode-map "\C-d" 'scroll-up-half-screen)
(define-key view-buffer-mode-map "d" 'scroll-up-half-screen)
(define-key view-buffer-mode-map "s" 'search-forward)
(define-key view-buffer-mode-map "r" 'search-backward)
(define-key view-buffer-mode-map "/" 're-search-forward)
(define-key view-buffer-mode-map "\\" 're-search-backward)
(define-key view-buffer-mode-map "\C-?" 'scroll-down)
(define-key view-buffer-mode-map "." 'beginning-of-buffer)
(define-key view-buffer-mode-map "e" 'end-of-buffer)
(define-key view-buffer-mode-map "<" 'beginning-of-buffer)
(define-key view-buffer-mode-map ">" 'end-of-buffer)
(define-key view-buffer-mode-map "g" 'goto-line)
(define-key view-buffer-mode-map "=" 'what-line)
(define-key view-buffer-mode-map "n" 'next-occurrence)
(define-key view-buffer-mode-map "p" 'previous-occurrence)
(define-key view-buffer-mode-map "?" 'describe-view-buffer-mode)
(define-key view-buffer-mode-map "\C-hm" 'describe-view-buffer-mode))
(defun view-buffer-mode ()
"Mode to view the current buffer. Toggles on each call.
The bindings are:\\{view-buffer-mode-map}"
(interactive)
(if viewing-buffer
;; if we are currently viewing a buffer, restore the
;; original buffer
(progn
(use-local-map old-local-map)
(setq buffer-read-only old-buffer-read-only
viewing-buffer nil))
;; save the local map and the state of buffer-read-only
(setq old-local-map (current-local-map))
(use-local-map view-buffer-mode-map)
(setq old-buffer-read-only buffer-read-only
buffer-read-only t
viewing-buffer t))
;; make sure to update the mode line
(set-buffer-modified-p (buffer-modified-p)))
(defun describe-view-buffer-mode ()
"Display documentation of View buffer mode."
(interactive)
(with-output-to-temp-buffer "*Help*"
(princ "View Buffer Mode:\n")
(princ (documentation 'view-buffer-mode))
(print-help-return-message)))
(defun scroll-up-line ()
(interactive)
(scroll-up 1))
(defun scroll-up-half-screen ()
(interactive)
(scroll-up (/ (window-height) 2)))
;; the following two functions are handy to use with M-x occur
(defun next-occurrence ()
"Find the next occurrence from the Occur buffer, if any."
(interactive)
(let ((occbuf (get-buffer "*Occur*")))
(if (or (null occbuf)
(progn (set-buffer occbuf)
(not (eq major-mode 'occur-mode))))
(error "Occur buffer does not exist.")
;; skip past the current match
(forward-line 1)
;; look for the next line number
(if (re-search-forward "^[ 0-9]+" nil t)
(let ((occwin (get-buffer-window occbuf)))
;; must be at beginning of line in order for
;; occur-mode-goto-occurrence to work.
(beginning-of-line)
(if occwin
(set-window-point occwin (point)))
(occur-mode-goto-occurrence))
(message "End of matches.")
;; go back to the line where we started
(forward-line -1)))))
(defun previous-occurrence ()
"Find the previous occurrence from the Occur buffer, if any."
(interactive)
(let ((occbuf (get-buffer "*Occur*")))
(if (or (null occbuf)
(progn (set-buffer occbuf)
(not (eq major-mode 'occur-mode))))
(error "Occur buffer does not exist.")
;; look for the previous line number
(if (re-search-backward "^[ 0-9]+" nil t)
(let ((occwin (get-buffer-window occbuf)))
(if occwin
(set-window-point occwin (point)))
(occur-mode-goto-occurrence))
(message "Beginning of matches.")))))