From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:403:4ea1::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id QMM4AC/jyGG4SgAAgWs5BA (envelope-from ) for ; Sun, 26 Dec 2021 22:48:31 +0100 Received: from aspmx1.migadu.com ([2001:41d0:8:6d80::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id IDa6NS7jyGFa/wAAG6o9tA (envelope-from ) for ; Sun, 26 Dec 2021 22:48:30 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 5347C27230 for ; Sun, 26 Dec 2021 22:48:30 +0100 (CET) Received: from localhost ([::1]:35078 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1n1bNV-0000VX-Hk for larch@yhetil.org; Sun, 26 Dec 2021 16:48:29 -0500 Received: from eggs.gnu.org ([209.51.188.92]:42862) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1n1bM3-0000VO-7b for emacs-orgmode@gnu.org; Sun, 26 Dec 2021 16:46:59 -0500 Received: from relay4-d.mail.gandi.net ([217.70.183.196]:53181) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1n1bLz-0000JE-Dv for emacs-orgmode@gnu.org; Sun, 26 Dec 2021 16:46:57 -0500 Received: (Authenticated sender: admin@nicolasgoaziou.fr) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id AE6E6E0003; Sun, 26 Dec 2021 21:46:52 +0000 (UTC) From: Nicolas Goaziou To: Jonas Bernoulli Subject: Re: [PATCH 2/2] ox-texinfo: Define definition commands using description lists References: <87pmqhmvg1.fsf@bernoul.li> <20211218214038.9459-1-jonas@bernoul.li> <20211218214038.9459-3-jonas@bernoul.li> Date: Sun, 26 Dec 2021 22:46:51 +0100 In-Reply-To: <20211218214038.9459-3-jonas@bernoul.li> (Jonas Bernoulli's message of "Sat, 18 Dec 2021 22:40:38 +0100") Message-ID: <87sfuf9gz8.fsf@nicolasgoaziou.fr> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain Received-SPF: pass client-ip=217.70.183.196; envelope-from=mail@nicolasgoaziou.fr; helo=relay4-d.mail.gandi.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kyle@kyleam.com, emacs-orgmode@gnu.org Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1640555310; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post; bh=mIH1/pM9s6M/CtG2C5jGeosb7rqYCt++yd0usy43M2I=; b=Ywqk2INKJyAzPaXmSnoSyKsU2uvCm7k2ujQtebqoZ5CRFN0rehRGqg1QD/lcVZDP2QAADk M6e+vI7D2ds1Mo1p2Zo4gkE8EAnwiFL5j466K3ssgouZas5yA4Ddd0V7nmHXmkgQ4N9RyK SWJWLnppDQE513nYCF7EC0gfcFUjxiW5/ai4MugB/jtl3KTnXRb5aQ0ZSYdfSMRvcrSAr3 QTBCDLrNlxlBVwRJkCa2Ig10DtYZKa/gtvqk+Lr607GVPQptTeIrs2H0TIP5jPP5pQ/3XU PC3MHPSyVqfE3/8xkHjwF5EEwdZlrHdko/pC7ydiLBQHffW86zKHEKzVKOtk8w== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1640555310; a=rsa-sha256; cv=none; b=cS/GLOLHgaB/MoVNfgUQv6KYS7tZe9y65TAoP/oIRjNNxp0bWfENZWOS85O3dNxU4AzCJU +BXCunW7OdVwkYfWCHkb18VWN6LqFpKKaTMeAWUhaNT1IWaZCrM00G8teQW4ec5a6NTFJ1 3Rge4aK+344slh2jRIljCrC4qBzLdGRGgXav8c3SjYMS/1Oz8pWFyFqu0b5eFGbiFOchN8 4+tifsX9bHYDFSDy0aEjQXyOvxQwG53pKnKpiOjK2uLG3UdMwCLm/XqoOe8KYeLM++UkYB suAPCa7Q1xiW+xiTVw7al9mF0W6ZC9z1X8ehR/J9jtZGsOfxsetBd2EmwFRFHQ== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Spam-Score: -3.17 Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org" X-Migadu-Queue-Id: 5347C27230 X-Spam-Score: -3.17 X-Migadu-Scanner: scn1.migadu.com X-TUID: d1DNCA8n0C89 Hello, Thanks. Jonas Bernoulli writes: > +#+begin_example > +- Key: C-n (do-something) :: > + This command does something. > + > +- User Option: do-something-somehow :: > + This option controls how exactly ~do-something~ does its thing. > +#+end_example > + > +#+texinfo: @noindent > +becomes > + > +#+begin_example > +@table @asis > +@item @kbd{C-c C-c} (@code{do-something}) > +@kindex C-c C-c > +@findex do-something > +This command does something. > +@end table There's a mismatch between the keys. > +Key items don't have to specify the respective command in parenthesis > +as done above; that part is optional. Simply put: Command in parenthesis, as done above, is optional. > +Regardless of which approach you use, you must define the =kbd= macro > +(see [[*Macro Replacement]]), which you can then use anywhere in the Org > +file: > + > +#+begin_example > +,#+macro: kbd (eval (let ((case-fold-search nil) (regexp (regexp-opt '("SPC" "RET" "LFD" "TAB" "BS" "ESC" "DELETE" "SHIFT" "Ctrl" "Meta" "Alt" "Cmd" "Super" "UP" "LEFT" "RIGHT" "DOWN") 'words))) (format "@@texinfo:@kbd{@@%s@@texinfo:}@@" (replace-regexp-in-string regexp "@@texinfo:@key{@@\\&@@texinfo:}@@" $1 t)))) > #+end_example Ouch. I don't think we should expect users to define this in order to use the feature being implemented. IOW, it should work out of the box. I think the functions responsible for generating the Texinfo code should handle this without relying on the macro. Of course, if that part is factored out, the macro might, in turn, make use of it. > +(defconst org-texinfo--definition-command-regexp > + (format "\\`%s: \\(.+\\)" > + (regexp-opt > + (delq nil (mapcar #'cdr org-texinfo--definition-command-alist)) > + 1)) What is 1 meaning here? Do you mean t? > +(defun org-texinfo--separate-definitions (tree _backend info) > + "Split up descriptive lists that contain Texinfo definition > commands." You need to document the arguments. > + (org-element-map tree 'plain-list > + (lambda (plain-list) > + (when (eq (org-element-property :type plain-list) 'descriptive) > + (let ((contents (org-element-contents plain-list)) > + item items) Nitpick: (items nil) > + (while (setq item (pop contents)) nitpick: Use dolist. > + (pcase-let ((`(,cmd . ,args) (org-texinfo--match-definition item))) > + (cond > + (cmd > + (when items > + (org-texinfo--split-plain-list plain-list (nreverse items)) > + (setq items nil)) > + (org-texinfo--split-definition plain-list item cmd args)) > + (t > + (when args > + (org-texinfo--massage-key-item plain-list item args)) > + (push item items))))) > + (unless (org-element-contents plain-list) > + (org-element-extract-element plain-list))))) > + info) > + tree) > + > +(defun org-texinfo--match-definition (item) > + "Return a cons-cell if ITEM specifies a Texinfo definition command. > +The car is the command and the cdr is its arguments." > + (let ((tag (car-safe (org-element-property :tag item)))) > + (and tag > + (stringp tag) > + (string-match org-texinfo--definition-command-regexp tag) > + (pcase-let* > + ((cmd (car (rassoc (match-string-no-properties 1 tag) > + org-texinfo--definition-command-alist))) > + (`(,cmd ,category) > + (and cmd (save-match-data (split-string cmd " ")))) > + (args (match-string-no-properties 2 tag))) > + (cons cmd (if category (concat category " " args) args)))))) > + > +(defun org-texinfo--split-definition (plain-list item cmd args) > + "Insert a definition command before list PLAIN-LIST. > +Replace list item ITEM with a special-block that inherits the > +contents of ITEM and whose type and Texinfo attributes are > +specified by CMD and ARGS." > + (let ((contents (org-element-contents item))) > + (org-element-insert-before > + (apply #'org-element-create 'special-block > + (list :type cmd > + :attr_texinfo (list (format ":options %s" args)) > + :post-blank (if contents 1 0)) > + (mapc #'org-element-extract-element contents)) > + plain-list)) > + (org-element-extract-element item)) > + > +(defun org-texinfo--split-plain-list (plain-list items) > + "Insert a new plain list before the plain list PLAIN-LIST. > +Remove ITEMS from PLAIN-LIST and use them as the contents of the > +new plain list." > + (org-element-insert-before > + (apply #'org-element-create 'plain-list > + (list :type 'descriptive :post-blank 1) > + (mapc #'org-element-extract-element items)) > + plain-list)) > + > +(defun org-texinfo--massage-key-item (plain-list item args) > + "In PLAIN-LIST modify ITEM based on ARGS. > +Reformat ITEM'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