Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists

2022-01-05 Thread Jonas Bernoulli
Nicolas Goaziou  writes:

> Hello,
>
> Jonas Bernoulli  writes:
>
>> Would it be okay to represent e.g. "C-c SPC" as:
>>
>>(export-snippet
>> (:back-end "texinfo" :value "@kbd{C-c @key{SPC}}" :post-blank 0 :parent 
>> #2))
>
> Just use (org-export-raw-string "@kbd{C-c @key{SPC}}") instead.

That works.  I must of done something wrong when first trying that.

>> I think that is one of the things I tried that ox-texinfo insisted on
>> quoting anyway.  I might misremember, so I will have another look.
>
> `org-export-raw-string' is a recent addition in Org.
>
>> Above I suggested using an `export-snippet' element (instead of `raw');
>> to me that seems appropriate too.
>
> I think that's abusing export snippets. They are more user-oriented,
> e.g. filters can apply to them.
>
> Note you can write (org-export-raw-string (some-public-function "C-c
> SPC")) where (some-public-function "C-c SPC") => "@kbd{C-c @key{SPC}}",
> as done currently by the "kbd" macro.

I named it org-texinfo-kbd-macro and wrote it so that it can be used by
the kbd macro.  I have changed doc/doc-setup.org to use it.

DEL was missing from the list of special keys.

 Cheers,
 Jonas



Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists

2021-12-29 Thread Nicolas Goaziou
Hello,

Jonas Bernoulli  writes:

> Would it be okay to represent e.g. "C-c SPC" as:
>
>(export-snippet
> (:back-end "texinfo" :value "@kbd{C-c @key{SPC}}" :post-blank 0 :parent 
> #2))

Just use (org-export-raw-string "@kbd{C-c @key{SPC}}") instead.

> I think that is one of the things I tried that ox-texinfo insisted on
> quoting anyway.  I might misremember, so I will have another look.

`org-export-raw-string' is a recent addition in Org.

> Above I suggested using an `export-snippet' element (instead of `raw');
> to me that seems appropriate too.

I think that's abusing export snippets. They are more user-oriented,
e.g. filters can apply to them.

Note you can write (org-export-raw-string (some-public-function "C-c
SPC")) where (some-public-function "C-c SPC") => "@kbd{C-c @key{SPC}}",
as done currently by the "kbd" macro.

Regards,
-- 
Nicolas Goaziou



Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists

2021-12-27 Thread Jonas Bernoulli
Nicolas Goaziou  writes:

> There's a mismatch between the keys.

Fixed.

> Simply put:
>
> Command in parenthesis, as done above, is optional.

Done.

>> +Regardless of which approach you use, you must define the =kbd= macro
>> +(see [[*Macro Replacement]]), which you can then use anywhere in the Org
>> +file:
>> +
>> +#+begin_example
>> +,#+macro: kbd (eval (let ((case-fold-search nil) (regexp (regexp-opt 
>> '("SPC" "RET" "LFD" "TAB" "BS" "ESC" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" 
>> "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN") 'words))) (format 
>> "@@texinfo:@kbd{@@%s@@texinfo:}@@" (replace-regexp-in-string regexp 
>> "@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t
>>  #+end_example
>
> Ouch. I don't think we should expect users to define this in order to
> use the feature being implemented. IOW, it should work out of the box.

Luckily that's already how it works; I just chose to not document the
fallback (done that now).  If the macro is not available, then @code{}
is used instead.

> I think the functions responsible for generating the Texinfo code should
> handle this without relying on the macro.

I tried but could not get it to work that way.  Whatever I tried
ox-texinfo insisted on breaking it by adding quotes.

I didn't go as far as to try injecting export-snippet elements into the
tree because without using org-macro-replace-all it seemed painful to do
that.  But on second thought...

Would it be okay to represent e.g. "C-c SPC" as:

   (export-snippet
(:back-end "texinfo" :value "@kbd{C-c @key{SPC}}" :post-blank 0 :parent #2))

instead of the more painful to construct:

   (export-snippet
(:back-end "texinfo" :value "@kbd{" :begin 317 :end 334 :post-blank 0 
:parent #2))
   #("C-c " 0 4
 (:parent #2))
   (export-snippet
(:back-end "texinfo" :value "@key{" :begin 338 :end 355 :post-blank 0 
:parent #2))
   #("SPC" 0 3
 (:parent #2))
   (export-snippet
(:back-end "texinfo" :value "}" :begin 358 :end 371 :post-blank 0 :parent 
#2))
   (export-snippet
(:back-end "texinfo" :value "}" :begin 371 :end 384 :post-blank 0 :parent 
#2))

> Of course, if that part is
> factored out, the macro might, in turn, make use of it.

>> +(defconst org-texinfo--definition-command-regexp
>> +  (format "\\`%s: \\(.+\\)"
>> +  (regexp-opt
>> +   (delq nil (mapcar #'cdr org-texinfo--definition-command-alist))
>> +   1))
>
> What is 1 meaning here? Do you mean t?

Yes. Done.

>> +(defun org-texinfo--separate-definitions (tree _backend info)
>> +  "Split up descriptive lists that contain Texinfo definition
>> commands."
>
> You need to document the arguments.
>> +  (org-element-map tree 'plain-list
>> +(lambda (plain-list)
>> +  (when (eq (org-element-property :type plain-list) 'descriptive)
>> +(let ((contents (org-element-contents plain-list))
>> +  item items)
>
> Nitpick: (items nil)

Done.

>> +  (while (setq item (pop contents))
>
> nitpick: Use dolist.

Err, that's what I would usually do.  Not sure why not here.

Done.

>> +(if (string-match " +(\\([^()]+\\)) *\\'" args)
>
> Could you use `rx' here?

Done.

(Not a fan personally.  IMO rx is less readable than a plain old
regexp, though that's probably just because I never took the time
to retrain myself.)

>> +(setq key (substring args 0 (match-beginning 0))
>> +  cmd (match-string 1 args))
>> +  (setq key args))
>> +(org-element-put-property
>> + item :tag
>> + (nconc (if (assoc "kbd" org-macro-templates)
>> +(let ((templates org-macro-templates))
>> +  (with-temp-buffer
>> +(insert (format "{{{kbd(%s)}}}" key))
>
> Here, there could be a function building the key chord, and you could
> wrap the result into a raw string (see `org-export-raw-string').

I think that is one of the things I tried that ox-texinfo insisted on
quoting anyway.  I might misremember, so I will have another look.
Above I suggested using an `export-snippet' element (instead of `raw');
to me that seems appropriate too.

 Cheers,
 Jonas



Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists

2021-12-26 Thread Nicolas Goaziou
Hello,

Thanks.

Jonas Bernoulli  writes:

> +#+begin_example
> +- Key: C-n (do-something) ::
> +  This command does something.
> +
> +- User Option: do-something-somehow ::
> +  This option controls how exactly ~do-something~ does its thing.
> +#+end_example
> +
> +#+texinfo: @noindent
> +becomes
> +
> +#+begin_example
> +@table @asis
> +@item @kbd{C-c C-c} (@code{do-something})
> +@kindex C-c C-c
> +@findex do-something
> +This command does something.
> +@end table

There's a mismatch between the keys.

> +Key items don't have to specify the respective command in parenthesis
> +as done above; that part is optional.

Simply put:

Command in parenthesis, as done above, is optional.

> +Regardless of which approach you use, you must define the =kbd= macro
> +(see [[*Macro Replacement]]), which you can then use anywhere in the Org
> +file:
> +
> +#+begin_example
> +,#+macro: kbd (eval (let ((case-fold-search nil) (regexp (regexp-opt '("SPC" 
> "RET" "LFD" "TAB" "BS" "ESC" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" "Cmd" 
> "Super" "UP" "LEFT" "RIGHT" "DOWN") 'words))) (format 
> "@@texinfo:@kbd{@@%s@@texinfo:}@@" (replace-regexp-in-string regexp 
> "@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t
>  #+end_example

Ouch. I don't think we should expect users to define this in order to
use the feature being implemented. IOW, it should work out of the box.

I think the functions responsible for generating the Texinfo code should
handle this without relying on the macro. Of course, if that part is
factored out, the macro might, in turn, make use of it.

> +(defconst org-texinfo--definition-command-regexp
> +  (format "\\`%s: \\(.+\\)"
> +  (regexp-opt
> +   (delq nil (mapcar #'cdr org-texinfo--definition-command-alist))
> +   1))

What is 1 meaning here? Do you mean t?


> +(defun org-texinfo--separate-definitions (tree _backend info)
> +  "Split up descriptive lists that contain Texinfo definition
> commands."

You need to document the arguments.
> +  (org-element-map tree 'plain-list
> +(lambda (plain-list)
> +  (when (eq (org-element-property :type plain-list) 'descriptive)
> +(let ((contents (org-element-contents plain-list))
> +  item items)

Nitpick: (items nil)

> +  (while (setq item (pop contents))

nitpick: Use dolist.

> +(pcase-let ((`(,cmd . ,args) (org-texinfo--match-definition 
> item)))
> +  (cond
> +   (cmd
> +(when items
> +  (org-texinfo--split-plain-list plain-list (nreverse items))
> +  (setq items nil))
> +(org-texinfo--split-definition plain-list item cmd args))
> +   (t
> +(when args
> +  (org-texinfo--massage-key-item plain-list item args))
> +(push item items)
> +  (unless (org-element-contents plain-list)
> +(org-element-extract-element plain-list)
> +info)
> +  tree)
> +
> +(defun org-texinfo--match-definition (item)
> +  "Return a cons-cell if ITEM specifies a Texinfo definition command.
> +The car is the command and the cdr is its arguments."
> +  (let ((tag (car-safe (org-element-property :tag item
> +(and tag
> + (stringp tag)
> + (string-match org-texinfo--definition-command-regexp tag)
> + (pcase-let*
> + ((cmd (car (rassoc (match-string-no-properties 1 tag)
> + org-texinfo--definition-command-alist)))
> +  (`(,cmd ,category)
> +   (and cmd (save-match-data (split-string cmd " "
> +  (args (match-string-no-properties 2 tag)))
> +   (cons cmd (if category (concat category " " args) args))
> +
> +(defun org-texinfo--split-definition (plain-list item cmd args)
> +  "Insert a definition command before list PLAIN-LIST.
> +Replace list item ITEM with a special-block that inherits the
> +contents of ITEM and whose type and Texinfo attributes are
> +specified by CMD and ARGS."
> +  (let ((contents (org-element-contents item)))
> +(org-element-insert-before
> + (apply #'org-element-create 'special-block
> +(list :type cmd
> +  :attr_texinfo (list (format ":options %s" args))
> +  :post-blank (if contents 1 0))
> +(mapc #'org-element-extract-element contents))
> + plain-list))
> +  (org-element-extract-element item))
> +
> +(defun org-texinfo--split-plain-list (plain-list items)
> +  "Insert a new plain list before the plain list PLAIN-LIST.
> +Remove ITEMS from PLAIN-LIST and use them as the contents of the
> +new plain list."
> +  (org-element-insert-before
> +   (apply #'org-element-create 'plain-list
> +  (list :type 'descriptive :post-blank 1)
> +  (mapc #'org-element-extract-element items))
> +   plain-list))
> +
> +(defun org-texinfo--massage-key-item (plain-list item args)
> +  "In PLAIN-LIST modify ITEM based on ARGS.
> +Reformat ITEM'

[PATCH 2/2] ox-texinfo: Define definition commands using description lists

2021-12-18 Thread Jonas Bernoulli
* doc/org-manual.org (Plain lists in Texinfo export): Document use
of definition command prefixes in description lists.

* lisp/ox-texinfo.el (org-texinfo--definition-command-alist)
(org-texinfo--definition-command-regexp): New variables.
* lisp/ox-texinfo.el (org-texinfo--filter-parse-tree): Call
org-texinfo--separate-definitions.
* lisp/ox-texinfo.el (org-texinfo--separate-definitions)
(org-texinfo--match-definition, org-texinfo--split-definition)
(org-texinfo--split-plain-list, org-texinfo--massage-key-item):
New functions.
---
 doc/org-manual.org |  98 -
 lisp/ox-texinfo.el | 132 -
 2 files changed, 227 insertions(+), 3 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index b8bb391c2..e8d777875 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15303,7 +15303,99 @@ output can also be produced with:
 ,#+attr_texinfo: :table-type vtable :indic asis
 - foo ::
 + bar ::
-  This is the common text for foo and bar.
+  This is the common text for variables foo and bar.
+#+end_example
+
+Likewise, the Texinfo export back-end supports two approaches to
+writing Texinfo definition commands (see [[info:texinfo::Definition
+Commands]]).  One of them uses description lists and is describe below,
+the other is described in [[*Special blocks in Texinfo export]].
+
+Items in a description list in a Org file that begin with =Function:=
+or certain other prefixes are converted using Texinfo definition
+commands.  This works even if other items in the same list do not have
+such a prefix; if necessary a single description list is converted
+using multiple tables (such as =@vtable=) and definition commands
+(such as =@defun=).
+
+#+begin_example
+- Function: org-texinfo-drawer drawer contents info ::
+  Transcode a DRAWER element from Org to Texinfo.
+#+end_example
+
+#+texinfo: @noindent
+becomes
+
+#+begin_example
+@defun org-texinfo-drawer drawer contents info ::
+  Transcode a DRAWER element from Org to Texinfo.
+@end defun
+#+end_example
+
+The recognized prefixes are =Command:=, =Function:=, =Macro:=,
+=Special Form:=, =Variable:= and =User Option:=.  These are the same
+prefixes that appear in the Info file for the respective definition
+commands.  For example a =Function:= item in the Org file is converted
+to a =@defun= command in the Texinfo file, which in turn is converted
+to a definition prefixed with =-- Function:= in the Info file.
+
+As a special case the prefix =Key:= is also recognized.  No Texinfo
+definition command exists for key bindings and the output in Info
+files also lacks the =Key:= prefix.  Even so this special case is
+supported because it provides a convenient shorthand, as illustrated
+here:
+
+#+begin_example
+- Key: C-n (do-something) ::
+  This command does something.
+
+- User Option: do-something-somehow ::
+  This option controls how exactly ~do-something~ does its thing.
+#+end_example
+
+#+texinfo: @noindent
+becomes
+
+#+begin_example
+@table @asis
+@item @kbd{C-c C-c} (@code{do-something})
+@kindex C-c C-c
+@findex do-something
+This command does something.
+@end table
+
+@defopt do-something-somehow
+This option controls how exactly @code{do-something} does its thing.
+@end defopt
+#+end_example
+
+Key items don't have to specify the respective command in parenthesis
+as done above; that part is optional.
+
+You can get the same result using the alternative approach (see
+[[*Special blocks in Texinfo export]]), which is more verbose and less
+similar to the final Info/HTML/PDF output (but more similar to the
+intermediate Texinfo file):
+
+#+begin_example
+- {{{kbd(C-c C-c)}}} (~do-something~) ::
+
+  #+kindex: C-c C-c
+  #+findex: do-something
+  This command does something.
+
+,#+attr_texinfo: :options do-something-somehow
+,#+begin_defopt
+  This option controls how exactly ~do-something~ does its thing.
+,#+end_defopt
+#+end_example
+
+Regardless of which approach you use, you must define the =kbd= macro
+(see [[*Macro Replacement]]), which you can then use anywhere in the Org
+file:
+
+#+begin_example
+,#+macro: kbd (eval (let ((case-fold-search nil) (regexp (regexp-opt '("SPC" 
"RET" "LFD" "TAB" "BS" "ESC" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" "Cmd" "Super" 
"UP" "LEFT" "RIGHT" "DOWN") 'words))) (format 
"@@texinfo:@kbd{@@%s@@texinfo:}@@" (replace-regexp-in-string regexp 
"@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t
 #+end_example
 
 *** Tables in Texinfo export
@@ -15373,6 +15465,10 @@ your king.
 :DESCRIPTION: Special block attributes.
 :END:
 
+The Texinfo export back-end supports two approaches to writing Texinfo
+definition commands.  One of them is describe here, the other in
+[[*Plain lists in Texinfo export]].
+
 #+cindex: @samp{ATTR_TEXINFO}, keyword
 
 The Texinfo export back-end converts special blocks to commands with
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 35862357d..cc9fca918 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -83,7