summaryrefslogtreecommitdiff
path: root/lisp/tempo.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/tempo.el')
-rw-r--r--lisp/tempo.el194
1 files changed, 84 insertions, 110 deletions
diff --git a/lisp/tempo.el b/lisp/tempo.el
index fe7a866954b..b7ad680c2a9 100644
--- a/lisp/tempo.el
+++ b/lisp/tempo.el
@@ -116,8 +116,7 @@
"Prompt user for strings in templates.
If this variable is non-nil, `tempo-insert' prompts the
user for text to insert in the templates."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
(defcustom tempo-insert-region nil
"Automatically insert current region when there is a `r' in the template
@@ -126,20 +125,17 @@ elements, unless the template function is given a prefix (or a non-nil
argument). If this variable is non-nil, the behavior is reversed.
In Transient Mark mode, this option is unused."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
(defcustom tempo-show-completion-buffer t
"If non-nil, show a buffer with possible completions, when only
a partial completion can be found."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
(defcustom tempo-leave-completion-buffer nil
"If nil, a completion buffer generated by \\[tempo-complete-tag]
disappears at the next keypress; otherwise, it remains forever."
- :type 'boolean
- :group 'tempo)
+ :type 'boolean)
;;; Internal variables
@@ -168,7 +164,7 @@ documentation for the function `tempo-complete-tag' for more info.
"Indicates if the tag collection needs to be rebuilt.")
(defvar-local tempo-marks nil
- "A list of marks to jump to with `\\[tempo-forward-mark]' and `\\[tempo-backward-mark]'.")
+ "A list of marks to jump to with \\[tempo-forward-mark] and \\[tempo-backward-mark].")
(defvar-local tempo-match-finder "\\b\\([[:word:]]+\\)\\="
"The regexp or function used to find the string to match against tags.
@@ -189,11 +185,12 @@ returns a pair of the form (STRING . POS), where STRING is the string
used for matching and POS is the buffer position after which text
should be replaced with a template.")
-(defvar tempo-user-elements nil
+(define-obsolete-variable-alias 'tempo-user-elements 'tempo-user-element-functions "30.1")
+(defvar tempo-user-element-functions nil
"Element handlers for user-defined elements.
-A list of symbols which are bound to functions that take one argument.
-This function should return something to be sent to `tempo-insert' if
-it recognizes the argument, and nil otherwise.")
+This is an abnormal hook where the functions are called with one argument
+\(an element in a template) and they should return something to be sent to
+`tempo-insert' if they recognize the argument, and nil otherwise.")
(defvar-local tempo-named-insertions nil
"Temporary storage for named insertions.")
@@ -201,6 +198,10 @@ it recognizes the argument, and nil otherwise.")
(defvar-local tempo-region-start (make-marker)
"Region start when inserting around the region.")
+;; Insertion by the template at the region start position should move
+;; the marker to preserve the original region contents.
+(set-marker-insertion-type tempo-region-start t)
+
(defvar-local tempo-region-stop (make-marker)
"Region stop when inserting around the region.")
@@ -262,7 +263,7 @@ The elements in ELEMENTS can be of several types:
- `n>': Inserts a newline and indents line.
- `o': Like `%' but leaves the point before the newline.
- nil: It is ignored.
- - Anything else: Each function in `tempo-user-elements' is called
+ - Anything else: Each function in `tempo-user-element-functions' is called
with it as argument until one of them returns non-nil, and the
result is inserted. If all of them return nil, it is evaluated and
the result is treated as an element to be inserted. One additional
@@ -274,14 +275,13 @@ The elements in ELEMENTS can be of several types:
name)))
(command-name template-name))
(set template-name elements)
- (fset command-name (list 'lambda (list '&optional 'arg)
- (or documentation
- (concat "Insert a " name "."))
- (list 'interactive "*P")
- (list 'tempo-insert-template (list 'quote
- template-name)
- (list 'if 'tempo-insert-region
- (list 'not 'arg) 'arg))))
+ (fset command-name (lambda (&optional arg)
+ (:documentation
+ (or documentation (concat "Insert a " name ".")))
+ (interactive "*P")
+ (tempo-insert-template template-name
+ (if tempo-insert-region
+ (not arg) arg))))
(and tag
(tempo-add-tag tag template-name taglist))
command-name))
@@ -325,72 +325,58 @@ elements are replaced with the current region.
See documentation for `tempo-define-template' for the kind of elements
possible."
- (cond ((stringp element) (tempo-process-and-insert-string element))
- ((and (consp element)
- (eq (car element) 'p)) (tempo-insert-prompt-compat
- (cdr element)))
- ((and (consp element)
- (eq (car element) 'P)) (let ((tempo-interactive t))
- (tempo-insert-prompt-compat
- (cdr element))))
-;;; ((and (consp element)
-;;; (eq (car element) 'v)) (tempo-save-named
-;;; (nth 1 element)
-;;; nil
-;;; (nth 2 element)))
- ((and (consp element)
- (eq (car element) 'r)) (if on-region
- (goto-char tempo-region-stop)
- (tempo-insert-prompt-compat
- (cdr element))))
- ((and (consp element)
- (eq (car element) 'r>)) (if on-region
- (progn
- (goto-char tempo-region-stop)
- (indent-region (mark) (point) nil))
- (tempo-insert-prompt-compat
- (cdr element))))
- ((and (consp element)
- (eq (car element) 's)) (tempo-insert-named (car (cdr element))))
- ((and (consp element)
- (eq (car element) 'l)) (mapcar (lambda (elt)
- (tempo-insert elt on-region))
- (cdr element)))
- ((eq element 'p) (tempo-insert-mark (point-marker)))
- ((eq element 'r) (if on-region
- (goto-char tempo-region-stop)
- (tempo-insert-mark (point-marker))))
- ((eq element 'r>) (if on-region
- (progn
- (goto-char tempo-region-stop)
- (indent-region (mark) (point) nil))
- (tempo-insert-mark (point-marker))))
- ((eq element '>) (indent-according-to-mode))
- ((eq element '&) (if (not (or (= (current-column) 0)
- (save-excursion
- (re-search-backward
- "^\\s-*\\=" nil t))))
- (insert "\n")))
- ((eq element '%) (if (not (or (eolp)
- (save-excursion
- (re-search-forward
- "\\=\\s-*$" nil t))))
- (insert "\n")))
- ((eq element 'n) (insert "\n"))
- ((eq element 'n>) (insert "\n") (indent-according-to-mode))
- ;; Bug: If the 'o is the first element in a template, strange
- ;; things can happen when the template is inserted at the
- ;; beginning of a line.
- ((eq element 'o) (if (not (or on-region
- (eolp)
- (save-excursion
- (re-search-forward
- "\\=\\s-*$" nil t))))
- (open-line 1)))
- ((null element))
- (t (tempo-insert (or (tempo-is-user-element element)
- (eval element))
- on-region))))
+ (pcase element
+ ((pred stringp) (tempo-process-and-insert-string element))
+ (`(p . ,rest) (tempo-insert-prompt-compat rest))
+ (`(P . ,rest) (let ((tempo-interactive t))
+ (tempo-insert-prompt-compat rest)))
+ ;; (`(v ,name ,data) (tempo-save-named name nil data))
+ (`(r . ,rest) (if on-region
+ (goto-char tempo-region-stop)
+ (tempo-insert-prompt-compat rest)))
+ (`(r> . ,rest) (if on-region
+ (progn
+ (goto-char tempo-region-stop)
+ (indent-region tempo-region-start
+ tempo-region-stop))
+ (tempo-insert-prompt-compat rest)))
+ (`(s ,name) (tempo-insert-named name))
+ (`(l . ,rest) (dolist (elt rest) (tempo-insert elt on-region)))
+ ('p (tempo-insert-mark (point-marker)))
+ ('r (if on-region
+ (goto-char tempo-region-stop)
+ (tempo-insert-mark (point-marker))))
+ ('r> (if on-region
+ (progn
+ (goto-char tempo-region-stop)
+ (indent-region tempo-region-start tempo-region-stop))
+ (tempo-insert-mark (point-marker))))
+ ('> (indent-according-to-mode))
+ ('& (if (not (or (= (current-column) 0)
+ (save-excursion
+ (re-search-backward
+ "^\\s-*\\=" nil t))))
+ (insert "\n")))
+ ('% (if (not (or (eolp)
+ (save-excursion
+ (re-search-forward
+ "\\=\\s-*$" nil t))))
+ (insert "\n")))
+ ('n (insert "\n"))
+ ('n> (insert "\n") (indent-according-to-mode))
+ ;; Bug: If the 'o is the first element in a template, strange
+ ;; things can happen when the template is inserted at the
+ ;; beginning of a line.
+ ('o (if (not (or on-region
+ (eolp)
+ (save-excursion
+ (re-search-forward
+ "\\=\\s-*$" nil t))))
+ (open-line 1)))
+ ('nil nil)
+ (_ (tempo-insert (or (tempo-is-user-element element)
+ (eval element t))
+ on-region))))
;;;
;;; tempo-insert-prompt
@@ -400,7 +386,7 @@ possible."
PROMPT can be either a prompt string, or a list of arguments to
`tempo-insert-prompt', or nil."
(if (consp prompt) ; not nil either
- (apply 'tempo-insert-prompt prompt)
+ (apply #'tempo-insert-prompt prompt)
(tempo-insert-prompt prompt)))
(defun tempo-insert-prompt (prompt &optional save-name no-insert)
@@ -445,14 +431,8 @@ never prompted."
;;; tempo-is-user-element
(defun tempo-is-user-element (element)
- "Try all the user-defined element handlers in `tempo-user-elements'."
- ;; Sigh... I need (some list)
- (catch 'found
- (mapc (lambda (handler)
- (let ((result (funcall handler element)))
- (if result (throw 'found result))))
- tempo-user-elements)
- (throw 'found nil)))
+ "Try all the user-defined element handlers in `tempo-user-element-functions'."
+ (run-hook-with-args-until-success 'tempo-user-element-functions element))
;;;
;;; tempo-forget-insertions
@@ -602,7 +582,7 @@ TAG-LIST is a symbol whose variable value is a tag list created with
`tempo-add-tag'.
COMPLETION-FUNCTION is an obsolete option for specifying an optional
-function or string that is used by `\\[tempo-complete-tag]' to find a
+function or string that is used by \\[tempo-complete-tag] to find a
string to match the tag against. It has the same definition as the
variable `tempo-match-finder'. In this version, supplying a
COMPLETION-FUNCTION just sets `tempo-match-finder' locally."
@@ -636,12 +616,12 @@ If `tempo-dirty-collection' is nil, the old collection is reused."
(or (and (not tempo-dirty-collection)
tempo-collection)
(setq tempo-collection
- (apply (function append)
+ (apply #'append
(mapcar (lambda (tag-list)
; If the format for
; tempo-local-tags changes,
; change this
- (eval (car tag-list)))
+ (eval (car tag-list) t))
tempo-local-tags))))
(setq tempo-dirty-collection nil)))
@@ -653,16 +633,10 @@ If `tempo-dirty-collection' is nil, the old collection is reused."
FINDER is a function or a string. Returns (STRING . POS), or nil
if no reasonable string is found."
(cond ((stringp finder)
- (let (successful)
- (save-excursion
- (or (setq successful (re-search-backward finder nil t))
- 0))
- (if successful
- (cons (buffer-substring (match-beginning 1)
- (match-end 1)) ; This seems to be a
- ; bug in emacs
- (match-beginning 1))
- nil)))
+ (if (save-excursion (re-search-backward finder nil t))
+ (cons (match-string 1) ; This seems to be a bug in Emacs (?)
+ (match-beginning 1))
+ nil))
(t
(funcall finder))))