forked from mirrors/org-mode
org-tempo: Various improvements
* lisp/org-tempo.el (org-tempo-keywords-alist): Improve docstring. (org-tempo--update-maybe): (org-tempo--keys): New function. (org-tempo-complete-tag): (org-tempo-setup): (org-tempo-add-templates): Use new functions. (org-tempo-add-block): Smarter position of point. * testing/lisp/test-org-tempo.el (test-org-tempo/cursor-placement): (test-org-tempo/space-first-line): New tests. * testing/lisp/test-org-tempo.el (test-org-tempo/completion): Adapt test to changes. Org Tempo more carefully checks for new definitions. When inserting blocks point will differ depending on whether it is source block.
This commit is contained in:
parent
b56df737b7
commit
e5f6cb6c8b
|
@ -34,7 +34,7 @@
|
||||||
;;
|
;;
|
||||||
;; `tempo' can also be used to define more sophisticated keywords
|
;; `tempo' can also be used to define more sophisticated keywords
|
||||||
;; completions. See the section "Additional keywords" below for
|
;; completions. See the section "Additional keywords" below for
|
||||||
;; additional details.
|
;; examples.
|
||||||
;;
|
;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
|
@ -65,7 +65,9 @@ and KEYWORD. The tempo snippet \"<KEY\" is expand to the KEYWORD
|
||||||
value.
|
value.
|
||||||
|
|
||||||
For example \"<l\" at the beginning of a line is expanded to
|
For example \"<l\" at the beginning of a line is expanded to
|
||||||
#+latex:"
|
\"#+latex:\".
|
||||||
|
|
||||||
|
Note: the tempo function for \"#+include\" is defined elsewhere."
|
||||||
:group 'org-tempo
|
:group 'org-tempo
|
||||||
:type '(repeat (cons (string :tag "Key")
|
:type '(repeat (cons (string :tag "Key")
|
||||||
(string :tag "Keyword")))
|
(string :tag "Keyword")))
|
||||||
|
@ -76,23 +78,35 @@ For example \"<l\" at the beginning of a line is expanded to
|
||||||
;;; Org Tempo functions and setup.
|
;;; Org Tempo functions and setup.
|
||||||
|
|
||||||
(defun org-tempo-setup ()
|
(defun org-tempo-setup ()
|
||||||
(org-tempo-add-templates)
|
(org-tempo--update-maybe)
|
||||||
(tempo-use-tag-list 'org-tempo-tags)
|
(tempo-use-tag-list 'org-tempo-tags)
|
||||||
(setq-local tempo-match-finder "^ *\\(<[[:word:]]+\\)\\="))
|
(setq-local tempo-match-finder "^ *\\(<[[:word:]]+\\)\\="))
|
||||||
|
|
||||||
|
(defun org-tempo--keys ()
|
||||||
|
"Return a list of all Org Tempo expansion strings, like \"<s\"."
|
||||||
|
(mapcar (lambda (pair) (format "<%s" (car pair)))
|
||||||
|
(append org-structure-template-alist
|
||||||
|
org-tempo-keywords-alist)))
|
||||||
|
|
||||||
|
(defun org-tempo--update-maybe ()
|
||||||
|
"Check and add new Org Tempo templates if necessary.
|
||||||
|
In particular, if new entries were added to
|
||||||
|
`org-structure-template-alist' or `org-tempo-keywords-alist', new
|
||||||
|
Tempo templates will be added."
|
||||||
|
(unless (cl-every (lambda (key) (assoc key org-tempo-tags))
|
||||||
|
(org-tempo--keys))
|
||||||
|
(org-tempo-add-templates)))
|
||||||
|
|
||||||
(defun org-tempo-add-templates ()
|
(defun org-tempo-add-templates ()
|
||||||
"Update all Org Tempo templates.
|
"Update all Org Tempo templates.
|
||||||
|
|
||||||
Goes through `org-structure-template-alist' and
|
Goes through `org-structure-template-alist' and
|
||||||
`org-tempo-keywords-alist'."
|
`org-tempo-keywords-alist'."
|
||||||
(let ((keys (mapcar (lambda (pair) (format "<%c" (car pair)))
|
(let ((keys (org-tempo--keys)))
|
||||||
(append org-structure-template-alist
|
|
||||||
org-tempo-keywords-alist))))
|
|
||||||
;; Check for duplicated snippet keys and warn if any are found.
|
;; Check for duplicated snippet keys and warn if any are found.
|
||||||
(when (> (length keys) (length (delete-dups keys)))
|
(when (> (length keys) (length (delete-dups keys)))
|
||||||
(warn
|
(warn
|
||||||
"Duplicated keys in `org-structure-template-alist' and `org-tempo-keywords-alist'"))
|
"Duplicated keys in `org-structure-template-alist' and `org-tempo-keywords-alist'"))
|
||||||
|
|
||||||
;; Remove any keys already defined in case they have been updated.
|
;; Remove any keys already defined in case they have been updated.
|
||||||
(setq org-tempo-tags
|
(setq org-tempo-tags
|
||||||
(cl-remove-if (lambda (tag) (member (car tag) keys)) org-tempo-tags))
|
(cl-remove-if (lambda (tag) (member (car tag) keys)) org-tempo-tags))
|
||||||
|
@ -102,9 +116,11 @@ Goes through `org-structure-template-alist' and
|
||||||
(defun org-tempo-add-block (entry)
|
(defun org-tempo-add-block (entry)
|
||||||
"Add block entry from `org-structure-template-alist'."
|
"Add block entry from `org-structure-template-alist'."
|
||||||
(let* ((key (format "<%s" (car entry)))
|
(let* ((key (format "<%s" (car entry)))
|
||||||
(name (cdr entry)))
|
(name (cdr entry))
|
||||||
|
(special (member name '("src" "export"))))
|
||||||
(tempo-define-template (format "org-%s" (replace-regexp-in-string " " "-" name))
|
(tempo-define-template (format "org-%s" (replace-regexp-in-string " " "-" name))
|
||||||
`(,(format "#+begin_%s " name) p '> n n
|
`(,(format "#+begin_%s%s" name (if special " " ""))
|
||||||
|
,(when special 'p) '> n '> ,(unless special 'p) n
|
||||||
,(format "#+end_%s" (car (split-string name " ")))
|
,(format "#+end_%s" (car (split-string name " ")))
|
||||||
>)
|
>)
|
||||||
key
|
key
|
||||||
|
@ -126,10 +142,12 @@ Goes through `org-structure-template-alist' and
|
||||||
Unlike to `tempo-complete-tag', do not give a signal if a partial
|
Unlike to `tempo-complete-tag', do not give a signal if a partial
|
||||||
completion or no match at all is found. Return nil if expansion
|
completion or no match at all is found. Return nil if expansion
|
||||||
didn't succeed."
|
didn't succeed."
|
||||||
|
(org-tempo--update-maybe)
|
||||||
;; `tempo-complete-tag' returns its SILENT argument when there is no
|
;; `tempo-complete-tag' returns its SILENT argument when there is no
|
||||||
;; completion available at all.
|
;; completion available at all.
|
||||||
(not (eq 'fail (tempo-complete-tag 'fail))))
|
(not (eq 'fail (tempo-complete-tag 'fail))))
|
||||||
|
|
||||||
|
|
||||||
;;; Additional keywords
|
;;; Additional keywords
|
||||||
|
|
||||||
(defun org-tempo--include-file ()
|
(defun org-tempo--include-file ()
|
||||||
|
@ -160,8 +178,6 @@ didn't succeed."
|
||||||
(add-hook 'org-mode-hook 'org-tempo-setup)
|
(add-hook 'org-mode-hook 'org-tempo-setup)
|
||||||
(add-hook 'org-tab-before-tab-emulation-hook 'org-tempo-complete-tag)
|
(add-hook 'org-tab-before-tab-emulation-hook 'org-tempo-complete-tag)
|
||||||
|
|
||||||
(org-tempo-add-templates)
|
|
||||||
|
|
||||||
;; Enable Org Tempo in all open Org buffers.
|
;; Enable Org Tempo in all open Org buffers.
|
||||||
(dolist (b (org-buffer-list 'files))
|
(dolist (b (org-buffer-list 'files))
|
||||||
(with-current-buffer b (org-tempo-setup)))
|
(with-current-buffer b (org-tempo-setup)))
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
(org-tempo-setup)
|
(org-tempo-setup)
|
||||||
(call-interactively 'org-cycle)
|
(call-interactively 'org-cycle)
|
||||||
(buffer-string))
|
(buffer-string))
|
||||||
"#+begin_export latex \n\n#+end_export"))
|
"#+begin_export latex\n\n#+end_export"))
|
||||||
;; Tab should work for expansion.
|
;; Tab should work for expansion.
|
||||||
(should
|
(should
|
||||||
(equal (org-test-with-temp-text "<L<point>"
|
(equal (org-test-with-temp-text "<L<point>"
|
||||||
|
@ -59,6 +59,45 @@
|
||||||
(buffer-string))
|
(buffer-string))
|
||||||
"<k"))
|
"<k"))
|
||||||
|
|
||||||
|
(ert-deftest test-org-tempo/space-first-line ()
|
||||||
|
"Test space on first line after expansion."
|
||||||
|
;; Normal blocks should have no space at the end of the first line.
|
||||||
|
(should (zerop
|
||||||
|
(org-test-with-temp-text "<l<point>"
|
||||||
|
(org-tempo-setup)
|
||||||
|
(tempo-complete-tag)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(end-of-line)
|
||||||
|
(skip-chars-backward " "))))
|
||||||
|
;; src blocks, export blocks and keywords should have one space at
|
||||||
|
;; the end of the first line.
|
||||||
|
(should (cl-every (apply-partially 'eq 1)
|
||||||
|
(mapcar (lambda (s)
|
||||||
|
(org-test-with-temp-text (format "<%s<point>" s)
|
||||||
|
(org-tempo-setup)
|
||||||
|
(tempo-complete-tag)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(end-of-line)
|
||||||
|
(abs (skip-chars-backward " "))))
|
||||||
|
'("s" "E" "L")))))
|
||||||
|
|
||||||
|
(ert-deftest test-org-tempo/cursor-placement ()
|
||||||
|
"Test the placement of the cursor after tempo expand"
|
||||||
|
;; Normal blocks place point "inside" block.
|
||||||
|
(should
|
||||||
|
(eq (org-test-with-temp-text "<l<point>"
|
||||||
|
(org-tempo-setup)
|
||||||
|
(tempo-complete-tag)
|
||||||
|
(point))
|
||||||
|
(length "#\\+begin_export latex\n")))
|
||||||
|
;; Special block stop at end of #+begin line.
|
||||||
|
(should
|
||||||
|
(eq (org-test-with-temp-text "<s<point>"
|
||||||
|
(org-tempo-setup)
|
||||||
|
(tempo-complete-tag)
|
||||||
|
(point))
|
||||||
|
(length "#\\+begin_src "))))
|
||||||
|
|
||||||
(ert-deftest test-org-tempo/add-new-templates ()
|
(ert-deftest test-org-tempo/add-new-templates ()
|
||||||
"Test that new structures and keywords are added correctly."
|
"Test that new structures and keywords are added correctly."
|
||||||
;; New blocks should be added.
|
;; New blocks should be added.
|
||||||
|
|
Loading…
Reference in a new issue