summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus <rasmus@gmx.us>2017-12-21 12:59:36 +0100
committerRasmus <rasmus@gmx.us>2018-04-08 12:47:12 +0200
commite5f6cb6c8b6c26772a92410a657b6986842dd23e (patch)
treece579ce3b38f7693b9f4ccdb90bc813632949c57
parentb56df737b7392845c6e00d4cc52801e64c105f8b (diff)
downloadorg-mode-e5f6cb6c8b6c26772a92410a657b6986842dd23e.tar.gz
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.
-rw-r--r--lisp/org-tempo.el38
-rw-r--r--testing/lisp/test-org-tempo.el41
2 files changed, 67 insertions, 12 deletions
diff --git a/lisp/org-tempo.el b/lisp/org-tempo.el
index a41c994..e1268b8 100644
--- a/lisp/org-tempo.el
+++ b/lisp/org-tempo.el
@@ -34,7 +34,7 @@
;;
;; `tempo' can also be used to define more sophisticated keywords
;; completions. See the section "Additional keywords" below for
-;; additional details.
+;; examples.
;;
;;; Code:
@@ -65,7 +65,9 @@ and KEYWORD. The tempo snippet \"<KEY\" is expand to the KEYWORD
value.
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
:type '(repeat (cons (string :tag "Key")
(string :tag "Keyword")))
@@ -76,23 +78,35 @@ For example \"<l\" at the beginning of a line is expanded to
;;; Org Tempo functions and setup.
(defun org-tempo-setup ()
- (org-tempo-add-templates)
+ (org-tempo--update-maybe)
(tempo-use-tag-list 'org-tempo-tags)
(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 ()
"Update all Org Tempo templates.
Goes through `org-structure-template-alist' and
`org-tempo-keywords-alist'."
- (let ((keys (mapcar (lambda (pair) (format "<%c" (car pair)))
- (append org-structure-template-alist
- org-tempo-keywords-alist))))
+ (let ((keys (org-tempo--keys)))
;; Check for duplicated snippet keys and warn if any are found.
(when (> (length keys) (length (delete-dups keys)))
(warn
"Duplicated keys in `org-structure-template-alist' and `org-tempo-keywords-alist'"))
-
;; Remove any keys already defined in case they have been updated.
(setq 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)
"Add block entry from `org-structure-template-alist'."
(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))
- `(,(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 " ")))
>)
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
completion or no match at all is found. Return nil if expansion
didn't succeed."
+ (org-tempo--update-maybe)
;; `tempo-complete-tag' returns its SILENT argument when there is no
;; completion available at all.
(not (eq 'fail (tempo-complete-tag 'fail))))
+
;;; Additional keywords
(defun org-tempo--include-file ()
@@ -160,8 +178,6 @@ didn't succeed."
(add-hook 'org-mode-hook 'org-tempo-setup)
(add-hook 'org-tab-before-tab-emulation-hook 'org-tempo-complete-tag)
-(org-tempo-add-templates)
-
;; Enable Org Tempo in all open Org buffers.
(dolist (b (org-buffer-list 'files))
(with-current-buffer b (org-tempo-setup)))
diff --git a/testing/lisp/test-org-tempo.el b/testing/lisp/test-org-tempo.el
index 6c751d4..1840b35 100644
--- a/testing/lisp/test-org-tempo.el
+++ b/testing/lisp/test-org-tempo.el
@@ -41,7 +41,7 @@
(org-tempo-setup)
(call-interactively 'org-cycle)
(buffer-string))
- "#+begin_export latex \n\n#+end_export"))
+ "#+begin_export latex\n\n#+end_export"))
;; Tab should work for expansion.
(should
(equal (org-test-with-temp-text "<L<point>"
@@ -59,6 +59,45 @@
(buffer-string))
"<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 ()
"Test that new structures and keywords are added correctly."
;; New blocks should be added.