From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms13.migadu.com with LMTPS id uAXVMFYjM2fQBAEAqHPOHw:P1 (envelope-from ) for ; Tue, 12 Nov 2024 09:43:50 +0000 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0.migadu.com with LMTPS id uAXVMFYjM2fQBAEAqHPOHw (envelope-from ) for ; Tue, 12 Nov 2024 10:43:50 +0100 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=gmail.com header.s=20230601 header.b=SGMOGjAs; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=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" ARC-Seal: i=1; s=key1; d=yhetil.org; t=1731404630; a=rsa-sha256; cv=none; b=owp4NCHAmW4TO1M2FpjDp2W+Qv8CKV4z/HfYZfUR3apIv9xY/0ITGgeJ5zqjyfDXNyMsXI 8qW2Q0Y1o81rXbET2QRYQjPEsuE5beQs4vyfLNK1xDsVbDcwhNMk9daFc3QJ6maOHig8dP Fe7bdatofudG0biJ0d08Jm10F1fXV7KKAMrj7s4cVUCP6Rm0A5XpYZFp+b1cUKG/nuXscY ttrzWwD7mgUZBF1iMpRKB63EPQm7gD65t4a8Qxvk+mxtkFhFefHxSYKfaFTXV1Afevje/8 HBmm4C1JdB/bD6/ZND7buGq1YCu8DqerxMREyoiS/3cYD8MgIS7ZeVTtiSlo1w== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=fail ("body hash did not verify") header.d=gmail.com header.s=20230601 header.b=SGMOGjAs; dmarc=fail reason="SPF not aligned (relaxed)" header.from=gmail.com (policy=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" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1731404630; 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:dkim-signature; bh=mJz7Ytx4jGujmCN8FSqKRiSHFg0cRNc4sSKtKpLDbzo=; b=Y1mSzQsmjjYUF05VDR0LXagUF1mPAuH9ZDXjSMWl965EHJP4B9vb/YIxay0qlZnPs0xF+f yPyD+G0Al0Ec+rQavrlPwOKpV08rEXHCxEWL5g9s5K2pqTOw6z5C/V+D+7w1WstkGSnHu5 acsNQmd7qvfgkxiqBDz2yfXYJehYN/cXHszDk3OC89mrQBpXOgzVpVD5Usz/qFML7Kj7HP RpEsoOObaFQq3YZak/H6ktkc1Tf6h+Rejit3wUGEUJL/DphR7l6SLZ262gmTz43jeDFGoI arIGVffjMrhkmSYbB0UifCvbJoreMZyVIcVpllgBIP8sDaR/CUJwBfAFX2Iazw== 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 53B89195F1 for ; Tue, 12 Nov 2024 10:43:50 +0100 (CET) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tAnAF-0004jl-Jy; Tue, 12 Nov 2024 04:26:23 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tAnA9-0004jQ-C6 for emacs-orgmode@gnu.org; Tue, 12 Nov 2024 04:26:17 -0500 Received: from mail-lf1-x136.google.com ([2a00:1450:4864:20::136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tAnA7-0001sc-1L for emacs-orgmode@gnu.org; Tue, 12 Nov 2024 04:26:17 -0500 Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-539f4d8ef66so8115881e87.1 for ; Tue, 12 Nov 2024 01:26:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1731403570; x=1732008370; darn=gnu.org; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=ReA6YUhZhflqqSNnBM5yg72mlgvJVAMEHo4stKBpcGI=; b=SGMOGjAs3dIxy7AWFgtNsJsYcHTvDv7pydmACd5UQ+oiVoZcu3WEGJAD2Qe37m+3GB Nq/njB69+LqBYUX0DMAPjC451CIr1h77dlzgRd/lWEwekgV/WYIkU5wHGDmSVTRYConZ Iy/rA02S3wQr1S4YUmA/z326yETqIdZIiRzEaW1TTiWSB1KVQqVSw38S4xUKtUkJ2TvI H05VaEDh8fIjL+F5ixuOC0OdwpM98/HLoREcX2am0awTABu5x9CarnXrLhCu47ojtnUD kyDmvRVnoT3VttDsX01nxCAF65qEH1WY1ihGCegN0FjiVx/1KSAyA9Gk5TxNuIH8lgwH y+jA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731403570; x=1732008370; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=ReA6YUhZhflqqSNnBM5yg72mlgvJVAMEHo4stKBpcGI=; b=la7w+lPPvQZB0UhkEImuKir58vQ6KBlTmGkPuteVGDQxm+WZCRyGFd7k9RECTh7zMo X+Bb/dKO1sqQGHx0gssgvlHjKFr7gOO8ddZ9roltOej56hNXk4qsFWafLn7mvXNiN2rY SDoiTqF1LHPBJ0dFe160kYI3iuEBP0hnWnh1E7s1VVJxP7mK6mqe0grtSx/sNUuLqYkH 2wtvEWTrTCbkSsTEn5xhJmiEHG5T2m3oLQK5GK8++p2x/muciB5n6Nv5kykmvdcMWFiM 1dgTGi4LgNNDJ0ZHlbxrV5/+z6N5Tgax4w2CO5+xDgHYFZCARFdWVU/AwLVkCAJFljav bW5g== X-Forwarded-Encrypted: i=1; AJvYcCVDremaBujlXHNMLb7AxBsDvlFzsVwEyqTCEsOgBRKsB5UfdjlypoRWqCG7GxfQfeLzcqa8U5JrG31Ie09N@gnu.org X-Gm-Message-State: AOJu0YwU7ka9y5ZZEwc2uVqAyQ9csCNaGHJaJlByi1WioxfD/vMrW2Vx fVjznLDE1XGxkk1hGxPq9dRhu/+Av65s8aIET23P/UDkDdPuv8iWKNu/sg== X-Google-Smtp-Source: AGHT+IGhhdZM2zXKdxCT94u62Wd5oIXx1ygCAXRQDr3vEQ/OnHUFip+vATnlfTrgC5FjwQVMpMBn2Q== X-Received: by 2002:a05:6512:1191:b0:539:f67b:b849 with SMTP id 2adb3069b0e04-53d862f33b4mr6131817e87.49.1731403569808; Tue, 12 Nov 2024 01:26:09 -0800 (PST) Received: from barbar (82-181-23-112.bb.dnainternet.fi. [82.181.23.112]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-53d82685620sm1843786e87.63.2024.11.12.01.26.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 01:26:08 -0800 (PST) From: =?utf-8?Q?Tor-bj=C3=B6rn_Claesson?= To: Ihor Radchenko Cc: Jonas Bernoulli , emacs-orgmode@gnu.org Subject: Re: Org-cite: Replace basic follow-processor with transient menu? In-Reply-To: <87jzd9ojj0.fsf@localhost> (Ihor Radchenko's message of "Mon, 11 Nov 2024 15:52:03 +0000") References: <8734m28l9a.fsf@gmail.com> <87r0839jfc.fsf@bernoul.li> <874j4ueo1x.fsf@localhost> <87bjz2tam2.fsf@gmail.com> <87msil77oi.fsf@localhost> <87ed3wnlv4.fsf@gmail.com> <874j4sccuv.fsf@localhost> <87jzdo2e4m.fsf@gmail.com> <87a5eievav.fsf@localhost> <87wmhlmp83.fsf@gmail.com> <871pzte929.fsf@localhost> <87v7x548ri.fsf@gmail.com> <87y120daue.fsf@localhost> <874j4m9ep6.fsf@gmail.com> <87h68gfqj1.fsf@localhost> <87pln3f3cc.fsf@localhost> <87jzd9ojj0.fsf@localhost> Date: Tue, 12 Nov 2024 11:26:06 +0200 Message-ID: <87cyj0ajm9.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::136; envelope-from=tclaesson@gmail.com; helo=mail-lf1-x136.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, 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: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: 6.66 X-Spam-Score: 6.66 X-Migadu-Queue-Id: 53B89195F1 X-Migadu-Scanner: mx10.migadu.com X-TUID: kYwiOTCak8DU --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ihor Radchenko writes: > See my comments below. Thanks for taking the time to look at this! >> +*** Menu for choosing how to follow citations >> +If invoked with a prefix of C-- C-u, following citations with >> +the org-cite-basic citation backend will no present a transient menu, >> +offering choices for how to follow citations. > > I imagine C-- C-u more as a toggle - if `org-cite-basic-follow-ask' is > t, it disables the menu; enables otherwise. That is more useful, thanks! > >> +(defcustom org-cite-basic-follow-ask nil >> + "Should `org-cite-basic' ask how to follow citations? >> + >> +When this option is nil, `org-cite-basic-follow' opens the bibliography= entry. >> +Otherwise, `org-cite-basic-follow' will display a transient menu prompt= ing the=20 >> +user for an action. The contents of this menu can be customized in=20 >> +`org-cite-basic-follow-actions'." > > Note: our convention is to use double space between sentences. > There are also typos, but that's a minor thing I can fix myself before > merging. Ah, bummer. I have fixed (at least some) of those typos. >> +(defcustom org-cite-basic-follow-actions >> + '[["Open" >> + ("b" "bibliography entry" (org-cite-basic-goto !citation !prefix))= ]] >> + "Actions in the `org-cite-basic-follow' transient menu. >> + >> +This option uses the same syntax as `transient-define-prefix', see Info= node >> +`(transient)Binding Suffix and Infix Commands'. In addition, it is poss= ible=20 >> +to specify a function call for the COMMAND part, where !citation,=20 >> +!prefix, and !citation-key can be used to access those values.=20 >> + >> +If COMMAND is a lambda form, it can access the citation and prefix like= this: >> + >> + (lambda (citation prefix) >> + (interactive (transient-scope)) >> + ...)" > > Could we make !prefix, and !citation work in lambdas? We should be able > to. Sure! It took me some trial and error to get the list splicing right but now it works in lambdas to. I added another helper to do let binding. >> +(transient-define-prefix org-cite-basic-follow (citation &optional pref= ix) >> + "Follow citation. >> + >> +This transient is invoked through `org-open-at-point'.=20 >> +When `org-open-at-point' is invoked > > It should not matter for this command where it is called from. > You can simply drop references to `org-open-at-point' > > We can even make the prefix work as a standalone command. Simply using > interactive spec. > > (interactive > (list (let ((obj (org-element-context))) > (pcase (org-element-type obj) > ((or citation citation-reference) obj) > (_ (user-error "No citation at point")))))) I was not able to get this to work. >> ... with a negative prefix, +or `org-cite-basic-follow-ask' is >> non-nil, it will present +a transient menu prompting the user for an >> action. Otherwise, +it will open the bibliography entry for the >> citation at point. > >> +Suffixes can not be added to this transient menu using the ordinary >> +`transient-append-suffix' or `transient-insert-suffix', instead, the >> +contents of the menu are defined in the variable >> +`org-cite-basic-follow-actions'." > > Suffixes can be added. Try > > (transient-append-suffix 'org-cite-basic-follow nil > '[["Other" ("t" "test" (lambda () (interactive) (message "Hello!")))]]) Ah, I didn't know you could nil the position. >> +(defun org-cite-basic-follow--parse-suffix-specification (specification) >> + (pcase specification > > Please, add the docstring. > Ok. >> + ((and val `(,key ,desc (,fn . ,fn-args) . ,other)) >> + (if (eq fn 'lambda) val >> + `(,key ,desc >> + (lambda () >> + (interactive) >> + (let ((!citation (car (transient-scope))) >> + (!prefix (cadr (transient-scope))) >> + (!citation-key >> + (org-element-property :key (car (transient-scope= ))))) > > `org-open-at-point' may be called with point at citation rather than > citation reference. Citation object does not have :key property. > > I think that we should drop !citation-key spec and instead specify that > the command may be called with citation or citation-reference object in != citation. `org-cite-basic-goto' handles this by prompting the user for a key, if it is called with a citation object. I adopted this approach. (I find the !citation-key useful for a lot of things I like to do to citations, and would like to keep it.) >> +(defun org-cite-basic-follow--setup (_) >> + (transient-parse-suffixes > > Docstring here as well. Ok. Version 2 of the patch is attached. Cheers, Tor-bj=C3=B6rn --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-lisp-oc-basic.el-Transient-menu-for-following-citati-v2.patch Content-Description: transient-follower-version2 >From e91fff9f6c03e2c766dee410f46382398f883997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor-bj=C3=B6rn=20Claesson?= Date: Tue, 12 Nov 2024 11:09:16 +0200 Subject: [PATCH] lisp/oc-basic.el: Transient menu for following citations * lisp/oc-basic.el (require 'transient): Pull in transient. (org-cite-basic-follow-ask): New customization option. should `org-cite-basic-follow' prompt the user for an action? (org-cite-basic-follow-actions): New customization option, that specifies the contents of the transient menu. (org-cite-basic-follow): New function. Displays a menu asking how to follow a citation if `org-cite-basic-follow-ask' is non-nil. Otherwise, it retains the default behaviour of opening the bibliography entry. This can be inversed with a negative prefix argument. (org-cite-basic-follow--parse-suffix-specification, org-cite-basic-follow--wrap-function, and org-cite-basic-follow--setup): Helper functions for `org-cite-basic-follow'. (org-cite-register-processor 'basic): Update the basic citation processor to follow citations using `org-cite-basic-follow'. * etc/ORG_NEWS (Menu for choosing how to follow citations): Describe the new feature (New option ~org-cite-basic-follow-ask~): Describe this new customization option. (New option ~org-cite-basic-follow-actions~): Describe this new customization option, which specifies the layout of the `org-cite-basic-follow' transient menu. This change was co-authored with much support from Ihor Radchenko and Jonas Bernoulli, thanks! --- etc/ORG-NEWS | 22 +++++++++++ lisp/oc-basic.el | 95 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index de4f11b25..b859b0ada 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -114,6 +114,15 @@ The keybindings in the repeat-maps can be changed by customizing See the new [[info:org#Repeating commands]["Repeating commands"]] section in Org mode manual. +*** Menu for choosing how to follow citations + +Following citations with the org-cite-basic citation backend can now present a +transient menu. To show this menu, set ~org-cite-basic-follow-ask~ to non-nil. +This behaviour can be reversed with a negativ prefix. + +The contents of this menu can be customized in +~org-cite-basic-follow-actions~. + ** New and changed options # Chanes deadling with changing default values of customizations, @@ -158,6 +167,19 @@ English. The default value is ~t~ as the CSL standard assumes that English titles are specified in sentence-case but the bibtex bibliography format requires them to be written in title-case. +*** New option ~org-cite-basic-follow-ask~ + +When this option is non-nil, following a citation with the basic citation +backend will present a transient menu with choices for how to follow the +citation. +If nil, following a citation will open its bibliography entry. + +This behaviour can be reversed with a negative prefix argument. + +*** New option ~org-cite-basic-follow-actions~ + +This option specifies the options presented by ~org-cite-basic-follow~. + ** New functions and changes in function arguments # This also includes changes in function behavior from Elisp perspective. diff --git a/lisp/oc-basic.el b/lisp/oc-basic.el index e207a1997..c3fc3f34d 100644 --- a/lisp/oc-basic.el +++ b/lisp/oc-basic.el @@ -74,6 +74,7 @@ (require 'map) (require 'oc) (require 'seq) +(require 'transient) (declare-function org-open-at-point "org" (&optional arg)) (declare-function org-open-file "org" (path &optional in-emacs line search)) @@ -140,6 +141,30 @@ :type 'face :safe #'facep) +(defcustom org-cite-basic-follow-ask nil + "Should `org-cite-basic' ask how to follow citations? + +When this option is nil, `org-cite-basic-follow' opens the bibliography entry. +Otherwise, `org-cite-basic-follow' will display a transient menu prompting the +user for an action. The contents of this menu can be customized in +`org-cite-basic-follow-actions'." + :group 'org-cite + :package-version '(Org . "9.8") + :type 'boolean) + +(defcustom org-cite-basic-follow-actions + '[["Open" + ("b" "bibliography entry" (org-cite-basic-goto !citation !prefix))]] + "Actions in the `org-cite-basic-follow' transient menu. + +This option uses the same syntax as `transient-define-prefix', see Info node +`(transient)Binding Suffix and Infix Commands'. In addition, it is possible +to specify a function call for the COMMAND part, where !citation, +!prefix, and !citation-key can be used to access those values." + :group 'org-cite + :package-version '(Org . "9.8") + :type 'sexp) + ;;; Internal variables (defvar org-cite-basic--bibliography-cache nil @@ -832,6 +857,74 @@ present in the citation." (bibtex-set-dialect) (bibtex-search-entry key))))) +(transient-define-prefix org-cite-basic-follow (citation &optional prefix) + "Follow citation. + +If `org-cite-basic-follow-ask' is non-nil, this transient will present +a menu prompting the user for an action. +Otherwise, it will open the bibliography entry for the citation at point. +This behaviour is inverted when the transient is called with a negative prefix +argument. + +The contents of the menu are defined in the variable +`org-cite-basic-follow-actions'." + [:class transient-columns + :setup-children org-cite-basic-follow--setup + :pad-keys t] + (interactive) + (if (xor org-cite-basic-follow-ask + (equal prefix '(-4))) + (transient-setup 'org-cite-basic-follow nil nil + :scope (list citation prefix)) + (org-cite-basic-goto citation prefix))) + +(defun org-cite-basic-follow--wrap-function (fn-args &optional fn) + "Provide !citation, !prefix, and !citation-key symbols." + (append + `(let ((!citation (car (transient-scope))) + (!prefix (cadr (transient-scope))) + (!citation-key + (if (org-element-type-p (car (transient-scope)) 'citation-reference) + (org-element-property :key (car (transient-scope))) + (pcase (org-cite-get-references (car (transient-scope)) t) + (`(,key) key) + (keys + (or (completing-read "Select citation key: " keys nil t) + (user-error "Aborted")))))))) + (if fn + `((,fn ,@fn-args)) + fn-args))) + +(defun org-cite-basic-follow--parse-suffix-specification (specification) + "Handle special syntax for `org-cite-basic-follow-actions'." + (pcase specification + (`(,key ,desc (lambda ,args . ,fn-args) . ,other) + `(,key ,desc + (lambda ,args + ,(unless (and (listp (car fn-args)) + (equal (caar fn-args) + 'interactive)) + '(interactive)) + ,(org-cite-basic-follow--wrap-function fn-args)) + ,@other)) + (`(,key ,desc (,fn . ,fn-args) . ,other) + `(,key ,desc + (lambda () + (interactive) + ,(org-cite-basic-follow--wrap-function fn-args fn)) + ,@other)) + (other other))) + +(defun org-cite-basic-follow--setup (_) + "Update `org-cite-basic-follow' when `org-cite-basic-follow-actions' changes." + (transient-parse-suffixes + 'org-cite-basic-follow + (cl-map 'vector + (lambda (group) + (cl-map 'vector #'org-cite-basic-follow--parse-suffix-specification + group)) + org-cite-basic-follow-actions))) + ;;; "Insert" capability (defun org-cite-basic--complete-style (_) @@ -920,7 +1013,7 @@ Raise an error when no bibliography is set in the buffer." :activate #'org-cite-basic-activate :export-citation #'org-cite-basic-export-citation :export-bibliography #'org-cite-basic-export-bibliography - :follow #'org-cite-basic-goto + :follow #'org-cite-basic-follow :insert (org-cite-make-insert-processor #'org-cite-basic--complete-key #'org-cite-basic--complete-style) :cite-styles -- 2.46.0 --=-=-=--