Update years in copyright notice; nfc.
[bpt/emacs.git] / lisp / abbrev.el
CommitLineData
c0274f38 1;;; abbrev.el --- abbrev mode commands for Emacs
e2fbf49d 2
0d30b337 3;; Copyright (C) 1985, 1986, 1987, 1992, 2002, 2003, 2004,
aaef169d 4;; 2005, 2006 Free Software Foundation, Inc.
e2fbf49d 5
6228c05b 6;; Maintainer: FSF
f5f727f8 7;; Keywords: abbrev convenience
e9571d2a 8
e2fbf49d
JB
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
e5167999 13;; the Free Software Foundation; either version 2, or (at your option)
e2fbf49d
JB
14;; any later version.
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
b578f267 22;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
e2fbf49d 25
e41b2db1
ER
26;;; Commentary:
27
28;; This facility is documented in the Emacs Manual.
29
e5167999 30;;; Code:
e2fbf49d 31
7cfedc97 32(defcustom only-global-abbrevs nil
e7fdaf63 33 "Non-nil means user plans to use global abbrevs only.
1d1e35a0
RS
34This makes the commands that normally define mode-specific abbrevs
35define global abbrevs instead."
36 :type 'boolean
f5f727f8
DN
37 :group 'abbrev-mode
38 :group 'convenience)
e2fbf49d 39
68d9550f 40(defun abbrev-mode (&optional arg)
38002bff 41 "Toggle Abbrev mode in the current buffer.
a864e33e 42With argument ARG, turn abbrev mode on iff ARG is positive.
38002bff 43In Abbrev mode, inserting an abbreviation causes it to expand
e2fbf49d
JB
44and be replaced by its expansion."
45 (interactive "P")
46 (setq abbrev-mode
47 (if (null arg) (not abbrev-mode)
48 (> (prefix-numeric-value arg) 0)))
e47df26a 49 (force-mode-line-update))
1d1e35a0
RS
50
51(defcustom abbrev-mode nil
38002bff 52 "Enable or disable Abbrev mode.
5cf1c7ac
RS
53Non-nil means automatically expand abbrevs as they are inserted.
54
38002bff 55Setting this variable with `setq' changes it for the current buffer.
5cf1c7ac 56Changing it with \\[customize] sets the default value.
38002bff
RS
57Interactively, use the command `abbrev-mode'
58to enable or disable Abbrev mode in the current buffer."
1d1e35a0
RS
59 :type 'boolean
60 :group 'abbrev-mode)
61
e2fbf49d 62\f
e7fdaf63
JPW
63(defvar edit-abbrevs-map
64 (let ((map (make-sparse-keymap)))
65 (define-key map "\C-x\C-s" 'edit-abbrevs-redefine)
66 (define-key map "\C-c\C-c" 'edit-abbrevs-redefine)
67 map)
38002bff 68 "Keymap used in `edit-abbrevs'.")
e2fbf49d
JB
69
70(defun kill-all-abbrevs ()
71 "Undefine all defined abbrevs."
72 (interactive)
73 (let ((tables abbrev-table-name-list))
74 (while tables
75 (clear-abbrev-table (symbol-value (car tables)))
76 (setq tables (cdr tables)))))
77
ad9d51b2
RS
78(defun copy-abbrev-table (table)
79 "Make a new abbrev-table with the same abbrevs as TABLE."
80 (let ((new-table (make-abbrev-table)))
81 (mapatoms
82 (lambda (symbol)
83 (define-abbrev new-table
84 (symbol-name symbol)
85 (symbol-value symbol)
86 (symbol-function symbol)))
87 table)
88 new-table))
89
e2fbf49d
JB
90(defun insert-abbrevs ()
91 "Insert after point a description of all defined abbrevs.
92Mark is set after the inserted text."
93 (interactive)
94 (push-mark
95 (save-excursion
71baa28f
EZ
96 (let ((tables abbrev-table-name-list))
97 (while tables
98 (insert-abbrev-table-description (car tables) t)
99 (setq tables (cdr tables))))
100 (point))))
e2fbf49d 101
c88a9944
GM
102(defun list-abbrevs (&optional local)
103 "Display a list of defined abbrevs.
104If LOCAL is non-nil, interactively when invoked with a
105prefix arg, display only local, i.e. mode-specific, abbrevs.
106Otherwise display all abbrevs."
107 (interactive "P")
108 (display-buffer (prepare-abbrev-list-buffer local)))
109
110(defun abbrev-table-name (table)
111 "Value is the name of abbrev table TABLE."
112 (let ((tables abbrev-table-name-list)
113 found)
114 (while (and (not found) tables)
115 (when (eq (symbol-value (car tables)) table)
116 (setq found (car tables)))
117 (setq tables (cdr tables)))
118 found))
7cfedc97 119
c88a9944 120(defun prepare-abbrev-list-buffer (&optional local)
e2fbf49d 121 (save-excursion
25160ec0
GM
122 (let ((table local-abbrev-table))
123 (set-buffer (get-buffer-create "*Abbrevs*"))
124 (erase-buffer)
125 (if local
126 (insert-abbrev-table-description (abbrev-table-name table) t)
127 (dolist (table abbrev-table-name-list)
128 (insert-abbrev-table-description table t)))
129 (goto-char (point-min))
130 (set-buffer-modified-p nil)
131 (edit-abbrevs-mode)
132 (current-buffer))))
e2fbf49d
JB
133
134(defun edit-abbrevs-mode ()
135 "Major mode for editing the list of abbrev definitions.
136\\{edit-abbrevs-map}"
137 (interactive)
1a96d1f3 138 (kill-all-local-variables)
e2fbf49d
JB
139 (setq major-mode 'edit-abbrevs-mode)
140 (setq mode-name "Edit-Abbrevs")
1a96d1f3
LK
141 (use-local-map edit-abbrevs-map)
142 (run-mode-hooks 'edit-abbrevs-mode-hook))
e2fbf49d
JB
143
144(defun edit-abbrevs ()
145 "Alter abbrev definitions by editing a list of them.
146Selects a buffer containing a list of abbrev definitions.
147You can edit them and type \\<edit-abbrevs-map>\\[edit-abbrevs-redefine] to redefine abbrevs
148according to your editing.
149Buffer contains a header line for each abbrev table,
150 which is the abbrev table name in parentheses.
151This is followed by one line per abbrev in that table:
152NAME USECOUNT EXPANSION HOOK
153where NAME and EXPANSION are strings with quotes,
154USECOUNT is an integer, and HOOK is any valid function
155or may be omitted (it is usually omitted)."
156 (interactive)
157 (switch-to-buffer (prepare-abbrev-list-buffer)))
158
159(defun edit-abbrevs-redefine ()
160 "Redefine abbrevs according to current buffer contents."
161 (interactive)
162 (define-abbrevs t)
163 (set-buffer-modified-p nil))
164
165(defun define-abbrevs (&optional arg)
166 "Define abbrevs according to current visible buffer contents.
167See documentation of `edit-abbrevs' for info on the format of the
168text you must have in the buffer.
169With argument, eliminate all abbrev definitions except
170the ones defined from the buffer now."
171 (interactive "P")
172 (if arg (kill-all-abbrevs))
173 (save-excursion
71baa28f
EZ
174 (goto-char (point-min))
175 (while (and (not (eobp)) (re-search-forward "^(" nil t))
176 (let* ((buf (current-buffer))
177 (table (read buf))
178 abbrevs name hook exp count sys)
179 (forward-line 1)
180 (while (progn (forward-line 1)
181 (not (eolp)))
182 (setq name (read buf) count (read buf))
183 (if (equal count '(sys))
184 (setq sys t count (read buf)))
185 (setq exp (read buf))
186 (skip-chars-backward " \t\n\f")
187 (setq hook (if (not (eolp)) (read buf)))
188 (skip-chars-backward " \t\n\f")
189 (setq abbrevs (cons (list name exp hook count sys) abbrevs)))
190 (define-abbrev-table table abbrevs)))))
e2fbf49d
JB
191
192(defun read-abbrev-file (&optional file quietly)
193 "Read abbrev definitions from file written with `write-abbrev-file'.
194Optional argument FILE is the name of the file to read;
195it defaults to the value of `abbrev-file-name'.
d0b6d945 196Optional second argument QUIETLY non-nil means don't display a message."
e2fbf49d
JB
197 (interactive "fRead abbrev file: ")
198 (load (if (and file (> (length file) 0)) file abbrev-file-name)
199 nil quietly)
d0b6d945 200 (setq abbrevs-changed nil))
e2fbf49d
JB
201
202(defun quietly-read-abbrev-file (&optional file)
e7fdaf63 203 "Read abbrev definitions from file written with `write-abbrev-file'.
e2fbf49d
JB
204Optional argument FILE is the name of the file to read;
205it defaults to the value of `abbrev-file-name'.
d0b6d945 206Does not display any message."
71baa28f 207 ;(interactive "fRead abbrev file: ")
e2fbf49d
JB
208 (read-abbrev-file file t))
209
68063965
LT
210(defun write-abbrev-file (&optional file)
211 "Write all user-level abbrev definitions to a file of Lisp code.
212This does not include system abbrevs; it includes only the abbrev tables
213listed in listed in `abbrev-table-name-list'.
e2fbf49d 214The file written can be loaded in another session to define the same abbrevs.
68063965
LT
215The argument FILE is the file name to write. If omitted or nil, the file
216specified in `abbrev-file-name' is used."
e2fbf49d
JB
217 (interactive
218 (list
219 (read-file-name "Write abbrev file: "
220 (file-name-directory (expand-file-name abbrev-file-name))
221 abbrev-file-name)))
e2fbf49d
JB
222 (or (and file (> (length file) 0))
223 (setq file abbrev-file-name))
a166f623
DL
224 (let ((coding-system-for-write 'emacs-mule))
225 (with-temp-file file
226 (insert ";;-*-coding: emacs-mule;-*-\n")
71baa28f
EZ
227 (dolist (table
228 ;; We sort the table in order to ease the automatic
229 ;; merging of different versions of the user's abbrevs
230 ;; file. This is useful, for example, for when the
231 ;; user keeps their home directory in a revision
232 ;; control system, and is therefore keeping multiple
233 ;; slightly-differing copies loosely synchronized.
234 (sort (copy-sequence abbrev-table-name-list)
235 (lambda (s1 s2)
236 (string< (symbol-name s1)
237 (symbol-name s2)))))
a166f623 238 (insert-abbrev-table-description table nil)))))
e2fbf49d
JB
239\f
240(defun add-mode-abbrev (arg)
241 "Define mode-specific abbrev for last word(s) before point.
242Argument is how many words before point form the expansion;
243or zero means the region is the expansion.
244A negative argument means to undefine the specified abbrev.
245Reads the abbreviation in the minibuffer.
246
247Don't use this function in a Lisp program; use `define-abbrev' instead."
248 (interactive "p")
249 (add-abbrev
250 (if only-global-abbrevs
71296446 251 global-abbrev-table
e2fbf49d
JB
252 (or local-abbrev-table
253 (error "No per-mode abbrev table")))
254 "Mode" arg))
255
256(defun add-global-abbrev (arg)
257 "Define global (all modes) abbrev for last word(s) before point.
258The prefix argument specifies the number of words before point that form the
259expansion; or zero means the region is the expansion.
260A negative argument means to undefine the specified abbrev.
261This command uses the minibuffer to read the abbreviation.
262
263Don't use this function in a Lisp program; use `define-abbrev' instead."
264 (interactive "p")
265 (add-abbrev global-abbrev-table "Global" arg))
266
267(defun add-abbrev (table type arg)
268 (let ((exp (and (>= arg 0)
34f3cd03 269 (buffer-substring-no-properties
e2fbf49d
JB
270 (point)
271 (if (= arg 0) (mark)
272 (save-excursion (forward-word (- arg)) (point))))))
273 name)
274 (setq name
275 (read-string (format (if exp "%s abbrev for \"%s\": "
276 "Undefine %s abbrev: ")
277 type exp)))
a0f88464 278 (set-text-properties 0 (length name) nil name)
e2fbf49d
JB
279 (if (or (null exp)
280 (not (abbrev-expansion name table))
281 (y-or-n-p (format "%s expands to \"%s\"; redefine? "
282 name (abbrev-expansion name table))))
283 (define-abbrev table (downcase name) exp))))
7cfedc97 284
e66b273f 285(defun inverse-add-mode-abbrev (n)
e2fbf49d
JB
286 "Define last word before point as a mode-specific abbrev.
287With prefix argument N, defines the Nth word before point.
288This command uses the minibuffer to read the expansion.
289Expands the abbreviation after defining it."
290 (interactive "p")
291 (inverse-add-abbrev
292 (if only-global-abbrevs
7cfedc97 293 global-abbrev-table
e2fbf49d
JB
294 (or local-abbrev-table
295 (error "No per-mode abbrev table")))
e66b273f 296 "Mode" n))
e2fbf49d 297
e66b273f 298(defun inverse-add-global-abbrev (n)
e2fbf49d
JB
299 "Define last word before point as a global (mode-independent) abbrev.
300With prefix argument N, defines the Nth word before point.
301This command uses the minibuffer to read the expansion.
302Expands the abbreviation after defining it."
303 (interactive "p")
e66b273f 304 (inverse-add-abbrev global-abbrev-table "Global" n))
e2fbf49d
JB
305
306(defun inverse-add-abbrev (table type arg)
46684068 307 (let (name exp start end)
e2fbf49d 308 (save-excursion
46684068
GM
309 (forward-word (1+ (- arg)))
310 (setq end (point))
311 (backward-word 1)
312 (setq start (point)
313 name (buffer-substring-no-properties start end)))
314
315 (setq exp (read-string (format "%s expansion for \"%s\": " type name)
316 nil nil nil t))
317 (when (or (not (abbrev-expansion name table))
318 (y-or-n-p (format "%s expands to \"%s\"; redefine? "
319 name (abbrev-expansion name table))))
320 (define-abbrev table (downcase name) exp)
321 (save-excursion
322 (goto-char end)
323 (expand-abbrev)))))
e2fbf49d
JB
324
325(defun abbrev-prefix-mark (&optional arg)
326 "Mark current point as the beginning of an abbrev.
327Abbrev to be expanded starts here rather than at beginning of word.
328This way, you can expand an abbrev with a prefix: insert the prefix,
68063965
LT
329use this command, then insert the abbrev. This command inserts a
330temporary hyphen after the prefix \(until the intended abbrev
331expansion occurs).
332If the prefix is itself an abbrev, this command expands it, unless
333ARG is non-nil. Interactively, ARG is the prefix argument."
e2fbf49d
JB
334 (interactive "P")
335 (or arg (expand-abbrev))
336 (setq abbrev-start-location (point-marker)
337 abbrev-start-location-buffer (current-buffer))
338 (insert "-"))
339
340(defun expand-region-abbrevs (start end &optional noquery)
341 "For abbrev occurrence in the region, offer to expand it.
e66b273f
JB
342The user is asked to type `y' or `n' for each occurrence.
343A prefix argument means don't query; expand all abbrevs."
e2fbf49d
JB
344 (interactive "r\nP")
345 (save-excursion
346 (goto-char start)
347 (let ((lim (- (point-max) end))
348 pnt string)
349 (while (and (not (eobp))
350 (progn (forward-word 1)
351 (<= (setq pnt (point)) (- (point-max) lim))))
352 (if (abbrev-expansion
353 (setq string
34f3cd03 354 (buffer-substring-no-properties
e2fbf49d
JB
355 (save-excursion (forward-word -1) (point))
356 pnt)))
357 (if (or noquery (y-or-n-p (format "Expand `%s'? " string)))
358 (expand-abbrev)))))))
c0274f38 359
ab5796a9 360;;; arch-tag: dbd6f3ae-dfe3-40ba-b00f-f9e3ff960df5
c0274f38 361;;; abbrev.el ends here