page.el 5.47 KB
Newer Older
1
;;; page.el --- page motion commands for Emacs
Eric S. Raymond's avatar
Eric S. Raymond committed
2

Glenn Morris's avatar
Glenn Morris committed
3
;; Copyright (C) 1985, 2001, 2002, 2003, 2004, 2005,
4
;;   2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Joseph Arceneaux's avatar
Joseph Arceneaux committed
5

Eric S. Raymond's avatar
Eric S. Raymond committed
6
;; Maintainer: FSF
7
;; Keywords: wp convenience
Eric S. Raymond's avatar
Eric S. Raymond committed
8

Joseph Arceneaux's avatar
Joseph Arceneaux committed
9 10
;; This file is part of GNU Emacs.

11
;; GNU Emacs is free software: you can redistribute it and/or modify
Joseph Arceneaux's avatar
Joseph Arceneaux committed
12
;; it under the terms of the GNU General Public License as published by
13 14
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Joseph Arceneaux's avatar
Joseph Arceneaux committed
15 16 17 18 19 20 21

;; GNU Emacs 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.

;; You should have received a copy of the GNU General Public License
22
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Joseph Arceneaux's avatar
Joseph Arceneaux committed
23

24 25 26 27 28
;;; Commentary:

;; This code provides the page-oriented movement and selection commands
;; documented in the Emacs manual.

Eric S. Raymond's avatar
Eric S. Raymond committed
29
;;; Code:
Joseph Arceneaux's avatar
Joseph Arceneaux committed
30 31 32

(defun forward-page (&optional count)
  "Move forward to page boundary.  With arg, repeat, or go back if negative.
Jim Blandy's avatar
Jim Blandy committed
33 34
A page boundary is any line whose beginning matches the regexp
`page-delimiter'."
Joseph Arceneaux's avatar
Joseph Arceneaux committed
35 36 37
  (interactive "p")
  (or count (setq count 1))
  (while (and (> count 0) (not (eobp)))
Richard M. Stallman's avatar
Richard M. Stallman committed
38 39 40
    ;; In case the page-delimiter matches the null string,
    ;; don't find a match without moving.
    (if (bolp) (forward-char 1))
Joseph Arceneaux's avatar
Joseph Arceneaux committed
41 42 43 44 45
    (if (re-search-forward page-delimiter nil t)
	nil
      (goto-char (point-max)))
    (setq count (1- count)))
  (while (and (< count 0) (not (bobp)))
46 47 48 49 50
    ;; In case the page-delimiter matches the null string,
    ;; don't find a match without moving.
    (and (save-excursion (re-search-backward page-delimiter nil t))
	 (= (match-end 0) (point))
	 (goto-char (match-beginning 0)))
Joseph Arceneaux's avatar
Joseph Arceneaux committed
51
    (forward-char -1)
52 53 54 55 56
    (if (re-search-backward page-delimiter nil t)
	;; We found one--move to the end of it.
	(goto-char (match-end 0))
      ;; We found nothing--go to beg of buffer.
      (goto-char (point-min)))
Joseph Arceneaux's avatar
Joseph Arceneaux committed
57 58 59 60
    (setq count (1+ count))))

(defun backward-page (&optional count)
  "Move backward to page boundary.  With arg, repeat, or go fwd if negative.
Jim Blandy's avatar
Jim Blandy committed
61 62
A page boundary is any line whose beginning matches the regexp
`page-delimiter'."
Joseph Arceneaux's avatar
Joseph Arceneaux committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  (interactive "p")
  (or count (setq count 1))
  (forward-page (- count)))

(defun mark-page (&optional arg)
  "Put mark at end of page, point at beginning.
A numeric arg specifies to move forward or backward by that many pages,
thus marking a page other than the one point was originally in."
  (interactive "P")
  (setq arg (if arg (prefix-numeric-value arg) 0))
  (if (> arg 0)
      (forward-page arg)
    (if (< arg 0)
        (forward-page (1- arg))))
  (forward-page)
78
  (push-mark nil t t)
Joseph Arceneaux's avatar
Joseph Arceneaux committed
79 80 81 82 83 84 85 86 87 88 89 90 91
  (forward-page -1))

