diff --git a/CHANGELOG.md b/CHANGELOG.md index 50d986c..f03ae77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,10 @@ - [#93](https://github.com/bbatsov/adoc-mode/pull/93): `adoc-preview` deletes the HTML file it writes next to the document when the buffer is killed or Emacs exits, live preview or not. It used to be left behind unless `adoc-live-preview-mode` was on. - [#93](https://github.com/bbatsov/adoc-mode/pull/93): The `auto` preview backend only picks the xwidget pane when Emacs has xwidget support, and falls back to `eww` otherwise. It used to pick it on any graphical Emacs and then fail. - [#93](https://github.com/bbatsov/adoc-mode/pull/93): In an Antora component, Flymake no longer reports `include::partial$x.adoc[]` and other Antora resource includes as missing files. Asciidoctor can't resolve those on its own. +- [#94](https://github.com/bbatsov/adoc-mode/pull/94): Fix the AsciiDoc menu entries that pointed at commands that don't exist (the xref, image and comment ones). The comment entry is backed by the new `adoc-insert-comment`, which comments out every line of the region at column 0, and the "Passthrough macros" submenu shows its help text. +- [#94](https://github.com/bbatsov/adoc-mode/pull/94): The tempo templates are documented with the AsciiDoc help text again (see `C-h f tempo-template-adoc-emphasis`), instead of a bare "Insert a adoc-emphasis." +- [#94](https://github.com/bbatsov/adoc-mode/pull/94): The trademark and dash templates insert `(TM)` and `--`, which Asciidoctor replaces with ™ and an em dash, as their menu entries say. They inserted `(T)` and `---`, which stay as they are. +- [#94](https://github.com/bbatsov/adoc-mode/pull/94): Tempo templates, and loading `adoc-mode` itself, no longer fail with `wrong-type-argument symbolp` when the current command is a lambda (a key bound to one, a hydra, or a transient). ## 0.9.0 (2026-06-02) diff --git a/adoc-mode-tempo.el b/adoc-mode-tempo.el index ed29286..0eea98b 100644 --- a/adoc-mode-tempo.el +++ b/adoc-mode-tempo.el @@ -31,40 +31,6 @@ ;; Defined in adoc-mode.el; declarations without initial values ;; silence the byte-compiler without interfering with defcustom/defconst. (defvar adoc-title-style) -(defvar adoc-help-emphasis) -(defvar adoc-help-bold) -(defvar adoc-help-monospace) -(defvar adoc-help-single-quote) -(defvar adoc-help-double-quote) -(defvar adoc-help-attributed) -(defvar adoc-help-underline) -(defvar adoc-help-overline) -(defvar adoc-help-line-through) -(defvar adoc-help-nobreak) -(defvar adoc-help-nowrap) -(defvar adoc-help-pre-wrap) -(defvar adoc-help-line-break) -(defvar adoc-help-page-break) -(defvar adoc-help-ruler-line) -(defvar adoc-help-entity-reference) -(defvar adoc-help-literal-paragraph) -(defvar adoc-help-delimited-block-comment) -(defvar adoc-help-delimited-block-passthrouh) -(defvar adoc-help-delimited-block-listing) -(defvar adoc-help-delimited-block-literal) -(defvar adoc-help-delimited-block-quote) -(defvar adoc-help-delimited-block-example) -(defvar adoc-help-delimited-block-sidebar) -(defvar adoc-help-delimited-block-open-block) -(defvar adoc-help-list-item-continuation) -(defvar adoc-help-url) -(defvar adoc-help-anchor) -(defvar adoc-help-xref) -(defvar adoc-help-pass) -(defvar adoc-help-asciimath) -(defvar adoc-help-latexmath) -(defvar adoc-help-pass-+++) -(defvar adoc-help-pass-$$) (declare-function adoc-make-two-line-title-underline "adoc-mode") (declare-function adoc-insert-indented "adoc-mode") @@ -97,10 +63,19 @@ which can be truthy even without an active region." (advice-add 'tempo-insert-template :around #'adoc-tempo-insert-template-fix) -(defun adoc-tempo-define (&rest args) - (if (eq adoc-tempo-frwk 'tempo-snippets) - (apply 'tempo-define-snippet args) ;; optional package, not always available - (apply #'tempo-define-template args))) +(defun adoc-tempo-define (name elements &optional tag doc) + "Define the tempo template NAME from ELEMENTS and TAG. +See `tempo-define-template'. DOC is the template's docstring, or a +variable holding it. The variable is only read when the docstring +is asked for: the help text is defined in adoc-mode.el, which can +load (or be byte-compiled) after this file." + (let ((args (list name elements tag (and (stringp doc) doc)))) + (if (eq adoc-tempo-frwk 'tempo-snippets) + (apply 'tempo-define-snippet args) ;; optional package, not always available + (apply #'tempo-define-template args))) + (when (and doc (symbolp doc)) + (put (intern (concat "tempo-template-" name)) 'function-documentation + `(bound-and-true-p ,doc)))) (defun adoc-template-str-title (&optional level title-text) "Returns the string tempo-template-adoc-title-x would insert" @@ -112,46 +87,46 @@ which can be truthy even without an active region." (buffer-substring-no-properties (point-min) (point-max))))) ;; Text formatting - constrained quotes -(adoc-tempo-define "adoc-emphasis" '("_" (r "text" text) "_") nil (bound-and-true-p adoc-help-emphasis)) -(adoc-tempo-define "adoc-bold" '("*" (r "text" text) "*") nil (bound-and-true-p adoc-help-bold)) -(adoc-tempo-define "adoc-typewriter-face" '("+" (r "text" text) "+") nil (bound-and-true-p adoc-help-monospace)) +(adoc-tempo-define "adoc-emphasis" '("_" (r "text" text) "_") nil 'adoc-help-emphasis) +(adoc-tempo-define "adoc-bold" '("*" (r "text" text) "*") nil 'adoc-help-bold) +(adoc-tempo-define "adoc-typewriter-face" '("+" (r "text" text) "+") nil 'adoc-help-monospace) (adoc-tempo-define "adoc-monospace-literal" '("`" (r "text" text) "`")) ;; Modern curved (smart) quotes: "`text`" and '`text`'. These replace the ;; deprecated AsciiDoc.py `text' / ``text'' templates. -(adoc-tempo-define "adoc-double-curved-quote" '("\"`" (r "text" text) "`\"") nil (bound-and-true-p adoc-help-double-quote)) -(adoc-tempo-define "adoc-single-curved-quote" '("'`" (r "text" text) "`'") nil (bound-and-true-p adoc-help-single-quote)) -(adoc-tempo-define "adoc-attributed" '("[" p "]#" (r "text" text) "#") nil (bound-and-true-p adoc-help-attributed)) -(adoc-tempo-define "adoc-underline" '("[.underline]#" (r "text" text) "#") nil (bound-and-true-p adoc-help-underline)) -(adoc-tempo-define "adoc-overline" '("[.overline]#" (r "text" text) "#") nil (bound-and-true-p adoc-help-overline)) -(adoc-tempo-define "adoc-line-through" '("[.line-through]#" (r "text" text) "#") nil (bound-and-true-p adoc-help-line-through)) -(adoc-tempo-define "adoc-nobreak" '("[.nobreak]#" (r "text" text) "#") nil (bound-and-true-p adoc-help-nobreak)) -(adoc-tempo-define "adoc-nowrap" '("[.nowrap]#" (r "text" text) "#") nil (bound-and-true-p adoc-help-nowrap)) -(adoc-tempo-define "adoc-pre-wrap" '("[.pre-wrap]#" (r "text" text) "#") nil (bound-and-true-p adoc-help-pre-wrap)) +(adoc-tempo-define "adoc-double-curved-quote" '("\"`" (r "text" text) "`\"") nil 'adoc-help-double-quote) +(adoc-tempo-define "adoc-single-curved-quote" '("'`" (r "text" text) "`'") nil 'adoc-help-single-quote) +(adoc-tempo-define "adoc-attributed" '("[" p "]#" (r "text" text) "#") nil 'adoc-help-attributed) +(adoc-tempo-define "adoc-underline" '("[.underline]#" (r "text" text) "#") nil 'adoc-help-underline) +(adoc-tempo-define "adoc-overline" '("[.overline]#" (r "text" text) "#") nil 'adoc-help-overline) +(adoc-tempo-define "adoc-line-through" '("[.line-through]#" (r "text" text) "#") nil 'adoc-help-line-through) +(adoc-tempo-define "adoc-nobreak" '("[.nobreak]#" (r "text" text) "#") nil 'adoc-help-nobreak) +(adoc-tempo-define "adoc-nowrap" '("[.nowrap]#" (r "text" text) "#") nil 'adoc-help-nowrap) +(adoc-tempo-define "adoc-pre-wrap" '("[.pre-wrap]#" (r "text" text) "#") nil 'adoc-help-pre-wrap) ;; Text formatting - unconstrained quotes -(adoc-tempo-define "adoc-emphasis-uc" '("__" (r "text" text) "__") nil (bound-and-true-p adoc-help-emphasis)) -(adoc-tempo-define "adoc-bold-uc" '("**" (r "text" text) "**") nil (bound-and-true-p adoc-help-bold)) -(adoc-tempo-define "adoc-monospace-uc" '("++" (r "text" text) "++") nil (bound-and-true-p adoc-help-monospace)) -(adoc-tempo-define "adoc-attributed-uc" '("[" p "]##" (r "text" text) "##") nil (bound-and-true-p adoc-help-attributed)) +(adoc-tempo-define "adoc-emphasis-uc" '("__" (r "text" text) "__") nil 'adoc-help-emphasis) +(adoc-tempo-define "adoc-bold-uc" '("**" (r "text" text) "**") nil 'adoc-help-bold) +(adoc-tempo-define "adoc-monospace-uc" '("++" (r "text" text) "++") nil 'adoc-help-monospace) +(adoc-tempo-define "adoc-attributed-uc" '("[" p "]##" (r "text" text) "##") nil 'adoc-help-attributed) (adoc-tempo-define "adoc-superscript" '("^" (r "text" text) "^")) (adoc-tempo-define "adoc-subscript" '("~" (r "text" text) "~")) ;; Text formatting - misc -(adoc-tempo-define "adoc-line-break" '((if (eq (char-before) ?\s) "" " ") "+" %) nil (bound-and-true-p adoc-help-line-break)) -(adoc-tempo-define "adoc-page-break" '(bol "<<<" %) nil (bound-and-true-p adoc-help-page-break)) -(adoc-tempo-define "adoc-ruler-line" '(bol "---" %) nil (bound-and-true-p adoc-help-ruler-line)) +(adoc-tempo-define "adoc-line-break" '((if (eq (char-before) ?\s) "" " ") "+" %) nil 'adoc-help-line-break) +(adoc-tempo-define "adoc-page-break" '(bol "<<<" %) nil 'adoc-help-page-break) +(adoc-tempo-define "adoc-ruler-line" '(bol "---" %) nil 'adoc-help-ruler-line) ;; Text formatting - replacements (adoc-tempo-define "adoc-copyright" '("(C)")) -(adoc-tempo-define "adoc-trademark" '("(T)")) +(adoc-tempo-define "adoc-trademark" '("(TM)")) (adoc-tempo-define "adoc-registered-trademark" '("(R)")) -(adoc-tempo-define "adoc-dash" '("---")) +(adoc-tempo-define "adoc-dash" '("--")) (adoc-tempo-define "adoc-ellipsis" '("...")) (adoc-tempo-define "adoc-right-arrow" '("->")) (adoc-tempo-define "adoc-left-arrow" '("<-")) (adoc-tempo-define "adoc-right-double-arrow" '("=>")) (adoc-tempo-define "adoc-left-double-arrow" '("<=")) -(adoc-tempo-define "adoc-entity-reference" '("&" r ";") nil (bound-and-true-p adoc-help-entity-reference)) +(adoc-tempo-define "adoc-entity-reference" '("&" r ";") nil 'adoc-help-entity-reference) ;; Titles ;; todo @@ -187,7 +162,7 @@ Is influenced by customization variables such as `adoc-title-style'.")))) (adoc-tempo-define "adoc-block-title" '(bol "." (r "text" text) %)) ;; Paragraphs -(adoc-tempo-define "adoc-literal-paragraph" '(bol " " (r "text" text) %) nil (bound-and-true-p adoc-help-literal-paragraph)) +(adoc-tempo-define "adoc-literal-paragraph" '(bol " " (r "text" text) %) nil 'adoc-help-literal-paragraph) (adoc-tempo-define "adoc-paragraph-tip" '(bol "TIP: " (r "text" text) %)) (adoc-tempo-define "adoc-paragraph-note" '(bol "NOTE: " (r "text" text) %)) (adoc-tempo-define "adoc-paragraph-important" '(bol "IMPORTANT: " (r "text" text) %)) @@ -197,28 +172,28 @@ Is influenced by customization variables such as `adoc-title-style'.")))) ;; delimited blocks (adoc-tempo-define "adoc-delimited-block-comment" '(bol (make-string 50 ?/) n (r-or-n "text" text) bol (make-string 50 ?/) %) - nil (bound-and-true-p adoc-help-delimited-block-comment)) + nil 'adoc-help-delimited-block-comment) (adoc-tempo-define "adoc-delimited-block-passthrough" '(bol (make-string 50 ?+) n (r-or-n "text" text) bol (make-string 50 ?+) %) - nil (bound-and-true-p adoc-help-delimited-block-passthrouh)) + nil 'adoc-help-delimited-block-passthrouh) (adoc-tempo-define "adoc-delimited-block-listing" '(bol (make-string 50 ?-) n (r-or-n "text" text) bol (make-string 50 ?-) %) - nil (bound-and-true-p adoc-help-delimited-block-listing)) + nil 'adoc-help-delimited-block-listing) (adoc-tempo-define "adoc-delimited-block-literal" '(bol (make-string 50 ?.) n (r-or-n "text" text) bol (make-string 50 ?.) %) - nil (bound-and-true-p adoc-help-delimited-block-literal)) + nil 'adoc-help-delimited-block-literal) (adoc-tempo-define "adoc-delimited-block-quote" '(bol (make-string 50 ?_) n (r-or-n "text" text) bol (make-string 50 ?_) %) - nil (bound-and-true-p adoc-help-delimited-block-quote)) + nil 'adoc-help-delimited-block-quote) (adoc-tempo-define "adoc-delimited-block-example" '(bol (make-string 50 ?=) n (r-or-n "text" text) bol (make-string 50 ?=) %) - nil (bound-and-true-p adoc-help-delimited-block-example)) + nil 'adoc-help-delimited-block-example) (adoc-tempo-define "adoc-delimited-block-sidebar" '(bol (make-string 50 ?*) n (r-or-n "text" text) bol (make-string 50 ?*) %) - nil (bound-and-true-p adoc-help-delimited-block-sidebar)) + nil 'adoc-help-delimited-block-sidebar) (adoc-tempo-define "adoc-delimited-block-open-block" '(bol "--" n (r-or-n "text" text) bol "--" %) - nil (bound-and-true-p adoc-help-delimited-block-open-block)) + nil 'adoc-help-delimited-block-open-block) ;; Lists ;; TODO: customize indentation @@ -235,7 +210,7 @@ Is influenced by customization variables such as `adoc-title-style'.")))) (adoc-tempo-define "adoc-implicit-numbered-list-item-4" '(bol (adoc-insert-indented ".... " 4) (r "text" text))) (adoc-tempo-define "adoc-implicit-numbered-list-item-5" '(bol (adoc-insert-indented "..... " 5) (r "text" text))) (adoc-tempo-define "adoc-labeled-list-item" '(bol (p "label" label) ":: " (r "text" text))) -(adoc-tempo-define "adoc-list-item-continuation" '(bol "+" %) nil (bound-and-true-p adoc-help-list-item-continuation)) +(adoc-tempo-define "adoc-list-item-continuation" '(bol "+" %) nil 'adoc-help-list-item-continuation) ;; tables (adoc-tempo-define "adoc-example-table" @@ -245,22 +220,23 @@ Is influenced by customization variables such as `adoc-title-style'.")))) "|===\n" % )) ;; Macros (inline & block) -(adoc-tempo-define "adoc-url" '("http://foo.com") nil (bound-and-true-p adoc-help-url)) -(adoc-tempo-define "adoc-url-caption" '("http://foo.com[" (r "caption" caption) "]") nil (bound-and-true-p adoc-help-url)) -(adoc-tempo-define "adoc-email" '("bob@foo.com") nil (bound-and-true-p adoc-help-url)) -(adoc-tempo-define "adoc-email-caption" '("mailto:" (p "address" address) "[" (r "caption" caption) "]") nil (bound-and-true-p adoc-help-url)) -(adoc-tempo-define "adoc-anchor" '("[[" (r "id" id) "]]") nil (bound-and-true-p adoc-help-anchor)) -(adoc-tempo-define "adoc-anchor-default-syntax" '("anchor:" (r "id" id) "[" (p "xreflabel" xreflabel) "]") nil (bound-and-true-p adoc-help-anchor)) -(adoc-tempo-define "adoc-xref" '("<<" (p "id" id) "," (r "caption" caption) ">>") nil (bound-and-true-p adoc-help-xref)) -(adoc-tempo-define "adoc-xref-default-syntax" '("xref:" (p "id" id) "[" (r "caption" caption) "]") nil (bound-and-true-p adoc-help-xref)) +(adoc-tempo-define "adoc-url" '("http://foo.com") nil 'adoc-help-url) +(adoc-tempo-define "adoc-url-caption" '("http://foo.com[" (r "caption" caption) "]") nil 'adoc-help-url) +(adoc-tempo-define "adoc-email" '("bob@foo.com") nil 'adoc-help-url) +(adoc-tempo-define "adoc-email-caption" '("mailto:" (p "address" address) "[" (r "caption" caption) "]") nil 'adoc-help-url) +(adoc-tempo-define "adoc-anchor" '("[[" (r "id" id) "]]") nil 'adoc-help-anchor) +(adoc-tempo-define "adoc-anchor-default-syntax" '("anchor:" (r "id" id) "[" (p "xreflabel" xreflabel) "]") nil 'adoc-help-anchor) +(adoc-tempo-define "adoc-xref" '("<<" (p "id" id) "," (r "caption" caption) ">>") nil 'adoc-help-xref) +(adoc-tempo-define "adoc-xref-default-syntax" '("xref:" (p "id" id) "[" (r "caption" caption) "]") nil 'adoc-help-xref) (adoc-tempo-define "adoc-image" '("image:" (r "target-path" target-path) "[" (p "caption" caption) "]")) +(adoc-tempo-define "adoc-comment" '(bol "// " %) nil 'adoc-help-comment) ;; Passthrough -(adoc-tempo-define "adoc-pass" '("pass:[" (r "text" text) "]") nil (bound-and-true-p adoc-help-pass)) -(adoc-tempo-define "adoc-asciimath" '("asciimath:[" (r "text" text) "]") nil (bound-and-true-p adoc-help-asciimath)) -(adoc-tempo-define "adoc-latexmath" '("latexmath:[" (r "text" text) "]") nil (bound-and-true-p adoc-help-latexmath)) -(adoc-tempo-define "adoc-pass-+++" '("+++" (r "text" text) "+++") nil (bound-and-true-p adoc-help-pass-+++)) -(adoc-tempo-define "adoc-pass-$$" '("$$" (r "text" text) "$$") nil (bound-and-true-p adoc-help-pass-$$)) +(adoc-tempo-define "adoc-pass" '("pass:[" (r "text" text) "]") nil 'adoc-help-pass) +(adoc-tempo-define "adoc-asciimath" '("asciimath:[" (r "text" text) "]") nil 'adoc-help-asciimath) +(adoc-tempo-define "adoc-latexmath" '("latexmath:[" (r "text" text) "]") nil 'adoc-help-latexmath) +(adoc-tempo-define "adoc-pass-+++" '("+++" (r "text" text) "+++") nil 'adoc-help-pass-+++) +(adoc-tempo-define "adoc-pass-$$" '("$$" (r "text" text) "$$") nil 'adoc-help-pass-$$) ; backticks handled in tempo-template-adoc-monospace-literal ;;;; tempo handlers @@ -299,7 +275,8 @@ passed the on-region argument." ;; called that eventually brought us here. If we came here not by an ;; interactive call to tempo-template-xxx we can't have a clue - assume ;; nil. - (arg (if (string-match "^tempo-template-" (symbol-name this-command)) + (arg (if (and (symbolp this-command) + (string-prefix-p "tempo-template-" (symbol-name this-command))) current-prefix-arg nil)) ;; copy from tempo-define-template diff --git a/adoc-mode.el b/adoc-mode.el index 90ff44e..f344620 100644 --- a/adoc-mode.el +++ b/adoc-mode.el @@ -3681,6 +3681,24 @@ new customization demands." (font-lock-ensure))) ;;;; misc +(defun adoc-insert-comment (&optional beg end) + "Comment out the lines between BEG and END, or start a comment line. +Interactively BEG and END delimit the active region. An AsciiDoc +comment line starts with `//' in the first column, so every line gets +one there." + (interactive (when (use-region-p) + (list (region-beginning) (region-end)))) + (if (not beg) + (tempo-template-adoc-comment) + (save-excursion + (let ((end (copy-marker end))) + (goto-char beg) + (beginning-of-line) + (while (< (point) end) + (insert "// ") + (forward-line 1)) + (set-marker end nil))))) + (defun adoc-insert-indented (str indent-level) "Indents and inserts STR such that point is at INDENT-LEVEL." (indent-to (- (* tab-width indent-level) (length str))) @@ -5286,15 +5304,15 @@ ITEMS is a list of (name pos . level)." :help ,adoc-help-anchor] ["Anchor (syntax 2): anchor:id[xreflabel]" tempo-template-adoc-anchor-default-syntax :help ,adoc-help-anchor] - ["Xref (syntax 1): <>" adoc-xref + ["Xref (syntax 1): <>" tempo-template-adoc-xref :help ,adoc-help-xref] - ["Xref (syntax 2): xref:id[caption]" adoc-xref-default-syntax + ["Xref (syntax 2): xref:id[caption]" tempo-template-adoc-xref-default-syntax :help ,adoc-help-xref] - ["Image: image:target-path[caption]" adoc-image] - ["Comment: //" tempo-template-adoc-comment + ["Image: image:target-path[caption]" tempo-template-adoc-image] + ["Comment: //" adoc-insert-comment :help ,adoc-help-comment] ("Passthrough macros" - :help adoc-help-passthrough-macros + :help ,adoc-help-passthrough-macros ["pass:[text]" tempo-template-adoc-pass :help ,adoc-help-pass] ["ASCIIMath: asciimath:[text]" tempo-template-adoc-asciimath diff --git a/test/adoc-mode-tempo-test.el b/test/adoc-mode-tempo-test.el index 232c7d2..3354540 100644 --- a/test/adoc-mode-tempo-test.el +++ b/test/adoc-mode-tempo-test.el @@ -129,6 +129,63 @@ (adoc-test-trans "" "++++++" '(tempo-template-adoc-pass-+++)) (adoc-test-trans "lorem dolor" "lorem +++ipsum+++ dolor" '(tempo-template-adoc-pass-+++)) (adoc-test-trans "" "$$$$" '(tempo-template-adoc-pass-$$)) - (adoc-test-trans "lorem dolor" "lorem $$ipsum$$ dolor" '(tempo-template-adoc-pass-$$)))) + (adoc-test-trans "lorem dolor" "lorem $$ipsum$$ dolor" '(tempo-template-adoc-pass-$$))) + + (it "inserts the replacements the menu advertises" + (adoc-test-trans "" "(TM)" '(tempo-template-adoc-trademark)) + (adoc-test-trans "" "--" '(tempo-template-adoc-dash))) + + (it "inserts a comment line" + (adoc-test-trans "" "// " '(adoc-insert-comment)) + (adoc-test-trans "lorem!" "lorem\n// " '(adoc-insert-comment))) + + (it "comments out every line of the region" + (dolist (case '(("a\nb\nc" 1 6 "// a\n// b\n// c") + ;; partly selected lines are commented whole + ("xx a\n b\nc" 4 9 "// xx a\n// b\nc"))) + (with-temp-buffer + (adoc-mode) + (insert (nth 0 case)) + (adoc-insert-comment (nth 1 case) (nth 2 case)) + (expect (buffer-string) :to-equal (nth 3 case))))) + + (it "documents the templates with the AsciiDoc help text" + (expect (documentation 'tempo-template-adoc-emphasis) + :to-match (regexp-quote adoc-help-emphasis))) + + (it "works when the current command is a lambda" + ;; e.g. a template run from a key bound to a lambda, or from a hydra + (with-temp-buffer + (adoc-mode) + (let ((this-command (lambda () (interactive)))) + (expect (tempo-template-adoc-title-2) :not :to-throw))))) + +(defun adoc-test--menu-items (keymap) + "Return the (BINDING . HELP) of every item in the menu KEYMAP. +Submenus are included." + (let (items) + (map-keymap + (lambda (_event item) + (when (eq (car-safe item) 'menu-item) + (let ((binding (nth 2 item)) + (help (plist-get (nthcdr 3 item) :help))) + (if (keymapp binding) + (setq items (append (adoc-test--menu-items binding) items)) + (push (cons binding help) items))))) + keymap) + items)) + +(describe "the AsciiDoc menu" + (let ((items (adoc-test--menu-items (lookup-key adoc-mode-map [menu-bar])))) + (it "only offers commands that exist" + (expect items :not :to-be nil) + (expect (cl-remove-if (lambda (item) (or (null (car item)) (commandp (car item)))) + items) + :to-be nil)) + + (it "has help text, not symbols, as help" + (expect (cl-remove-if (lambda (item) (or (null (cdr item)) (stringp (cdr item)))) + items) + :to-be nil)))) ;;; adoc-mode-tempo-test.el ends here