In Transient Mark mode, this option is unused."
: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)
-
;;; Internal variables
(defvar tempo-insert-string-functions nil
(defvar tempo-tags nil
"An association list with tags and corresponding templates.")
-(defvar-local tempo-local-tags '((tempo-tags . nil))
- "A list of locally installed tag completion lists.
-It is an association list where the car of every element is a symbol
-whose variable value is a template list. The cdr part, if non-nil,
-is a function or a regexp that defines the string to match. See the
-documentation for the function `tempo-complete-tag' for more info.
-
-`tempo-tags' is always in the last position in this list.")
-
(defvar-local tempo-collection nil
"A collection of all the tags defined for the current buffer.")
(tempo-insert-template template-name
(if tempo-insert-region
(not arg) arg))))
- (and tag
- (tempo-add-tag tag template-name taglist))
+ (when tag
+ (add-to-list (or taglist 'tempo-tags) (cons tag template-name)))
command-name))
+(defvar tempo-on-region nil)
+
;;;
;;; tempo-insert-template
-(defun tempo-insert-template (template &optional on-region)
+;;;###autoload
+(defun tempo-insert-template (template &optional _)
"Insert a template.
TEMPLATE is the template to be inserted. If ON-REGION is non-nil the
`r' elements are replaced with the current region. In Transient Mark
mode, ON-REGION is ignored and assumed true if the region is active."
(unwind-protect
- (progn
- (if (or (and transient-mark-mode
- mark-active))
- (setq on-region t))
- (and on-region
- (set-marker tempo-region-start (min (mark) (point)))
- (set-marker tempo-region-stop (max (mark) (point))))
- (if on-region
- (goto-char tempo-region-start))
+ (let ((tempo-on-region (use-region-p)))
+ (when tempo-on-region
+ (set-marker tempo-region-start (use-region-beginning))
+ (set-marker tempo-region-stop (use-region-end))
+ (goto-char tempo-region-start))
(save-excursion
(tempo-insert-mark (point-marker))
- (mapc (lambda (elt)
- (tempo-insert elt on-region))
- (if (symbolp template) (symbol-value template) template))
+ (if (symbolp template)
+ (apply #'tempo-insert (symbol-value template))
+ (tempo-insert template))
(tempo-insert-mark (point-marker)))
(tempo-forward-mark))
- (tempo-forget-insertions)
- (and transient-mark-mode
- (deactivate-mark))))
+ (setq tempo-named-insertions nil)))
;;;
;;; tempo-insert
-(defun tempo-insert (element on-region)
- "Insert a template ELEMENT.
-Insert one element from a template. If ON-REGION is non-nil the `r'
-elements are replaced with the current region.
+(defun tempo-insert (&rest elements)
+ "Insert template ELEMENTS.
See documentation for `tempo-define-template' for the kind of elements
possible."
- (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))
+ (dolist (element elements)
+ (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 tempo-on-region
+ (goto-char tempo-region-stop)
+ (tempo-insert-prompt-compat rest)))
+ (`(r> . ,rest) (if tempo-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))))
+ (`(s ,name) (tempo-insert-named name))
+ (`(l . ,rest) (dolist (elt rest) (tempo-insert elt)))
+ ('p (tempo-insert-mark (point-marker)))
+ ('r (if tempo-on-region
+ (goto-char tempo-region-stop)
+ (tempo-insert-mark (point-marker))))
+ ('r> (if tempo-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))
+ ('^ (indent-region (car tempo-marks) (point)))
+ ('& (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% (if (nth 4 (syntax-ppss)) (insert "\n") (message "nope")))
+ ('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 tempo-on-region
+ (eolp)
+ (save-excursion
+ (re-search-forward
+ "\\=\\s-*$" nil t))))
+ (open-line 1)))
+ ('nil nil)
+ (_ (tempo-insert
+ (run-hook-with-args-until-success 'tempo-user-element-functions element))))))
;;;
;;; tempo-insert-prompt
(t
(tempo-insert-mark (point-marker))))))
-;;;
-;;; tempo-is-user-element
-
-(defun tempo-is-user-element (element)
- "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
-
-(defun tempo-forget-insertions ()
- "Forget all the saved named insertions."
- (setq tempo-named-insertions nil))
-
;;;
;;; tempo-save-named
((stringp insertion)
(insert insertion))
(t
- (tempo-insert insertion nil)))))
-
+ (tempo-insert insertion)))))
;;;
;;; tempo-process-and-insert-string
(defun tempo-process-and-insert-string (string)
- "Insert a string from a template.
+ "Insert a STRING from a template.
Run a string through the preprocessors in `tempo-insert-string-functions'
and insert the results."
(cond ((null tempo-insert-string-functions)
;;; tempo-insert-mark
(defun tempo-insert-mark (mark)
- "Insert a mark `tempo-marks' while keeping it sorted."
+ "Add a MARK to `tempo-marks' while keeping it sorted."
(cond ((null tempo-marks) (setq tempo-marks (list mark)))
((< mark (car tempo-marks)) (setq tempo-marks (cons mark tempo-marks)))
(t (let ((lp tempo-marks))
(if prev-mark
(goto-char prev-mark))))
-;;;
-;;; tempo-add-tag
-
-(defun tempo-add-tag (tag template &optional tag-list)
- "Add a template tag.
-Add the TAG, that should complete to TEMPLATE to the list in TAG-LIST,
-or to `tempo-tags' if TAG-LIST is nil. If TAG was already in the list,
-replace its template with TEMPLATE."
-
- (interactive "sTag: \nCTemplate: ")
- (if (null tag-list)
- (setq tag-list 'tempo-tags))
- (let ((entry (assoc tag (symbol-value tag-list))))
- (if entry
- ;; Tag is already in the list, assign a new template to it.
- (setcdr entry template)
- ;; Tag is not present in the list, add it with its template.
- (set tag-list (cons (cons tag template) (symbol-value tag-list)))))
- ;; Invalidate globally if we're modifying 'tempo-tags'.
- (tempo-invalidate-collection (eq tag-list 'tempo-tags)))
-
-;;;
-;;; tempo-use-tag-list
-
-(defun tempo-use-tag-list (tag-list &optional completion-function)
- "Install TAG-LIST to be used for template completion in the current buffer.
-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
-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."
- (alist-set tag-list tempo-local-tags completion-function)
- (if completion-function
- (setq tempo-match-finder completion-function))
- (tempo-invalidate-collection))
-
-;;;
-;;; tempo-invalidate-collection
-
-(defun tempo-invalidate-collection (&optional global)
- "Mark the tag collection as obsolete.
-Whenever it is needed again it will be rebuilt. If GLOBAL is non-nil,
-mark the tag collection of all buffers as obsolete, not just the
-current one."
- (if global
- (dolist (buffer (buffer-list))
- (with-current-buffer buffer
- (when (assq 'tempo-dirty-collection (buffer-local-variables))
- (setq tempo-dirty-collection t))))
- (setq tempo-dirty-collection t)))
-
-;;;
-;;; tempo-build-collection
-
-(defun tempo-build-collection ()
- "Build a collection of all the tags and return it.
-If `tempo-dirty-collection' is nil, the old collection is reused."
- (prog1
- (or (and (not tempo-dirty-collection)
- tempo-collection)
- (setq tempo-collection
- (apply #'append
- (mapcar (lambda (tag-list)
- ; If the format for
- ; tempo-local-tags changes,
- ; change this
- (eval (car tag-list) t))
- tempo-local-tags))))
- (setq tempo-dirty-collection nil)))
-
;;;
;;; tempo-find-match-string
If a single match is found, the corresponding template is expanded in
place of the matching string."
(interactive "*")
- (let* ((collection (tempo-build-collection))
+ (let* ((collection tempo-tags)
(match-info (tempo-find-match-string tempo-match-finder))
(match-string (car match-info))
(match-start (cdr match-info))
(insert \" \")))"
(interactive "*")
- (let* ((collection (tempo-build-collection))
+ (let* ((collection tempo-tags)
(match-info (tempo-find-match-string tempo-match-finder))
(match-string (car match-info))
(match-start (cdr match-info))