diff options
Diffstat (limited to 'lisp/tempo.el')
-rw-r--r-- | lisp/tempo.el | 194 |
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)))) |