emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/hyperbole 0d56d6712e: Hargs iform (#161)


From: ELPA Syncer
Subject: [elpa] externals/hyperbole 0d56d6712e: Hargs iform (#161)
Date: Sat, 5 Feb 2022 03:57:39 -0500 (EST)

branch: externals/hyperbole
commit 0d56d6712ef0eedb9e5602d4b6c4f8a8220dd032
Author: Mats Lidell <mats.lidell@lidells.se>
Commit: GitHub <noreply@github.com>

    Hargs iform (#161)
    
    * Use macro to define const vectors
    
    * Add test cases
---
 ChangeLog           |  11 ++
 hargs.el            | 338 ++++++++++++++++++++++++++--------------------------
 test/hargs-tests.el |  56 +++++++++
 3 files changed, 234 insertions(+), 171 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a1ce29804a..f318afc6b2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2022-02-04  Mats Lidell  <matsl@gnu.org>
+
+* test/hargs-tests.el (hargs-get-verify-extension-characters)
+    (hargs-get-verify-extension-characters-K+): Test cases for extension
+    characters.
+
+* hargs.el (hargs:make-iform-vector): Converted to macro.
+    (hargs:iform-vector): Use defconst.
+    (hargs:iform-extensions-vector): Use defconst.
+    Patch from Stefan Monnier. Thank you Stefan.
+
 2022-02-03  Mats Lidell  <matsl@gnu.org>
 
 * hypb.el (hypb--installation-type): Return 10 digit git hash.
diff --git a/hargs.el b/hargs.el
index 7d9afb46e6..4d0ac3259d 100644
--- a/hargs.el
+++ b/hargs.el
@@ -224,19 +224,26 @@ element of the list is always the symbol 'args."
                "(hargs:get): Bad interactive-entry command character: `%c'"
                cmd))))))
 
