comparison lisp/tempo.el @ 7410:4eca60cb3c4d

(tempo-insert-region, tempo-show-completion-buffer, tempo-leave-completion-buffer): New variables. (tempo-complete-tag): Added a completion buffer mechanism. (tempo-display-completions): New function. (tempo-insert-template): An extension to the (p ...) tag enables named insertion for later insertion using a (s ...) tag.
author Richard M. Stallman <rms@gnu.org>
date Sun, 08 May 1994 21:11:37 +0000
parents eb888748ca9b
children 488c5be866c3
comparison
equal deleted inserted replaced
7409:fe56a02838ba 7410:4eca60cb3c4d
1 ;;; tempo.el --- templates with hotspots 1 ;;; tempo.el --- templates with hotspots
2 ;; Copyright (C) 1994 Free Software Foundation, Inc. 2 ;; Copyright (C) 1994 Free Software Foundation, Inc.
3 3
4 ;; Author: David K}gedal <davidk@lysator.liu.se > 4 ;; Author: David K}gedal <davidk@lysator.liu.se >
5 ;; Created: 16 Feb 1994 5 ;; Created: 16 Feb 1994
6 ;; Version: 1.0 6 ;; Version: 1.1.1
7 ;; Keywords: extensions, languages, tools 7 ;; Keywords: extensions, languages, tools
8 8
9 ;; This file is part of GNU Emacs. 9 ;; This file is part of GNU Emacs.
10 10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify 11 ;; GNU Emacs is free software; you can redistribute it and/or modify
87 (defvar tempo-interactive nil 87 (defvar tempo-interactive nil
88 "*Prompt user for strings in templates. 88 "*Prompt user for strings in templates.
89 If this variable is non-nil, `tempo-insert' prompts the 89 If this variable is non-nil, `tempo-insert' prompts the
90 user for text to insert in the templates") 90 user for text to insert in the templates")
91 91
92 (defvar tempo-insert-region nil
93 "*Automatically insert current region when there is a `r' in the template
94 If this variable is NIL, `r' elements will be treated just like `p'
95 elements, unless the template function is given a prefix (or a non-nil
96 argument). If this variable is non-NIL, the behaviour is reversed.")
97
98 (defvar tempo-show-completion-buffer t
99 "*If non-NIL, show a buffer with possible completions, when only
100 a partial completion can be found")
101
102 (defvar tempo-leave-completion-buffer nil
103 "*If NIL, a completion buffer generated by \\[tempo-complete-tag]
104 disappears at the next keypress; otherwise, it remains forever.")
105
92 (defvar tempo-insert-string-functions nil 106 (defvar tempo-insert-string-functions nil
93 "List of functions to run when inserting a string. 107 "List of functions to run when inserting a string.
94 Each function is called with a single arg, STRING." ) 108 Each function is called with a single arg, STRING." )
95 109
96 (defvar tempo-tags nil 110 (defvar tempo-tags nil
109 (defvar tempo-marks nil 123 (defvar tempo-marks nil
110 "A list of marks to jump to with `\\[tempo-forward-mark]' and `\\[tempo-backward-mark]'.") 124 "A list of marks to jump to with `\\[tempo-forward-mark]' and `\\[tempo-backward-mark]'.")
111 125
112 (defvar tempo-default-match-finder "\\b\\([^\\b]*\\)\\=" 126 (defvar tempo-default-match-finder "\\b\\([^\\b]*\\)\\="
113 "The default regexp used to find the string to match against the tags.") 127 "The default regexp used to find the string to match against the tags.")
128
129 (defvar tempo-named-insertions nil
130 "Temporary storage for named insertions")
114 131
115 ;; Make some variables local to every buffer 132 ;; Make some variables local to every buffer
116 133
117 (make-variable-buffer-local 'tempo-marks) 134 (make-variable-buffer-local 'tempo-marks)
118 (make-variable-buffer-local 'tempo-local-tags) 135 (make-variable-buffer-local 'tempo-local-tags)
140 - A string. It is sent to the hooks in `tempo-insert-string-functions', 157 - A string. It is sent to the hooks in `tempo-insert-string-functions',
141 and the result is inserted. 158 and the result is inserted.
142 - The symbol 'p. This position is saved in `tempo-marks'. 159 - The symbol 'p. This position is saved in `tempo-marks'.
143 - The symbol 'r. If `tempo-insert' is called with ON-REGION non-nil 160 - The symbol 'r. If `tempo-insert' is called with ON-REGION non-nil
144 the current region is placed here. Otherwise it works like 'p. 161 the current region is placed here. Otherwise it works like 'p.
145 - (p . PROMPT) If `tempo-interactive' is non-nil, the user is 162 - (p PROMPT <NAME>) If `tempo-interactive' is non-nil, the user is
146 prompted in the minbuffer with PROMPT for a string to be inserted. 163 prompted in the minbuffer with PROMPT for a string to be inserted.
164 If the optional parameter NAME is non-nil, the text is saved for
165 later insertion with the `s' tag.
147 If `tempo-interactive is nil, it works like 'p. 166 If `tempo-interactive is nil, it works like 'p.
148 - (r . PROMPT) like the previou, but if `tempo-interactive' is nil 167 - (r PROMPT) like the previous, but if `tempo-interactive' is nil
149 and `tempo-insert' is called with ON-REGION non-nil, the current 168 and `tempo-insert' is called with ON-REGION non-nil, the current
150 region is placed here. 169 region is placed here.
170 - (s NAME) Inserts text previously read with the (p ..) construct.
171 Finds the insertion saved under NAME and inserts it. Acts like 'p
172 if tempo-interactive is nil.
151 - '& If there is only whitespace between the line start and point, 173 - '& If there is only whitespace between the line start and point,
152 nothing happens. Otherwise a newline is inserted. 174 nothing happens. Otherwise a newline is inserted.
153 - '% If there is only whitespace between point and end-of-line 175 - '% If there is only whitespace between point and end-of-line
154 nothing happens. Otherwise a newline is inserted. 176 nothing happens. Otherwise a newline is inserted.
155 - 'n inserts a newline. 177 - 'n inserts a newline.
167 (fset command-name (list 'lambda (list '&optional 'arg) 189 (fset command-name (list 'lambda (list '&optional 'arg)
168 (or documentation 190 (or documentation
169 (concat "Insert a " name ".")) 191 (concat "Insert a " name "."))
170 (list 'interactive "*P") 192 (list 'interactive "*P")
171 (list 'tempo-insert-template (list 'quote 193 (list 'tempo-insert-template (list 'quote
172 template-name) 194 template-name)
173 'arg))) 195 (list 'if 'tempo-insert-region
196 (list 'not 'arg) 'arg))))
174 (and tag 197 (and tag
175 (tempo-add-tag tag template-name taglist)) 198 (tempo-add-tag tag template-name taglist))
176 command-name)) 199 command-name))
177 200
178 ;;; 201 ;;;
188 (save-excursion 211 (save-excursion
189 (tempo-insert-mark (point-marker)) 212 (tempo-insert-mark (point-marker))
190 (mapcar 'tempo-insert 213 (mapcar 'tempo-insert
191 (symbol-value template)) 214 (symbol-value template))
192 (tempo-insert-mark (point-marker))) 215 (tempo-insert-mark (point-marker)))
193 (tempo-forward-mark)) 216 (tempo-forward-mark)
217 (tempo-forget-insertions))
194 218
195 ;;; 219 ;;;
196 ;;; tempo-insert 220 ;;; tempo-insert
197 221
198 (defun tempo-insert (element) 222 (defun tempo-insert (element)
204 (tempo-insert-prompt (cdr element))) 228 (tempo-insert-prompt (cdr element)))
205 ((and (consp element) (eq (car element) 'r)) 229 ((and (consp element) (eq (car element) 'r))
206 (if on-region 230 (if on-region
207 (exchange-point-and-mark) 231 (exchange-point-and-mark)
208 (tempo-insert-prompt (cdr element)))) 232 (tempo-insert-prompt (cdr element))))
233 ((and (consp element) (eq (car element) 's))
234 (if tempo-interactive
235 (tempo-insert-named (cdr element))
236 (tempo-insert-mark (point-marker))))
209 ((eq element 'p) (tempo-insert-mark (point-marker))) 237 ((eq element 'p) (tempo-insert-mark (point-marker)))
210 ((eq element 'r) (if on-region 238 ((eq element 'r) (if on-region
211 (exchange-point-and-mark) 239 (exchange-point-and-mark)
212 (tempo-insert-mark (point-marker)))) 240 (tempo-insert-mark (point-marker))))
213 ((eq element '>) (indent-according-to-mode)) 241 ((eq element '>) (indent-according-to-mode))
232 (defun tempo-insert-prompt (prompt) 260 (defun tempo-insert-prompt (prompt)
233 "Prompt for a text string and insert it in the current buffer. 261 "Prompt for a text string and insert it in the current buffer.
234 If the variable `tempo-interactive' is non-nil the user is prompted 262 If the variable `tempo-interactive' is non-nil the user is prompted
235 for a string in the minibuffer, which is then inserted in the current 263 for a string in the minibuffer, which is then inserted in the current
236 buffer. If `tempo-interactive' is nil, the current point is placed on 264 buffer. If `tempo-interactive' is nil, the current point is placed on
237 `tempo-forward-mark-list'. 265 `tempo-mark'.
238 266
239 PROMPT is the prompt string." 267 PROMPT is the prompt string or a list containing the prompt string and
268 a name to save the inserted text under."
240 (if tempo-interactive 269 (if tempo-interactive
241 (insert (read-string prompt)) 270 (let ((prompt-string (if (listp prompt)
271 (car prompt)
272 prompt))
273 (save-name (and (listp prompt) (nth 1 prompt)))
274 inserted-text)
275
276 (progn
277 (setq inserted-text (read-string prompt-string))
278 (insert inserted-text)
279 (if save-name
280 (tempo-remember-insertion save-name inserted-text))))
242 (tempo-insert-mark (point-marker)))) 281 (tempo-insert-mark (point-marker))))
282
283 ;;;
284 ;;; tempo-remember-insertion
285
286 (defun tempo-remember-insertion (save-name string)
287 "Save the text in STRING under the name SAVE-NAME for later retrieval."
288 (setq tempo-named-insertions (cons (cons save-name string)
289 tempo-named-insertions)))
290
291 ;;;
292 ;;; tempo-forget-insertions
293
294 (defun tempo-forget-insertions ()
295 "Forget all the saved named insertions."
296 (setq tempo-named-insertions nil))
297
298 ;;;
299 ;;; tempo-insert-named
300
301 (defun tempo-insert-named (elt)
302 "Insert the previous insertion saved under a named specified in ELT.
303 The name is in the car of ELT."
304 (let* ((name (car elt))
305 (insertion (cdr (assq name tempo-named-insertions))))
306 (if insertion
307 (insert insertion)
308 (error "Named insertion not found"))))
243 309
244 ;;; 310 ;;;
245 ;;; tempo-process-and-insert-string 311 ;;; tempo-process-and-insert-string
246 312
247 (defun tempo-process-and-insert-string (string) 313 (defun tempo-process-and-insert-string (string)
248 "Insert a string from a template. 314 "Insert a string from a template.
249 Run a string through the preprocessors in `tempo-insert-string-functions' 315 Run a string through the preprocessors in `tempo-insert-string-functions'
250 and insert the results." 316 and insert the results."
251
252 (cond ((null tempo-insert-string-functions) 317 (cond ((null tempo-insert-string-functions)
253 nil) 318 nil)
254 ((symbolp tempo-insert-string-functions) 319 ((symbolp tempo-insert-string-functions)
255 (setq string 320 (setq string
256 (apply tempo-insert-string-functions (list string)))) 321 (apply tempo-insert-string-functions (list string))))
379 444
380 ;;; 445 ;;;
381 ;;; tempo-complete-tag 446 ;;; tempo-complete-tag
382 447
383 (defun tempo-complete-tag (&optional silent) 448 (defun tempo-complete-tag (&optional silent)
384 "Look for a tag and expand it.. 449 "Look for a tag and expand it.
385 450
386 It goes through the tag lists in `tempo-local-tags' (this includes 451 It goes through the tag lists in `tempo-local-tags' (this includes
387 `tempo-tags') and for each list it uses the corresponding match-finder 452 `tempo-tags') and for each list it uses the corresponding match-finder
388 function, or `tempo-default-match-finder' if none is given, and tries 453 function, or `tempo-default-match-finder' if none is given, and tries
389 to match the match string against the tags in the list using 454 to match the match string against the tags in the list using
395 When doing partial completion, only tags in the currently examined 460 When doing partial completion, only tags in the currently examined
396 list are considered, so if you provide similar tags in different lists 461 list are considered, so if you provide similar tags in different lists
397 in `tempo-local-tags', the result may not be desirable. 462 in `tempo-local-tags', the result may not be desirable.
398 463
399 If no match is found or a partial match is found, and SILENT is 464 If no match is found or a partial match is found, and SILENT is
400 non-nil, the function will give a signal." 465 non-nil, the function will give a signal.
401 466
467 If tempo-show-completion-buffer is non-NIL, a buffer containing
468 possible completions is displayed when a partial completion is found."
469
470 ;; This function is really messy. Some cleaning up is necessary.
402 (interactive) 471 (interactive)
403 (if (catch 'completed 472 (if (catch 'completed
404 (mapcar 473 (mapcar
405 (function 474 (function
406 (lambda (tag-list-a) 475 (lambda (tag-list-a)
409 tempo-default-match-finder)) 478 tempo-default-match-finder))
410 (match-info (tempo-find-match-string match-string-finder)) 479 (match-info (tempo-find-match-string match-string-finder))
411 (match-string (car match-info)) 480 (match-string (car match-info))
412 (match-start (cdr match-info)) 481 (match-start (cdr match-info))
413 (compl (or (cdr (assoc match-string tag-list)) 482 (compl (or (cdr (assoc match-string tag-list))
414 (try-completion (car match-info) 483 (try-completion match-string
415 tag-list)))) 484 tag-list))))
416 485
417 (if compl ;any match 486 (if compl ;any match
418 (delete-region match-start (point))) 487 (delete-region match-start (point)))
419 488
420 (cond 489 (cond
421 ((null compl) 490 ((null compl) ; No match
422 nil) 491 nil)
423 ((symbolp compl) 492 ((symbolp compl) ; ??
424 (tempo-insert-template compl nil) 493 (tempo-insert-template compl nil)
425 (throw 'completed t)) 494 (throw 'completed t))
426 ((eq compl t) 495 ((eq compl t) ; Exact, sole match
427 (tempo-insert-template (cdr (assoc match-string tag-list)) 496 (tempo-insert-template (cdr (assoc match-string tag-list))
428 nil) 497 nil)
429 (throw 'completed t)) 498 (throw 'completed t))
430 ((stringp compl) 499 ((stringp compl) ; (partial) completion found
431 (let ((compl2 (assoc compl tag-list))) 500 (let ((compl2 (assoc compl tag-list)))
432 (if compl2 501 (if compl2
433 (tempo-insert-template (cdr compl2) nil) 502 (tempo-insert-template (cdr compl2) nil)
434 (insert compl) 503 (insert compl)
435 (if (string= match-string compl) 504 (if t ;(string= match-string compl)
436 (if (not silent) 505 (if tempo-show-completion-buffer
437 (ding))))) 506 (tempo-display-completions match-string
507 tag-list)
508 (if (not silent)
509 (ding))))))
438 (throw 'completed t)))))) 510 (throw 'completed t))))))
439 tempo-local-tags) 511 tempo-local-tags)
440 ;; No completion found. Return nil 512 ;; No completion found. Return nil
441 nil) 513 nil)
442 ;; Do nothing if a completion was found 514 ;; Do nothing if a completion was found
444 ;; No completion was found 516 ;; No completion was found
445 (if (not silent) 517 (if (not silent)
446 (ding)) 518 (ding))
447 nil)) 519 nil))
448 520
521 ;;;
522 ;;; tempo-display-completions
523
524 (defun tempo-display-completions (string tag-list)
525 "Show a buffer containing possible completions for STRING."
526 (if tempo-leave-completion-buffer
527 (with-output-to-temp-buffer "*Completions*"
528 (display-completion-list
529 (all-completions string tag-list)))
530 (save-window-excursion
531 (with-output-to-temp-buffer "*Completions*"
532 (display-completion-list
533 (all-completions string tag-list)))
534 (sit-for 32767))))
535
449 ;;; tempo.el ends here 536 ;;; tempo.el ends here