Switch to recommended form of GPLv3 permissions notice.
[bpt/emacs.git] / lisp / register.el
CommitLineData
55535639 1;;; register.el --- register commands for Emacs
c88ab9ce 2
c90f2757 3;; Copyright (C) 1985, 1993, 1994, 2001, 2002, 2003, 2004,
409cc4a3 4;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
9750e079 5
4821e2af 6;; Maintainer: FSF
d7b4d18f 7;; Keywords: internal
4821e2af 8
efeae993
RS
9;; This file is part of GNU Emacs.
10
eb3fa2cf 11;; GNU Emacs is free software: you can redistribute it and/or modify
efeae993 12;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
efeae993
RS
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
efeae993 23
d9ecc911
ER
24;;; Commentary:
25
26;; This package of functions emulates and somewhat extends the venerable
27;; TECO's `register' feature, which permits you to save various useful
28;; pieces of buffer state to named variables. The entry points are
29;; documented in the Emacs user's manual.
30
4821e2af 31;;; Code:
efeae993
RS
32
33(defvar register-alist nil
34 "Alist of elements (NAME . CONTENTS), one for each Emacs register.
070c2506 35NAME is a character (a number). CONTENTS is a string, number, marker or list.
22073dda 36A list of strings represents a rectangle.
28cbd14d
RS
37A list of the form (file . NAME) represents the file named NAME.
38A list of the form (file-query NAME POSITION) represents position POSITION
070c2506
KH
39 in the file named NAME, but query before visiting it.
40A list of the form (WINDOW-CONFIGURATION POSITION)
41 represents a saved window configuration plus a saved value of point.
42A list of the form (FRAME-CONFIGURATION POSITION)
43 represents a saved frame configuration plus a saved value of point.")
efeae993 44
1b8cac5d
RS
45(defun get-register (reg)
46 "Return contents of Emacs register named REG, or nil if none."
47 (cdr (assq reg register-alist)))
efeae993 48
1b8cac5d
RS
49(defun set-register (register value)
50 "Set contents of Emacs register named REGISTER to VALUE. Returns VALUE.
22073dda 51See the documentation of the variable `register-alist' for possible VALUE."
1b8cac5d 52 (let ((aelt (assq register register-alist)))
efeae993
RS
53 (if aelt
54 (setcdr aelt value)
ddbb3cc7 55 (push (cons register value) register-alist))
efeae993
RS
56 value))
57
1b8cac5d 58(defun point-to-register (register &optional arg)
b42e6156 59 "Store current location of point in register REGISTER.
0cc89026 60With prefix argument, store current frame configuration.
b42e6156 61Use \\[jump-to-register] to go to that location or restore that configuration.
efeae993 62Argument is a character, naming the register."
b42e6156 63 (interactive "cPoint to register: \nP")
ddbb3cc7
SM
64 ;; Turn the marker into a file-ref if the buffer is killed.
65 (add-hook 'kill-buffer-hook 'register-swap-out nil t)
1b8cac5d 66 (set-register register
070c2506
KH
67 (if arg (list (current-frame-configuration) (point-marker))
68 (point-marker))))
efeae993 69
1b8cac5d 70(defun window-configuration-to-register (register &optional arg)
83b5d757
RS
71 "Store the window configuration of the selected frame in register REGISTER.
72Use \\[jump-to-register] to restore the configuration.
73Argument is a character, naming the register."
5f517806 74 (interactive "cWindow configuration to register: \nP")
b4a91f43
KH
75 ;; current-window-configuration does not include the value
76 ;; of point in the current buffer, so record that separately.
070c2506 77 (set-register register (list (current-window-configuration) (point-marker))))
83b5d757 78
1b8cac5d 79(defun frame-configuration-to-register (register &optional arg)
83b5d757
RS
80 "Store the window configuration of all frames in register REGISTER.
81Use \\[jump-to-register] to restore the configuration.
82Argument is a character, naming the register."
5f517806 83 (interactive "cFrame configuration to register: \nP")
b4a91f43
KH
84 ;; current-frame-configuration does not include the value
85 ;; of point in the current buffer, so record that separately.
070c2506 86 (set-register register (list (current-frame-configuration) (point-marker))))
83b5d757 87
31e1d920 88(defalias 'register-to-point 'jump-to-register)
1b8cac5d 89(defun jump-to-register (register &optional delete)
efeae993 90 "Move point to location stored in a register.
22073dda
RS
91If the register contains a file name, find that file.
92 \(To put a file name in a register, you must use `set-register'.)
83b5d757
RS
93If the register contains a window configuration (one frame) or a frame
94configuration (all frames), restore that frame or all frames accordingly.
e7683fff 95First argument is a character, naming the register.
1542ad37
RS
96Optional second arg non-nil (interactively, prefix argument) says to
97delete any existing frames that the frame configuration doesn't mention.
a21d94f9 98\(Otherwise, these frames are iconified.)"
e7683fff 99 (interactive "cJump to register: \nP")
1b8cac5d 100 (let ((val (get-register register)))
376a7584 101 (cond
b4a91f43
KH
102 ((and (consp val) (frame-configuration-p (car val)))
103 (set-frame-configuration (car val) (not delete))
104 (goto-char (cadr val)))
105 ((and (consp val) (window-configuration-p (car val)))
106 (set-window-configuration (car val))
107 (goto-char (cadr val)))
376a7584 108 ((markerp val)
8c4ca60c
KH
109 (or (marker-buffer val)
110 (error "That register's buffer no longer exists"))
376a7584
JB
111 (switch-to-buffer (marker-buffer val))
112 (goto-char val))
22073dda
RS
113 ((and (consp val) (eq (car val) 'file))
114 (find-file (cdr val)))
28cbd14d
RS
115 ((and (consp val) (eq (car val) 'file-query))
116 (or (find-buffer-visiting (nth 1 val))
117 (y-or-n-p (format "Visit file %s again? " (nth 1 val)))
118 (error "Register access aborted"))
119 (find-file (nth 1 val))
120 (goto-char (nth 2 val)))
376a7584
JB
121 (t
122 (error "Register doesn't contain a buffer position or configuration")))))
efeae993 123
28cbd14d 124(defun register-swap-out ()
ddbb3cc7 125 "Turn markers into file-query references when a buffer is killed."
28cbd14d 126 (and buffer-file-name
ddbb3cc7
SM
127 (dolist (elem register-alist)
128 (and (markerp (cdr elem))
129 (eq (marker-buffer (cdr elem)) (current-buffer))
130 (setcdr elem
131 (list 'file-query
132 buffer-file-name
133 (marker-position (cdr elem))))))))
28cbd14d 134
0e07a458 135(defun number-to-register (number register)
070c2506
KH
136 "Store a number in a register.
137Two args, NUMBER and REGISTER (a character, naming the register).
4d2caa07
KH
138If NUMBER is nil, a decimal number is read from the buffer starting
139at point, and point moves to the end of that number.
070c2506
KH
140Interactively, NUMBER is the prefix arg (none means nil)."
141 (interactive "P\ncNumber to register: ")
4f23d31c 142 (set-register register
0e07a458
KH
143 (if number
144 (prefix-numeric-value number)
4d2caa07
KH
145 (if (looking-at "\\s-*-?[0-9]+")
146 (progn
147 (goto-char (match-end 0))
fe22eed0 148 (string-to-number (match-string 0)))
070c2506
KH
149 0))))
150
0e07a458 151(defun increment-register (number register)
070c2506 152 "Add NUMBER to the contents of register REGISTER.
0e07a458 153Interactively, NUMBER is the prefix arg."
070c2506 154 (interactive "p\ncIncrement register: ")
0e07a458 155 (or (numberp (get-register register))
070c2506 156 (error "Register does not contain a number"))
0e07a458 157 (set-register register (+ number (get-register register))))
efeae993 158
1b8cac5d 159(defun view-register (register)
efeae993 160 "Display what is contained in register named REGISTER.
1b8cac5d 161The Lisp value REGISTER is a character."
efeae993 162 (interactive "cView register: ")
1b8cac5d 163 (let ((val (get-register register)))
efeae993 164 (if (null val)
1b8cac5d 165 (message "Register %s is empty" (single-key-description register))
efeae993 166 (with-output-to-temp-buffer "*Output*"
92840a31
RS
167 (describe-register-1 register t)))))
168
169(defun list-registers ()
170 "Display a list of nonempty registers saying briefly what they contain."
171 (interactive)
172 (let ((list (copy-sequence register-alist)))
173 (setq list (sort list (lambda (a b) (< (car a) (car b)))))
174 (with-output-to-temp-buffer "*Output*"
175 (dolist (elt list)
176 (when (get-register (car elt))
177 (describe-register-1 (car elt))
178 (terpri))))))
179
180(defun describe-register-1 (register &optional verbose)
181 (princ "Register ")
182 (princ (single-key-description register))
183 (princ " contains ")
6ed21409
RS
184 (let ((val (get-register register)))
185 (cond
186 ((numberp val)
187 (princ val))
188
189 ((markerp val)
190 (let ((buf (marker-buffer val)))
191 (if (null buf)
192 (princ "a marker in no buffer")
193 (princ "a buffer position:\n buffer ")
194 (princ (buffer-name buf))
195 (princ ", position ")
196 (princ (marker-position val)))))
197
198 ((and (consp val) (window-configuration-p (car val)))
199 (princ "a window configuration."))
200
201 ((and (consp val) (frame-configuration-p (car val)))
202 (princ "a frame configuration."))
203
204 ((and (consp val) (eq (car val) 'file))
205 (princ "the file ")
206 (prin1 (cdr val))
207 (princ "."))
208
209 ((and (consp val) (eq (car val) 'file-query))
210 (princ "a file-query reference:\n file ")
211 (prin1 (car (cdr val)))
212 (princ ",\n position ")
213 (princ (car (cdr (cdr val))))
214 (princ "."))
215
216 ((consp val)
217 (if verbose
218 (progn
219 (princ "the rectangle:\n")
220 (while val
221 (princ " ")
222 (princ (car val))
223 (terpri)
224 (setq val (cdr val))))
225 (princ "a rectangle starting with ")
226 (princ (car val))))
227
228 ((stringp val)
9c7cc04b
RS
229 (if (eq yank-excluded-properties t)
230 (set-text-properties 0 (length val) nil val)
231 (remove-list-of-text-properties 0 (length val)
232 yank-excluded-properties val))
6ed21409
RS
233 (if verbose
234 (progn
235 (princ "the text:\n")
236 (princ val))
f1180544 237 (cond
13d6f302
RS
238 ;; Extract first N characters starting with first non-whitespace.
239 ((string-match (format "[^ \t\n].\\{,%d\\}"
240 ;; Deduct 6 for the spaces inserted below.
241 (min 20 (max 0 (- (window-width) 6))))
242 val)
243 (princ "text starting with\n ")
244 (princ (match-string 0 val)))
245 ((string-match "^[ \t\n]+$" val)
246 (princ "whitespace"))
247 (t
248 (princ "the empty string")))))
6ed21409
RS
249 (t
250 (princ "Garbage:\n")
251 (if verbose (prin1 val))))))
efeae993 252
1b8cac5d
RS
253(defun insert-register (register &optional arg)
254 "Insert contents of register REGISTER. (REGISTER is a character.)
efeae993
RS
255Normally puts point before and mark after the inserted text.
256If optional second arg is non-nil, puts mark before and point after.
257Interactively, second arg is non-nil if prefix arg is supplied."
ecfc7eb3 258 (interactive "*cInsert register: \nP")
efeae993 259 (push-mark)
1b8cac5d 260 (let ((val (get-register register)))
cbd4993c
KH
261 (cond
262 ((consp val)
263 (insert-rectangle val))
264 ((stringp val)
e7c765c3 265 (insert-for-yank val))
070c2506 266 ((numberp val)
cbd4993c
KH
267 (princ val (current-buffer)))
268 ((and (markerp val) (marker-position val))
269 (princ (marker-position val) (current-buffer)))
270 (t
271 (error "Register does not contain text"))))
efeae993
RS
272 (if (not arg) (exchange-point-and-mark)))
273
1b8cac5d
RS
274(defun copy-to-register (register start end &optional delete-flag)
275 "Copy region into register REGISTER. With prefix arg, delete as well.
276Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
efeae993
RS
277START and END are buffer positions indicating what to copy."
278 (interactive "cCopy to register: \nr\nP")
13191e32 279 (set-register register (filter-buffer-substring start end))
efeae993
RS
280 (if delete-flag (delete-region start end)))
281
1b8cac5d
RS
282(defun append-to-register (register start end &optional delete-flag)
283 "Append region to text in register REGISTER.
284With prefix arg, delete as well.
285Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
efeae993
RS
286START and END are buffer positions indicating what to append."
287 (interactive "cAppend to register: \nr\nP")
c81f72ce
TTN
288 (let ((reg (get-register register))
289 (text (filter-buffer-substring start end)))
290 (set-register
291 register (cond ((not reg) text)
292 ((stringp reg) (concat reg text))
293 (t (error "Register does not contain text")))))
efeae993
RS
294 (if delete-flag (delete-region start end)))
295
1b8cac5d
RS
296(defun prepend-to-register (register start end &optional delete-flag)
297 "Prepend region to text in register REGISTER.
298With prefix arg, delete as well.
299Called from program, takes four args: REGISTER, START, END and DELETE-FLAG.
efeae993
RS
300START and END are buffer positions indicating what to prepend."
301 (interactive "cPrepend to register: \nr\nP")
c81f72ce
TTN
302 (let ((reg (get-register register))
303 (text (filter-buffer-substring start end)))
304 (set-register
305 register (cond ((not reg) text)
306 ((stringp reg) (concat text reg))
307 (t (error "Register does not contain text")))))
efeae993
RS
308 (if delete-flag (delete-region start end)))
309
1b8cac5d
RS
310(defun copy-rectangle-to-register (register start end &optional delete-flag)
311 "Copy rectangular region into register REGISTER.
5ef5d6ce
RS
312With prefix arg, delete as well. To insert this register
313in the buffer, use \\[insert-register].
314
315Called from a program, takes four args: REGISTER, START, END and DELETE-FLAG.
efeae993
RS
316START and END are buffer positions giving two corners of rectangle."
317 (interactive "cCopy rectangle to register: \nr\nP")
1b8cac5d 318 (set-register register
efeae993
RS
319 (if delete-flag
320 (delete-extract-rectangle start end)
321 (extract-rectangle start end))))
c88ab9ce 322
0f214cdf 323(provide 'register)
cbee283d 324;; arch-tag: ce14dd68-8265-475f-9341-5d4ec5a53035
c88ab9ce 325;;; register.el ends here