(defun narrow-to-page (&optional arg)
  "Make text outside current page invisible.
A numeric arg specifies to move forward or backward by that many pages,
thus showing a page other than the one point was originally in."
  (interactive "P")
  (setq arg (if arg (prefix-numeric-value arg) 0))
  (save-excursion
    (widen)
    (if (> arg 0)
	(forward-page arg)
      (if (< arg 0)
92 93 94 95 96 97 98 99 100 101
	  (let ((adjust 0)
		(opoint (point)))
	    ;; If we are not now at the beginning of a page,
	    ;; move back one extra time, to get to the start of this page.
	    (save-excursion
	      (beginning-of-line)
	      (or (and (looking-at page-delimiter)
		       (eq (match-end 0) opoint))
		  (setq adjust 1)))
	    (forward-page (- arg adjust)))))
Joseph Arceneaux's avatar
Joseph Arceneaux committed
102
    ;; Find the end of the page.
103
    (set-match-data nil)
Joseph Arceneaux's avatar
Joseph Arceneaux committed
104 105 106 107
    (forward-page)
    ;; If we stopped due to end of buffer, stay there.
    ;; If we stopped after a page delimiter, put end of restriction
    ;; at the beginning of that line.
108 109 110 111 112 113
    ;; Before checking the match that was found,
    ;; verify that forward-page actually set the match data.
    (if (and (match-beginning 0)
	     (save-excursion
	       (goto-char (match-beginning 0)) ; was (beginning-of-line)
	       (looking-at page-delimiter)))
114
	(goto-char (match-beginning 0))) ; was (beginning-of-line)
Joseph Arceneaux's avatar
Joseph Arceneaux committed
115 116 117 118 119 120 121 122 123 124 125
    (narrow-to-region (point)
		      (progn
			;; Find the top of the page.
			(forward-page -1)
			;; If we found beginning of buffer, stay there.
			;; If extra text follows page delimiter on same line,
			;; include it.
			;; Otherwise, show text starting with following line.
			(if (and (eolp) (not (bobp)))
			    (forward-line 1))
			(point)))))
Eric S. Raymond's avatar
Eric S. Raymond committed
126
(put 'narrow-to-page 'disabled t)
Joseph Arceneaux's avatar
Joseph Arceneaux committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153

(defun count-lines-page ()
  "Report number of lines on current page, and how many are before or after point."
  (interactive)
  (save-excursion
    (let ((opoint (point)) beg end
	  total before after)
      (forward-page)
      (beginning-of-line)
      (or (looking-at page-delimiter)
	  (end-of-line))
      (setq end (point))
      (backward-page)
      (setq beg (point))
      (setq total (count-lines beg end)
	    before (count-lines beg opoint)
	    after (count-lines opoint end))
      (message "Page has %d lines (%d + %d)" total before after))))

(defun what-page ()
  "Print page and line number of point."
  (interactive)
  (save-restriction
    (widen)
    (save-excursion
      (let ((count 1)
	    (opoint (point)))
154
	(goto-char (point-min))
Joseph Arceneaux's avatar
Joseph Arceneaux committed
155
	(while (re-search-forward page-delimiter opoint t)
156 157
          (if (= (match-beginning 0) (match-end 0))
              (forward-char 1))
Joseph Arceneaux's avatar
Joseph Arceneaux committed
158
	  (setq count (1+ count)))
Chong Yidong's avatar
Chong Yidong committed
159 160 161
	(message "Page %d, line %d" count (line-number-at-pos opoint))))))


Richard M. Stallman's avatar
Richard M. Stallman committed
162 163 164

;;; Place `provide' at end of file.
(provide 'page)
Eric S. Raymond's avatar
Eric S. Raymond committed
165

166
;; arch-tag: e8d7a0bd-8655-4b6e-b852-f2ee25316a1d
Eric S. Raymond's avatar
Eric S. Raymond committed
167
;;; page.el ends here