>From b377640c04e9318d67fcb74dfcfd9b455d78dca9 Mon Sep 17 00:00:00 2001 From: Federico Tedin Date: Mon, 13 May 2019 15:55:09 -0300 Subject: [PATCH 1/1] Use lexical-binding in tempo.el and add tests * lisp/tempo.el: Use lexical-binding. (tempo-define-template): Expand documentation to mention `tempo-user-elements'. (tempo-named-insertions, tempo-region-start, tempo-region-stop): Make them buffer-local. * test/lisp/tempo-tests.el: Add tests for tempo.el. --- lisp/tempo.el | 18 ++- test/lisp/tempo-tests.el | 229 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 test/lisp/tempo-tests.el diff --git a/lisp/tempo.el b/lisp/tempo.el index 28afbec0f4..66192439cc 100644 --- a/lisp/tempo.el +++ b/lisp/tempo.el @@ -1,4 +1,4 @@ -;;; tempo.el --- Flexible template insertion +;;; tempo.el --- Flexible template insertion -*- lexical-binding: t; -*- ;; Copyright (C) 1994-1995, 2001-2019 Free Software Foundation, Inc. @@ -211,6 +211,9 @@ tempo-region-stop (make-variable-buffer-local 'tempo-match-finder) (make-variable-buffer-local 'tempo-collection) (make-variable-buffer-local 'tempo-dirty-collection) +(make-variable-buffer-local 'tempo-named-insertions) +(make-variable-buffer-local 'tempo-region-start) +(make-variable-buffer-local 'tempo-region-stop) ;;; Functions @@ -268,11 +271,14 @@ tempo-define-template - `n>': Inserts a newline and indents line. - `o': Like `%' but leaves the point before the newline. - nil: It is ignored. - - Anything else: It is evaluated and the result is treated as an - element to be inserted. One additional tag is useful for these - cases. If an expression returns a list (l foo bar), the elements - after `l' will be inserted according to the usual rules. This makes - it possible to return several elements from one expression." + - Anything else: Each function in `tempo-user-elements' 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 + tag is useful for these cases. If an expression returns a list (l + foo bar), the elements after `l' will be inserted according to the + usual rules. This makes it possible to return several elements + from one expression." (let* ((template-name (intern (concat "tempo-template-" name))) (command-name template-name)) diff --git a/test/lisp/tempo-tests.el b/test/lisp/tempo-tests.el new file mode 100644 index 0000000000..4ce0830700 --- /dev/null +++ b/test/lisp/tempo-tests.el @@ -0,0 +1,229 @@ +;;; tempo-tests.el --- Test suite for tempo.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2019 Free Software Foundation, Inc. + +;; Author: Federico Tedin +;; Keywords: tempo + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'tempo) + +(ert-deftest string-element-test () + "Test a template containing a string element." + (with-temp-buffer + (tempo-define-template "test" '("GNU Emacs Tempo test")) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "GNU Emacs Tempo test")))) + +(ert-deftest p-bare-element-test () + "Test a template containing a bare `p' element." + (with-temp-buffer + (tempo-define-template "test" '("abcde" p)) + (tempo-insert-template 'tempo-template-test nil) + (tempo-forward-mark) + (should (equal (point) 6)))) + +(ert-deftest r-bare-element-test () + "Test a template containing a bare `r' element." + (with-temp-buffer + (tempo-define-template "test" '("abcde" r "ghijk")) + (insert "F") + (set-mark-command nil) + (goto-char (point-min)) + (tempo-insert-template 'tempo-template-test t) + (should (equal (buffer-string) "abcdeFghijk")))) + +(ert-deftest p-element-test () + "Testing template containing a `p' (prompt) element." + (with-temp-buffer + (tempo-define-template "test" '("hello " (p ">"))) + (setq tempo-interactive t) + (cl-letf (((symbol-function 'read-string) (lambda (_) "world"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "hello world")))) + +(ert-deftest P-element-test () + "Testing template containing a `P' (prompt) element." + (with-temp-buffer + (tempo-define-template "test" '("hello " (P ">"))) + (setq tempo-interactive nil) ;; `P' will ignore this + (cl-letf (((symbol-function 'read-string) (lambda (_) "world"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "hello world")))) + +(ert-deftest r-element-test () + "Testing template containing an `r' (with prompt) element." + (with-temp-buffer + (tempo-define-template "test" '("abcde" (r ">") "ghijk")) + (setq tempo-interactive t) + (cl-letf (((symbol-function 'read-string) (lambda (_) "F"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "abcdeFghijk")))) + +(ert-deftest s-element-test () + "Testing template containing an `s' element." + (with-temp-buffer + (tempo-define-template "test" '("hello " (p ">" P1) " " (s P1))) + (setq tempo-interactive t) + (cl-letf (((symbol-function 'read-string) (lambda (_) "world!"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "hello world! world!")))) + +(ert-deftest &-element-test () + "Testing template containing an `&' element." + (tempo-define-template "test" '(& "test")) + (with-temp-buffer + (insert " ") + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) " test"))) + (with-temp-buffer + (insert "hello") + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "hello\ntest")))) + +(ert-deftest %-element-test () + "Testing template containing an `%' element." + (tempo-define-template "test" '("test" %)) + (with-temp-buffer + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "test"))) + (with-temp-buffer + (insert "hello") + (goto-char (point-min)) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "test\nhello")))) + +(ert-deftest n-element-test () + "Testing template containing an `n' element." + (tempo-define-template "test" '("test" n "test")) + (with-temp-buffer + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "test\ntest")))) + +(ert-deftest n>-element-test () + "Testing template containing an `n>' element." + (tempo-define-template "test" '("(progn" n> "(list 1 2 3))")) + (with-temp-buffer + (emacs-lisp-mode) + (tempo-insert-template 'tempo-template-test nil) + ;; Tempo should have inserted two spaces before (list 1 2 3) + (should (equal (buffer-string) "(progn\n (list 1 2 3))")))) + +(ert-deftest >-element-test () + "Testing template containing a `>' element." + (with-temp-buffer + (emacs-lisp-mode) + (insert "(progn\n)") + (backward-char) + (tempo-define-template "test" '("(list 1 2 3)" >)) + (tempo-insert-template 'tempo-template-test nil) + ;; Tempo should have inserted two spaces before (list 1 2 3) + (should (equal (buffer-string) "(progn\n (list 1 2 3))")))) + +(ert-deftest r>-bare-element-test () + "Testing template containing a bare `r>' element." + (with-temp-buffer + (tempo-define-template "test" '("(progn" n r> ")")) + (emacs-lisp-mode) + (insert "(list 1 2 3)") + (set-mark-command nil) + (goto-char (point-min)) + (tempo-insert-template 'tempo-template-test t) + ;; Tempo should have inserted two spaces before (list 1 2 3) + (should (equal (buffer-string) "(progn\n (list 1 2 3))")))) + +(ert-deftest r>-element-test () + "Testing template containing an `r>' (with prompt) element." + (tempo-define-template "test" '("(progn" n (r> ":") ")")) + (with-temp-buffer + ;; Test on-region use + (emacs-lisp-mode) + (setq tempo-interactive nil) + (insert "(list 1 2 3)") + (set-mark-command nil) + (goto-char (point-min)) + (tempo-insert-template 'tempo-template-test t) + (should (equal (buffer-string) "(progn\n (list 1 2 3))"))) + (with-temp-buffer + ;; Test interactive use + (emacs-lisp-mode) + (setq tempo-interactive t) + (cl-letf (((symbol-function 'read-string) (lambda (_) " (list 1 2 3)"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "(progn\n (list 1 2 3))")))) + +(ert-deftest o-element-test () + "Testing template containing an `o' element." + (with-temp-buffer + (tempo-define-template "test" '("test" o)) + (insert "hello") + (goto-char (point-min)) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "test\nhello")) + (should (equal (point) 5)))) + +(ert-deftest nil-element-test () + "Testing template with nil elements." + (with-temp-buffer + (tempo-define-template "test" '("Hello," nil " World!")) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "Hello, World!")))) + +(ert-deftest eval-element-test () + "Testing template with Emacs Lisp expressions." + (with-temp-buffer + (tempo-define-template "test" '((int-to-string (+ 1 1)) "=" (concat "1" "+1"))) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "2=1+1")))) + +(ert-deftest l-element-test () + "Testing template containing an `l' element." + (with-temp-buffer + (tempo-define-template "test" '("list: " (l "1, " "2, " (int-to-string (+ 1 2))))) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "list: 1, 2, 3")))) + +(ert-deftest tempo-user-elements-test () + "Testing a template containing an element to be used as an argument +in a call to a function in `tempo-user-elements'." + (with-temp-buffer + (make-variable-buffer-local 'tempo-user-elements) + (add-to-list 'tempo-user-elements (lambda (x) (int-to-string (* x x)))) + (tempo-define-template "test" '(1 " " 2 " " 3 " " 4)) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "1 4 9 16")))) + +(ert-deftest expand-tag-test () + "Testing expansion of a template with a tag." + (with-temp-buffer + (tempo-define-template "test" '("Hello, World!") "hello") + (insert "hello") + (tempo-complete-tag) + (should (equal (buffer-string) "Hello, World!")))) + +(ert-deftest expand-partial-tag-test () + "Testing expansion of a template with a tag, with a partial match." + (with-temp-buffer + (tempo-define-template "test" '("Hello, World!") "hello") + (insert "hel") + (tempo-complete-tag) + (should (equal (buffer-string) "Hello, World!")))) + +(provide 'tempo-tests) +;;; tempo-tests.el ends here -- 2.17.1