*** empty log message ***
[bpt/emacs.git] / lisp / abbrev.el
CommitLineData
c0274f38 1;;; abbrev.el --- abbrev mode commands for Emacs
e2fbf49d 2
e5167999 3;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
e2fbf49d 4
f5f727f8 5;; Keywords: abbrev convenience
e9571d2a 6
e2fbf49d
JB
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
e5167999 11;; the Free Software Foundation; either version 2, or (at your option)
e2fbf49d
JB
12;; any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
b578f267
EN
20;; along with GNU Emacs; see the file COPYING. If not, write to the
21;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22;; Boston, MA 02111-1307, USA.
e2fbf49d 23
e41b2db1
ER
24;;; Commentary:
25
26;; This facility is documented in the Emacs Manual.
27
e5167999 28;;; Code:
e2fbf49d 29
1d1e35a0
RS
30(defcustom only-global-abbrevs nil
31 "*t means user plans to use global abbrevs only.
32This makes the commands that normally define mode-specific abbrevs
33define global abbrevs instead."
34 :type 'boolean
f5f727f8
DN
35 :group 'abbrev-mode
36 :group 'convenience)
e2fbf49d
JB
37
38(defun abbrev-mode (arg)
39 "Toggle abbrev mode.
a864e33e 40With argument ARG, turn abbrev mode on iff ARG is positive.
e2fbf49d
JB
41In abbrev mode, inserting an abbreviation causes it to expand
42and be replaced by its expansion."
43 (interactive "P")
44 (setq abbrev-mode
45 (if (null arg) (not abbrev-mode)
46 (> (prefix-numeric-value arg) 0)))
e47df26a 47 (force-mode-line-update))
1d1e35a0
RS
48
49(defcustom abbrev-mode nil
50 "Toggle abbrev mode.
5cf1c7ac
RS
51Non-nil means automatically expand abbrevs as they are inserted.
52
53This variable automatically becomes buffer-local when set in any fashion.
54Changing it with \\[customize] sets the default value.
55Use the command `abbrev-mode' to enable or disable Abbrev mode in the current
56buffer."
1d1e35a0
RS
57 :type 'boolean
58 :group 'abbrev-mode)
59
e2fbf49d
JB
60\f
61(defvar edit-abbrevs-map nil
62 "Keymap used in edit-abbrevs.")
63(if edit-abbrevs-map
64 nil
65 (setq edit-abbrevs-map (make-sparse-keymap))
66 (define-key edit-abbrevs-map "\C-x\C-s" 'edit-abbrevs-redefine)
67 (define-key edit-abbrevs-map "\C-c\C-c" 'edit-abbrevs-redefine))
68
69(defun kill-all-abbrevs ()
70 "Undefine all defined abbrevs."
71 (interactive)
72 (let ((tables abbrev-table-name-list))
73 (while tables
74 (clear-abbrev-table (symbol-value (car tables)))
75 (setq tables (cdr tables)))))
76
77(defun insert-abbrevs ()
78 "Insert after point a description of all defined abbrevs.
79Mark is set after the inserted text."
80 (interactive)
81 (push-mark
82 (save-excursion
83 (let ((tables abbrev-table-name-list))
84 (while tables
85 (insert-abbrev-table-description (car tables) t)
86 (setq tables (cdr tables))))
87 (point))))
88
89(defun list-abbrevs ()
90 "Display a list of all defined abbrevs."
91 (interactive)
92 (display-buffer (prepare-abbrev-list-buffer)))
93
94(defun prepare-abbrev-list-buffer ()
95 (save-excursion
96 (set-buffer (get-buffer-create "*Abbrevs*"))
97 (erase-buffer)
98 (let ((tables abbrev-table-name-list))
99 (while tables
100 (insert-abbrev-table-description (car tables) t)
101 (setq tables (cdr tables))))
102 (goto-char (point-min))
103 (set-buffer-modified-p nil)
104 (edit-abbrevs-mode))
105 (get-buffer-create "*Abbrevs*"))
106
107(defun edit-abbrevs-mode ()
108 "Major mode for editing the list of abbrev definitions.
109\\{edit-abbrevs-map}"
110 (interactive)
111 (setq major-mode 'edit-abbrevs-mode)
112 (setq mode-name "Edit-Abbrevs")
113 (use-local-map edit-abbrevs-map))
114
115(defun edit-abbrevs ()
116 "Alter abbrev definitions by editing a list of them.
117Selects a buffer containing a list of abbrev definitions.
118You can edit them and type \\<edit-abbrevs-map>\\[edit-abbrevs-redefine] to redefine abbrevs
119according to your editing.
120Buffer contains a header line for each abbrev table,
121 which is the abbrev table name in parentheses.
122This is followed by one line per abbrev in that table:
123NAME USECOUNT EXPANSION HOOK
124where NAME and EXPANSION are strings with quotes,
125USECOUNT is an integer, and HOOK is any valid function
126or may be omitted (it is usually omitted)."
127 (interactive)
128 (switch-to-buffer (prepare-abbrev-list-buffer)))
129
130(defun edit-abbrevs-redefine ()
131 "Redefine abbrevs according to current buffer contents."
132 (interactive)
133 (define-abbrevs t)
134 (set-buffer-modified-p nil))
135
136(defun define-abbrevs (&optional arg)
137 "Define abbrevs according to current visible buffer contents.
138See documentation of `edit-abbrevs' for info on the format of the
139text you must have in the buffer.
140With argument, eliminate all abbrev definitions except
141the ones defined from the buffer now."
142 (interactive "P")
143 (if arg (kill-all-abbrevs))
144 (save-excursion
145 (goto-char (point-min))
146 (while (and (not (eobp)) (re-search-forward "^(" nil t))
147 (let* ((buf (current-buffer))
148 (table (read buf))
ba343182 149 abbrevs name hook exp count)
e2fbf49d
JB
150 (forward-line 1)
151 (while (progn (forward-line 1)
152 (not (eolp)))
153 (setq name (read buf) count (read buf) exp (read buf))
154 (skip-chars-backward " \t\n\f")
155 (setq hook (if (not (eolp)) (read buf)))
156 (skip-chars-backward " \t\n\f")
157 (setq abbrevs (cons (list name exp hook count) abbrevs)))
158 (define-abbrev-table table abbrevs)))))
159
160(defun read-abbrev-file (&optional file quietly)
161 "Read abbrev definitions from file written with `write-abbrev-file'.
162Optional argument FILE is the name of the file to read;
163it defaults to the value of `abbrev-file-name'.
164Optional second argument QUIETLY non-nil means don't print anything."
165 (interactive "fRead abbrev file: ")
166 (load (if (and file (> (length file) 0)) file abbrev-file-name)
167 nil quietly)
168 (setq save-abbrevs t abbrevs-changed nil))
169
170(defun quietly-read-abbrev-file (&optional file)
171 "Read abbrev definitions from file written with write-abbrev-file.
172Optional argument FILE is the name of the file to read;
173it defaults to the value of `abbrev-file-name'.
174Does not print anything."
175 ;(interactive "fRead abbrev file: ")
176 (read-abbrev-file file t))
177
178(defun write-abbrev-file (file)
e5167999 179 "Write all abbrev definitions to a file of Lisp code.
e2fbf49d
JB
180The file written can be loaded in another session to define the same abbrevs.
181The argument FILE is the file name to write."
182 (interactive
183 (list
184 (read-file-name "Write abbrev file: "
185 (file-name-directory (expand-file-name abbrev-file-name))
186 abbrev-file-name)))
e2fbf49d
JB
187 (or (and file (> (length file) 0))
188 (setq file abbrev-file-name))
189 (save-excursion
190 (set-buffer (get-buffer-create " write-abbrev-file"))
191 (erase-buffer)
192 (let ((tables abbrev-table-name-list))
193 (while tables
194 (insert-abbrev-table-description (car tables) nil)
195 (setq tables (cdr tables))))
196 (write-region 1 (point-max) file)
197 (erase-buffer)))
198\f
199(defun add-mode-abbrev (arg)
200 "Define mode-specific abbrev for last word(s) before point.
201Argument is how many words before point form the expansion;
202or zero means the region is the expansion.
203A negative argument means to undefine the specified abbrev.
204Reads the abbreviation in the minibuffer.
205
206Don't use this function in a Lisp program; use `define-abbrev' instead."
207 (interactive "p")
208 (add-abbrev
209 (if only-global-abbrevs
210 global-abbrev-table
211 (or local-abbrev-table
212 (error "No per-mode abbrev table")))
213 "Mode" arg))
214
215(defun add-global-abbrev (arg)
216 "Define global (all modes) abbrev for last word(s) before point.
217The prefix argument specifies the number of words before point that form the
218expansion; or zero means the region is the expansion.
219A negative argument means to undefine the specified abbrev.
220This command uses the minibuffer to read the abbreviation.
221
222Don't use this function in a Lisp program; use `define-abbrev' instead."
223 (interactive "p")
224 (add-abbrev global-abbrev-table "Global" arg))
225
226(defun add-abbrev (table type arg)
227 (let ((exp (and (>= arg 0)
34f3cd03 228 (buffer-substring-no-properties
e2fbf49d
JB
229 (point)
230 (if (= arg 0) (mark)
231 (save-excursion (forward-word (- arg)) (point))))))
232 name)
233 (setq name
234 (read-string (format (if exp "%s abbrev for \"%s\": "
235 "Undefine %s abbrev: ")
236 type exp)))
a0f88464 237 (set-text-properties 0 (length name) nil name)
e2fbf49d
JB
238 (if (or (null exp)
239 (not (abbrev-expansion name table))
240 (y-or-n-p (format "%s expands to \"%s\"; redefine? "
241 name (abbrev-expansion name table))))
242 (define-abbrev table (downcase name) exp))))
243
244(defun inverse-add-mode-abbrev (arg)
245 "Define last word before point as a mode-specific abbrev.
246With prefix argument N, defines the Nth word before point.
247This command uses the minibuffer to read the expansion.
248Expands the abbreviation after defining it."
249 (interactive "p")
250 (inverse-add-abbrev
251 (if only-global-abbrevs
252 global-abbrev-table
253 (or local-abbrev-table
254 (error "No per-mode abbrev table")))
255 "Mode" arg))
256
257(defun inverse-add-global-abbrev (arg)
258 "Define last word before point as a global (mode-independent) abbrev.
259With prefix argument N, defines the Nth word before point.
260This command uses the minibuffer to read the expansion.
261Expands the abbreviation after defining it."
262 (interactive "p")
263 (inverse-add-abbrev global-abbrev-table "Global" arg))
264
265(defun inverse-add-abbrev (table type arg)
266 (let (name nameloc exp)
267 (save-excursion
268 (forward-word (- arg))
34f3cd03
DL
269 (setq name (buffer-substring-no-properties
270 (point) (progn (forward-word 1) (setq nameloc (point))))))
a0f88464 271 (set-text-properties 0 (length name) nil name)
e2fbf49d 272 (setq exp (read-string (format "%s expansion for \"%s\": "
189a69d0 273 type name) nil nil nil t))
e2fbf49d
JB
274 (if (or (not (abbrev-expansion name table))
275 (y-or-n-p (format "%s expands to \"%s\"; redefine? "
276 name (abbrev-expansion name table))))
277 (progn
278 (define-abbrev table (downcase name) exp)
279 (save-excursion
280 (goto-char nameloc)
281 (expand-abbrev))))))
282
283(defun abbrev-prefix-mark (&optional arg)
284 "Mark current point as the beginning of an abbrev.
285Abbrev to be expanded starts here rather than at beginning of word.
286This way, you can expand an abbrev with a prefix: insert the prefix,
287use this command, then insert the abbrev."
288 (interactive "P")
289 (or arg (expand-abbrev))
290 (setq abbrev-start-location (point-marker)
291 abbrev-start-location-buffer (current-buffer))
292 (insert "-"))
293
294(defun expand-region-abbrevs (start end &optional noquery)
295 "For abbrev occurrence in the region, offer to expand it.
296The user is asked to type y or n for each occurrence.
297A prefix argument means don't query; expand all abbrevs.
298If called from a Lisp program, arguments are START END &optional NOQUERY."
299 (interactive "r\nP")
300 (save-excursion
301 (goto-char start)
302 (let ((lim (- (point-max) end))
303 pnt string)
304 (while (and (not (eobp))
305 (progn (forward-word 1)
306 (<= (setq pnt (point)) (- (point-max) lim))))
307 (if (abbrev-expansion
308 (setq string
34f3cd03 309 (buffer-substring-no-properties
e2fbf49d
JB
310 (save-excursion (forward-word -1) (point))
311 pnt)))
312 (if (or noquery (y-or-n-p (format "Expand `%s'? " string)))
313 (expand-abbrev)))))))
c0274f38
ER
314
315;;; abbrev.el ends here