-(defun hargs:make-iform-vector (iform-alist)
-  "Return a vector built from IFORM-ALIST used for looking up interactive 
command code characters."
+(defmacro hargs:make-iform-vector (&rest iform-alist)
+  "Return a vector of interactive command code characters.
+IFORM-ALIST is a list of elements of the form
+    (INTERACTIVE-CMD-CHR  (ARGUMENT-TYPE . GET-ARGUMENT-FORM))
+GET-ARGUMENT-FORM is executed in a context where it has access to
+two variables `prompt' and `default'."
   ;; Vector needs to have 1 more elts than the highest char code for
   ;; interactive commands.
-  (let* ((size (1+ (car (sort (mapcar 'car iform-alist) '>))))
-        (vec (make-vector size nil)))
-    (mapc (lambda (elt)
-           (aset vec (car elt)
-                 `(lambda (prompt default)
-                    (setq hargs:reading-type ',(cadr elt))
-                    ,(cddr elt))))
-         iform-alist)
-    vec))
+  (let ((size (1+ (car (sort (mapcar #'car iform-alist) #'>))))
+        (vecsym (make-symbol "vec")))
+    `(let ((,vecsym (make-vector ',size nil)))
+       ,@(mapcar (lambda (elt)
+                  `(aset ,vecsym ',(car elt)
+                         (lambda (prompt default)
+                           (ignore prompt default) ;Don't warn if not used.
+                           ;; FIXME: Why `setq' instead of let-binding?
+                           (setq hargs:reading-symbol ',(cadr elt))
+                           ,(cddr elt))))
+                iform-alist)
+       ,vecsym)))
 
 (defun hargs:prompt (prompt default &optional default-prompt)
   "Return string of PROMPT including DEFAULT.
@@ -500,7 +507,7 @@ Insert in minibuffer if active or in other window if 
minibuffer is inactive."
          entry)))))
 
 (defun hargs:iform-read (iform &optional default-args)
-  "Read action arguments according to IFORM, a list with car = 'interactive.
+  "Read action arguments according to IFORM, a list with car = `interactive'.
 With optional DEFAULT-ARGS equal to t, the current button is being modified, so
 its attribute values should be presented as defaults.  Otherwise, use
 DEFAULT-ARGS as a list of defaults to present when reading arguments.
@@ -686,182 +693,171 @@ help when appropriate."
 ;;; Private variables
 ;;; ************************************************************************
 
-(defvar hargs:iforms nil
-  "Alist of (interactive-cmd-chr . (argument-type . get-argument-form)) elts.")
-(setq   hargs:iforms
-       '(
-         ;; Get function symbol.
-         (?a . (symbol .
-                (intern (completing-read prompt obarray 'fboundp t default))))
-         ;; Get name of existing buffer.
-         (?b . (buffer .
+(defconst hargs:iform-vector
+  (hargs:make-iform-vector
+   ;; Get function symbol.
+   (?a . (symbol .
+                (intern (completing-read prompt obarray #'fboundp t default))))
+   ;; Get name of existing buffer.
+   (?b . (buffer .
                 (progn
                   (or default (setq default (other-buffer (current-buffer))))
                   (read-buffer prompt default t))))
-         ;; Get name of possibly nonexistent buffer.
-         (?B . (buffer .
+   ;; Get name of possibly nonexistent buffer.
+   (?B . (buffer .
                 (progn
                   (or default (setq default (other-buffer (current-buffer))))
                   (read-buffer prompt default nil))))
-         ;; Get character.
-         (?c . (character .
-                (progn (message
-                        (if default
-                            (hargs:prompt prompt
-                                          (if (integerp default)
-                                              (char-to-string default)
-                                            default)
-                                          "Curr:")
-                          prompt))
-                       (char-to-string (read-char)))))
-         ;; Get symbol for interactive function, a command.
-         (?C . (symbol .
+   ;; Get character.
+   (?c . (character .
+                   (progn (message
+                           (if default
+                               (hargs:prompt prompt
+                                             (if (integerp default)
+                                                 (char-to-string default)
+                                               default)
+                                             "Curr:")
+                             prompt))
+                          (char-to-string (read-char)))))
+   ;; Get symbol for interactive function, a command.
+   (?C . (symbol .
                 (intern
-                 (completing-read prompt obarray 'commandp t default))))
-         ;; Get value of point; does not do I/O.
-         (?d . (integer . (point)))
-         ;; Get directory name.
-         (?D . (directory .
-                (progn
-                  (or default (setq default default-directory))
-                  (read-file-name prompt default default 'existing))))
-         ;; Get existing file name.
-         (?f . (file .
-                (read-file-name prompt default default
-                                (if (eq system-type 'vax-vms)
-                                    nil 'existing))))
-         ;; Get possibly nonexistent file name.
-         (?F . (file . (read-file-name prompt default default nil)))
-         ;; Get key sequence.
-         (?k . (key .
-                (key-description (read-key-sequence
-                                  (if default
-                                      (hargs:prompt prompt default "Curr:")
-                                    prompt)))))
-         ;; Get key sequence without converting uppercase or shifted
-         ;; function keys to their unshifted equivalents.
-         (?K . (key .
-                (key-description (read-key-sequence
-                                  (if default
-                                      (hargs:prompt prompt default "Curr:")
-                                    prompt)
-                                  nil t))))
-         ;; Get value of mark.  Does not do I/O.
-         (?m . (integer . (marker-position (mark-marker))))
-         ;; Get numeric prefix argument or a number from the minibuffer.
-         (?N . (integer .
-                (if prefix-arg
-                    (prefix-numeric-value prefix-arg)
-                  (let ((arg))
-                    (while (not (integerp
-                                 (setq arg (read-minibuffer prompt default))))
-                      (beep))
-                    arg))))
-         ;; Get number from minibuffer.
-         (?n . (integer .
-                (let ((arg))
-                  (while (not (integerp
-                               (setq arg (read-minibuffer prompt default))))
-                    (beep))
-                  arg)))
-         ;; Get numeric prefix argument.  No I/O.
-         (?p . (prefix-arg .
-                (prefix-numeric-value prefix-arg)))
-         ;; Get prefix argument in raw form.  No I/O.
-         (?P . (prefix-arg . prefix-arg))
-         ;; Get region, point and mark as 2 args.  No I/O
-         (?r . (region .
+                 (completing-read prompt obarray #'commandp t default))))
+   ;; Get value of point; does not do I/O.
+   (?d . (integer . (point)))
+   ;; Get directory name.
+   (?D . (directory .
+                   (progn
+                     (or default (setq default default-directory))
+                     (read-file-name prompt default default 'existing))))
+   ;; Get existing file name.
+   (?f . (file .
+              (read-file-name prompt default default
+                              (if (eq system-type 'vax-vms)
+                                  nil 'existing))))
+   ;; Get possibly nonexistent file name.
+   (?F . (file . (read-file-name prompt default default nil)))
+   ;; Get key sequence.
+   (?k . (key .
+             (key-description (read-key-sequence
+                               (if default
+                                   (hargs:prompt prompt default "Curr:")
+                                 prompt)))))
+   ;; Get key sequence without converting uppercase or shifted
+   ;; function keys to their unshifted equivalents.
+   (?K . (key .
+             (key-description (read-key-sequence
+                               (if default
+                                   (hargs:prompt prompt default "Curr:")
+                                 prompt)
+                               nil t))))
+   ;; Get value of mark.  Does not do I/O.
+   (?m . (integer . (marker-position (mark-marker))))
+   ;; Get numeric prefix argument or a number from the minibuffer.
+   (?N . (integer .
+                 (if prefix-arg
+                     (prefix-numeric-value prefix-arg)
+                   (let ((arg))
+                     (while (not (integerp
+                                  (setq arg (read-minibuffer prompt default))))
+                       (beep))
+                     arg))))
+   ;; Get number from minibuffer.
+   (?n . (integer .
+                 (let ((arg))
+                   (while (not (integerp
+                                (setq arg (read-minibuffer prompt default))))
+                     (beep))
+                   arg)))
+   ;; Get numeric prefix argument.  No I/O.
+   (?p . (prefix-arg .
+                    (prefix-numeric-value prefix-arg)))
+   ;; Get prefix argument in raw form.  No I/O.
+   (?P . (prefix-arg . prefix-arg))
+   ;; Get region, point and mark as 2 args.  No I/O
+   (?r . (region .
                 (if (marker-position (mark-marker))
                     (list 'args (min (point) (mark t))
                           (max (point) (mark t)))
                   (list 'args nil nil))))
-         ;; Get string.
-         (?s . (string . (read-string prompt default)))
-         ;; Get symbol.
-         (?S . (symbol .
+   ;; Get string.
+   (?s . (string . (read-string prompt default)))
+   ;; Get symbol.
+   (?S . (symbol .
                 (read-from-minibuffer
                  prompt default minibuffer-local-ns-map 'sym)))
-         ;; Get variable name: symbol that is user-variable-p.
-         (?v . (symbol . (read-variable
-                          (if default
-                              (hargs:prompt prompt default "Curr:")
-                            prompt))))
-         ;; Get Lisp expression but don't evaluate.
-         (?x . (sexpression . (read-minibuffer prompt default)))
-         ;; Get Lisp expression and evaluate.
-         (?X . (sexpression . (eval-minibuffer prompt default)))))
-
-(defvar hargs:iform-vector nil
+   ;; Get variable name: symbol that is user-variable-p.
+   (?v . (symbol . (read-variable
+                   (if default
+                       (hargs:prompt prompt default "Curr:")
+                     prompt))))
+   ;; Get Lisp expression but don't evaluate.
+   (?x . (sexpression . (read-minibuffer prompt default)))
+   ;; Get Lisp expression and evaluate.
+   (?X . (sexpression . (eval-minibuffer prompt default))))
   "Vector of forms for each interactive command character code.")
-(setq   hargs:iform-vector (hargs:make-iform-vector hargs:iforms))
-
-(defvar hargs:iforms-extensions nil
-  "Hyperbole extension alist of (interactive-cmd-chr . (argument-type . 
get-argument-form)) elts.")
-(setq   hargs:iforms-extensions
-       '(
-         ;; Get existing Info node name, possibly prefixed with its (filename).
-         (?I . (Info-node .
-                (let ((prev-reading-p hargs:reading-type))
-                  (unwind-protect
-                      (progn (require 'info)
-                             (setq hargs:reading-type 'Info-node)
-                             ;; Prevent empty completions list from
-                             ;; triggering an error in Info-read-node-name.
-                             (unless Info-current-file-completions
-                               (condition-case nil
-                                   (Info-build-node-completions)
-                                 (error (setq Info-current-file-completions 
'(("None"))))))
-                             (Info-read-node-name prompt))
-                    (setq hargs:reading-type prev-reading-p)))))
-         ;; Get kcell from koutline.
-         (?K . (kcell . (hargs:read-match
-                         prompt
-                         ;; Match to "0" and visible cell labels only
-                         (cons "0"
-                               (kview:map-tree (lambda (view) 
(kcell-view:label)) kview t t))
-                         nil t (kcell-view:visible-label) 'kcell)))
-         ;; Get kcell or path reference for use in a link.
-         (?L . (klink . (hargs:read prompt nil default nil 'klink)))
-         ;; Get existing mail msg date and file.
-         (?M . (mail . (progn
-                         (while
-                             (or (not (listp
-                                       (setq default
-                                             (read-minibuffer
-                                              (hargs:prompt
-                                               prompt ""
-                                               "list of (date mail-file)")
-                                              default))))
-                                 (/= (length default) 2)
-                                 (not (and (stringp (car (cdr default)))
-                                           (file-exists-p
-                                            (car (cdr default))))))
-                           (beep))
-                         default)))
-         ;; Get a Koutline viewspec.
-         (?V . (kvspec . (hargs:read prompt nil nil nil 'kvspec)))
-         ;; Get existing Info index item name, possibly prefixed with its 
(filename).
-         (?X . (Info-index-item .
-                (let ((prev-reading-p hargs:reading-type))
-                  (unwind-protect
-                      (let (file item)
-                        (require 'info)
-                        (setq hargs:reading-type 'Info-index-item
-                              item (Info-read-index-item-name prompt))
-                        (if (string-match "^(\\([^\)]+\\))\\(.*\\)" item)
-                            item
-                          (if (setq file 
(Info-current-filename-sans-extension))
-                              (format "(%s)%s" file item)
-                            item)))
-                    (setq hargs:reading-type prev-reading-p)))))))
-
-(defvar hargs:iform-extensions-vector nil
+
+(defconst hargs:iform-extensions-vector
+  (hargs:make-iform-vector
+   ;; Get existing Info node name, possibly prefixed with its (filename).
+   (?I . (Info-node .
+                   (let ((prev-reading-p hargs:reading-symbol))
+                     (unwind-protect
+                         (progn (require 'info)
+                                (setq hargs:reading-symbol 'Info-node)
+                                ;; Prevent empty completions list from
+                                ;; triggering an error in Info-read-node-name.
+                                (unless Info-current-file-completions
+                                  (condition-case nil
+                                      (Info-build-node-completions)
+                                    (error (setq Info-current-file-completions 
'(("None"))))))
+                                (Info-read-node-name prompt))
+                       (setq hargs:reading-symbol prev-reading-p)))))
+   ;; Get kcell from koutline.
+   (?K . (kcell . (hargs:read-match
+                  prompt
+                  ;; Match to "0" and visible cell labels only
+                  (cons "0"
+                        (kview:map-tree (lambda (kview) (kcell-view:label)) 
kview t t))
+                  nil t (kcell-view:visible-label) 'kcell)))
+   ;; Get kcell or path reference for use in a link.
+   (?L . (klink . (hargs:read prompt nil default nil 'klink)))
+   ;; Get existing mail msg date and file.
+   (?M . (mail . (progn
+                  (while
+                      (or (not (listp
+                                (setq default
+                                      (read-minibuffer
+                                       (hargs:prompt
+                                        prompt ""
+                                        "list of (date mail-file)")
+                                       default))))
+                          (/= (length default) 2)
+                          (not (and (stringp (car (cdr default)))
+                                    (file-exists-p
+                                     (car (cdr default))))))
+                    (beep))
+                  default)))
+   ;; Get a Koutline viewspec.
+   (?V . (kvspec . (hargs:read prompt nil nil nil 'kvspec)))
+   ;; Get existing Info index item name, possibly prefixed with its (filename).
+   (?X . (Info-index-item .
+                         (let ((prev-reading-p hargs:reading-symbol))
+                           (unwind-protect
+                               (let (file item)
+                                 (require 'info)
+                                 (setq hargs:reading-symbol 'Info-index-item
+                                       item (Info-read-index-item-name prompt))
+                                 (if (string-match "^(\\([^\)]+\\))\\(.*\\)" 
item)
+                                     item
+                                   (if (setq file 
(Info-current-filename-sans-extension))
+                                       (format "(%s)%s" file item)
+                                     item)))
+                             (setq hargs:reading-symbol prev-reading-p))))))
   "Vector of forms for each interactive command character code.")
-(setq   hargs:iform-extensions-vector
-       (hargs:make-iform-vector hargs:iforms-extensions))
 
 (defvar hargs:string-to-complete nil
-  "The string in the minibuffer the last time a completions buffer was 
generated, or nil.")
+  "Minibuffer content the last time a completions buffer was generated, or 
nil.")
 
 (provide 'hargs)
 
diff --git a/test/hargs-tests.el b/test/hargs-tests.el
new file mode 100644
index 0000000000..5f7dac31f6
--- /dev/null
+++ b/test/hargs-tests.el
@@ -0,0 +1,56 @@
+;;; hargs-tests.el --- Tests for hargs.el                -*- lexical-binding: 
t; -*-
+;;
+;; Author:       Mats Lidell <matsl@gnu.org>
+;;
+;; Orig-Date:    04-Feb-22 at 23:00:00
+;; Last-Mod:     04-Feb-22 at 23:00:00 by Mats Lidell
+;;
+;; Copyright (C) 2022  Free Software Foundation, Inc.
+;; See the "HY-COPY" file for license information.
+;;
+;; This file is part of GNU Hyperbole.
+
+;;; Commentary:
+;;
+;; Tests for "../hargs.el"
+
+;;; Code:
+
+(require 'ert)
+(require 'with-simulated-input)
+(require 'hargs)
+
+(ert-deftest hargs-get-verify-extension-characters ()
+  "Verify hyperbole extension characters are indentified."
+  (skip-unless (not noninteractive))
+  (let ((file (make-temp-file "hypb")))
+    (unwind-protect
+        (progn
+          (with-simulated-input "xyz RET"
+            (should (string= (hargs:get "+I: ") "xyz")))
+          (with-simulated-input "xyz RET"
+            (should (string= (hargs:get "+L: ") "xyz")))
+          (with-simulated-input '((insert "xyz" file) "RET")'
+            (should (equal (hargs:get "+M: ") (list "xyz" file))))
+          (with-simulated-input "xyz RET"
+            (should (string= (hargs:get "+V: ") "xyz")))
+          (with-simulated-input "xyz RET"
+            (should (string= (hargs:get "+X: ") "(dir)xyz")))
+          (should-error (hargs:get "+A: ") :type 'error))
+      (delete-file file))))
+
+(ert-deftest hargs-get-verify-extension-characters-+K ()
+  "Verify hyperbole extension character +K is indentified."
+  (cl-letf (((symbol-function 'hargs:read-match) (lambda (prompt a &optional b 
c d e) "xyz"))
+           ((symbol-function 'kview:map-tree) (lambda (a b c d) nil))
+           ((symbol-function 'kcell-view:visible-label) (lambda () nil)))
+    (should (string= (hargs:get "+K: ") "xyz"))))
+
+;; This file can't be byte-compiled without `with-simulated-input' which
+;; is not part of the actual dependencies, so:
+;;   Local Variables:
+;;   no-byte-compile: t
+;;   End:
+
+(provide 'hargs-tests)
+;;; hargs-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]