aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Tedin2019-05-14 09:16:00 -0300
committerBasil L. Contovounesios2019-05-21 15:23:23 +0100
commiteb2e9a2ca29f7d5e3b97709e9eca14fa5556ac63 (patch)
tree1cf8ff22d7dae507eb4ea9bb8fcb2165e2375791
parent5856512911488e40609be5685e64f9fb8cd395ad (diff)
downloademacs-eb2e9a2ca29f7d5e3b97709e9eca14fa5556ac63.tar.gz
emacs-eb2e9a2ca29f7d5e3b97709e9eca14fa5556ac63.zip
Use lexical-binding in tempo.el and add tests
For discussion, see the following thread: https://lists.gnu.org/archive/html/emacs-devel/2019-05/msg00395.html * lisp/tempo.el: Use lexical-binding. (tempo-define-template): Expand documentation to mention `tempo-user-elements'. (tempo-local-tags, tempo-collection, tempo-dirty-collection) (tempo-marks, tempo-match-finder): Define with defvar-local. (tempo-named-insertions, tempo-region-start, tempo-region-stop): Make them automatically buffer-local. * test/lisp/tempo-tests.el: Add tests for tempo.el.
-rw-r--r--lisp/tempo.el41
-rw-r--r--test/lisp/tempo-tests.el228
2 files changed, 246 insertions, 23 deletions
diff --git a/lisp/tempo.el b/lisp/tempo.el
index 28afbec0f49..e3b9c76a5b8 100644
--- a/lisp/tempo.el
+++ b/lisp/tempo.el
@@ -1,11 +1,11 @@
1;;; tempo.el --- Flexible template insertion 1;;; tempo.el --- Flexible template insertion -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 1994-1995, 2001-2019 Free Software Foundation, Inc. 3;; Copyright (C) 1994-1995, 2001-2019 Free Software Foundation, Inc.
4 4
5;; Author: David Kågedal <davidk@lysator.liu.se> 5;; Author: David Kågedal <davidk@lysator.liu.se>
6;; Created: 16 Feb 1994 6;; Created: 16 Feb 1994
7;; Kågedal's last version number: 1.2.4 7;; Kågedal's last version number: 1.2.4
8;; Keywords: extensions, languages, tools 8;; Keywords: abbrev, extensions, languages, tools
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
11 11
@@ -152,7 +152,7 @@ setting it to (upcase), for example.")
152(defvar tempo-tags nil 152(defvar tempo-tags nil
153 "An association list with tags and corresponding templates.") 153 "An association list with tags and corresponding templates.")
154 154
155(defvar tempo-local-tags '((tempo-tags . nil)) 155(defvar-local tempo-local-tags '((tempo-tags . nil))
156 "A list of locally installed tag completion lists. 156 "A list of locally installed tag completion lists.
157It is an association list where the car of every element is a symbol 157It is an association list where the car of every element is a symbol
158whose variable value is a template list. The cdr part, if non-nil, 158whose variable value is a template list. The cdr part, if non-nil,
@@ -161,16 +161,16 @@ documentation for the function `tempo-complete-tag' for more info.
161 161
162`tempo-tags' is always in the last position in this list.") 162`tempo-tags' is always in the last position in this list.")
163 163
164(defvar tempo-collection nil 164(defvar-local tempo-collection nil
165 "A collection of all the tags defined for the current buffer.") 165 "A collection of all the tags defined for the current buffer.")
166 166
167(defvar tempo-dirty-collection t 167(defvar-local tempo-dirty-collection t
168 "Indicates if the tag collection needs to be rebuilt.") 168 "Indicates if the tag collection needs to be rebuilt.")
169 169
170(defvar tempo-marks nil 170(defvar-local tempo-marks nil
171 "A list of marks to jump to with `\\[tempo-forward-mark]' and `\\[tempo-backward-mark]'.") 171 "A list of marks to jump to with `\\[tempo-forward-mark]' and `\\[tempo-backward-mark]'.")
172 172
173(defvar tempo-match-finder "\\b\\([[:word:]]+\\)\\=" 173(defvar-local tempo-match-finder "\\b\\([[:word:]]+\\)\\="
174 "The regexp or function used to find the string to match against tags. 174 "The regexp or function used to find the string to match against tags.
175 175
176If `tempo-match-finder' is a string, it should contain a regular 176If `tempo-match-finder' is a string, it should contain a regular
@@ -195,23 +195,15 @@ A list of symbols which are bound to functions that take one argument.
195This function should return something to be sent to `tempo-insert' if 195This function should return something to be sent to `tempo-insert' if
196it recognizes the argument, and nil otherwise.") 196it recognizes the argument, and nil otherwise.")
197 197
198(defvar tempo-named-insertions nil 198(defvar-local tempo-named-insertions nil
199 "Temporary storage for named insertions.") 199 "Temporary storage for named insertions.")
200 200
201(defvar tempo-region-start (make-marker) 201(defvar-local tempo-region-start (make-marker)
202 "Region start when inserting around the region.") 202 "Region start when inserting around the region.")
203 203
204(defvar tempo-region-stop (make-marker) 204(defvar-local tempo-region-stop (make-marker)
205 "Region stop when inserting around the region.") 205 "Region stop when inserting around the region.")
206 206
207;; Make some variables local to every buffer
208
209(make-variable-buffer-local 'tempo-marks)
210(make-variable-buffer-local 'tempo-local-tags)
211(make-variable-buffer-local 'tempo-match-finder)
212(make-variable-buffer-local 'tempo-collection)
213(make-variable-buffer-local 'tempo-dirty-collection)
214
215;;; Functions 207;;; Functions
216 208
217;; 209;;
@@ -268,11 +260,14 @@ The elements in ELEMENTS can be of several types:
268 - `n>': Inserts a newline and indents line. 260 - `n>': Inserts a newline and indents line.
269 - `o': Like `%' but leaves the point before the newline. 261 - `o': Like `%' but leaves the point before the newline.
270 - nil: It is ignored. 262 - nil: It is ignored.
271 - Anything else: It is evaluated and the result is treated as an 263 - Anything else: Each function in `tempo-user-elements' is called
272 element to be inserted. One additional tag is useful for these 264 with it as argument until one of them returns non-nil, and the
273 cases. If an expression returns a list (l foo bar), the elements 265 result is inserted. If all of them return nil, it is evaluated and
274 after `l' will be inserted according to the usual rules. This makes 266 the result is treated as an element to be inserted. One additional
275 it possible to return several elements from one expression." 267 tag is useful for these cases. If an expression returns a list (l
268 foo bar), the elements after `l' will be inserted according to the
269 usual rules. This makes it possible to return several elements
270 from one expression."
276 (let* ((template-name (intern (concat "tempo-template-" 271 (let* ((template-name (intern (concat "tempo-template-"
277 name))) 272 name)))
278 (command-name template-name)) 273 (command-name template-name))
diff --git a/test/lisp/tempo-tests.el b/test/lisp/tempo-tests.el
new file mode 100644
index 00000000000..6e610ffa6ea
--- /dev/null
+++ b/test/lisp/tempo-tests.el
@@ -0,0 +1,228 @@
1;;; tempo-tests.el --- Test suite for tempo.el -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2019 Free Software Foundation, Inc.
4
5;; Author: Federico Tedin <federicotedin@gmail.com>
6;; Keywords: abbrev
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
22
23;;; Code:
24
25(require 'tempo)
26(eval-when-compile (require 'cl-lib))
27
28(ert-deftest tempo-string-element-test ()
29 "Test a template containing a string element."
30 (with-temp-buffer
31 (tempo-define-template "test" '("GNU Emacs Tempo test"))
32 (tempo-insert-template 'tempo-template-test nil)
33 (should (equal (buffer-string) "GNU Emacs Tempo test"))))
34
35(ert-deftest tempo-p-bare-element-test ()
36 "Test a template containing a bare `p' element."
37 (with-temp-buffer
38 (tempo-define-template "test" '("abcde" p))
39 (tempo-insert-template 'tempo-template-test nil)
40 (tempo-forward-mark)
41 (should (equal (point) 6))))
42
43(ert-deftest tempo-r-bare-element-test ()
44 "Test a template containing a bare `r' element."
45 (with-temp-buffer
46 (tempo-define-template "test" '("abcde" r "ghijk"))
47 (insert "F")
48 (set-mark (point))
49 (goto-char (point-min))
50 (tempo-insert-template 'tempo-template-test t)
51 (should (equal (buffer-string) "abcdeFghijk"))))
52
53(ert-deftest tempo-p-element-test ()
54 "Testing template containing a `p' (prompt) element."
55 (with-temp-buffer
56 (tempo-define-template "test" '("hello " (p ">")))
57 (let ((tempo-interactive t))
58 (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world")))
59 (tempo-insert-template 'tempo-template-test nil))
60 (should (equal (buffer-string) "hello world")))))
61
62(ert-deftest tempo-P-element-test ()
63 "Testing template containing a `P' (prompt) element."
64 (with-temp-buffer
65 (tempo-define-template "test" '("hello " (P ">")))
66 ;; By default, `tempo-interactive' is nil, `P' should ignore this.
67 (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world")))
68 (tempo-insert-template 'tempo-template-test nil))
69 (should (equal (buffer-string) "hello world"))))
70
71(ert-deftest tempo-r-element-test ()
72 "Testing template containing an `r' (with prompt) element."
73 (with-temp-buffer
74 (tempo-define-template "test" '("abcde" (r ">") "ghijk"))
75 (let ((tempo-interactive t))
76 (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "F")))
77 (tempo-insert-template 'tempo-template-test nil))
78 (should (equal (buffer-string) "abcdeFghijk")))))
79
80(ert-deftest tempo-s-element-test ()
81 "Testing template containing an `s' element."
82 (with-temp-buffer
83 (tempo-define-template "test" '("hello " (p ">" P1) " " (s P1)))
84 (let ((tempo-interactive t))
85 (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world!")))
86 (tempo-insert-template 'tempo-template-test nil))
87 (should (equal (buffer-string) "hello world! world!")))))
88
89(ert-deftest tempo-&-element-test ()
90 "Testing template containing an `&' element."
91 (tempo-define-template "test" '(& "test"))
92 (with-temp-buffer
93 (insert " ")
94 (tempo-insert-template 'tempo-template-test nil)
95 (should (equal (buffer-string) " test")))
96 (with-temp-buffer
97 (insert "hello")
98 (tempo-insert-template 'tempo-template-test nil)
99 (should (equal (buffer-string) "hello\ntest"))))
100
101(ert-deftest tempo-%-element-test ()
102 "Testing template containing an `%' element."
103 (tempo-define-template "test" '("test" %))
104 (with-temp-buffer
105 (tempo-insert-template 'tempo-template-test nil)
106 (should (equal (buffer-string) "test")))
107 (with-temp-buffer
108 (insert "hello")
109 (goto-char (point-min))
110 (tempo-insert-template 'tempo-template-test nil)
111 (should (equal (buffer-string) "test\nhello"))))
112
113(ert-deftest tempo-n-element-test ()
114 "Testing template containing an `n' element."
115 (tempo-define-template "test" '("test" n "test"))
116 (with-temp-buffer
117 (tempo-insert-template 'tempo-template-test nil)
118 (should (equal (buffer-string) "test\ntest"))))
119
120(ert-deftest tempo-n>-element-test ()
121 "Testing template containing an `n>' element."
122 (tempo-define-template "test" '("(progn" n> "(list 1 2 3))"))
123 (with-temp-buffer
124 (emacs-lisp-mode)
125 (tempo-insert-template 'tempo-template-test nil)
126 ;; Tempo should have inserted two spaces before (list 1 2 3)
127 (should (equal (buffer-string) "(progn\n (list 1 2 3))"))))
128
129(ert-deftest tempo->-element-test ()
130 "Testing template containing a `>' element."
131 (with-temp-buffer
132 (emacs-lisp-mode)
133 (insert "(progn\n)")
134 (backward-char)
135 (tempo-define-template "test" '("(list 1 2 3)" >))
136 (tempo-insert-template 'tempo-template-test nil)
137 ;; Tempo should have inserted two spaces before (list 1 2 3)
138 (should (equal (buffer-string) "(progn\n (list 1 2 3))"))))
139
140(ert-deftest tempo-r>-bare-element-test ()
141 "Testing template containing a bare `r>' element."
142 (with-temp-buffer
143 (tempo-define-template "test" '("(progn" n r> ")"))
144 (emacs-lisp-mode)
145 (insert "(list 1 2 3)")
146 (set-mark (point))
147 (goto-char (point-min))
148 (tempo-insert-template 'tempo-template-test t)
149 ;; Tempo should have inserted two spaces before (list 1 2 3)
150 (should (equal (buffer-string) "(progn\n (list 1 2 3))"))))
151
152(ert-deftest tempo-r>-element-test ()
153 "Testing template containing an `r>' (with prompt) element."
154 (tempo-define-template "test" '("(progn" n (r> ":") ")"))
155 (with-temp-buffer
156 ;; Test on-region use
157 (emacs-lisp-mode)
158 (insert "(list 1 2 3)")
159 (set-mark (point))
160 (goto-char (point-min))
161 (tempo-insert-template 'tempo-template-test t)
162 (should (equal (buffer-string) "(progn\n (list 1 2 3))")))
163 (with-temp-buffer
164 ;; Test interactive use
165 (emacs-lisp-mode)
166 (let ((tempo-interactive t))
167 (cl-letf (((symbol-function 'read-string) (lambda (&rest _) " (list 1 2 3)")))
168 (tempo-insert-template 'tempo-template-test nil))
169 (should (equal (buffer-string) "(progn\n (list 1 2 3))")))))
170
171(ert-deftest tempo-o-element-test ()
172 "Testing template containing an `o' element."
173 (with-temp-buffer
174 (tempo-define-template "test" '("test" o))
175 (insert "hello")
176 (goto-char (point-min))
177 (tempo-insert-template 'tempo-template-test nil)
178 (should (equal (buffer-string) "test\nhello"))
179 (should (equal (point) 5))))
180
181(ert-deftest tempo-nil-element-test ()
182 "Testing template with nil elements."
183 (with-temp-buffer
184 (tempo-define-template "test" '("Hello," nil " World!"))
185 (tempo-insert-template 'tempo-template-test nil)
186 (should (equal (buffer-string) "Hello, World!"))))
187
188(ert-deftest tempo-eval-element-test ()
189 "Testing template with Emacs Lisp expressions."
190 (with-temp-buffer
191 (tempo-define-template "test" '((int-to-string (+ 1 1)) "=" (concat "1" "+1")))
192 (tempo-insert-template 'tempo-template-test nil)
193 (should (equal (buffer-string) "2=1+1"))))
194
195(ert-deftest tempo-l-element-test ()
196 "Testing template containing an `l' element."
197 (with-temp-buffer
198 (tempo-define-template "test" '("list: " (l "1, " "2, " (int-to-string (+ 1 2)))))
199 (tempo-insert-template 'tempo-template-test nil)
200 (should (equal (buffer-string) "list: 1, 2, 3"))))
201
202(ert-deftest tempo-tempo-user-elements-test ()
203 "Testing a template with elements for `tempo-user-elements'."
204 (with-temp-buffer
205 (make-local-variable 'tempo-user-elements)
206 (add-to-list 'tempo-user-elements (lambda (x) (int-to-string (* x x))))
207 (tempo-define-template "test" '(1 " " 2 " " 3 " " 4))
208 (tempo-insert-template 'tempo-template-test nil)
209 (should (equal (buffer-string) "1 4 9 16"))))
210
211(ert-deftest tempo-expand-tag-test ()
212 "Testing expansion of a template with a tag."
213 (with-temp-buffer
214 (tempo-define-template "test" '("Hello, World!") "hello")
215 (insert "hello")
216 (tempo-complete-tag)
217 (should (equal (buffer-string) "Hello, World!"))))
218
219(ert-deftest tempo-expand-partial-tag-test ()
220 "Testing expansion of a template with a tag, with a partial match."
221 (with-temp-buffer
222 (tempo-define-template "test" '("Hello, World!") "hello")
223 (insert "hel")
224 (tempo-complete-tag)
225 (should (equal (buffer-string) "Hello, World!"))))
226
227(provide 'tempo-tests)
228;;; tempo-tests.el ends here