[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/hyperbole 0d56d6712e: Hargs iform (#161),
ELPA Syncer <=