;;; view.el --- peruse file or buffer without editing
;; Copyright (C) 1985, 1989, 1994, 1995, 1997, 2000, 2001, 2002,
-;; 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
;; Author: K. Shane Hartman
;; Maintainer: Inge Frick <inge@nada.kth.se>
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
"Peruse file or buffer without editing."
:link '(function-link view-mode)
:link '(custom-manual "(emacs)Misc File Ops")
- :group 'wp
- :group 'editing)
+ :group 'wp)
(defcustom view-highlight-face 'highlight
- "*The face used for highlighting the match found by View mode search."
+ "The face used for highlighting the match found by View mode search."
:type 'face
:group 'view)
;; doesn't say if leaving view mode should restore windows or not. The latter
;; is now controlled by the presence of a value in `view-return-to-alist'.
(defcustom view-scroll-auto-exit nil
- "*Non-nil means scrolling past the end of buffer exits View mode.
+ "Non-nil means scrolling past the end of buffer exits View mode.
A value of nil means attempting to scroll past the end of the buffer,
only rings the bell and gives a message on how to leave."
:type 'boolean
:group 'view)
(defcustom view-try-extend-at-buffer-end nil
- "*Non-nil means try to load more of file when reaching end of buffer.
+ "Non-nil means try to load more of file when reaching end of buffer.
This variable is mainly intended to be temporarily set to non-nil by
the F command in view-mode, but you can set it to t if you want the action
for all scroll commands in view mode."
;;;###autoload
(defcustom view-remove-frame-by-deleting t
- "*Determine how View mode removes a frame no longer needed.
+ "Determine how View mode removes a frame no longer needed.
If nil, make an icon of the frame. If non-nil, delete the frame."
:type 'boolean
:group 'view
:version "23.1")
(defcustom view-exits-all-viewing-windows nil
- "*Non-nil means restore all windows used to view buffer.
+ "Non-nil means restore all windows used to view buffer.
Commands that restore windows when finished viewing a buffer, apply to all
windows that display the buffer and have restore information in
`view-return-to-alist'.
:group 'view)
(defcustom view-inhibit-help-message nil
- "*Non-nil inhibits the help message shown upon entering View mode."
+ "Non-nil inhibits the help message shown upon entering View mode."
:type 'boolean
:group 'view
:version "22.1")
(defvar view-old-Helper-return-blurb)
(make-variable-buffer-local 'view-old-Helper-return-blurb)
-;; Just to avoid warnings.
-(defvar Helper-return-blurb)
-
(defvar view-page-size nil
"Default number of lines to scroll by View page commands.
If nil that means use the window size.")
"Overlay used to display where a search operation found its match.
This is local in each buffer, once it is used.")
(make-variable-buffer-local 'view-overlay)
-
-(unless (assq 'view-mode minor-mode-alist)
- (setq minor-mode-alist
- (cons (list 'view-mode
- (propertize " View"
- 'local-map mode-line-minor-mode-keymap
- 'help-echo "mouse-3: minor mode menu"))
- minor-mode-alist)))
\f
;; Define keymap inside defvar to make it easier to load changes.
;; Some redundant "less"-like key bindings below have been commented out.
(define-key map "c" 'View-leave)
(define-key map "Q" 'View-quit-all)
(define-key map "E" 'View-exit-and-edit)
-; (define-key map "v" 'View-exit)
+ ;; (define-key map "v" 'View-exit)
(define-key map "e" 'View-exit)
(define-key map "q" 'View-quit)
-; (define-key map "N" 'View-search-last-regexp-backward)
+ ;; (define-key map "N" 'View-search-last-regexp-backward)
(define-key map "p" 'View-search-last-regexp-backward)
(define-key map "n" 'View-search-last-regexp-forward)
-; (define-key map "?" 'View-search-regexp-backward) ; Less does this.
+ ;; (define-key map "?" 'View-search-regexp-backward) ; Less does this.
(define-key map "\\" 'View-search-regexp-backward)
(define-key map "/" 'View-search-regexp-forward)
(define-key map "r" 'isearch-backward)
(define-key map "@" 'View-back-to-mark)
(define-key map "." 'set-mark-command)
(define-key map "%" 'View-goto-percent)
-; (define-key map "G" 'View-goto-line-last)
+ ;; (define-key map "G" 'View-goto-line-last)
(define-key map "g" 'View-goto-line)
(define-key map "=" 'what-line)
(define-key map "F" 'View-revert-buffer-scroll-page-forward)
-; (define-key map "k" 'View-scroll-line-backward)
+ ;; (define-key map "k" 'View-scroll-line-backward)
(define-key map "y" 'View-scroll-line-backward)
-; (define-key map "j" 'View-scroll-line-forward)
+ ;; (define-key map "j" 'View-scroll-line-forward)
(define-key map "\n" 'View-scroll-line-forward)
(define-key map "\r" 'View-scroll-line-forward)
(define-key map "u" 'View-scroll-half-page-backward)
(define-key map "d" 'View-scroll-half-page-forward)
(define-key map "z" 'View-scroll-page-forward-set-page-size)
(define-key map "w" 'View-scroll-page-backward-set-page-size)
-; (define-key map "b" 'View-scroll-page-backward)
+ ;; (define-key map "b" 'View-scroll-page-backward)
(define-key map "\C-?" 'View-scroll-page-backward)
-; (define-key map "f" 'View-scroll-page-forward)
+ ;; (define-key map "f" 'View-scroll-page-forward)
(define-key map " " 'View-scroll-page-forward)
(define-key map "o" 'View-scroll-to-buffer-end)
(define-key map ">" 'end-of-buffer)
(define-key map "?" 'describe-mode) ; Maybe do as less instead? See above.
(define-key map "h" 'describe-mode)
map))
-
-(or (assq 'view-mode minor-mode-map-alist)
- (setq minor-mode-map-alist
- (cons (cons 'view-mode view-mode-map) minor-mode-map-alist)))
\f
;;; Commands that enter or exit view mode.
;; kill a buffer modified by the user. A buffer in view mode can
;; become modified if the user types C-x C-q, edits the buffer, then
;; types C-x C-q again to return to view mode.
+;;;###autoload
(defun kill-buffer-if-not-modified (buf)
"Like `kill-buffer', but does nothing if the buffer is modified."
(let ((buf (get-buffer buf)))
(unless (file-exists-p file) (error "%s does not exist" file))
(let ((had-a-buf (get-file-buffer file))
(buffer (find-file-noselect file)))
- (if (eq (with-current-buffer buffer
- (get major-mode 'mode-class))
- 'special)
- (progn
- (switch-to-buffer buffer)
- (message "Not using View mode because the major mode is special"))
- (view-buffer buffer (and (not had-a-buf) 'kill-buffer-if-not-modified)))))
+ (view-buffer buffer (and (not had-a-buf) 'kill-buffer-if-not-modified))))
;;;###autoload
(defun view-file-other-window (file)
Optional argument EXIT-ACTION is either nil or a function with buffer as
argument. This function is called when finished viewing buffer. Use
-this argument instead of explicitly setting `view-exit-action'."
+this argument instead of explicitly setting `view-exit-action'.
+
+Do not set EXIT-ACTION to `kill-buffer' when BUFFER visits a
+file: Users may suspend viewing in order to modify the buffer.
+Exiting View mode will then discard the user's edits. Setting
+EXIT-ACTION to `kill-buffer-if-not-modified' avoids this."
(interactive "bView buffer: ")
- (let ((undo-window (list (window-buffer) (window-start) (window-point))))
- (switch-to-buffer buffer)
- (view-mode-enter (cons (selected-window) (cons nil undo-window))
- exit-action)))
+ (if (eq (with-current-buffer buffer
+ (get major-mode 'mode-class))
+ 'special)
+ (progn
+ (switch-to-buffer buffer)
+ (message "Not using View mode because the major mode is special"))
+ (let ((undo-window (list (window-buffer) (window-start) (window-point))))
+ (switch-to-buffer buffer)
+ (view-mode-enter (cons (selected-window) (cons nil undo-window))
+ exit-action))))
;;;###autoload
(defun view-buffer-other-window (buffer &optional not-return exit-action)
exit-action)))
\f
;;;###autoload
-(defun view-mode (&optional arg)
+(define-minor-mode view-mode
;; In the following documentation string we have to use some explicit key
;; bindings instead of using the \\[] construction. The reason for this
;; is that most commands have more than one key binding.
then \\[View-leave], \\[View-quit] and \\[View-kill-and-leave] will return to that buffer.
Entry to view-mode runs the normal hook `view-mode-hook'."
- (interactive "P")
- (unless (and arg ; Do nothing if already OK.
- (if (> (prefix-numeric-value arg) 0) view-mode (not view-mode)))
- (if view-mode (view-mode-disable)
- (view-mode-enable))))
+ :lighter " View" :keymap view-mode-map
+ (if view-mode (view-mode-enable) (view-mode-disable)))
\f
(defun view-mode-enable ()
"Turn on View mode."
view-page-size nil
view-half-page-size nil
view-old-buffer-read-only buffer-read-only
- buffer-read-only t
- view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb)
- Helper-return-blurb)
- Helper-return-blurb
- (format "continue viewing %s"
- (if (buffer-file-name)
- (file-name-nondirectory (buffer-file-name))
- (buffer-name))))
+ buffer-read-only t)
+ (if (boundp 'Helper-return-blurb)
+ (setq view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb)
+ Helper-return-blurb)
+ Helper-return-blurb
+ (format "continue viewing %s"
+ (if (buffer-file-name)
+ (file-name-nondirectory (buffer-file-name))
+ (buffer-name)))))
(force-mode-line-update)
(run-hooks 'view-mode-hook))
;; so that View mode stays off if toggle-read-only is called.
(if (local-variable-p 'view-read-only)
(kill-local-variable 'view-read-only))
- (setq view-mode nil
- Helper-return-blurb view-old-Helper-return-blurb)
+ (setq view-mode nil)
+ (if (boundp 'Helper-return-blurb)
+ (setq Helper-return-blurb view-old-Helper-return-blurb))
(if buffer-read-only
(setq buffer-read-only view-old-buffer-read-only)))
(old-buf-info (cdr (cdr (car alist)))))
(if all-win (select-window window))
(cond
- ((and (consp old-buf-info) ; Case 3.
- (buffer-live-p (car old-buf-info)))
- (set-window-buffer window (car old-buf-info)) ; old-buf
- (set-window-start window (car (cdr old-buf-info)))
- (set-window-point window (car (cdr (cdr old-buf-info)))))
+ ((consp old-buf-info) ; Case 3.
+ (if (buffer-live-p (car old-buf-info))
+ (progn
+ (set-window-buffer window (car old-buf-info)) ; old-buf
+ (set-window-start window (car (cdr old-buf-info)))
+ (set-window-point window (car (cdr (cdr old-buf-info)))))
+ (bury-buffer)))
((eq old-buf-info 'quit-window)
(quit-window)) ; Case 4.
(old-buf-info ; Case 2 or 5.
;; Not the only frame, so can safely be removed.
(if view-remove-frame-by-deleting
(delete-frame frame)
- (setq notlost t) ; Keep the window. See below.
+ (setq notlost t) ; Keep the window. See below.
(iconify-frame frame))))))))
;; If a frame is removed by iconifying it, the window is not
;; really lost. In this case we keep the entry in
(when exit-action
;; Don't do that: If the user wants to quit the *Help* buffer a
;; second time it won't have any effect.
-;;; (setq view-exit-action nil)
+ ;;(setq view-exit-action nil)
(funcall exit-action buffer))
(force-mode-line-update))))
\f
;;; Some help routines.
(defun view-window-size ()
- ;; Window height excluding mode line.
- (1- (window-height)))
-
-;(defun view-last-command (&optional who what)
-; (setq view-last-command-entry this-command)
-; (setq view-last-command who)
-; (setq view-last-command-argument what))
-
-;(defun View-repeat-last-command ()
-; "Repeat last command issued in View mode."
-; (interactive)
-; (if (and view-last-command
-; (eq view-last-command-entry last-command))
-; (funcall view-last-command view-last-command-argument))
-; (setq this-command view-last-command-entry))
+ ;; Return the height of the current window, excluding the mode line.
+ ;; Using `window-line-height' accounts for variable-height fonts.
+ (let ((h (window-line-height -1)))
+ (if h
+ (1+ (nth 1 h))
+ ;; This should not happen, but if `window-line-height' returns
+ ;; nil, fall back on `window-height'.
+ (1- (window-height)))))
+
+;; (defun view-last-command (&optional who what)
+;; (setq view-last-command-entry this-command)
+;; (setq view-last-command who)
+;; (setq view-last-command-argument what))
+
+;; (defun View-repeat-last-command ()
+;; "Repeat last command issued in View mode."
+;; (interactive)
+;; (if (and view-last-command
+;; (eq view-last-command-entry last-command))
+;; (funcall view-last-command view-last-command-argument))
+;; (setq this-command view-last-command-entry))
(defun view-recenter ()
- ;; Center point in window.
- (recenter (/ (view-window-size) 2)))
+ ;; Recenter point in window and redisplay normally.
+ (recenter '(1)))
(defun view-page-size-default (lines)
- ;; Get page size.
- (let ((default (- (view-window-size) next-screen-context-lines)))
- (if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
- default
- (min (abs lines) default))))
+ ;; If LINES is nil, 0, or larger than `view-window-size', return nil.
+ ;; Otherwise, return LINES.
+ (and lines
+ (not (zerop (setq lines (prefix-numeric-value lines))))
+ (<= (abs lines)
+ (abs (- (view-window-size) next-screen-context-lines)))
+ (abs lines)))
(defun view-set-half-page-size-default (lines)
;; Get and maybe set half page size.
(point-max)))
(view-recenter))
-;(defun View-goto-line-last (&optional line)
-;"Move to last (or prefix LINE) line in View mode.
-;Display is centered at LINE.
-;Sets mark at starting position and pushes mark ring."
-; (interactive "P")
-; (push-mark)
-; (if line (goto-line (prefix-numeric-value line))
-; (goto-char (point-max))
-; (beginning-of-line))
-; (view-recenter))
+;; (defun View-goto-line-last (&optional line)
+;; "Move to last (or prefix LINE) line in View mode.
+;; Display is centered at LINE.
+;; Sets mark at starting position and pushes mark ring."
+;; (interactive "P")
+;; (push-mark)
+;; (if line (goto-line (prefix-numeric-value line))
+;; (goto-char (point-max))
+;; (beginning-of-line))
+;; (view-recenter))
(defun View-goto-line (&optional line)
"Move to first (or prefix LINE) line in View mode.
Also set the mark at the position where point was."
(interactive "p")
(push-mark)
- (goto-line line)
+ (goto-char (point-min))
+ (forward-line (1- line))
(view-recenter))
(defun View-back-to-mark (&optional ignore)
\f
(defun view-scroll-lines (lines backward default maxdefault)
;; This function does the job for all the scrolling commands.
- ;; Scroll forward LINES lines. If BACKWARD is true scroll backwards.
- ;; If LINES is negative scroll in the other direction. If LINES is 0 or nil,
- ;; scroll DEFAULT lines. If MAXDEFAULT is true then scroll no more than a
- ;; window full.
+ ;; Scroll forward LINES lines. If BACKWARD is non-nil, scroll backwards.
+ ;; If LINES is negative scroll in the other direction.
+ ;; If LINES is 0 or nil, scroll DEFAULT lines (if DEFAULT is nil, scroll
+ ;; by one page). If MAXDEFAULT is non-nil, scroll no more than a window.
(if (or (null lines) (zerop (setq lines (prefix-numeric-value lines))))
(setq lines default))
- (when (< lines 0)
- (setq backward (not backward)) (setq lines (- lines)))
- (setq default (view-page-size-default nil)) ; Max scrolled at a time.
- (if maxdefault (setq lines (min lines default)))
- (cond
- (backward (scroll-down lines))
- ((view-really-at-end)
- (if view-scroll-auto-exit (View-quit)
- (ding)
- (view-end-message)))
- (t (while (> lines default)
- (scroll-up default)
- (setq lines (- lines default))
- (if (view-really-at-end) (setq lines 0)))
- (scroll-up lines)
- (if (view-really-at-end) (view-end-message))
- (move-to-window-line -1)
- (beginning-of-line))))
+ (when (and lines (< lines 0))
+ (setq backward (not backward) lines (- lines)))
+ (when (and maxdefault lines (> lines (view-window-size)))
+ (setq lines nil))
+ (cond (backward (scroll-down lines))
+ ((view-really-at-end)
+ (if view-scroll-auto-exit
+ (View-quit)
+ (ding)
+ (view-end-message)))
+ (t (scroll-up lines)
+ (if (view-really-at-end) (view-end-message)))))
(defun view-really-at-end ()
;; Return true if buffer end visible. Maybe revert buffer and test.
(defun View-scroll-line-forward (&optional lines)
"Scroll forward one line (or prefix LINES lines) in View mode.
-See also `View-scroll-page-forward,' but note that scrolling is limited
+See also `View-scroll-page-forward', but note that scrolling is limited
to minimum of LINES and one window-full."
(interactive "P")
(view-scroll-lines lines nil 1 t))
(defun view-search (times regexp)
;; This function does the job for all the View-search- commands.
- ;; Search for the TIMESt match for REGEXP. If TIMES is negative
- ;; search backwards. If REGEXP is nil use `view-last-regexp'.
- ;; Charcters "!" and "@" have a special meaning at the beginning of
+ ;; Search for the TIMESt match for REGEXP. If TIMES is negative
+ ;; search backwards. If REGEXP is nil use `view-last-regexp'.
+ ;; Characters "!" and "@" have a special meaning at the beginning of
;; REGEXP and are removed from REGEXP before the search "!" means
;; search for lines with no match for REGEXP. "@" means search in
;; the whole buffer, don't start searching from the present point.
(provide 'view)
-;;; arch-tag: 6d0ace36-1d12-4de3-8de3-1fa3231636d7
+;; arch-tag: 6d0ace36-1d12-4de3-8de3-1fa3231636d7
;;; view.el ends here