From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Federico Tedin Newsgroups: gmane.emacs.devel Subject: Re: [PATCH] Unit tests and lexical-binding for Tempo Date: Tue, 14 May 2019 18:44:09 -0300 Message-ID: <875zqcr9sm.fsf@gmail.com> References: <87h89yqiwu.fsf@gmail.com> <87k1etamhs.fsf@tcd.ie> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="211588"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux) Cc: emacs-devel@gnu.org To: "Basil L. Contovounesios" Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue May 14 23:48:15 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hQfHT-000smL-5H for ged-emacs-devel@m.gmane.org; Tue, 14 May 2019 23:48:15 +0200 Original-Received: from localhost ([127.0.0.1]:55185 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hQfHR-0003FH-PE for ged-emacs-devel@m.gmane.org; Tue, 14 May 2019 17:48:13 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:49859) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hQfDd-00012n-QY for emacs-devel@gnu.org; Tue, 14 May 2019 17:44:19 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hQfDb-0000Jd-Co for emacs-devel@gnu.org; Tue, 14 May 2019 17:44:17 -0400 Original-Received: from mail-qt1-x842.google.com ([2607:f8b0:4864:20::842]:32858) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hQfDa-0000Gn-Vv for emacs-devel@gnu.org; Tue, 14 May 2019 17:44:15 -0400 Original-Received: by mail-qt1-x842.google.com with SMTP id m32so948069qtf.0 for ; Tue, 14 May 2019 14:44:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=aPLCJHUa7Z4ZsPP3YvefmY6yyGhhDdkv4XtGD3uU/pc=; b=vbaeudPdaGPMk75macmhxQDUGvDN6iSyFMpTP2HmeA4KtaU9vuRgDA39MROv1xLDdI 88gsVckiOGay4PEaUhK7+sFsUm+q8Lfsc2zGpAbaiJI9NTjKBlhnF5t5chCXX/Yr4K6Q /vhnMjvScGyRLaffE5IfK2WYWCmyG/cPfe51TWTwk49aX1MWt1WZmzAANYUibaLRav4e k08zJ4pH1pwgbICYn0211ZVlAXu97xajbWJFTbR1DRC04F+5lD/N/vV+lJmLny7Plnc8 TS5EmlNQI+RowZOMh/Sdh9Ay6s79SzkOhd5G39of4mRiVoaJgmWDBeMkuEhmV3Z9uOOT pipQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=aPLCJHUa7Z4ZsPP3YvefmY6yyGhhDdkv4XtGD3uU/pc=; b=DNo+sj5g5fA3SVlwAVVMDf8XzDv8s/D8wuXoyqSUrHFWU1YXN+3kZgLKf1AKH6CBHm YFzTL5g9MSAOhYS+z4wUyGfNOfWpApgpFJcWzJC9aKtbycHCoSYRv0XcJfhOyU3XuGz3 dYZtOs7ymn/agXiqvqwwiERKebiMdMxZOO5DJBoujOaNe5QfSlkJEBTXUAX8KxqyoMuL C+cXh00R/AWN9tTa2JYNm+g6+xbEJ0OwYHsxAYPymeRvZ8MOfYhb8vF1DkQ1tMBiA6yg rLAeoIfLkCU3qJ6HChTq9xpSQ2v85b8Ju5qgFkpbURz1XTj2mIB1KUciUG+jPKUGXu1X Oq5w== X-Gm-Message-State: APjAAAXzrZwF34QEVM1E9Jy1+T5u9cSJtW0weH28IBJ5SOCBR7Yd2cgY T7AdqIAM87wO+7ozLUWesV3iu7gK3og= X-Google-Smtp-Source: APXvYqxz2AHZherZqmEnjxpXJdPVbKimGxawoBDaUE7Prvh3Ni6iWMVZcrNKd7N03DBhzaHGPhLzsA== X-Received: by 2002:aed:2a55:: with SMTP id k21mr31686140qtf.1.1557870253296; Tue, 14 May 2019 14:44:13 -0700 (PDT) Original-Received: from hideo ([181.170.211.157]) by smtp.gmail.com with ESMTPSA id d58sm180075qtb.11.2019.05.14.14.44.10 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 14 May 2019 14:44:12 -0700 (PDT) In-Reply-To: <87k1etamhs.fsf@tcd.ie> (Basil L. Contovounesios's message of "Tue, 14 May 2019 01:49:35 +0100") X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::842 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:236522 Archived-At: --=-=-= Content-Type: text/plain Hi Basil, thanks for taking the time to review the patch. I've fixed the mistakes using the suggestions you made. I've also added the 'abbrev' tag to tempo.el. --=-=-= Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename=tempo.patch Content-Transfer-Encoding: quoted-printable Content-Description: patch >From dad0f0a6841e321cfca4c2962e3ce384199ff51e Mon Sep 17 00:00:00 2001 From: federicotdn Date: Tue, 14 May 2019 09:16:00 -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 | 41 ++++----- test/lisp/tempo-tests.el | 229 +++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 247 insertions(+), 23 deletions(-) create mode 100644 test/lisp/tempo-tests.el diff --git a/lisp/tempo.el b/lisp/tempo.el index 28afbec..e3b9c76 100644 --- a/lisp/tempo.el +++ b/lisp/tempo.el @@ -1,11 +1,11 @@ -;;; tempo.el --- Flexible template insertion +;;; tempo.el --- Flexible template insertion -*- lexical-binding: t; -*- =20 ;; Copyright (C) 1994-1995, 2001-2019 Free Software Foundation, Inc. =20 ;; Author: David K=C3=A5gedal ;; Created: 16 Feb 1994 ;; K=C3=A5gedal's last version number: 1.2.4 -;; Keywords: extensions, languages, tools +;; Keywords: abbrev, extensions, languages, tools =20 ;; This file is part of GNU Emacs. =20 @@ -152,7 +152,7 @@ tempo-insert-string-functions (defvar tempo-tags nil "An association list with tags and corresponding templates.") =20 -(defvar tempo-local-tags '((tempo-tags . nil)) +(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, @@ -161,16 +161,16 @@ tempo-local-tags =20 `tempo-tags' is always in the last position in this list.") =20 -(defvar tempo-collection nil +(defvar-local tempo-collection nil "A collection of all the tags defined for the current buffer.") =20 -(defvar tempo-dirty-collection t +(defvar-local tempo-dirty-collection t "Indicates if the tag collection needs to be rebuilt.") =20 -(defvar tempo-marks nil +(defvar-local tempo-marks nil "A list of marks to jump to with `\\[tempo-forward-mark]' and `\\[tempo-= backward-mark]'.") =20 -(defvar tempo-match-finder "\\b\\([[:word:]]+\\)\\=3D" +(defvar-local tempo-match-finder "\\b\\([[:word:]]+\\)\\=3D" "The regexp or function used to find the string to match against tags. =20 If `tempo-match-finder' is a string, it should contain a regular @@ -195,23 +195,15 @@ tempo-user-elements This function should return something to be sent to `tempo-insert' if it recognizes the argument, and nil otherwise.") =20 -(defvar tempo-named-insertions nil +(defvar-local tempo-named-insertions nil "Temporary storage for named insertions.") =20 -(defvar tempo-region-start (make-marker) +(defvar-local tempo-region-start (make-marker) "Region start when inserting around the region.") =20 -(defvar tempo-region-stop (make-marker) +(defvar-local tempo-region-stop (make-marker) "Region stop when inserting around the region.") =20 -;; Make some variables local to every buffer - -(make-variable-buffer-local 'tempo-marks) -(make-variable-buffer-local 'tempo-local-tags) -(make-variable-buffer-local 'tempo-match-finder) -(make-variable-buffer-local 'tempo-collection) -(make-variable-buffer-local 'tempo-dirty-collection) - ;;; Functions =20 ;; @@ -268,11 +260,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 0000000..6dac856 --- /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: abbrev + +;; 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) +(eval-when-compile (require 'cl-lib)) + +(ert-deftest tempo-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 tempo-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 tempo-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 (point)) + (goto-char (point-min)) + (tempo-insert-template 'tempo-template-test t) + (should (equal (buffer-string) "abcdeFghijk")))) + +(ert-deftest tempo-p-element-test () + "Testing template containing a `p' (prompt) element." + (with-temp-buffer + (tempo-define-template "test" '("hello " (p ">"))) + (let ((tempo-interactive t)) + (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world")= )) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "hello world"))))) + +(ert-deftest tempo-P-element-test () + "Testing template containing a `P' (prompt) element." + (with-temp-buffer + (tempo-define-template "test" '("hello " (P ">"))) + ;; By default, `tempo-interactive' is nil, `P' should ignore this. + (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "hello world")))) + +(ert-deftest tempo-r-element-test () + "Testing template containing an `r' (with prompt) element." + (with-temp-buffer + (tempo-define-template "test" '("abcde" (r ">") "ghijk")) + (let ((tempo-interactive t)) + (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "F"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "abcdeFghijk"))))) + +(ert-deftest tempo-s-element-test () + "Testing template containing an `s' element." + (with-temp-buffer + (tempo-define-template "test" '("hello " (p ">" P1) " " (s P1))) + (let ((tempo-interactive t)) + (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "world!"= ))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "hello world! world!"))))) + +(ert-deftest tempo-&-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 tempo-%-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 tempo-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 tempo-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 tempo->-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 tempo-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 (point)) + (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 tempo-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) + (insert "(list 1 2 3)") + (set-mark (point)) + (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) + (let ((tempo-interactive t)) + (cl-letf (((symbol-function 'read-string) (lambda (&rest _) " (list= 1 2 3)"))) + (tempo-insert-template 'tempo-template-test nil)) + (should (equal (buffer-string) "(progn\n (list 1 2 3))"))))) + +(ert-deftest tempo-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 tempo-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 tempo-eval-element-test () + "Testing template with Emacs Lisp expressions." + (with-temp-buffer + (tempo-define-template "test" '((int-to-string (+ 1 1)) "=3D" (concat = "1" "+1"))) + (tempo-insert-template 'tempo-template-test nil) + (should (equal (buffer-string) "2=3D1+1")))) + +(ert-deftest tempo-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-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-local-variable '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 tempo-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 tempo-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 --=20 2.7.4 --=-=-=--