* Merging ox-texinfo+ into ox-texinfo
@ 2021-11-09 18:01 Jonas Bernoulli
2021-11-19 12:46 ` Nicolas Goaziou
0 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2021-11-09 18:01 UTC (permalink / raw)
To: emacs-orgmode
Hello,
In the olden days before Org's own manual was written using an org-mode
file, I started doing just that for Magit. Because ox-texinfo.el wasn't
quite there yet I wrote an extension, ox-texinfo+.el, to fill in the
gaps. Since then I have written seven more manuals that use my
extension.
I recently talked to Bastien about this and he encouraged to bring up
the possibility of merging ox-texinfo+.el into ox-texinfo.el.
ox-texinfo+ (https://github.com/tarsius/ox-texinfo-plus) has several
features but the one I would like to talk about now is the following.
[If you want to look at the other features now, then please use the
"next" branch as I am in the process of trimming some of them down
or even removing them completely. The main feature is the same in
the "master" and "next" branches.]
Create `@deffn` and similar definition items by writing list
items in Org that look similar to what they will look like in
Info. To enable this, add:
#+TEXINFO_DEFFN: t
to your Org file. After doing that, you can create definition
items like so:
- Command: magit-section-show
Show the body of the current section.
- Function: magit-git-exit-code &rest args
- Macro: magit-insert-section &rest args
- Variable: magit-display-buffer-noselect
- User Option: magit-display-buffer-function
- Key: q, magit-mode-bury-buffer
I propose that we add this as an optional feature to ox-texinfo.el
itself.
IMO the biggest advantage of this style is that it leads to a prettier
org file, which is suitable for direct consumption by end-users. It is
also easier to write in this style by package authors who might not want
to fully familiarize themselves with all the peculiarities of writing an
org file intended for export to texinfo.
It is possible to mix the two styles; you can use the ox-texinfo+.el
style for most or all definitions but use the additional flexibility of
ox-texinfo.el, when that is needed.
What do you think? Might this be something that could be merged?
The reason I am bringing this up now after years of maintaining this as
an extension is that I would like to finally stop checking in both the
*.org and *.texi files into git. [Non]GNU Elpa already supports this
and I plan to implement it for Melpa as well. It would be much nicer if
the only additional requirement for an *elpa was to have a recent enough
Org version installed, instead of that and also ox-texinfo+.el.
Cheers,
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Merging ox-texinfo+ into ox-texinfo
2021-11-09 18:01 Merging ox-texinfo+ into ox-texinfo Jonas Bernoulli
@ 2021-11-19 12:46 ` Nicolas Goaziou
2021-11-20 21:06 ` Jonas Bernoulli
0 siblings, 1 reply; 47+ messages in thread
From: Nicolas Goaziou @ 2021-11-19 12:46 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> I recently talked to Bastien about this and he encouraged to bring up
> the possibility of merging ox-texinfo+.el into ox-texinfo.el.
>
> ox-texinfo+ (https://github.com/tarsius/ox-texinfo-plus) has several
> features but the one I would like to talk about now is the following.
[...]
>
> Create `@deffn` and similar definition items by writing list
> items in Org that look similar to what they will look like in
> Info. To enable this, add:
>
> #+TEXINFO_DEFFN: t
>
> to your Org file. After doing that, you can create definition
> items like so:
>
> - Command: magit-section-show
>
> Show the body of the current section.
>
> - Function: magit-git-exit-code &rest args
> - Macro: magit-insert-section &rest args
> - Variable: magit-display-buffer-noselect
> - User Option: magit-display-buffer-function
> - Key: q, magit-mode-bury-buffer
>
> I propose that we add this as an optional feature to ox-texinfo.el
> itself.
I like the idea, thank you for suggesting it.
The chosen UI is rather odd however. I cannot think of another use of
controlling export thhough "#+keyword: boolean" syntax. Usually, we
extend the "options" keyword. It could become, for example:
#+options: texinfo+:t
Could it be possible to use that syntax instead?
> It is possible to mix the two styles; you can use the ox-texinfo+.el
> style for most or all definitions but use the additional flexibility of
> ox-texinfo.el, when that is needed.
How is it possible? Keywords are global. How do you change value
locally?
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Merging ox-texinfo+ into ox-texinfo
2021-11-19 12:46 ` Nicolas Goaziou
@ 2021-11-20 21:06 ` Jonas Bernoulli
2021-11-21 12:41 ` Nicolas Goaziou
0 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2021-11-20 21:06 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> I like the idea, thank you for suggesting it.
Great :D
>> #+TEXINFO_DEFFN: t
>
> The chosen UI is rather odd however. I cannot think of another use of
> controlling export thhough "#+keyword: boolean" syntax. Usually, we
> extend the "options" keyword. It could become, for example:
>
> #+options: texinfo+:t
>
> Could it be possible to use that syntax instead?
Of course. I probably used the separate keyword because all the entries
for ox-texinfo's :options-alist did that too, but if that's not how this
is usually done for booleans, then I see no reason not to change it.
>> It is possible to mix the two styles; you can use the ox-texinfo+.el
>> style for most or all definitions but use the additional flexibility of
>> ox-texinfo.el, when that is needed.
>
> How is it possible? Keywords are global. How do you change value
> locally?
Well... it turned out not to be true, but I should be able to get it to
work. The idea is that the new shorthand handling is only used if such
a shorthand is actually used by the item that is being processed. All
other list items should effectively be treated as before, but that isn't
the case yet. For now all non-shorthand list items are simply treated
as @item, but `org-texinfo+-item' could be changed to instead fall back
to the `org-texinfo-item's default behavior in those cases. (It would
still have to check whether it needs to begin and/or end the "item
container" (itemize/table/...), so it is not completely trivial, but
should be doable.)
For testing purposes I have moved the relevant `ox-texinfo+.el' code
into `ox-texinfo.el', changing only how the feature has to be enabled,
and everything that worked before continues to work. If the feature is
enabled, then my manuals are exported the same as before and with the
feature disabled org-manual.org also results in the same texi file as
before.
So I have to address the above issue and then we also have to think
about naming. I was thinking about using the term "shorthands"; instead
of "texinfo-deffn:t" we could use "texinfo-shorthands:t". The functions
need to be renamed too of course, but IMO simply replacing "ox-texinfo+"
with "ox-texinfo-shorthand" is quite ugly. Do you have a suggestion for
that? All the new functions could be placed in the "Item" section.
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Merging ox-texinfo+ into ox-texinfo
2021-11-20 21:06 ` Jonas Bernoulli
@ 2021-11-21 12:41 ` Nicolas Goaziou
2021-11-30 16:58 ` Jonas Bernoulli
0 siblings, 1 reply; 47+ messages in thread
From: Nicolas Goaziou @ 2021-11-21 12:41 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> Of course. I probably used the separate keyword because all the entries
> for ox-texinfo's :options-alist did that too, but if that's not how this
> is usually done for booleans, then I see no reason not to change it.
More precisely, there's an historical distinction between string values
and other values (symbols, numbers...). The former is set by keywords,
the latter is obtained with "options". Consequently, all the entries in
ox-texinfo's :options-alist are used to set strings.
> Well... it turned out not to be true, but I should be able to get it to
> work. The idea is that the new shorthand handling is only used if such
> a shorthand is actually used by the item that is being processed. All
> other list items should effectively be treated as before, but that isn't
> the case yet. For now all non-shorthand list items are simply treated
> as @item, but `org-texinfo+-item' could be changed to instead fall back
> to the `org-texinfo-item's default behavior in those cases. (It would
> still have to check whether it needs to begin and/or end the "item
> container" (itemize/table/...), so it is not completely trivial, but
> should be doable.)
Then I suggest to use "attr_texinfo" keyword, for example:
#+attr_texinfo: :shorthand t
- item...
This way, we ensure the change is local. `org-texinfo-item' already
checks :sep attribute.
In this case, there's no need to add a new keyword or extend "options".
> So I have to address the above issue and then we also have to think
> about naming. I was thinking about using the term "shorthands"; instead
> of "texinfo-deffn:t" we could use "texinfo-shorthands:t". The functions
> need to be renamed too of course, but IMO simply replacing "ox-texinfo+"
> with "ox-texinfo-shorthand" is quite ugly. Do you have a suggestion for
> that? All the new functions could be placed in the "Item" section.
I see no reason to change the prefix, since these functions are part of
ox-texinfo. I didn't look closely at your code, tho, so I may be wide of
the mark.
WDYT?
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: Merging ox-texinfo+ into ox-texinfo
2021-11-21 12:41 ` Nicolas Goaziou
@ 2021-11-30 16:58 ` Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
0 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2021-11-30 16:58 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Sorry for the delay, I got side-tracked with many other things.
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>>> It is possible to mix the two styles;
>>
>> Well... it turned out not to be true, but I should be able to get it
>> to work.
>
> Then I suggest to use "attr_texinfo" keyword, for example:
>
> #+attr_texinfo: :shorthand t
> - item...
>
> This way, we ensure the change is local. `org-texinfo-item' already
> checks :sep attribute.
I am sure I can get it to work just fine without a need for that.
It just turns out that I haven't done so yet, because I only used the
ox-texinfo+ style in manuals that use that style exclusively. Now
that you have signaled that there is a good change that this would be
included in Org, putting in the work to use both styles in parallel is
actually justified.
But it likely will be a few weeks until I get to work because I looked
at the current implementation again and decided that it would be better
to start over and do the work using org-element instead of at the latest
possible moment when strings are being concatenated as ox-texinfo+
currently does.
> I see no reason to change the prefix, since these functions are part of
> ox-texinfo. I didn't look closely at your code, tho, so I may be wide of
> the mark.
I haven't started working on the org-element based implementation yet,
but I expect that won't actually need any new function definitions so,
the question is moot anyway. (But just in case: I agree.)
Cheers,
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH 0/2] ox-texinfo: Define definition commands using description lists
2021-11-30 16:58 ` Jonas Bernoulli
@ 2021-12-18 21:40 ` Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx Jonas Bernoulli
` (5 more replies)
0 siblings, 6 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2021-12-18 21:40 UTC (permalink / raw)
To: emacs-orgmode; +Cc: kyle, mail
Hello again,
The new implementation of the proposed feature is now ready.
Unlike the old implementation it works by filtering the parse tree
(instead of doing it later by advising `org-texinfo-plain-list' and
`org-texinfo-item'), and it expects the use of description lists to
define description commands (instead of regular unordered lists).
I have already updated the manuals of borg, epkg, forge, ghub,
magit, magit-section, transient and with-editor to this new style and
it worked very well.
Executive summary: This adds a second, alternative style to write
(in Org files) Texinfo definition commands that closely resembles the
final Info/HMTL/PDF output instead of the intermediate Texinfo file.
Likewise this adds a second, alternative style to group/"combine"
an @item with one or more $itemx. (See the first commit.)
These additions are described in more detail in the manual, which I
have updated. The other styles that are used in Org's own manual are
not affected and both styles can be used in the same manual.
Cheers,
Jonas
Jonas Bernoulli (2):
ox-texinfo: Turn a description list item with "+" bullet into @itemx
ox-texinfo: Define definition commands using description lists
doc/org-manual.org | 133 ++++++++++++++++++++++++++++++++---
lisp/ox-texinfo.el | 169 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 286 insertions(+), 16 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
@ 2021-12-18 21:40 ` Jonas Bernoulli
2021-12-26 21:37 ` Nicolas Goaziou
2021-12-18 21:40 ` [PATCH 2/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
` (4 subsequent siblings)
5 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2021-12-18 21:40 UTC (permalink / raw)
To: emacs-orgmode; +Cc: kyle, mail
* doc/org-manual.org (Plain lists in Texinfo export): Reorder and
document new functionality.
* lisp/ox-texinfo.el (org-texinfo--filter-parse-tree)
(org-texinfo--normalize-items): New functions.
* lisp/ox-texinfo.el (org-texinfo-item): Use @itemx or @item
depending on the used bullet.
---
doc/org-manual.org | 37 ++++++++++++++++++++++++++-----------
lisp/ox-texinfo.el | 39 +++++++++++++++++++++++++++++++++++----
2 files changed, 61 insertions(+), 15 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index b65e2f173..b8bb391c2 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15236,6 +15236,23 @@ This paragraph is preceded by...
:DESCRIPTION: List attributes.
:END:
+#+cindex: lettered lists, in Texinfo export
+#+cindex: enum, Texinfo attribute
+The Texinfo export back-end converts unordered and ordered lists in
+the Org file using the default command =@itemize=.
+
+Ordered lists are numbered when exported to Texinfo format. Such
+numbering obeys any counter (see [[*Plain Lists]]) in the first item of
+the list. The =:enum= attribute also let you start the list at a
+specific number, or switch to a lettered list, as illustrated here:
+
+#+begin_example
+#+ATTR_TEXINFO: :enum A
+1. Alpha
+2. Bravo
+3. Charlie
+#+end_example
+
#+cindex: @samp{ATTR_TEXINFO}, keyword
#+cindex: two-column tables, in Texinfo export
#+cindex: table-type, Texinfo attribute
@@ -15262,7 +15279,7 @@ entry in the first column of the table.
The following example illustrates all the attributes above:
#+begin_example
-,#+ATTR_TEXINFO: :table-type vtable :sep , :indic asis
+,#+attr_texinfo: :table-type vtable :sep , :indic asis
- foo, bar :: This is the common text for variables foo and bar.
#+end_example
@@ -15277,18 +15294,16 @@ This is the common text for variables foo and bar.
@end table
#+end_example
-#+cindex: lettered lists, in Texinfo export
-#+cindex: enum, Texinfo attribute
-Ordered lists are numbered when exported to Texinfo format. Such
-numbering obeys any counter (see [[*Plain Lists]]) in the first item of
-the list. The =:enum= attribute also let you start the list at
-a specific number, or switch to a lettered list, as illustrated here
+In description lists the used bullet is significant when exporting to
+Texinfo; when in doubt, then use =-=. An item that uses =+= instead
+becomes a new entry in the first column of the table. The above
+output can also be produced with:
#+begin_example
-#+ATTR_TEXINFO: :enum A
-1. Alpha
-2. Bravo
-3. Charlie
+,#+attr_texinfo: :table-type vtable :indic asis
+- foo ::
++ bar ::
+ This is the common text for foo and bar.
#+end_example
*** Tables in Texinfo export
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index b0125894a..35862357d 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -418,6 +418,11 @@ (defun org-texinfo--filter-section-blank-lines (headline _backend _info)
"Filter controlling number of blank lines after a section."
(replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" "\n\n" headline))
+(defun org-texinfo--filter-parse-tree (tree backend info)
+ "Normalize headlines and items."
+ (org-texinfo--normalize-headlines tree backend info)
+ (org-texinfo--normalize-items tree info))
+
(defun org-texinfo--normalize-headlines (tree _backend info)
"Normalize headlines in TREE.
@@ -443,6 +448,29 @@ (defun org-texinfo--normalize-headlines (tree _backend info)
info)
tree)
+(defun org-texinfo--normalize-items (tree info)
+ "Normalize items in TREE.
+
+INFO is a plist used as a communication channel.
+
+Items in description lists that use the \"+\" bullet are
+converted to `@itemx'. If another item is followed by such an
+item, then the first item should not be followed by a space,
+which this function takes care of.
+
+Return new tree."
+ (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)))
+ (while (setq item (pop contents))
+ (let ((next-item (car contents)))
+ (when (and next-item
+ (equal (org-element-property :bullet next-item) "+ "))
+ (org-element-put-property item :post-blank 0)))))))
+ info)
+ tree)
+
(defun org-texinfo--find-verb-separator (s)
"Return a character not used in string S.
This is used to choose a separator for constructs like \\verb."
@@ -998,13 +1026,16 @@ (defun org-texinfo-item (item contents info)
(let ((tag (org-export-data tag info)))
(if split
(split-string tag (regexp-quote split) t "[ \t\n]+")
- (list tag))))))
+ (list tag)))))
+ (command (if (equal (org-element-property :bullet item) "+ ")
+ "@itemx"
+ "@item")))
(format "%s\n%s"
(pcase items
- (`nil "@item")
- (`(,item) (concat "@item " item))
+ (`nil command)
+ (`(,item) (concat command " " item))
(`(,item . ,items)
- (concat "@item " item "\n"
+ (concat command " " item "\n"
(mapconcat (lambda (i) (concat "@itemx " i))
items
"\n"))))
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH 2/2] ox-texinfo: Define definition commands using description lists
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx Jonas Bernoulli
@ 2021-12-18 21:40 ` Jonas Bernoulli
2021-12-26 21:46 ` Nicolas Goaziou
2022-01-05 13:30 ` [PATCH v2 0/3] " Jonas Bernoulli
` (3 subsequent siblings)
5 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2021-12-18 21:40 UTC (permalink / raw)
To: emacs-orgmode; +Cc: kyle, mail
* 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 +83,7 @@ (org-export-define-backend 'texinfo
(verse-block . org-texinfo-verse-block))
:filters-alist
'((:filter-headline . org-texinfo--filter-section-blank-lines)
- (:filter-parse-tree . org-texinfo--normalize-headlines)
+ (:filter-parse-tree . org-texinfo--filter-parse-tree)
(:filter-section . org-texinfo--filter-section-blank-lines)
(:filter-final-output . org-texinfo--untabify))
:menu-entry
@@ -407,6 +407,23 @@ (defconst org-texinfo-inline-image-rules
(regexp-opt '("eps" "pdf" "png" "jpg" "jpeg" "gif" "svg"))))
"Rules characterizing image files that can be inlined.")
+(defconst org-texinfo--definition-command-alist
+ '(("deffn Command" . "Command")
+ ("defun" . "Function")
+ ("defmac" . "Macro")
+ ("defspec" . "Special Form")
+ ("defvar" . "Variable")
+ ("defopt" . "User Option")
+ (nil . "Key"))
+ "Alist mapping Texinfo definition commands to output in Info files.")
+
+(defconst org-texinfo--definition-command-regexp
+ (format "\\`%s: \\(.+\\)"
+ (regexp-opt
+ (delq nil (mapcar #'cdr org-texinfo--definition-command-alist))
+ 1))
+ "Regexp used to match definition commands in descriptive lists.")
+
\f
;;; Internal Functions
@@ -421,7 +438,8 @@ (defun org-texinfo--filter-section-blank-lines (headline _backend _info)
(defun org-texinfo--filter-parse-tree (tree backend info)
"Normalize headlines and items."
(org-texinfo--normalize-headlines tree backend info)
- (org-texinfo--normalize-items tree info))
+ (org-texinfo--normalize-items tree info)
+ (org-texinfo--separate-definitions tree backend info))
(defun org-texinfo--normalize-headlines (tree _backend info)
"Normalize headlines in TREE.
@@ -598,6 +616,116 @@ (defun org-texinfo--sectioning-structure (info)
(`(,_ ,_ . ,sections) sections)
(_ (user-error "Unknown Texinfo class: %S" class)))))
+(defun org-texinfo--separate-definitions (tree _backend info)
+ "Split up descriptive lists that contain Texinfo definition commands."
+ (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)
+ (while (setq item (pop contents))
+ (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's tag property and add findex and kindex entries to
+its content. If the bullet is \"+\" then use \"@itemx\" and deal with
+data from preceeding siblings that use such a bullet."
+ (let (key cmd)
+ (if (string-match " +(\\([^()]+\\)) *\\'" args)
+ (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))
+ (org-macro-replace-all templates)
+ (let ((tags (car (org-element-map (org-element-parse-buffer)
+ 'paragraph #'org-element-contents t))))
+ (dolist (tag tags)
+ (org-element-put-property tag :parent tags))
+ tags)))
+ `((code (:value ,key :post-blank 0))))
+ (and cmd `(" (" (code (:value ,cmd :post-blank 0)) ")"))))
+ (let ((findex (org-element-property :findex item))
+ (kindex (org-element-property :kindex item))
+ (next-item (cadr (memq item (org-element-contents plain-list))))
+ (mx (string-prefix-p "M-x " key)))
+ (when (and (not cmd) mx)
+ (setq cmd (substring key 4)))
+ (when (and cmd (not (member cmd findex)))
+ (setq findex (nconc findex (list cmd))))
+ (unless mx
+ (setq kindex (nconc kindex (list key))))
+ (if (and next-item
+ (equal (org-element-property :bullet next-item) "+ "))
+ (progn (org-element-put-property next-item :findex findex)
+ (org-element-put-property next-item :kindex kindex)
+ (org-element-put-property item :findex nil)
+ (org-element-put-property item :kindex nil))
+ (org-element-set-contents
+ item (nconc
+ (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
+ (mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
+ (org-element-contents item)))))))
+
;;; Template
(defun org-texinfo-template (contents info)
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx
2021-12-18 21:40 ` [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx Jonas Bernoulli
@ 2021-12-26 21:37 ` Nicolas Goaziou
2021-12-27 18:05 ` Jonas Bernoulli
0 siblings, 1 reply; 47+ messages in thread
From: Nicolas Goaziou @ 2021-12-26 21:37 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: kyle, emacs-orgmode
Hello,
Thanks. Some comments follow.
Jonas Bernoulli <jonas@bernoul.li> writes:
> +In description lists the used bullet is significant when exporting to
> +Texinfo; when in doubt, then use =-=. An item that uses =+= instead
> +becomes a new entry in the first column of the table. The above
> +output can also be produced with:
>
> #+begin_example
> -#+ATTR_TEXINFO: :enum A
> -1. Alpha
> -2. Bravo
> -3. Charlie
> +,#+attr_texinfo: :table-type vtable :indic asis
> +- foo ::
> ++ bar ::
> + This is the common text for foo and bar.
> #+end_example
The above is fragile, because pressing <C-c C-c> on an item will
"repair" the bullets. Therefore, you cannot support mixed bullets in the
same list.
> *** Tables in Texinfo export
> diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
> index b0125894a..35862357d 100644
> --- a/lisp/ox-texinfo.el
> +++ b/lisp/ox-texinfo.el
> @@ -418,6 +418,11 @@ (defun org-texinfo--filter-section-blank-lines (headline _backend _info)
> "Filter controlling number of blank lines after a section."
> (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" "\n\n" headline))
>
> +(defun org-texinfo--filter-parse-tree (tree backend info)
> + "Normalize headlines and items."
> + (org-texinfo--normalize-headlines tree backend info)
> + (org-texinfo--normalize-items tree info))
Could you expound the docstring? Arguments are missing, and "normalize"
is vague.
> + (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)))
> + (while (setq item (pop contents))
> + (let ((next-item (car contents)))
> + (when (and next-item
> + (equal (org-element-property :bullet next-item) "+ "))
The above will fail if `org-list-two-spaces-after-bullet-regexp' is
non-nil. You should compare the trimmed bullet with "+".
Anyhow, relying on mixed bullets is not great…
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists
2021-12-18 21:40 ` [PATCH 2/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
@ 2021-12-26 21:46 ` Nicolas Goaziou
2021-12-27 18:05 ` Jonas Bernoulli
0 siblings, 1 reply; 47+ messages in thread
From: Nicolas Goaziou @ 2021-12-26 21:46 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: kyle, emacs-orgmode
Hello,
Thanks.
Jonas Bernoulli <jonas@bernoul.li> 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's tag property and add findex and kindex entries to
> +its content. If the bullet is \"+\" then use \"@itemx\" and deal with
> +data from preceeding siblings that use such a bullet."
> + (let (key cmd)
> + (if (string-match " +(\\([^()]+\\)) *\\'" args)
Could you use `rx' here?
> + (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').
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx
2021-12-26 21:37 ` Nicolas Goaziou
@ 2021-12-27 18:05 ` Jonas Bernoulli
2021-12-30 9:40 ` Nicolas Goaziou
0 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2021-12-27 18:05 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: kyle, emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Hello,
>
> Thanks. Some comments follow.
Thanks for the review!
> Jonas Bernoulli <jonas@bernoul.li> writes:
>
>> +In description lists the used bullet is significant when exporting to
>> +Texinfo; when in doubt, then use =-=. An item that uses =+= instead
>> +becomes a new entry in the first column of the table. The above
>> +output can also be produced with:
>>
>> #+begin_example
>> -#+ATTR_TEXINFO: :enum A
>> -1. Alpha
>> -2. Bravo
>> -3. Charlie
>> +,#+attr_texinfo: :table-type vtable :indic asis
>> +- foo ::
>> ++ bar ::
>> + This is the common text for foo and bar.
>> #+end_example
>
> The above is fragile, because pressing <C-c C-c> on an item will
> "repair" the bullets. Therefore, you cannot support mixed bullets in the
> same list.
The alternative also isn't great (see below).
I vaguely remember having run into this feature before when using Org to
record a pros and cons list. As a maintainer I don't like this question
but; could this feature be made optional? (Of course one could use tags
to indicate whether an item is a pro or cons, but for such a simple use-
case that seems more work than necessary and less immediately obvious.)
>> *** Tables in Texinfo export
>> diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
>> index b0125894a..35862357d 100644
>> --- a/lisp/ox-texinfo.el
>> +++ b/lisp/ox-texinfo.el
>> @@ -418,6 +418,11 @@ (defun org-texinfo--filter-section-blank-lines (headline _backend _info)
>> "Filter controlling number of blank lines after a section."
>> (replace-regexp-in-string "\n\\(?:\n[ \t]*\\)*\\'" "\n\n" headline))
>>
>> +(defun org-texinfo--filter-parse-tree (tree backend info)
>> + "Normalize headlines and items."
>> + (org-texinfo--normalize-headlines tree backend info)
>> + (org-texinfo--normalize-items tree info))
>
> Could you expound the docstring? Arguments are missing, and "normalize"
> is vague.
This bothered me a bit too when writing it but at the same time
it seemed like overkill to replicate the docstrings of the called
functions. How do you feel about using a hook instead?
(defvar org-texinfo--filter-parse-tree-functions
'(org-texinfo--normalize-headlines
org-texinfo--normalize-items)
"List of functions the `texinfo' back-end applies to the parsed tree.
Each filter is called with three arguments: the parse tree, as
returned by `org-element-parse-buffer', the back-end, as
a symbol, and the communication channel, as a plist. It must
return the modified parse tree to transcode.")
Do you prefer to add the hook functions as done above or should each one
be added individually using add-hook?
>> + (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)))
>> + (while (setq item (pop contents))
>> + (let ((next-item (car contents)))
>> + (when (and next-item
>> + (equal (org-element-property :bullet next-item) "+ "))
>
> The above will fail if `org-list-two-spaces-after-bullet-regexp' is
> non-nil. You should compare the trimmed bullet with "+".
Done. Is this okay?:
(when (and next-item
(string-prefix-p
"+"
(org-element-property :bullet next-item)))
Or should the line-breaks go elsewhere?
> Anyhow, relying on mixed bullets is not great…
The alternative isn't great either.
For example:
- Key: C-c C-w (forge-browse-TYPE) ::
+ Key: C-c C-w (forge-browse-dwim) ::
+ Key: N b I (forge-browse-issues) ::
+ Key: N b P (forge-browse-pullreqs) ::
+ Key: N b t (forge-browse-topic) ::
+ Key: N b i (forge-browse-issue) ::
+ Key: N b p (forge-browse-pullreq) ::
These commands visit the topic, issue(s), pull-request(s), post,
branch, commit, or remote at point in a browser. ...
vs.
- Key: C-c C-w (forge-browse-TYPE), C-c C-w (forge-browse-dwim), N b I (forge-browse-issues), N b P (forge-browse-pullreqs), N b t (forge-browse-topic), N b i (forge-browse-issue), N b p (forge-browse-pullreq) ::
These commands visit the topic, issue(s), pull-request(s), post,
branch, commit, or remote at point in a browser. ...
I am sure I am gonna make mistakes when using the latter approach.
Cheers,
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists
2021-12-26 21:46 ` Nicolas Goaziou
@ 2021-12-27 18:05 ` Jonas Bernoulli
2021-12-30 0:57 ` Nicolas Goaziou
0 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2021-12-27 18:05 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: kyle, emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> 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
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists
2021-12-27 18:05 ` Jonas Bernoulli
@ 2021-12-30 0:57 ` Nicolas Goaziou
2022-01-05 13:16 ` Jonas Bernoulli
0 siblings, 1 reply; 47+ messages in thread
From: Nicolas Goaziou @ 2021-12-30 0:57 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: kyle, emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> 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
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx
2021-12-27 18:05 ` Jonas Bernoulli
@ 2021-12-30 9:40 ` Nicolas Goaziou
2022-01-05 13:12 ` Jonas Bernoulli
2022-01-23 15:01 ` Jonas Bernoulli
0 siblings, 2 replies; 47+ messages in thread
From: Nicolas Goaziou @ 2021-12-30 9:40 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: kyle, emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> I vaguely remember having run into this feature before when using Org to
> record a pros and cons list. As a maintainer I don't like this question
> but; could this feature be made optional? (Of course one could use tags
> to indicate whether an item is a pro or cons, but for such a simple use-
> case that seems more work than necessary and less immediately
> obvious.)
You can also make two lists. I don't think we should provide "pros ans
cons list", because it has implications outside export.
> This bothered me a bit too when writing it but at the same time
> it seemed like overkill to replicate the docstrings of the called
> functions. How do you feel about using a hook instead?
>
> (defvar org-texinfo--filter-parse-tree-functions
> '(org-texinfo--normalize-headlines
> org-texinfo--normalize-items)
> "List of functions the `texinfo' back-end applies to the parsed tree.
> Each filter is called with three arguments: the parse tree, as
> returned by `org-element-parse-buffer', the back-end, as
> a symbol, and the communication channel, as a plist. It must
> return the modified parse tree to transcode.")
Sure.
> Do you prefer to add the hook functions as done above or should each one
> be added individually using add-hook?
`add-hook' is more for users, I think.
> Done. Is this okay?:
>
> (when (and next-item
> (string-prefix-p
> "+"
> (org-element-property :bullet next-item)))
>
> Or should the line-breaks go elsewhere?
The line breaks do not matter much but it may fail if
(org-element-property :bullet next-item) returns nil.
>> Anyhow, relying on mixed bullets is not great…
>
> The alternative isn't great either.
>
> For example:
>
> - Key: C-c C-w (forge-browse-TYPE) ::
> + Key: C-c C-w (forge-browse-dwim) ::
> + Key: N b I (forge-browse-issues) ::
> + Key: N b P (forge-browse-pullreqs) ::
> + Key: N b t (forge-browse-topic) ::
> + Key: N b i (forge-browse-issue) ::
> + Key: N b p (forge-browse-pullreq) ::
>
> These commands visit the topic, issue(s), pull-request(s), post,
> branch, commit, or remote at point in a browser. ...
>
> vs.
>
> - Key: C-c C-w (forge-browse-TYPE), C-c C-w (forge-browse-dwim), N b I (forge-browse-issues), N b P (forge-browse-pullreqs), N b t (forge-browse-topic), N b i (forge-browse-issue), N b p (forge-browse-pullreq) ::
>
> These commands visit the topic, issue(s), pull-request(s), post,
> branch, commit, or remote at point in a browser. ...
>
> I am sure I am gonna make mistakes when using the latter approach.
True, but OTOH, the first option is not really possible. However, there
are still alternatives. For example, you could check blank lines between
items:
- key: a ::
- key: b ::
- key: c ::
- key: d ::
I suggest to require a special attribute before doing so, e.g.,
#+attr_texinfo: :compact t
- key: a ::
- key: b ::
- key: c ::
- key: d ::
Another option would be to merge consecutive lists with such an
attribute, for the same result:
#+attr_texinfo: :compact t
- key: a ::
- key: b ::
#+attr_texinfo: :compact t
- key: c ::
- key: d ::
- This is a regular list since it does not have :compact attribute.
IIRC, I did an experiment like this one when introducing matrices in
LaTeX export.
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx
2021-12-30 9:40 ` Nicolas Goaziou
@ 2022-01-05 13:12 ` Jonas Bernoulli
2022-01-23 15:01 ` Jonas Bernoulli
1 sibling, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-05 13:12 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: kyle, emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>> For example:
>>
>> - Key: C-c C-w (forge-browse-TYPE) ::
>> + Key: C-c C-w (forge-browse-dwim) ::
>> + Key: N b I (forge-browse-issues) ::
>> + Key: N b P (forge-browse-pullreqs) ::
>> + Key: N b t (forge-browse-topic) ::
>> + Key: N b i (forge-browse-issue) ::
>> + Key: N b p (forge-browse-pullreq) ::
>>
>> These commands visit the topic, issue(s), pull-request(s), post,
>> branch, commit, or remote at point in a browser. ...
>>
>> vs.
>>
>> - Key: C-c C-w (forge-browse-TYPE), C-c C-w (forge-browse-dwim), N b I (forge-browse-issues), N b P (forge-browse-pullreqs), N b t (forge-browse-topic), N b i (forge-browse-issue), N b p (forge-browse-pullreq) ::
>>
>> These commands visit the topic, issue(s), pull-request(s), post,
>> branch, commit, or remote at point in a browser. ...
>>
>> I am sure I am gonna make mistakes when using the latter approach.
>
> True, but OTOH, the first option is not really possible. However, there
> are still alternatives. For example, you could check blank lines between
> items:
>
> - key: a ::
> - key: b ::
>
> - key: c ::
> - key: d ::
>
> I suggest to require a special attribute before doing so, e.g.,
>
> #+attr_texinfo: :compact t
> - key: a ::
> - key: b ::
>
> - key: c ::
> - key: d ::
I went with that approach.
> Another option would be to merge consecutive lists with such an
> attribute, for the same result:
>
> #+attr_texinfo: :compact t
> - key: a ::
> - key: b ::
>
> #+attr_texinfo: :compact t
> - key: c ::
> - key: d ::
>
>
> - This is a regular list since it does not have :compact attribute.
Ordered lists are transcoded to @itemize, while description lists are
transcoded to @table or some other table command. So they cannot be
combined into one list-like thing in Texinfo.
The first two lists could be combined, but IMO it is better to only
require the :compact t once and avoid splitting the list and then
recombining the lists back into one.
Jonas
Ps: Slightly sad about loosing the +.
It looks very much like the x at the end of @itemx.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists
2021-12-30 0:57 ` Nicolas Goaziou
@ 2022-01-05 13:16 ` Jonas Bernoulli
0 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-05 13:16 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: kyle, emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Hello,
>
> Jonas Bernoulli <jonas@bernoul.li> 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
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v2 0/3] ox-texinfo: Define definition commands using description lists
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 2/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
@ 2022-01-05 13:30 ` Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
` (3 more replies)
2022-01-18 15:11 ` [PATCH v3 " Jonas Bernoulli
` (2 subsequent siblings)
5 siblings, 4 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-05 13:30 UTC (permalink / raw)
To: emacs-orgmode
I think I have addressed all you feedback.
The only difference when exporting org-manual.org is:
-When typing text into a field, Org treats @kbd{DEL},
+When typing text into a field, Org treats @kbd{@key{DEL}},
Jonas Bernoulli (3):
ox-texinfo: Add function for use by kbd macro
ox-texinfo: Optionally use @itemx for certain description list items
ox-texinfo: Define definition commands using description lists
doc/doc-setup.org | 2 +-
doc/org-manual.org | 135 ++++++++++++++++++++++++++---
lisp/ox-texinfo.el | 207 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 327 insertions(+), 17 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v2 1/3] ox-texinfo: Add function for use by kbd macro
2022-01-05 13:30 ` [PATCH v2 0/3] " Jonas Bernoulli
@ 2022-01-05 13:30 ` Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
` (2 subsequent siblings)
3 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-05 13:30 UTC (permalink / raw)
To: emacs-orgmode
* doc/doc-setup.org: Use org-texinfo-kbd-macro for kbd macro.
* doc/org-manual.org: Add new node "Key bindings in Texinfo export".
* lisp/ox-texinfo.el (org-texinfo-kbd-macro): New function.
---
doc/doc-setup.org | 2 +-
doc/org-manual.org | 27 +++++++++++++++++++++++++++
lisp/ox-texinfo.el | 23 ++++++++++++++++++++++-
3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/doc/doc-setup.org b/doc/doc-setup.org
index f59660e8e..59ad0eb60 100644
--- a/doc/doc-setup.org
+++ b/doc/doc-setup.org
@@ -49,5 +49,5 @@
# The "kbd" macro turns KBD into @kbd{KBD}. Additionally, it
# encloses case-sensitive special keys (SPC, RET...) within @key{...}.
-#+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))))
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
diff --git a/doc/org-manual.org b/doc/org-manual.org
index b65e2f173..a5aac7d61 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15353,6 +15353,33 @@ your king.
,#+END_QUOTE
#+end_example
+*** Key bindings in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: @@kbd Texinfo command.
+:END:
+
+Org does not provide any markup for key bindings that corresponds to
+Texinfo's ~@kbd~ and ~@key~ commands. One way to deal with this is to
+fall back to code syntax. =~C-x SPC~=, for example, is transcoded to
+~@code{C-x SPC}~.
+
+A better approach is to define and use an Org macro named ~kbd~. To
+make that easier the function ~org-texinfo-kbd-macro~ is provided,
+which is intended to be used like this:
+
+#+begin_example
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
+
+Type {{{kbd(C-c SPC)}}}.
+#+end_example
+
+#+texinfo: @noindent
+which becomes
+
+#+begin_example
+Type @kbd{C-c @key{SPC}}.
+#+end_example
+
*** Special blocks in Texinfo export
:PROPERTIES:
:DESCRIPTION: Special block attributes.
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index b0125894a..57cbcf6ad 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -1611,7 +1611,28 @@ (defun org-texinfo-verse-block (_verse-block contents _info)
(format "@display\n%s@end display" contents))
\f
-;;; Interactive functions
+;;; Public Functions
+
+(defun org-texinfo-kbd-macro (key &optional noquote)
+ "Quote KEY using @kbd{...} and if necessary $key{...}.
+
+This is intended to be used as an Org macro like so:
+
+ #+macro: kbd (eval (org-texinfo-kbd-macro $1))
+ Type {{{kbd(C-c SPC)}}}.
+
+Also see info node `(org)Key bindings in Texinfo export'.
+
+If optional NOQOUTE is non-nil, then do not add the quoting
+that is necessary when using this in an Org macro."
+ (format (if noquote "@kbd{%s}" "@@texinfo:@kbd{@@%s@@texinfo:}@@")
+ (let ((case-fold-search nil))
+ (replace-regexp-in-string
+ org-texinfo--quoted-keys-regexp
+ (if noquote "@key{\\&}" "@@texinfo:@key{@@\\&@@texinfo:}@@")
+ key t))))
+
+;;; Interactive Functions
;;;###autoload
(defun org-texinfo-export-to-texinfo
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 2/3] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-05 13:30 ` [PATCH v2 0/3] " Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
@ 2022-01-05 13:30 ` Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2022-01-14 23:01 ` [PATCH v2 0/3] " Jonas Bernoulli
3 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-05 13:30 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Reorder and
document new functionality.
* lisp/ox-texinfo.el: Add org-texinfo--combine-items to the list of
:filter-parse-tree functions of the texinfo backend.
* lisp/ox-texinfo.el (org-texinfo--combine-items) New function.
* lisp/ox-texinfo.el (org-texinfo-item) Transcode combined items to
one @item and one or more @itemx.
---
doc/org-manual.org | 38 +++++++++++++++++++++++++++-----------
lisp/ox-texinfo.el | 45 +++++++++++++++++++++++++++++++++++++++++----
2 files changed, 68 insertions(+), 15 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index a5aac7d61..b3c4a9bef 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15236,6 +15236,23 @@ This paragraph is preceded by...
:DESCRIPTION: List attributes.
:END:
+#+cindex: lettered lists, in Texinfo export
+#+cindex: enum, Texinfo attribute
+The Texinfo export back-end converts unordered and ordered lists in
+the Org file using the default command =@itemize=.
+
+Ordered lists are numbered when exported to Texinfo format. Such
+numbering obeys any counter (see [[*Plain Lists]]) in the first item of
+the list. The =:enum= attribute also let you start the list at a
+specific number, or switch to a lettered list, as illustrated here:
+
+#+begin_example
+#+ATTR_TEXINFO: :enum A
+1. Alpha
+2. Bravo
+3. Charlie
+#+end_example
+
#+cindex: @samp{ATTR_TEXINFO}, keyword
#+cindex: two-column tables, in Texinfo export
#+cindex: table-type, Texinfo attribute
@@ -15262,7 +15279,7 @@ entry in the first column of the table.
The following example illustrates all the attributes above:
#+begin_example
-,#+ATTR_TEXINFO: :table-type vtable :sep , :indic asis
+,#+attr_texinfo: :table-type vtable :indic asis :sep ,
- foo, bar :: This is the common text for variables foo and bar.
#+end_example
@@ -15277,18 +15294,17 @@ This is the common text for variables foo and bar.
@end table
#+end_example
-#+cindex: lettered lists, in Texinfo export
-#+cindex: enum, Texinfo attribute
-Ordered lists are numbered when exported to Texinfo format. Such
-numbering obeys any counter (see [[*Plain Lists]]) in the first item of
-the list. The =:enum= attribute also let you start the list at
-a specific number, or switch to a lettered list, as illustrated here
+The =:combine= attribute is an alternative to the =:sep= attribute,
+which allows writing each entry on its own line. If this attribute is
+non-nil and an item in a description list has no body but is followed
+by another item, then the second item is transcoded to =@itemx=. This
+example is transcoded to the same output as above.
#+begin_example
-#+ATTR_TEXINFO: :enum A
-1. Alpha
-2. Bravo
-3. Charlie
+,#+attr_texinfo: :table-type vtable :indic asis :combine t
+- foo ::
+- bar ::
+ This is the common text for variables foo and bar.
#+end_example
*** Tables in Texinfo export
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 57cbcf6ad..8f671ea13 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -83,7 +83,8 @@ (org-export-define-backend 'texinfo
(verse-block . org-texinfo-verse-block))
:filters-alist
'((:filter-headline . org-texinfo--filter-section-blank-lines)
- (:filter-parse-tree . org-texinfo--normalize-headlines)
+ (:filter-parse-tree . (org-texinfo--normalize-headlines
+ org-texinfo--combine-items))
(:filter-section . org-texinfo--filter-section-blank-lines)
(:filter-final-output . org-texinfo--untabify))
:menu-entry
@@ -421,7 +422,7 @@ (defun org-texinfo--filter-section-blank-lines (headline _backend _info)
(defun org-texinfo--normalize-headlines (tree _backend info)
"Normalize headlines in TREE.
-BACK-END is the symbol specifying back-end used for export.
+_BACKEND is the symbol `texinfo'; the back-end used for export.
INFO is a plist used as a communication channel.
Make sure every headline in TREE contains a section, since those
@@ -443,6 +444,37 @@ (defun org-texinfo--normalize-headlines (tree _backend info)
info)
tree)
+(defun org-texinfo--combine-items (tree _backend info)
+ "Normalize items in TREE.
+
+_BACKEND is the symbol `texinfo'; the back-end used for export.
+INFO is a plist used as a communication channel.
+
+Items in description lists that use the \"+\" bullet are
+converted to `@itemx'. If another item is followed by such an
+item, then the first item should not be followed by a space,
+which this function takes care of.
+
+Return new tree."
+ (org-element-map tree 'item
+ (lambda (item)
+ (let ((plain-list (org-element-property :parent item)))
+ (when (and (org-not-nil (org-export-read-attribute
+ :attr_texinfo plain-list :compact))
+ (eq (org-element-property :type plain-list) 'descriptive))
+ (let ((next-item
+ (cadr (memq item (org-element-contents plain-list)))))
+ (when (and next-item
+ (not (org-element-contents item))
+ (= (org-element-property :post-blank item) 1))
+ (org-element-put-property
+ next-item :itemx
+ (nconc (org-element-property :itemx item)
+ (list (org-element-property :tag item))))
+ (org-element-extract-element item))))))
+ info)
+ tree)
+
(defun org-texinfo--find-verb-separator (s)
"Return a character not used in string S.
This is used to choose a separator for constructs like \\verb."
@@ -994,8 +1026,13 @@ (defun org-texinfo-item (item contents info)
(org-export-read-attribute :attr_texinfo
(org-element-property :parent item)
:sep)))
- (items (and tag
- (let ((tag (org-export-data tag info)))
+ (items (org-element-property :itemx item))
+ (items (cond (items
+ (mapcar (lambda (tag) (org-export-data tag info))
+ (nconc items (list tag))))
+ ((not tag) nil)
+ (t
+ (setq tag (org-export-data tag info))
(if split
(split-string tag (regexp-quote split) t "[ \t\n]+")
(list tag))))))
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v2 3/3] ox-texinfo: Define definition commands using description lists
2022-01-05 13:30 ` [PATCH v2 0/3] " Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
@ 2022-01-05 13:30 ` Jonas Bernoulli
2022-01-14 23:01 ` [PATCH v2 0/3] " Jonas Bernoulli
3 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-05 13:30 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Document use
of definition command prefixes in description lists.
* lisp/ox-texinfo.el: Add org-texinfo--separate-definitions to the
list of :filter-parse-tree functions of the texinfo backend.
* lisp/ox-texinfo.el (org-texinfo--quoted-keys-regexp)
(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 | 70 +++++++++++++++++++++++
lisp/ox-texinfo.el | 139 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 209 insertions(+)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index b3c4a9bef..daa207a5d 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15307,6 +15307,72 @@ example is transcoded to the same output as above.
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-c C-c (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
+
+#+texinfo: @noindent
+Command in parenthesis, as done above, is optional.
+
*** Tables in Texinfo export
:PROPERTIES:
:DESCRIPTION: Table attributes.
@@ -15401,6 +15467,10 @@ Type @kbd{C-c @key{SPC}}.
: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 8f671ea13..a79f620c6 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -84,6 +84,7 @@ (org-export-define-backend 'texinfo
:filters-alist
'((:filter-headline . org-texinfo--filter-section-blank-lines)
(:filter-parse-tree . (org-texinfo--normalize-headlines
+ org-texinfo--separate-definitions
org-texinfo--combine-items))
(:filter-section . org-texinfo--filter-section-blank-lines)
(:filter-final-output . org-texinfo--untabify))
@@ -408,6 +409,30 @@ (defconst org-texinfo-inline-image-rules
(regexp-opt '("eps" "pdf" "png" "jpg" "jpeg" "gif" "svg"))))
"Rules characterizing image files that can be inlined.")
+(defvar org-texinfo--quoted-keys-regexp
+ (regexp-opt '("BS" "TAB" "RET" "ESC" "SPC" "DEL"
+ "LFD" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt"
+ "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN")
+ 'words)
+ "Regexp matching keys that have to be quoted using @key{KEY}.")
+
+(defconst org-texinfo--definition-command-alist
+ '(("deffn Command" . "Command")
+ ("defun" . "Function")
+ ("defmac" . "Macro")
+ ("defspec" . "Special Form")
+ ("defvar" . "Variable")
+ ("defopt" . "User Option")
+ (nil . "Key"))
+ "Alist mapping Texinfo definition commands to output in Info files.")
+
+(defconst org-texinfo--definition-command-regexp
+ (format "\\`%s: \\(.+\\)"
+ (regexp-opt
+ (delq nil (mapcar #'cdr org-texinfo--definition-command-alist))
+ t))
+ "Regexp used to match definition commands in descriptive lists.")
+
\f
;;; Internal Functions
@@ -602,6 +627,120 @@ (defun org-texinfo--sectioning-structure (info)
(`(,_ ,_ . ,sections) sections)
(_ (user-error "Unknown Texinfo class: %S" class)))))
+(defun org-texinfo--separate-definitions (tree _backend info)
+ "Split up descriptive lists in TREE that contain Texinfo definition commands.
+
+_BACKEND is the symbol `texinfo'; the back-end used for export.
+INFO is a plist used as a communication channel.
+
+Return new tree."
+ (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))
+ (items nil))
+ (dolist (item contents)
+ (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's tag property and add findex and kindex entries to
+its content. If the bullet is \"+\" then use \"@itemx\" and deal with
+data from preceeding siblings that use such a bullet."
+ (let (key cmd)
+ (if (string-match (rx (+ " ")
+ "(" (group (+ (not (any "()")))) ")"
+ (* " ")
+ eos)
+ args)
+ (setq key (substring args 0 (match-beginning 0))
+ cmd (match-string 1 args))
+ (setq key args))
+ (org-element-put-property
+ item :tag
+ (cons (org-export-raw-string (org-texinfo-kbd-macro key t))
+ (and cmd `(" (" (code (:value ,cmd :post-blank 0)) ")"))))
+ (let ((findex (org-element-property :findex item))
+ (kindex (org-element-property :kindex item))
+ (next-item (cadr (memq item (org-element-contents plain-list))))
+ (mx (string-prefix-p "M-x " key)))
+ (when (and (not cmd) mx)
+ (setq cmd (substring key 4)))
+ (when (and cmd (not (member cmd findex)))
+ (setq findex (nconc findex (list cmd))))
+ (unless mx
+ (setq kindex (nconc kindex (list key))))
+ (cond
+ ((and next-item
+ (org-not-nil
+ (org-export-read-attribute :attr_texinfo plain-list :compact))
+ (not (org-element-contents item))
+ (= (org-element-property :post-blank item) 1))
+ (org-element-put-property next-item :findex findex)
+ (org-element-put-property next-item :kindex kindex)
+ (org-element-put-property item :findex nil)
+ (org-element-put-property item :kindex nil))
+ (t
+ (org-element-set-contents
+ item (nconc
+ (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
+ (mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
+ (org-element-contents item))))))))
+
;;; Template
(defun org-texinfo-template (contents info)
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH v2 0/3] ox-texinfo: Define definition commands using description lists
2022-01-05 13:30 ` [PATCH v2 0/3] " Jonas Bernoulli
` (2 preceding siblings ...)
2022-01-05 13:30 ` [PATCH v2 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
@ 2022-01-14 23:01 ` Jonas Bernoulli
3 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-14 23:01 UTC (permalink / raw)
To: emacs-orgmode; +Cc: Nicolas Goaziou
Hello Nicolas,
Could you please have another look?
Cheers,
Jonas
Jonas Bernoulli <jonas@bernoul.li> writes:
> I think I have addressed all you feedback.
>
> The only difference when exporting org-manual.org is:
>
> -When typing text into a field, Org treats @kbd{DEL},
> +When typing text into a field, Org treats @kbd{@key{DEL}},
>
> Jonas Bernoulli (3):
> ox-texinfo: Add function for use by kbd macro
> ox-texinfo: Optionally use @itemx for certain description list items
> ox-texinfo: Define definition commands using description lists
>
> doc/doc-setup.org | 2 +-
> doc/org-manual.org | 135 ++++++++++++++++++++++++++---
> lisp/ox-texinfo.el | 207 +++++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 327 insertions(+), 17 deletions(-)
>
> --
> 2.34.1
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v3 0/3] ox-texinfo: Define definition commands using description lists
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
` (2 preceding siblings ...)
2022-01-05 13:30 ` [PATCH v2 0/3] " Jonas Bernoulli
@ 2022-01-18 15:11 ` Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
` (2 more replies)
2022-01-23 20:27 ` [PATCH v4 0/3] " Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
5 siblings, 3 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-18 15:11 UTC (permalink / raw)
To: emacs-orgmode
The code is the same as in v3, but I noticed that I had forgotten
to update one of the doc-strings, so that's fixed here.
Cheers,
Jonas
Jonas Bernoulli (3):
ox-texinfo: Add function for use by kbd macro
ox-texinfo: Optionally use @itemx for certain description list items
ox-texinfo: Define definition commands using description lists
doc/doc-setup.org | 2 +-
doc/org-manual.org | 135 ++++++++++++++++++++++++++---
lisp/ox-texinfo.el | 210 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 330 insertions(+), 17 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v3 1/3] ox-texinfo: Add function for use by kbd macro
2022-01-18 15:11 ` [PATCH v3 " Jonas Bernoulli
@ 2022-01-18 15:11 ` Jonas Bernoulli
2022-01-22 15:19 ` Nicolas Goaziou
2022-01-18 15:11 ` [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-18 15:11 UTC (permalink / raw)
To: emacs-orgmode
* doc/doc-setup.org: Use org-texinfo-kbd-macro for kbd macro.
* doc/org-manual.org: Add new node "Key bindings in Texinfo export".
* lisp/ox-texinfo.el (org-texinfo-kbd-macro): New function.
---
doc/doc-setup.org | 2 +-
doc/org-manual.org | 27 +++++++++++++++++++++++++++
lisp/ox-texinfo.el | 23 ++++++++++++++++++++++-
3 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/doc/doc-setup.org b/doc/doc-setup.org
index f59660e8e..59ad0eb60 100644
--- a/doc/doc-setup.org
+++ b/doc/doc-setup.org
@@ -49,5 +49,5 @@
# The "kbd" macro turns KBD into @kbd{KBD}. Additionally, it
# encloses case-sensitive special keys (SPC, RET...) within @key{...}.
-#+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))))
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
diff --git a/doc/org-manual.org b/doc/org-manual.org
index b65e2f173..a5aac7d61 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15353,6 +15353,33 @@ your king.
,#+END_QUOTE
#+end_example
+*** Key bindings in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: @@kbd Texinfo command.
+:END:
+
+Org does not provide any markup for key bindings that corresponds to
+Texinfo's ~@kbd~ and ~@key~ commands. One way to deal with this is to
+fall back to code syntax. =~C-x SPC~=, for example, is transcoded to
+~@code{C-x SPC}~.
+
+A better approach is to define and use an Org macro named ~kbd~. To
+make that easier the function ~org-texinfo-kbd-macro~ is provided,
+which is intended to be used like this:
+
+#+begin_example
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
+
+Type {{{kbd(C-c SPC)}}}.
+#+end_example
+
+#+texinfo: @noindent
+which becomes
+
+#+begin_example
+Type @kbd{C-c @key{SPC}}.
+#+end_example
+
*** Special blocks in Texinfo export
:PROPERTIES:
:DESCRIPTION: Special block attributes.
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index b0125894a..57cbcf6ad 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -1611,7 +1611,28 @@ (defun org-texinfo-verse-block (_verse-block contents _info)
(format "@display\n%s@end display" contents))
\f
-;;; Interactive functions
+;;; Public Functions
+
+(defun org-texinfo-kbd-macro (key &optional noquote)
+ "Quote KEY using @kbd{...} and if necessary $key{...}.
+
+This is intended to be used as an Org macro like so:
+
+ #+macro: kbd (eval (org-texinfo-kbd-macro $1))
+ Type {{{kbd(C-c SPC)}}}.
+
+Also see info node `(org)Key bindings in Texinfo export'.
+
+If optional NOQOUTE is non-nil, then do not add the quoting
+that is necessary when using this in an Org macro."
+ (format (if noquote "@kbd{%s}" "@@texinfo:@kbd{@@%s@@texinfo:}@@")
+ (let ((case-fold-search nil))
+ (replace-regexp-in-string
+ org-texinfo--quoted-keys-regexp
+ (if noquote "@key{\\&}" "@@texinfo:@key{@@\\&@@texinfo:}@@")
+ key t))))
+
+;;; Interactive Functions
;;;###autoload
(defun org-texinfo-export-to-texinfo
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-18 15:11 ` [PATCH v3 " Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
@ 2022-01-18 15:11 ` Jonas Bernoulli
2022-01-22 15:33 ` Nicolas Goaziou
2022-01-18 15:11 ` [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-18 15:11 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Reorder and
document new functionality.
* lisp/ox-texinfo.el: Add org-texinfo--combine-items to the list of
:filter-parse-tree functions of the texinfo backend.
* lisp/ox-texinfo.el (org-texinfo--combine-items) New function.
* lisp/ox-texinfo.el (org-texinfo-item) Transcode combined items to
one @item and one or more @itemx.
---
doc/org-manual.org | 38 +++++++++++++++++++++++++-----------
lisp/ox-texinfo.el | 48 ++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index a5aac7d61..b3c4a9bef 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15236,6 +15236,23 @@ This paragraph is preceded by...
:DESCRIPTION: List attributes.
:END:
+#+cindex: lettered lists, in Texinfo export
+#+cindex: enum, Texinfo attribute
+The Texinfo export back-end converts unordered and ordered lists in
+the Org file using the default command =@itemize=.
+
+Ordered lists are numbered when exported to Texinfo format. Such
+numbering obeys any counter (see [[*Plain Lists]]) in the first item of
+the list. The =:enum= attribute also let you start the list at a
+specific number, or switch to a lettered list, as illustrated here:
+
+#+begin_example
+#+ATTR_TEXINFO: :enum A
+1. Alpha
+2. Bravo
+3. Charlie
+#+end_example
+
#+cindex: @samp{ATTR_TEXINFO}, keyword
#+cindex: two-column tables, in Texinfo export
#+cindex: table-type, Texinfo attribute
@@ -15262,7 +15279,7 @@ entry in the first column of the table.
The following example illustrates all the attributes above:
#+begin_example
-,#+ATTR_TEXINFO: :table-type vtable :sep , :indic asis
+,#+attr_texinfo: :table-type vtable :indic asis :sep ,
- foo, bar :: This is the common text for variables foo and bar.
#+end_example
@@ -15277,18 +15294,17 @@ This is the common text for variables foo and bar.
@end table
#+end_example
-#+cindex: lettered lists, in Texinfo export
-#+cindex: enum, Texinfo attribute
-Ordered lists are numbered when exported to Texinfo format. Such
-numbering obeys any counter (see [[*Plain Lists]]) in the first item of
-the list. The =:enum= attribute also let you start the list at
-a specific number, or switch to a lettered list, as illustrated here
+The =:combine= attribute is an alternative to the =:sep= attribute,
+which allows writing each entry on its own line. If this attribute is
+non-nil and an item in a description list has no body but is followed
+by another item, then the second item is transcoded to =@itemx=. This
+example is transcoded to the same output as above.
#+begin_example
-#+ATTR_TEXINFO: :enum A
-1. Alpha
-2. Bravo
-3. Charlie
+,#+attr_texinfo: :table-type vtable :indic asis :combine t
+- foo ::
+- bar ::
+ This is the common text for variables foo and bar.
#+end_example
*** Tables in Texinfo export
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 57cbcf6ad..36e1436d7 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -83,7 +83,8 @@ (org-export-define-backend 'texinfo
(verse-block . org-texinfo-verse-block))
:filters-alist
'((:filter-headline . org-texinfo--filter-section-blank-lines)
- (:filter-parse-tree . org-texinfo--normalize-headlines)
+ (:filter-parse-tree . (org-texinfo--normalize-headlines
+ org-texinfo--combine-items))
(:filter-section . org-texinfo--filter-section-blank-lines)
(:filter-final-output . org-texinfo--untabify))
:menu-entry
@@ -421,7 +422,7 @@ (defun org-texinfo--filter-section-blank-lines (headline _backend _info)
(defun org-texinfo--normalize-headlines (tree _backend info)
"Normalize headlines in TREE.
-BACK-END is the symbol specifying back-end used for export.
+_BACKEND is the symbol `texinfo'; the back-end used for export.
INFO is a plist used as a communication channel.
Make sure every headline in TREE contains a section, since those
@@ -443,6 +444,40 @@ (defun org-texinfo--normalize-headlines (tree _backend info)
info)
tree)
+(defun org-texinfo--combine-items (tree _backend info)
+ "Combine certain description list items.
+
+_BACKEND is the symbol `texinfo'; the back-end used for export.
+INFO is a plist used as a communication channel.
+
+If the `:combine' attribute of a description list is non-nil and
+an item in that list has no body and is followed by another item,
+then remove the first item and prepend its `:tag' to that of the
+second item.
+
+Such an item that absorbed the tags of other items is later
+transcoded to one `@item', followed by one or more `@itemx'.
+
+Return new tree."
+ (org-element-map tree 'item
+ (lambda (item)
+ (let ((plain-list (org-element-property :parent item)))
+ (when (and (org-not-nil (org-export-read-attribute
+ :attr_texinfo plain-list :compact))
+ (eq (org-element-property :type plain-list) 'descriptive))
+ (let ((next-item
+ (cadr (memq item (org-element-contents plain-list)))))
+ (when (and next-item
+ (not (org-element-contents item))
+ (= (org-element-property :post-blank item) 1))
+ (org-element-put-property
+ next-item :itemx
+ (nconc (org-element-property :itemx item)
+ (list (org-element-property :tag item))))
+ (org-element-extract-element item))))))
+ info)
+ tree)
+
(defun org-texinfo--find-verb-separator (s)
"Return a character not used in string S.
This is used to choose a separator for constructs like \\verb."
@@ -994,8 +1029,13 @@ (defun org-texinfo-item (item contents info)
(org-export-read-attribute :attr_texinfo
(org-element-property :parent item)
:sep)))
- (items (and tag
- (let ((tag (org-export-data tag info)))
+ (items (org-element-property :itemx item))
+ (items (cond (items
+ (mapcar (lambda (tag) (org-export-data tag info))
+ (nconc items (list tag))))
+ ((not tag) nil)
+ (t
+ (setq tag (org-export-data tag info))
(if split
(split-string tag (regexp-quote split) t "[ \t\n]+")
(list tag))))))
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists
2022-01-18 15:11 ` [PATCH v3 " Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
@ 2022-01-18 15:11 ` Jonas Bernoulli
2022-01-23 0:02 ` Nicolas Goaziou
2 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-18 15:11 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Document use
of definition command prefixes in description lists.
* lisp/ox-texinfo.el: Add org-texinfo--separate-definitions to the
list of :filter-parse-tree functions of the texinfo backend.
* lisp/ox-texinfo.el (org-texinfo--quoted-keys-regexp)
(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 | 70 +++++++++++++++++++++++
lisp/ox-texinfo.el | 139 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 209 insertions(+)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index b3c4a9bef..daa207a5d 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15307,6 +15307,72 @@ example is transcoded to the same output as above.
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-c C-c (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
+
+#+texinfo: @noindent
+Command in parenthesis, as done above, is optional.
+
*** Tables in Texinfo export
:PROPERTIES:
:DESCRIPTION: Table attributes.
@@ -15401,6 +15467,10 @@ Type @kbd{C-c @key{SPC}}.
: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 36e1436d7..751ad1126 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -84,6 +84,7 @@ (org-export-define-backend 'texinfo
:filters-alist
'((:filter-headline . org-texinfo--filter-section-blank-lines)
(:filter-parse-tree . (org-texinfo--normalize-headlines
+ org-texinfo--separate-definitions
org-texinfo--combine-items))
(:filter-section . org-texinfo--filter-section-blank-lines)
(:filter-final-output . org-texinfo--untabify))
@@ -408,6 +409,30 @@ (defconst org-texinfo-inline-image-rules
(regexp-opt '("eps" "pdf" "png" "jpg" "jpeg" "gif" "svg"))))
"Rules characterizing image files that can be inlined.")
+(defvar org-texinfo--quoted-keys-regexp
+ (regexp-opt '("BS" "TAB" "RET" "ESC" "SPC" "DEL"
+ "LFD" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt"
+ "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN")
+ 'words)
+ "Regexp matching keys that have to be quoted using @key{KEY}.")
+
+(defconst org-texinfo--definition-command-alist
+ '(("deffn Command" . "Command")
+ ("defun" . "Function")
+ ("defmac" . "Macro")
+ ("defspec" . "Special Form")
+ ("defvar" . "Variable")
+ ("defopt" . "User Option")
+ (nil . "Key"))
+ "Alist mapping Texinfo definition commands to output in Info files.")
+
+(defconst org-texinfo--definition-command-regexp
+ (format "\\`%s: \\(.+\\)"
+ (regexp-opt
+ (delq nil (mapcar #'cdr org-texinfo--definition-command-alist))
+ t))
+ "Regexp used to match definition commands in descriptive lists.")
+
\f
;;; Internal Functions
@@ -605,6 +630,120 @@ (defun org-texinfo--sectioning-structure (info)
(`(,_ ,_ . ,sections) sections)
(_ (user-error "Unknown Texinfo class: %S" class)))))
+(defun org-texinfo--separate-definitions (tree _backend info)
+ "Split up descriptive lists in TREE that contain Texinfo definition commands.
+
+_BACKEND is the symbol `texinfo'; the back-end used for export.
+INFO is a plist used as a communication channel.
+
+Return new tree."
+ (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))
+ (items nil))
+ (dolist (item contents)
+ (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's tag property and add findex and kindex entries to
+its content. If the bullet is \"+\" then use \"@itemx\" and deal with
+data from preceeding siblings that use such a bullet."
+ (let (key cmd)
+ (if (string-match (rx (+ " ")
+ "(" (group (+ (not (any "()")))) ")"
+ (* " ")
+ eos)
+ args)
+ (setq key (substring args 0 (match-beginning 0))
+ cmd (match-string 1 args))
+ (setq key args))
+ (org-element-put-property
+ item :tag
+ (cons (org-export-raw-string (org-texinfo-kbd-macro key t))
+ (and cmd `(" (" (code (:value ,cmd :post-blank 0)) ")"))))
+ (let ((findex (org-element-property :findex item))
+ (kindex (org-element-property :kindex item))
+ (next-item (cadr (memq item (org-element-contents plain-list))))
+ (mx (string-prefix-p "M-x " key)))
+ (when (and (not cmd) mx)
+ (setq cmd (substring key 4)))
+ (when (and cmd (not (member cmd findex)))
+ (setq findex (nconc findex (list cmd))))
+ (unless mx
+ (setq kindex (nconc kindex (list key))))
+ (cond
+ ((and next-item
+ (org-not-nil
+ (org-export-read-attribute :attr_texinfo plain-list :compact))
+ (not (org-element-contents item))
+ (= (org-element-property :post-blank item) 1))
+ (org-element-put-property next-item :findex findex)
+ (org-element-put-property next-item :kindex kindex)
+ (org-element-put-property item :findex nil)
+ (org-element-put-property item :kindex nil))
+ (t
+ (org-element-set-contents
+ item (nconc
+ (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
+ (mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
+ (org-element-contents item))))))))
+
;;; Template
(defun org-texinfo-template (contents info)
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH v3 1/3] ox-texinfo: Add function for use by kbd macro
2022-01-18 15:11 ` [PATCH v3 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
@ 2022-01-22 15:19 ` Nicolas Goaziou
0 siblings, 0 replies; 47+ messages in thread
From: Nicolas Goaziou @ 2022-01-22 15:19 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> * doc/doc-setup.org: Use org-texinfo-kbd-macro for kbd macro.
> * doc/org-manual.org: Add new node "Key bindings in Texinfo export".
> * lisp/ox-texinfo.el (org-texinfo-kbd-macro): New function.
Thank you. Some comments follow.
> +(defun org-texinfo-kbd-macro (key &optional noquote)
> + "Quote KEY using @kbd{...} and if necessary $key{...}.
Typo: $key -> @key
> +This is intended to be used as an Org macro like so:
> +
> + #+macro: kbd (eval (org-texinfo-kbd-macro $1))
> + Type {{{kbd(C-c SPC)}}}.
> +
> +Also see info node `(org)Key bindings in Texinfo export'.
> +
> +If optional NOQOUTE is non-nil, then do not add the quoting
> +that is necessary when using this in an Org macro."
> + (format (if noquote "@kbd{%s}" "@@texinfo:@kbd{@@%s@@texinfo:}@@")
> + (let ((case-fold-search nil))
> + (replace-regexp-in-string
> + org-texinfo--quoted-keys-regexp
AFAICT the variable is not defined in the patch.
Otherwise, LGTM.
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-18 15:11 ` [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
@ 2022-01-22 15:33 ` Nicolas Goaziou
2022-01-23 1:26 ` Jonas Bernoulli
2022-01-23 20:43 ` Jonas Bernoulli
0 siblings, 2 replies; 47+ messages in thread
From: Nicolas Goaziou @ 2022-01-22 15:33 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> * doc/org-manual.org (Plain lists in Texinfo export): Reorder and
> document new functionality.
> * lisp/ox-texinfo.el: Add org-texinfo--combine-items to the list of
> :filter-parse-tree functions of the texinfo backend.
> * lisp/ox-texinfo.el (org-texinfo--combine-items) New function.
> * lisp/ox-texinfo.el (org-texinfo-item) Transcode combined items to
> one @item and one or more @itemx.
This looks good. I have some comments below.
> #+begin_example
> -,#+ATTR_TEXINFO: :table-type vtable :sep , :indic asis
> +,#+attr_texinfo: :table-type vtable :indic asis :sep ,
> - foo, bar :: This is the common text for variables foo and bar.
> #+end_example
This change is not needed. Org markup is capitalized in examples to make
it stand out. It's not great because 1) it is ugly 2) users may think
Org syntax is uppercase. But changing that is not the point of this patch.
> -#+ATTR_TEXINFO: :enum A
> -1. Alpha
> -2. Bravo
> -3. Charlie
> +,#+attr_texinfo: :table-type vtable :indic asis :combine t
> +- foo ::
> +- bar ::
> + This is the common text for variables foo and bar.
See above.
> (defun org-texinfo--normalize-headlines (tree _backend info)
> "Normalize headlines in TREE.
>
> -BACK-END is the symbol specifying back-end used for export.
> +_BACKEND is the symbol `texinfo'; the back-end used for export.
You don't need to document ignored arguments.
> +(defun org-texinfo--combine-items (tree _backend info)
> + "Combine certain description list items.
> +
> +_BACKEND is the symbol `texinfo'; the back-end used for export.
> +INFO is a plist used as a communication channel.
Same as above.
> +If the `:combine' attribute of a description list is non-nil and
> +an item in that list has no body and is followed by another item,
> +then remove the first item and prepend its `:tag' to that of the
> +second item.
> +
> +Such an item that absorbed the tags of other items is later
> +transcoded to one `@item', followed by one or more `@itemx'.
> +
> +Return new tree."
> + (org-element-map tree 'item
> + (lambda (item)
> + (let ((plain-list (org-element-property :parent item)))
> + (when (and (org-not-nil (org-export-read-attribute
> + :attr_texinfo plain-list :compact))
> + (eq (org-element-property :type plain-list) 'descriptive))
> + (let ((next-item
> + (cadr (memq item (org-element-contents plain-list)))))
I suggest to use `org-export-get-next-element', which is not as
low-level as this.
> + (when (and next-item
> + (not (org-element-contents item))
> + (= (org-element-property :post-blank item) 1))
Be careful, (org-element-property :post-blank item) may be nil.
I suggest to use (eq 1 (org-element-property :post-blank item)) instead.
> - (items (and tag
> - (let ((tag (org-export-data tag info)))
> + (items (org-element-property :itemx item))
> + (items (cond (items
> + (mapcar (lambda (tag) (org-export-data tag info))
> + (nconc items (list tag))))
> + ((not tag) nil)
> + (t
> + (setq tag (org-export-data tag info))
OK, but I think this is a bit convoluted. I wonder if we need
`org-texinfo--combine-items' at all. I.e., `org-texinfo-item' could
decide to prefix current tag with @itemx if 1) the item is empty 2) the
list has a non-nil :compact attribute 3) there's another item following
it. IOW, we do not need to rely on an :itemx property.
WDYT?
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists
2022-01-18 15:11 ` [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
@ 2022-01-23 0:02 ` Nicolas Goaziou
2022-01-23 1:14 ` Jonas Bernoulli
2022-01-23 14:45 ` Jonas Bernoulli
0 siblings, 2 replies; 47+ messages in thread
From: Nicolas Goaziou @ 2022-01-23 0:02 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> +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]].
Typo: one of them is described here
> +(defvar org-texinfo--quoted-keys-regexp
> + (regexp-opt '("BS" "TAB" "RET" "ESC" "SPC" "DEL"
> + "LFD" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt"
> + "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN")
> + 'words)
> + "Regexp matching keys that have to be quoted using @key{KEY}.")
OK. This is the one missing from first patch.
> +(defun org-texinfo--massage-key-item (plain-list item args)
> + "In PLAIN-LIST modify ITEM based on ARGS.
> +Reformat ITEM's tag property and add findex and kindex entries to
> +its content. If the bullet is \"+\" then use \"@itemx\" and deal with
> +data from preceeding siblings that use such a bullet."
The last sentence is a left-over from the previous prototype.
> + (t
> + (org-element-set-contents
> + item (nconc
> + (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
> + (mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
> + (org-element-contents item))))))))
Indentation seems a bit off, otherwise, LGTM.
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists
2022-01-23 0:02 ` Nicolas Goaziou
@ 2022-01-23 1:14 ` Jonas Bernoulli
2022-01-23 14:45 ` Jonas Bernoulli
1 sibling, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 1:14 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>> + (t
>> + (org-element-set-contents
>> + item (nconc
>> + (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
>> + (mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
>> + (org-element-contents item))))))))
>
> Indentation seems a bit off, otherwise, LGTM.
Are you only referring to the spaces that should be replaced with a tab?
"item (nconc\n" is also a bit weird so I changed that to
(org-element-set-contents
item
(nconc (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
(mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
(org-element-contents item))))))))
Cheers,
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-22 15:33 ` Nicolas Goaziou
@ 2022-01-23 1:26 ` Jonas Bernoulli
2022-01-23 20:43 ` Jonas Bernoulli
1 sibling, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 1:26 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>> #+begin_example
>> -,#+ATTR_TEXINFO: :table-type vtable :sep , :indic asis
>> +,#+attr_texinfo: :table-type vtable :indic asis :sep ,
>> - foo, bar :: This is the common text for variables foo and bar.
>> #+end_example
>
> This change is not needed. Org markup is capitalized in examples to make
> it stand out. It's not great because 1) it is ugly 2) users may think
> Org syntax is uppercase. But changing that is not the point of this patch.
Sorry about that; I also don't like it when contributors sneak in
cosmetic changes.
>> (defun org-texinfo--normalize-headlines (tree _backend info)
>> "Normalize headlines in TREE.
>>
>> -BACK-END is the symbol specifying back-end used for export.
>> +_BACKEND is the symbol `texinfo'; the back-end used for export.
>
> You don't need to document ignored arguments.
The argument was already documented before I touched this, and
additionally the given name was incorrect. Should I leave this
untouched to avoid making unrelated cosmetic changes or should
I remove this line?
>> +(defun org-texinfo--combine-items (tree _backend info)
>> + "Combine certain description list items.
>> +
>> +_BACKEND is the symbol `texinfo'; the back-end used for export.
>> +INFO is a plist used as a communication channel.
>
> Same as above.
This one is an addition so I am dropping it. (The reason I originally
added it in the above addition is that I saw it being present here.)
>> +If the `:combine' attribute of a description list is non-nil and
>> +an item in that list has no body and is followed by another item,
>> +then remove the first item and prepend its `:tag' to that of the
>> +second item.
>> +
>> +Such an item that absorbed the tags of other items is later
>> +transcoded to one `@item', followed by one or more `@itemx'.
>> +
>> +Return new tree."
>> + (org-element-map tree 'item
>> + (lambda (item)
>> + (let ((plain-list (org-element-property :parent item)))
>> + (when (and (org-not-nil (org-export-read-attribute
>> + :attr_texinfo plain-list :compact))
>> + (eq (org-element-property :type plain-list) 'descriptive))
>> + (let ((next-item
>> + (cadr (memq item (org-element-contents plain-list)))))
>
> I suggest to use `org-export-get-next-element', which is not as
> low-level as this.
Okay changed.
In the next commit, in org-texinfo--massage-key-item, I am also using
the low-level approach. That function isn't passed INFO, so I am unsure
what to do there. Looking at org-export-get-next-element it seems fine
to just pass it nil as INFO.
>> - (items (and tag
>> - (let ((tag (org-export-data tag info)))
>> + (items (org-element-property :itemx item))
>> + (items (cond (items
>> + (mapcar (lambda (tag) (org-export-data tag info))
>> + (nconc items (list tag))))
>> + ((not tag) nil)
>> + (t
>> + (setq tag (org-export-data tag info))
>
> OK, but I think this is a bit convoluted. I wonder if we need
> `org-texinfo--combine-items' at all. I.e., `org-texinfo-item' could
> decide to prefix current tag with @itemx if 1) the item is empty 2) the
> list has a non-nil :compact attribute 3) there's another item following
> it. IOW, we do not need to rely on an :itemx property.
I think so, but its bed time. I'll look into it tomorrow.
Thanks for the review,
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists
2022-01-23 0:02 ` Nicolas Goaziou
2022-01-23 1:14 ` Jonas Bernoulli
@ 2022-01-23 14:45 ` Jonas Bernoulli
1 sibling, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 14:45 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>> +(defun org-texinfo--massage-key-item (plain-list item args)
>> + "In PLAIN-LIST modify ITEM based on ARGS.
>> +Reformat ITEM's tag property and add findex and kindex entries to
>> +its content. If the bullet is \"+\" then use \"@itemx\" and deal with
>> +data from preceeding siblings that use such a bullet."
>
> The last sentence is a left-over from the previous prototype.
I have fixed that but the result is quite detailed because I didn't
manage to keep it short and actually correct at the same time.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx
2021-12-30 9:40 ` Nicolas Goaziou
2022-01-05 13:12 ` Jonas Bernoulli
@ 2022-01-23 15:01 ` Jonas Bernoulli
1 sibling, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 15:01 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: kyle, emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> I suggest to require a special attribute before doing so, e.g.,
>
> #+attr_texinfo: :compact t
> - key: a ::
> - key: b ::
>
> - key: c ::
> - key: d ::
I have noticed that I accidentally called it ":combine" in the
documentation and have fixed that. (Do you think we should stick
to ":compact"?)
I would actually prefer to be able to set this once per file, not
least because this looks a bit weird.
#+attr_texinfo: :compact t
- key: a ::
not "compact"
- key: c ::
- key: d ::
"compact"
> Another option would be to merge consecutive lists with such an
> attribute, for the same result:
>
> #+attr_texinfo: :compact t
> - key: a ::
> - key: b ::
>
> #+attr_texinfo: :compact t
> - key: c ::
> - key: d ::
That would seem like a fix for that issue, but as I mentioned before
that doesn't work because it results in two lists, each with one @item
and one @itemx.
You actually suggested that in your first reply:
>> #+TEXINFO_DEFFN: t
> The chosen UI is rather odd however. I cannot think of another use of
> controlling export thhough "#+keyword: boolean" syntax. Usually, we
> extend the "options" keyword. It could become, for example:
>
> #+options: texinfo+:t
>
> Could it be possible to use that syntax instead?
You later indicated that you would prefer to specify this per-list. I
implemented the approach that uses "+" to indicate @itemx items, because
that seemed even nicer to me (because more explicit) but you didn't like
that and so I went with the alternative that you suggested in response
to that attempt.
But I would like to take a step back and ask if
> #+options: texinfo+:t
still seems like a good idea to you. (If so, should that be used
instead of the per-list approach or as an alternative?)
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v4 0/3] ox-texinfo: Define definition commands using description lists
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
` (3 preceding siblings ...)
2022-01-18 15:11 ` [PATCH v3 " Jonas Bernoulli
@ 2022-01-23 20:27 ` Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
` (2 more replies)
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
5 siblings, 3 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 20:27 UTC (permalink / raw)
To: emacs-orgmode
We are getting closer, I think.
Tested with the Org and Magit manuals again. Passed.
Jonas Bernoulli (3):
ox-texinfo: Add function for use by kbd macro
ox-texinfo: Optionally use @itemx for certain description list items
ox-texinfo: Define definition commands using description lists
doc/doc-setup.org | 2 +-
doc/org-manual.org | 133 ++++++++++++++++++++++++--
lisp/ox-texinfo.el | 229 ++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 332 insertions(+), 32 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v4 1/3] ox-texinfo: Add function for use by kbd macro
2022-01-23 20:27 ` [PATCH v4 0/3] " Jonas Bernoulli
@ 2022-01-23 20:27 ` Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 20:27 UTC (permalink / raw)
To: emacs-orgmode
* doc/doc-setup.org: Use org-texinfo-kbd-macro for kbd macro.
* doc/org-manual.org: Add new node "Key bindings in Texinfo export".
* lisp/ox-texinfo.el (org-texinfo--quoted-keys-regexp): New variable.
* lisp/ox-texinfo.el (org-texinfo-kbd-macro): New function.
---
doc/doc-setup.org | 2 +-
doc/org-manual.org | 27 +++++++++++++++++++++++++++
lisp/ox-texinfo.el | 30 +++++++++++++++++++++++++++++-
3 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/doc/doc-setup.org b/doc/doc-setup.org
index 9d15505e2..786a0cb14 100644
--- a/doc/doc-setup.org
+++ b/doc/doc-setup.org
@@ -49,5 +49,5 @@
# The "kbd" macro turns KBD into @kbd{KBD}. Additionally, it
# encloses case-sensitive special keys (SPC, RET...) within @key{...}.
-#+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))))
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
diff --git a/doc/org-manual.org b/doc/org-manual.org
index b4c20f252..e88cf1ed9 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15353,6 +15353,33 @@ your king.
,#+END_QUOTE
#+end_example
+*** Key bindings in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: @@kbd Texinfo command.
+:END:
+
+Org does not provide any markup for key bindings that corresponds to
+Texinfo's ~@kbd~ and ~@key~ commands. One way to deal with this is to
+fall back to code syntax. =~C-x SPC~=, for example, is transcoded to
+~@code{C-x SPC}~.
+
+A better approach is to define and use an Org macro named ~kbd~. To
+make that easier the function ~org-texinfo-kbd-macro~ is provided,
+which is intended to be used like this:
+
+#+begin_example
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
+
+Type {{{kbd(C-c SPC)}}}.
+#+end_example
+
+#+texinfo: @noindent
+which becomes
+
+#+begin_example
+Type @kbd{C-c @key{SPC}}.
+#+end_example
+
*** Special blocks in Texinfo export
:PROPERTIES:
:DESCRIPTION: Special block attributes.
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 46806ccca..ddd405d05 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -407,6 +407,13 @@ (defconst org-texinfo-inline-image-rules
(regexp-opt '("eps" "pdf" "png" "jpg" "jpeg" "gif" "svg"))))
"Rules characterizing image files that can be inlined.")
+(defvar org-texinfo--quoted-keys-regexp
+ (regexp-opt '("BS" "TAB" "RET" "ESC" "SPC" "DEL"
+ "LFD" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt"
+ "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN")
+ 'words)
+ "Regexp matching keys that have to be quoted using @key{KEY}.")
+
\f
;;; Internal Functions
@@ -1611,7 +1618,28 @@ (defun org-texinfo-verse-block (_verse-block contents _info)
(format "@display\n%s@end display" contents))
\f
-;;; Interactive functions
+;;; Public Functions
+
+(defun org-texinfo-kbd-macro (key &optional noquote)
+ "Quote KEY using @kbd{...} and if necessary @key{...}.
+
+This is intended to be used as an Org macro like so:
+
+ #+macro: kbd (eval (org-texinfo-kbd-macro $1))
+ Type {{{kbd(C-c SPC)}}}.
+
+Also see info node `(org)Key bindings in Texinfo export'.
+
+If optional NOQOUTE is non-nil, then do not add the quoting
+that is necessary when using this in an Org macro."
+ (format (if noquote "@kbd{%s}" "@@texinfo:@kbd{@@%s@@texinfo:}@@")
+ (let ((case-fold-search nil))
+ (replace-regexp-in-string
+ org-texinfo--quoted-keys-regexp
+ (if noquote "@key{\\&}" "@@texinfo:@key{@@\\&@@texinfo:}@@")
+ key t))))
+
+;;; Interactive Functions
;;;###autoload
(defun org-texinfo-export-to-texinfo
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v4 2/3] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-23 20:27 ` [PATCH v4 0/3] " Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
@ 2022-01-23 20:27 ` Jonas Bernoulli
2022-01-23 21:17 ` Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2 siblings, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 20:27 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Reorder and
document new functionality.
* lisp/ox-texinfo.el (org-texinfo-item): In a description list when
its :compact attribute is non-nil, then transcode consecutive items
using one @item and one or more @itemx commands, if all of them
except for the last one lack content.
---
doc/org-manual.org | 36 +++++++++++++++++++++---------
lisp/ox-texinfo.el | 55 ++++++++++++++++++++++++++++++----------------
2 files changed, 62 insertions(+), 29 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index e88cf1ed9..344aaf3e7 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15236,6 +15236,23 @@ This paragraph is preceded by...
:DESCRIPTION: List attributes.
:END:
+#+cindex: lettered lists, in Texinfo export
+#+cindex: enum, Texinfo attribute
+The Texinfo export back-end converts unordered and ordered lists in
+the Org file using the default command =@itemize=.
+
+Ordered lists are numbered when exported to Texinfo format. Such
+numbering obeys any counter (see [[*Plain Lists]]) in the first item of
+the list. The =:enum= attribute also let you start the list at a
+specific number, or switch to a lettered list, as illustrated here:
+
+#+begin_example
+#+ATTR_TEXINFO: :enum A
+1. Alpha
+2. Bravo
+3. Charlie
+#+end_example
+
#+cindex: @samp{ATTR_TEXINFO}, keyword
#+cindex: two-column tables, in Texinfo export
#+cindex: table-type, Texinfo attribute
@@ -15277,18 +15294,17 @@ This is the common text for variables foo and bar.
@end table
#+end_example
-#+cindex: lettered lists, in Texinfo export
-#+cindex: enum, Texinfo attribute
-Ordered lists are numbered when exported to Texinfo format. Such
-numbering obeys any counter (see [[*Plain Lists]]) in the first item of
-the list. The =:enum= attribute also let you start the list at
-a specific number, or switch to a lettered list, as illustrated here
+The =:compact= attribute is an alternative to the =:sep= attribute,
+which allows writing each entry on its own line. If this attribute is
+non-nil and an item in a description list has no body but is followed
+by another item, then the second item is transcoded to =@itemx=. This
+example is transcoded to the same output as above.
#+begin_example
-#+ATTR_TEXINFO: :enum A
-1. Alpha
-2. Bravo
-3. Charlie
+,#+ATTR_TEXINFO: :table-type vtable :indic asis :compact t
+- foo ::
+- bar ::
+ This is the common text for variables foo and bar.
#+end_example
*** Tables in Texinfo export
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index ddd405d05..9b2c0616c 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -997,25 +997,42 @@ (defun org-texinfo-item (item contents info)
CONTENTS holds the contents of the item. INFO is a plist holding
contextual information."
(let* ((tag (org-element-property :tag item))
- (split (org-string-nw-p
- (org-export-read-attribute :attr_texinfo
- (org-element-property :parent item)
- :sep)))
- (items (and tag
- (let ((tag (org-export-data tag info)))
- (if split
- (split-string tag (regexp-quote split) t "[ \t\n]+")
- (list tag))))))
- (format "%s\n%s"
- (pcase items
- (`nil "@item")
- (`(,item) (concat "@item " item))
- (`(,item . ,items)
- (concat "@item " item "\n"
- (mapconcat (lambda (i) (concat "@itemx " i))
- items
- "\n"))))
- (or contents ""))))
+ (plain-list (org-element-property :parent item))
+ (compact (and (eq (org-element-property :type plain-list) 'descriptive)
+ (org-not-nil (org-export-read-attribute
+ :attr_texinfo plain-list :compact))))
+ (previous-item nil))
+ (when (and compact
+ (org-export-get-next-element item info)
+ (not (org-element-contents item))
+ (memq (org-element-property :post-blank previous-item)
+ '(1 nil)))
+ (org-element-put-property item :post-blank 0))
+ (if (and compact
+ (setq previous-item (org-export-get-previous-element item info))
+ (not (org-element-contents previous-item))
+ (eq 0 (org-element-property :post-blank previous-item)))
+ (format "@itemx%s\n%s"
+ (if tag (concat " " (org-export-data tag info)) "")
+ (or contents ""))
+ (let* ((split (org-string-nw-p (org-export-read-attribute
+ :attr_texinfo plain-list :sep)))
+ (items (and tag
+ (let ((tag (org-export-data tag info)))
+ (if split
+ (split-string tag (regexp-quote split)
+ t "[ \t\n]+")
+ (list tag))))))
+ (format "%s\n%s"
+ (pcase items
+ (`nil "@item")
+ (`(,item) (concat "@item " item))
+ (`(,item . ,items)
+ (concat "@item " item "\n"
+ (mapconcat (lambda (i) (concat "@itemx " i))
+ items
+ "\n"))))
+ (or contents ""))))))
;;;; Keyword
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v4 3/3] ox-texinfo: Define definition commands using description lists
2022-01-23 20:27 ` [PATCH v4 0/3] " Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
@ 2022-01-23 20:27 ` Jonas Bernoulli
2 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 20:27 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Document use
of definition command prefixes in description lists.
* lisp/ox-texinfo.el: Add org-texinfo--separate-definitions to the
list of :filter-parse-tree functions of the texinfo backend.
* lisp/ox-texinfo.el (org-texinfo--definition-command-alist)
(org-texinfo--definition-command-regexp): New variables.
* 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 | 70 ++++++++++++++++++++++
lisp/ox-texinfo.el | 144 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 213 insertions(+), 1 deletion(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index 344aaf3e7..83d77c949 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15307,6 +15307,72 @@ example is transcoded to the same output as above.
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-c C-c (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
+
+#+texinfo: @noindent
+Command in parenthesis, as done above, is optional.
+
*** Tables in Texinfo export
:PROPERTIES:
:DESCRIPTION: Table attributes.
@@ -15401,6 +15467,10 @@ Type @kbd{C-c @key{SPC}}.
:DESCRIPTION: Special block attributes.
:END:
+The Texinfo export back-end supports two approaches to writing Texinfo
+definition commands. One of them is described 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 9b2c0616c..7688ce0b8 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -83,7 +83,8 @@ (org-export-define-backend 'texinfo
(verse-block . org-texinfo-verse-block))
:filters-alist
'((:filter-headline . org-texinfo--filter-section-blank-lines)
- (:filter-parse-tree . org-texinfo--normalize-headlines)
+ (:filter-parse-tree . (org-texinfo--normalize-headlines
+ org-texinfo--separate-definitions))
(:filter-section . org-texinfo--filter-section-blank-lines)
(:filter-final-output . org-texinfo--untabify))
:menu-entry
@@ -414,6 +415,23 @@ (defvar org-texinfo--quoted-keys-regexp
'words)
"Regexp matching keys that have to be quoted using @key{KEY}.")
+(defconst org-texinfo--definition-command-alist
+ '(("deffn Command" . "Command")
+ ("defun" . "Function")
+ ("defmac" . "Macro")
+ ("defspec" . "Special Form")
+ ("defvar" . "Variable")
+ ("defopt" . "User Option")
+ (nil . "Key"))
+ "Alist mapping Texinfo definition commands to output in Info files.")
+
+(defconst org-texinfo--definition-command-regexp
+ (format "\\`%s: \\(.+\\)"
+ (regexp-opt
+ (delq nil (mapcar #'cdr org-texinfo--definition-command-alist))
+ t))
+ "Regexp used to match definition commands in descriptive lists.")
+
\f
;;; Internal Functions
@@ -577,6 +595,130 @@ (defun org-texinfo--sectioning-structure (info)
(`(,_ ,_ . ,sections) sections)
(_ (user-error "Unknown Texinfo class: %S" class)))))
+(defun org-texinfo--separate-definitions (tree _backend info)
+ "Split up descriptive lists in TREE that contain Texinfo definition commands.
+
+_BACKEND is the symbol `texinfo'; the back-end used for export.
+INFO is a plist used as a communication channel.
+
+Return new tree."
+ (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))
+ (items nil))
+ (dolist (item contents)
+ (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
+ :attr_texinfo (org-element-property :attr_texinfo plain-list)
+ :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's tag property and determine the arguments for the
+`@findex' and `@kindex' commands for ITEM and store them in ITEM
+using the `:findex' and `:kindex' properties.
+
+If PLAIN-LIST is a description list whose `:compact' attribute is
+non-nil and ITEM has no content but is followed by another item,
+then store the `@findex' and `@kindex' values in the next item.
+If the previous item stored its respecive values in this item,
+then move them to the next item."
+ (let ((key nil)
+ (cmd nil))
+ (if (string-match (rx (+ " ")
+ "(" (group (+ (not (any "()")))) ")"
+ (* " ")
+ eos)
+ args)
+ (setq key (substring args 0 (match-beginning 0))
+ cmd (match-string 1 args))
+ (setq key args))
+ (org-element-put-property
+ item :tag
+ (cons (org-export-raw-string (org-texinfo-kbd-macro key t))
+ (and cmd `(" (" (code (:value ,cmd :post-blank 0)) ")"))))
+ (let ((findex (org-element-property :findex item))
+ (kindex (org-element-property :kindex item))
+ (next-item (org-export-get-next-element item nil))
+ (mx (string-prefix-p "M-x " key)))
+ (when (and (not cmd) mx)
+ (setq cmd (substring key 4)))
+ (when (and cmd (not (member cmd findex)))
+ (setq findex (nconc findex (list cmd))))
+ (unless mx
+ (setq kindex (nconc kindex (list key))))
+ (cond
+ ((and next-item
+ (org-not-nil
+ (org-export-read-attribute :attr_texinfo plain-list :compact))
+ (not (org-element-contents item))
+ (eq 1 (org-element-property :post-blank item)))
+ (org-element-put-property next-item :findex findex)
+ (org-element-put-property next-item :kindex kindex)
+ (org-element-put-property item :findex nil)
+ (org-element-put-property item :kindex nil))
+ (t
+ (org-element-set-contents
+ item
+ (nconc (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
+ (mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
+ (org-element-contents item))))))))
+
;;; Template
(defun org-texinfo-template (contents info)
--
2.34.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-22 15:33 ` Nicolas Goaziou
2022-01-23 1:26 ` Jonas Bernoulli
@ 2022-01-23 20:43 ` Jonas Bernoulli
1 sibling, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 20:43 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
>> - (items (and tag
>> - (let ((tag (org-export-data tag info)))
>> + (items (org-element-property :itemx item))
>> + (items (cond (items
>> + (mapcar (lambda (tag) (org-export-data tag info))
>> + (nconc items (list tag))))
>> + ((not tag) nil)
>> + (t
>> + (setq tag (org-export-data tag info))
>
> OK, but I think this is a bit convoluted. I wonder if we need
> `org-texinfo--combine-items' at all. I.e., `org-texinfo-item' could
> decide to prefix current tag with @itemx if 1) the item is empty 2) the
> list has a non-nil :compact attribute 3) there's another item following
> it. IOW, we do not need to rely on an :itemx property.
Yes, `org-texinfo--combine-items' wasn't necessary and its better
without it. But just like when crossing the street we now have to look
in both directions. ;)
I have kept the :compact and :sep code-paths apart because mixing them
would result in something that resembles the code you called convoluted
and because I think it would not make sense to mix the two styles in the
same list anyway.
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v4 2/3] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-23 20:27 ` [PATCH v4 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
@ 2022-01-23 21:17 ` Jonas Bernoulli
0 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-23 21:17 UTC (permalink / raw)
To: emacs-orgmode
Small fix:
- (memq (org-element-property :post-blank previous-item)
- '(1 nil)))
+ (eq 1 (org-element-property :post-blank item)))
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
` (4 preceding siblings ...)
2022-01-23 20:27 ` [PATCH v4 0/3] " Jonas Bernoulli
@ 2022-01-31 23:45 ` Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 1/4] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
` (4 more replies)
5 siblings, 5 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-31 23:45 UTC (permalink / raw)
To: emacs-orgmode
This fixes the small last minute defect in v4 and removes a mention
of an unused argument like you told me too.
This also adds an export option to enable the "compact itemx" syntax
for all lists in a file. I mentioned that I would like to be able to
enable this feature for a complete file but haven't heard back yet.
I think it makes sense to allow enabling this per file because I would
expect that it is much more likely that someone would want to use this
feature for all lists or for no lists at all, than it is for them to
only want to use it for certain lists.
I picked "compact-itemx" as the name of the export option but it seems
that the names of most other options are much shorter, so maybe just
"itemx" would be better. I am a bit unsure about the name of the
variable as well.
Regards,
Jonas
Jonas Bernoulli (4):
ox-texinfo: Add function for use by kbd macro
ox-texinfo: Optionally use @itemx for certain description list items
ox-texinfo: Define definition commands using description lists
ox-texinfo: Allow enabling compact syntax for @itemx per file
doc/doc-setup.org | 2 +-
doc/org-manual.org | 137 +++++++++++++++++++++++--
lisp/ox-texinfo.el | 246 ++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 351 insertions(+), 34 deletions(-)
--
2.35.1
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH v5 1/4] ox-texinfo: Add function for use by kbd macro
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
@ 2022-01-31 23:45 ` Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 2/4] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
` (3 subsequent siblings)
4 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-31 23:45 UTC (permalink / raw)
To: emacs-orgmode
* doc/doc-setup.org: Use org-texinfo-kbd-macro for kbd macro.
* doc/org-manual.org: Add new node "Key bindings in Texinfo export".
* lisp/ox-texinfo.el (org-texinfo--quoted-keys-regexp): New variable.
* lisp/ox-texinfo.el (org-texinfo-kbd-macro): New function.
---
doc/doc-setup.org | 2 +-
doc/org-manual.org | 27 +++++++++++++++++++++++++++
lisp/ox-texinfo.el | 30 +++++++++++++++++++++++++++++-
3 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/doc/doc-setup.org b/doc/doc-setup.org
index 9d15505e2..786a0cb14 100644
--- a/doc/doc-setup.org
+++ b/doc/doc-setup.org
@@ -49,5 +49,5 @@
# The "kbd" macro turns KBD into @kbd{KBD}. Additionally, it
# encloses case-sensitive special keys (SPC, RET...) within @key{...}.
-#+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))))
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
diff --git a/doc/org-manual.org b/doc/org-manual.org
index 2c54fde87..bd11e05f6 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15353,6 +15353,33 @@ your king.
,#+END_QUOTE
#+end_example
+*** Key bindings in Texinfo export
+:PROPERTIES:
+:DESCRIPTION: @@kbd Texinfo command.
+:END:
+
+Org does not provide any markup for key bindings that corresponds to
+Texinfo's ~@kbd~ and ~@key~ commands. One way to deal with this is to
+fall back to code syntax. =~C-x SPC~=, for example, is transcoded to
+~@code{C-x SPC}~.
+
+A better approach is to define and use an Org macro named ~kbd~. To
+make that easier the function ~org-texinfo-kbd-macro~ is provided,
+which is intended to be used like this:
+
+#+begin_example
+#+macro: kbd (eval (org-texinfo-kbd-macro $1))
+
+Type {{{kbd(C-c SPC)}}}.
+#+end_example
+
+#+texinfo: @noindent
+which becomes
+
+#+begin_example
+Type @kbd{C-c @key{SPC}}.
+#+end_example
+
*** Special blocks in Texinfo export
:PROPERTIES:
:DESCRIPTION: Special block attributes.
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 46806ccca..ddd405d05 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -407,6 +407,13 @@ (defconst org-texinfo-inline-image-rules
(regexp-opt '("eps" "pdf" "png" "jpg" "jpeg" "gif" "svg"))))
"Rules characterizing image files that can be inlined.")
+(defvar org-texinfo--quoted-keys-regexp
+ (regexp-opt '("BS" "TAB" "RET" "ESC" "SPC" "DEL"
+ "LFD" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt"
+ "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN")
+ 'words)
+ "Regexp matching keys that have to be quoted using @key{KEY}.")
+
\f
;;; Internal Functions
@@ -1611,7 +1618,28 @@ (defun org-texinfo-verse-block (_verse-block contents _info)
(format "@display\n%s@end display" contents))
\f
-;;; Interactive functions
+;;; Public Functions
+
+(defun org-texinfo-kbd-macro (key &optional noquote)
+ "Quote KEY using @kbd{...} and if necessary @key{...}.
+
+This is intended to be used as an Org macro like so:
+
+ #+macro: kbd (eval (org-texinfo-kbd-macro $1))
+ Type {{{kbd(C-c SPC)}}}.
+
+Also see info node `(org)Key bindings in Texinfo export'.
+
+If optional NOQOUTE is non-nil, then do not add the quoting
+that is necessary when using this in an Org macro."
+ (format (if noquote "@kbd{%s}" "@@texinfo:@kbd{@@%s@@texinfo:}@@")
+ (let ((case-fold-search nil))
+ (replace-regexp-in-string
+ org-texinfo--quoted-keys-regexp
+ (if noquote "@key{\\&}" "@@texinfo:@key{@@\\&@@texinfo:}@@")
+ key t))))
+
+;;; Interactive Functions
;;;###autoload
(defun org-texinfo-export-to-texinfo
--
2.35.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v5 2/4] ox-texinfo: Optionally use @itemx for certain description list items
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 1/4] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
@ 2022-01-31 23:45 ` Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 3/4] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
` (2 subsequent siblings)
4 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-31 23:45 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Reorder and
document new functionality.
* lisp/ox-texinfo.el (org-texinfo-item): In a description list when
its :compact attribute is non-nil, then transcode consecutive items
using one @item and one or more @itemx commands, if all of them
except for the last one lack content.
---
doc/org-manual.org | 36 ++++++++++++++++++++++---------
lisp/ox-texinfo.el | 54 ++++++++++++++++++++++++++++++----------------
2 files changed, 61 insertions(+), 29 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index bd11e05f6..4a4a048aa 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15236,6 +15236,23 @@ This paragraph is preceded by...
:DESCRIPTION: List attributes.
:END:
+#+cindex: lettered lists, in Texinfo export
+#+cindex: enum, Texinfo attribute
+The Texinfo export back-end converts unordered and ordered lists in
+the Org file using the default command =@itemize=.
+
+Ordered lists are numbered when exported to Texinfo format. Such
+numbering obeys any counter (see [[*Plain Lists]]) in the first item of
+the list. The =:enum= attribute also let you start the list at a
+specific number, or switch to a lettered list, as illustrated here:
+
+#+begin_example
+#+ATTR_TEXINFO: :enum A
+1. Alpha
+2. Bravo
+3. Charlie
+#+end_example
+
#+cindex: @samp{ATTR_TEXINFO}, keyword
#+cindex: two-column tables, in Texinfo export
#+cindex: table-type, Texinfo attribute
@@ -15277,18 +15294,17 @@ This is the common text for variables foo and bar.
@end table
#+end_example
-#+cindex: lettered lists, in Texinfo export
-#+cindex: enum, Texinfo attribute
-Ordered lists are numbered when exported to Texinfo format. Such
-numbering obeys any counter (see [[*Plain Lists]]) in the first item of
-the list. The =:enum= attribute also let you start the list at
-a specific number, or switch to a lettered list, as illustrated here
+The =:compact= attribute is an alternative to the =:sep= attribute,
+which allows writing each entry on its own line. If this attribute is
+non-nil and an item in a description list has no body but is followed
+by another item, then the second item is transcoded to =@itemx=. This
+example is transcoded to the same output as above.
#+begin_example
-#+ATTR_TEXINFO: :enum A
-1. Alpha
-2. Bravo
-3. Charlie
+,#+ATTR_TEXINFO: :table-type vtable :indic asis :compact t
+- foo ::
+- bar ::
+ This is the common text for variables foo and bar.
#+end_example
*** Tables in Texinfo export
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index ddd405d05..83868a69e 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -997,25 +997,41 @@ (defun org-texinfo-item (item contents info)
CONTENTS holds the contents of the item. INFO is a plist holding
contextual information."
(let* ((tag (org-element-property :tag item))
- (split (org-string-nw-p
- (org-export-read-attribute :attr_texinfo
- (org-element-property :parent item)
- :sep)))
- (items (and tag
- (let ((tag (org-export-data tag info)))
- (if split
- (split-string tag (regexp-quote split) t "[ \t\n]+")
- (list tag))))))
- (format "%s\n%s"
- (pcase items
- (`nil "@item")
- (`(,item) (concat "@item " item))
- (`(,item . ,items)
- (concat "@item " item "\n"
- (mapconcat (lambda (i) (concat "@itemx " i))
- items
- "\n"))))
- (or contents ""))))
+ (plain-list (org-element-property :parent item))
+ (compact (and (eq (org-element-property :type plain-list) 'descriptive)
+ (org-not-nil (org-export-read-attribute
+ :attr_texinfo plain-list :compact))))
+ (previous-item nil))
+ (when (and compact
+ (org-export-get-next-element item info)
+ (not (org-element-contents item))
+ (eq 1 (org-element-property :post-blank item)))
+ (org-element-put-property item :post-blank 0))
+ (if (and compact
+ (setq previous-item (org-export-get-previous-element item info))
+ (not (org-element-contents previous-item))
+ (eq 0 (org-element-property :post-blank previous-item)))
+ (format "@itemx%s\n%s"
+ (if tag (concat " " (org-export-data tag info)) "")
+ (or contents ""))
+ (let* ((split (org-string-nw-p (org-export-read-attribute
+ :attr_texinfo plain-list :sep)))
+ (items (and tag
+ (let ((tag (org-export-data tag info)))
+ (if split
+ (split-string tag (regexp-quote split)
+ t "[ \t\n]+")
+ (list tag))))))
+ (format "%s\n%s"
+ (pcase items
+ (`nil "@item")
+ (`(,item) (concat "@item " item))
+ (`(,item . ,items)
+ (concat "@item " item "\n"
+ (mapconcat (lambda (i) (concat "@itemx " i))
+ items
+ "\n"))))
+ (or contents ""))))))
;;;; Keyword
--
2.35.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v5 3/4] ox-texinfo: Define definition commands using description lists
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 1/4] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 2/4] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
@ 2022-01-31 23:45 ` Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 4/4] ox-texinfo: Allow enabling compact syntax for @itemx per file Jonas Bernoulli
2022-02-08 23:46 ` [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists Nicolas Goaziou
4 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-31 23:45 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Document use
of definition command prefixes in description lists.
* lisp/ox-texinfo.el: Add org-texinfo--separate-definitions to the
list of :filter-parse-tree functions of the texinfo backend.
* lisp/ox-texinfo.el (org-texinfo--definition-command-alist)
(org-texinfo--definition-command-regexp): New variables.
* 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 | 70 ++++++++++++++++++++++
lisp/ox-texinfo.el | 141 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 210 insertions(+), 1 deletion(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index 4a4a048aa..d7d81c1d4 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15307,6 +15307,72 @@ example is transcoded to the same output as above.
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-c C-c (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
+
+#+texinfo: @noindent
+Command in parenthesis, as done above, is optional.
+
*** Tables in Texinfo export
:PROPERTIES:
:DESCRIPTION: Table attributes.
@@ -15401,6 +15467,10 @@ Type @kbd{C-c @key{SPC}}.
:DESCRIPTION: Special block attributes.
:END:
+The Texinfo export back-end supports two approaches to writing Texinfo
+definition commands. One of them is described 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 83868a69e..673084859 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -83,7 +83,8 @@ (org-export-define-backend 'texinfo
(verse-block . org-texinfo-verse-block))
:filters-alist
'((:filter-headline . org-texinfo--filter-section-blank-lines)
- (:filter-parse-tree . org-texinfo--normalize-headlines)
+ (:filter-parse-tree . (org-texinfo--normalize-headlines
+ org-texinfo--separate-definitions))
(:filter-section . org-texinfo--filter-section-blank-lines)
(:filter-final-output . org-texinfo--untabify))
:menu-entry
@@ -414,6 +415,23 @@ (defvar org-texinfo--quoted-keys-regexp
'words)
"Regexp matching keys that have to be quoted using @key{KEY}.")
+(defconst org-texinfo--definition-command-alist
+ '(("deffn Command" . "Command")
+ ("defun" . "Function")
+ ("defmac" . "Macro")
+ ("defspec" . "Special Form")
+ ("defvar" . "Variable")
+ ("defopt" . "User Option")
+ (nil . "Key"))
+ "Alist mapping Texinfo definition commands to output in Info files.")
+
+(defconst org-texinfo--definition-command-regexp
+ (format "\\`%s: \\(.+\\)"
+ (regexp-opt
+ (delq nil (mapcar #'cdr org-texinfo--definition-command-alist))
+ t))
+ "Regexp used to match definition commands in descriptive lists.")
+
\f
;;; Internal Functions
@@ -577,6 +595,127 @@ (defun org-texinfo--sectioning-structure (info)
(`(,_ ,_ . ,sections) sections)
(_ (user-error "Unknown Texinfo class: %S" class)))))
+(defun org-texinfo--separate-definitions (tree _backend info)
+ "Split up descriptive lists in TREE that contain Texinfo definition commands.
+INFO is a plist used as a communication channel.
+Return new tree."
+ (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))
+ (items nil))
+ (dolist (item contents)
+ (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
+ :attr_texinfo (org-element-property :attr_texinfo plain-list)
+ :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's tag property and determine the arguments for the
+`@findex' and `@kindex' commands for ITEM and store them in ITEM
+using the `:findex' and `:kindex' properties.
+
+If PLAIN-LIST is a description list whose `:compact' attribute is
+non-nil and ITEM has no content but is followed by another item,
+then store the `@findex' and `@kindex' values in the next item.
+If the previous item stored its respecive values in this item,
+then move them to the next item."
+ (let ((key nil)
+ (cmd nil))
+ (if (string-match (rx (+ " ")
+ "(" (group (+ (not (any "()")))) ")"
+ (* " ")
+ eos)
+ args)
+ (setq key (substring args 0 (match-beginning 0))
+ cmd (match-string 1 args))
+ (setq key args))
+ (org-element-put-property
+ item :tag
+ (cons (org-export-raw-string (org-texinfo-kbd-macro key t))
+ (and cmd `(" (" (code (:value ,cmd :post-blank 0)) ")"))))
+ (let ((findex (org-element-property :findex item))
+ (kindex (org-element-property :kindex item))
+ (next-item (org-export-get-next-element item nil))
+ (mx (string-prefix-p "M-x " key)))
+ (when (and (not cmd) mx)
+ (setq cmd (substring key 4)))
+ (when (and cmd (not (member cmd findex)))
+ (setq findex (nconc findex (list cmd))))
+ (unless mx
+ (setq kindex (nconc kindex (list key))))
+ (cond
+ ((and next-item
+ (org-not-nil
+ (org-export-read-attribute :attr_texinfo plain-list :compact))
+ (not (org-element-contents item))
+ (eq 1 (org-element-property :post-blank item)))
+ (org-element-put-property next-item :findex findex)
+ (org-element-put-property next-item :kindex kindex)
+ (org-element-put-property item :findex nil)
+ (org-element-put-property item :kindex nil))
+ (t
+ (org-element-set-contents
+ item
+ (nconc (mapcar (lambda (key) `(keyword (:key "KINDEX" :value ,key))) kindex)
+ (mapcar (lambda (cmd) `(keyword (:key "FINDEX" :value ,cmd))) findex)
+ (org-element-contents item))))))))
+
;;; Template
(defun org-texinfo-template (contents info)
--
2.35.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* [PATCH v5 4/4] ox-texinfo: Allow enabling compact syntax for @itemx per file
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
` (2 preceding siblings ...)
2022-01-31 23:45 ` [PATCH v5 3/4] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
@ 2022-01-31 23:45 ` Jonas Bernoulli
2022-02-08 23:46 ` [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists Nicolas Goaziou
4 siblings, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-01-31 23:45 UTC (permalink / raw)
To: emacs-orgmode
* doc/org-manual.org (Plain lists in Texinfo export): Document the
:texinfo-compact-itemx export option and variable
org-texinfo-compact-itemx.
* lisp/ox-texinfo.el: Add org-texinfo-compact-itemx to the
:options-alist of the texinfo backend.
* lisp/ox-texinfo.el (org-texinfo-compact-itemx): New option.
* lisp/ox-texinfo.el (org-texinfo--massage-key-item): Add INFO
argument and use the :texinfo-compact-itemx export option.
* lisp/ox-texinfo.el (org-texinfo-item): Use the
:texinfo-compact-itemx export option.
---
doc/org-manual.org | 6 +++++-
lisp/ox-texinfo.el | 35 ++++++++++++++++++++++++++---------
2 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index d7d81c1d4..7cd93ab0e 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -15307,7 +15307,11 @@ example is transcoded to the same output as above.
This is the common text for variables foo and bar.
#+end_example
-Likewise, the Texinfo export back-end supports two approaches to
+Support for this compact syntax can also be enabled for all lists in a
+file using the =compat-itemx= export option, or globally using the
+variable =org-texinfo-compact-itemx=.
+
+The Texinfo export back-end also 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]].
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 673084859..dba93e318 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -119,8 +119,8 @@ (org-export-define-backend 'texinfo
(:texinfo-table-default-markup nil nil org-texinfo-table-default-markup)
(:texinfo-text-markup-alist nil nil org-texinfo-text-markup-alist)
(:texinfo-format-drawer-function nil nil org-texinfo-format-drawer-function)
- (:texinfo-format-inlinetask-function nil nil org-texinfo-format-inlinetask-function)))
-
+ (:texinfo-format-inlinetask-function nil nil org-texinfo-format-inlinetask-function)
+ (:texinfo-compact-itemx nil "compact-itemx" org-texinfo-compact-itemx)))
\f
;;; User Configurable Variables
@@ -355,6 +355,19 @@ (defcustom org-texinfo-format-inlinetask-function
:group 'org-export-texinfo
:type 'function)
+;;;; Itemx
+
+(defcustom org-texinfo-compact-itemx nil
+ "Non-nil means certain items in description list are transcoded using `@itemx'.
+
+If this is non-nil and an item in a description list has no
+body but is followed by another item, then the second item is
+transcoded to `@itemx'. See info node `(org)Plain lists in
+Texinfo export' for how to enable this for individual lists."
+ :package-version '(Org . "9.6")
+ :group 'org-export-texinfo
+ :type 'boolean)
+
;;;; Compilation
(defcustom org-texinfo-info-process '("makeinfo --no-split %f")
@@ -614,7 +627,7 @@ (defun org-texinfo--separate-definitions (tree _backend info)
(org-texinfo--split-definition plain-list item cmd args))
(t
(when args
- (org-texinfo--massage-key-item plain-list item args))
+ (org-texinfo--massage-key-item plain-list item args info))
(push item items)))))
(unless (org-element-contents plain-list)
(org-element-extract-element plain-list)))))
@@ -663,7 +676,7 @@ (defun org-texinfo--split-plain-list (plain-list items)
(mapc #'org-element-extract-element items))
plain-list))
-(defun org-texinfo--massage-key-item (plain-list item args)
+(defun org-texinfo--massage-key-item (plain-list item args info)
"In PLAIN-LIST modify ITEM based on ARGS.
Reformat ITEM's tag property and determine the arguments for the
@@ -674,7 +687,9 @@ (defun org-texinfo--massage-key-item (plain-list item args)
non-nil and ITEM has no content but is followed by another item,
then store the `@findex' and `@kindex' values in the next item.
If the previous item stored its respecive values in this item,
-then move them to the next item."
+then move them to the next item.
+
+INFO is a plist used as a communication channel."
(let ((key nil)
(cmd nil))
(if (string-match (rx (+ " ")
@@ -701,8 +716,9 @@ (defun org-texinfo--massage-key-item (plain-list item args)
(setq kindex (nconc kindex (list key))))
(cond
((and next-item
- (org-not-nil
- (org-export-read-attribute :attr_texinfo plain-list :compact))
+ (or (plist-get info :texinfo-compact-itemx)
+ (org-not-nil
+ (org-export-read-attribute :attr_texinfo plain-list :compact)))
(not (org-element-contents item))
(eq 1 (org-element-property :post-blank item)))
(org-element-put-property next-item :findex findex)
@@ -1138,8 +1154,9 @@ (defun org-texinfo-item (item contents info)
(let* ((tag (org-element-property :tag item))
(plain-list (org-element-property :parent item))
(compact (and (eq (org-element-property :type plain-list) 'descriptive)
- (org-not-nil (org-export-read-attribute
- :attr_texinfo plain-list :compact))))
+ (or (plist-get info :texinfo-compact-itemx)
+ (org-not-nil (org-export-read-attribute
+ :attr_texinfo plain-list :compact)))))
(previous-item nil))
(when (and compact
(org-export-get-next-element item info)
--
2.35.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
` (3 preceding siblings ...)
2022-01-31 23:45 ` [PATCH v5 4/4] ox-texinfo: Allow enabling compact syntax for @itemx per file Jonas Bernoulli
@ 2022-02-08 23:46 ` Nicolas Goaziou
2022-02-11 20:01 ` Jonas Bernoulli
2022-02-15 21:01 ` [PATCH] etc/ORG-NEWS: Add news items about new features in texinfo exporter Jonas Bernoulli
4 siblings, 2 replies; 47+ messages in thread
From: Nicolas Goaziou @ 2022-02-08 23:46 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> This fixes the small last minute defect in v4 and removes a mention
> of an unused argument like you told me too.
>
> This also adds an export option to enable the "compact itemx" syntax
> for all lists in a file. I mentioned that I would like to be able to
> enable this feature for a complete file but haven't heard back yet.
>
> I think it makes sense to allow enabling this per file because I would
> expect that it is much more likely that someone would want to use this
> feature for all lists or for no lists at all, than it is for them to
> only want to use it for certain lists.
>
> I picked "compact-itemx" as the name of the export option but it seems
> that the names of most other options are much shorter, so maybe just
> "itemx" would be better. I am a bit unsure about the name of the
> variable as well.
Applied. Thank you! We can always revisit the variable name later.
Could you provides an ORG-NEWS entry for this?
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists
2022-02-08 23:46 ` [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists Nicolas Goaziou
@ 2022-02-11 20:01 ` Jonas Bernoulli
2022-02-15 21:01 ` [PATCH] etc/ORG-NEWS: Add news items about new features in texinfo exporter Jonas Bernoulli
1 sibling, 0 replies; 47+ messages in thread
From: Jonas Bernoulli @ 2022-02-11 20:01 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:
> Applied. Thank you! We can always revisit the variable name later.
Thanks to you too!
> Could you provides an ORG-NEWS entry for this?
Will do.
Cheers,
Jonas
^ permalink raw reply [flat|nested] 47+ messages in thread
* [PATCH] etc/ORG-NEWS: Add news items about new features in texinfo exporter
2022-02-08 23:46 ` [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists Nicolas Goaziou
2022-02-11 20:01 ` Jonas Bernoulli
@ 2022-02-15 21:01 ` Jonas Bernoulli
2022-02-22 19:14 ` Nicolas Goaziou
1 sibling, 1 reply; 47+ messages in thread
From: Jonas Bernoulli @ 2022-02-15 21:01 UTC (permalink / raw)
To: emacs-orgmode
---
etc/ORG-NEWS | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5a94e737e..fd29d39d7 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -63,6 +63,20 @@ list of various table options (between brackets in LaTeX export),
since certain tabular environments, such as longtblr of the
tabularray LaTeX package, provides this structure.
+*** New =:compact= attribute when exporting lists to Texinfo
+
+The =:compact= attribute allows exporting multiple description list
+items to one =@item= command and one or more =@itemx= commands. This
+feature can also be enabled for all description lists in a file using
+the =compact-itemx= export option, or globally using the
+~org-texinfo-compact-itemx~ variable.
+
+*** New shorthands recognized when exporting to Texinfo
+
+Items in a description list that begin with =Function:=, =Variable:=
+or certain related prefixes are converted using Texinfo definition
+commands.
+
** New functions and changes in function arguments
*** New function ~org-element-cache-map~ for quick mapping across Org elements
@@ -98,6 +112,11 @@ argument.
~org-get-tags~ now accepts Org element or buffer position as first
argument.
+*** New function ~org-texinfo-kbd-macro~
+
+This function is intended for us in the definition of a ~kbd~ macro in
+files that are exported to Texinfo.
+
** Miscellaneous
*** Styles are customizable in ~biblatex~ citation processor
--
2.35.1
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: [PATCH] etc/ORG-NEWS: Add news items about new features in texinfo exporter
2022-02-15 21:01 ` [PATCH] etc/ORG-NEWS: Add news items about new features in texinfo exporter Jonas Bernoulli
@ 2022-02-22 19:14 ` Nicolas Goaziou
0 siblings, 0 replies; 47+ messages in thread
From: Nicolas Goaziou @ 2022-02-22 19:14 UTC (permalink / raw)
To: Jonas Bernoulli; +Cc: emacs-orgmode
Hello,
Jonas Bernoulli <jonas@bernoul.li> writes:
> ---
> etc/ORG-NEWS | 19 +++++++++++++++++++
Applied. Thank you.
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 47+ messages in thread
end of thread, other threads:[~2022-02-22 19:20 UTC | newest]
Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-11-09 18:01 Merging ox-texinfo+ into ox-texinfo Jonas Bernoulli
2021-11-19 12:46 ` Nicolas Goaziou
2021-11-20 21:06 ` Jonas Bernoulli
2021-11-21 12:41 ` Nicolas Goaziou
2021-11-30 16:58 ` Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 0/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 1/2] ox-texinfo: Turn a description list item with "+" bullet into @itemx Jonas Bernoulli
2021-12-26 21:37 ` Nicolas Goaziou
2021-12-27 18:05 ` Jonas Bernoulli
2021-12-30 9:40 ` Nicolas Goaziou
2022-01-05 13:12 ` Jonas Bernoulli
2022-01-23 15:01 ` Jonas Bernoulli
2021-12-18 21:40 ` [PATCH 2/2] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2021-12-26 21:46 ` Nicolas Goaziou
2021-12-27 18:05 ` Jonas Bernoulli
2021-12-30 0:57 ` Nicolas Goaziou
2022-01-05 13:16 ` Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 0/3] " Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
2022-01-05 13:30 ` [PATCH v2 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2022-01-14 23:01 ` [PATCH v2 0/3] " Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 " Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-22 15:19 ` Nicolas Goaziou
2022-01-18 15:11 ` [PATCH v3 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
2022-01-22 15:33 ` Nicolas Goaziou
2022-01-23 1:26 ` Jonas Bernoulli
2022-01-23 20:43 ` Jonas Bernoulli
2022-01-18 15:11 ` [PATCH v3 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2022-01-23 0:02 ` Nicolas Goaziou
2022-01-23 1:14 ` Jonas Bernoulli
2022-01-23 14:45 ` Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 0/3] " Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 1/3] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 2/3] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
2022-01-23 21:17 ` Jonas Bernoulli
2022-01-23 20:27 ` [PATCH v4 3/3] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 0/4] " Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 1/4] ox-texinfo: Add function for use by kbd macro Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 2/4] ox-texinfo: Optionally use @itemx for certain description list items Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 3/4] ox-texinfo: Define definition commands using description lists Jonas Bernoulli
2022-01-31 23:45 ` [PATCH v5 4/4] ox-texinfo: Allow enabling compact syntax for @itemx per file Jonas Bernoulli
2022-02-08 23:46 ` [PATCH v5 0/4] ox-texinfo: Define definition commands using description lists Nicolas Goaziou
2022-02-11 20:01 ` Jonas Bernoulli
2022-02-15 21:01 ` [PATCH] etc/ORG-NEWS: Add news items about new features in texinfo exporter Jonas Bernoulli
2022-02-22 19:14 ` Nicolas Goaziou
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).