Hi!

(I'm trying to send this again, since it hasn't shown up in the list
archives for a week.)
Den sön 19 jan. 2025 kl 15:32 skrev Ihor Radchenko <yanta...@posteo.net>:

> It looks like we got no more ideas other than what have been already
> discussed.
>
> So, my tentative plan is the following:
>

Sounds good!

>
> 1. You finish your patch for org-cite
>

 My current version is attached. The difference vs. v5 is that the default
action is customizeable.

What do you think?

Cheers,
Tor-björn
From 571935cbb91589a20a9cc05b37156bb7c9186e24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tor-bj=C3=B6rn=20Claesson?= <t...@barbar.claesson.fi>
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.
(require 'org-element): Pull in org-element.
(org-cite-basic-follow-default-action): New customization option. The
default action for org-cite-basic-follow.
(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--get-key): New function. Get citation key from
citation or citation reference.
(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 performs the actions specified in
org-cite-basic-follow-default-action. This behaviour can be inversed
with a negative prefix argument.
(org-cite-basic-follow--parse-suffix-specification 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-default-action~): Describe this
new customization option.
(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     |  26 ++++++++++
 lisp/oc-basic.el | 123 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 140 insertions(+), 9 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index de4f11b25..617ef51b0 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.
 
+*** New transient menu when following 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 -4 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,23 @@ 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-default-action~
+The default action for org-cite-basic-follow.
+
+*** 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 perform the action spefified in
+~org-cite-basic-follow-default-action~.
+
+This behaviour can be reversed with a -4 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..24beb7ef4 100644
--- a/lisp/oc-basic.el
+++ b/lisp/oc-basic.el
@@ -74,6 +74,8 @@
 (require 'map)
 (require 'oc)
 (require 'seq)
+(require 'transient)
+(require 'org-element)
 
 (declare-function org-open-at-point "org" (&optional arg))
 (declare-function org-open-file "org" (path &optional in-emacs line search))
@@ -140,6 +142,46 @@
   :type 'face
   :safe #'facep)
 
+(defcustom org-cite-basic-follow-default-action 'org-cite-basic-goto
+  "The default action for `org-cite-basic-follow'."
+  :group 'org-cite
+  :package-version '(Org . "9.8")
+  :type 'sexp)
+
+(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' performs the action in 
+`org-cite-basic-follow-default-action'. 
+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))]
+    ["Copy"
+     ("d" "DOI"
+      (kill-new
+       (org-cite-basic--get-field
+        'doi
+        (org-cite-basic--get-key !citation))))]]
+  "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 (the citation
+object to be followed) and !prefix (any prefix argument to the follower) can be
+used to access those values. For example:
+(org-cite-basic-goto !citation !prefix) or
+(lambda () (message (org-element-property :key !citation)))"
+  :group 'org-cite
+  :package-version '(Org . "9.8")
+  :type 'sexp)
+
 
 ;;; Internal variables
 (defvar org-cite-basic--bibliography-cache nil
@@ -326,6 +368,16 @@ INFO is the export state, as a property list."
                 (map-keys entries))
               (org-cite-basic--parse-bibliography)))
 
+(defun org-cite-basic--get-key (citation-or-citation-reference)
+  "Return citation key for CITATION-OR-CITATION-KEY."
+  (if (org-element-type-p citation-or-citation-reference 'citation-reference)
+      (org-element-property :key citation-or-citation-reference)
+    (pcase (org-cite-get-references citation-or-citation-reference t)
+      (`(,key) key)
+      (keys
+       (or (completing-read "Select citation key: " keys nil t)
+           (user-error "Aborted"))))))
+
 (defun org-cite-basic--get-entry (key &optional info)
   "Return BibTeX entry for KEY, as an association list.
 When non-nil, INFO is the export state, as a property list."
@@ -805,14 +857,7 @@ export state, as a property list."
 When DATUM is a citation reference, open bibliography entry referencing
 the citation key.  Otherwise, select which key to follow among all keys
 present in the citation."
-  (let* ((key
-          (if (org-element-type-p datum 'citation-reference)
-              (org-element-property :key datum)
-            (pcase (org-cite-get-references datum t)
-              (`(,key) key)
-              (keys
-               (or (completing-read "Select citation key: " keys nil t)
-                   (user-error "Aborted"))))))
+  (let* ((key (org-cite-basic--get-key datum))
          (file
           (pcase (seq-find (pcase-lambda (`(,_ . ,entries))
                              (gethash key entries))
@@ -832,6 +877,66 @@ present in the citation."
        (bibtex-set-dialect)
        (bibtex-search-entry key)))))
 
+(transient-define-prefix org-cite-basic-follow (citation-object &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 call the function specified in 
+`org-cite-basic-follow-default-action' for the citation at point.  
+This behaviour is inverted when the transient is called with a -4 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
+    (list (let ((obj (org-element-context)))
+           (pcase (org-element-type obj)
+             ((or 'citation 'citation-reference) obj)
+             (_ (user-error "No citation at point"))))))
+  (if (xor org-cite-basic-follow-ask
+           (equal prefix '(-4)))
+      (transient-setup 'org-cite-basic-follow nil nil
+                       :scope (list :citation citation-object :prefix prefix))
+    (funcall org-cite-basic-follow-default-action citation-object prefix)))
+
+(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))
+              (let ((!citation (plist-get (transient-scope) :citation))
+                    (!prefix (plist-get (transient-scope) :prefix)))
+                ,@fn-args))
+            ,@other))
+    (`(,key ,desc (,fn . ,fn-args) . ,other)
+     `(,key ,desc
+            (lambda ()
+	      (interactive)
+              (let ((!citation (plist-get (transient-scope) :citation))
+                    (!prefix (plist-get (transient-scope) :prefix)))
+	        (,fn ,@fn-args)))
+            ,@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 +1025,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.47.1

Reply via email to