Tor-björn Claesson <tclaes...@gmail.com> writes:

> Please find attached a new version of the patch for review.

Since there will be a another update on the patch, I am just posting what
I've done so far with this version.

I simplified the code a bit and got rid of s.el functions.
See the attached patches on top of the patch I am replying to.

>From 1dac8c8945965a3b6a492b121a74e206a6d875c8 Mon Sep 17 00:00:00 2001
Message-ID: <1dac8c8945965a3b6a492b121a74e206a6d875c8.1751301583.git.yanta...@posteo.net>
From: Ihor Radchenko <yanta...@posteo.net>
Date: Mon, 30 Jun 2025 18:39:03 +0200
Subject: [PATCH 1/2] lisp/oc-basic.el (org-cite-basic-goto): Do not use s.el

---
 lisp/oc-basic.el | 62 ++++++++++++++++++++++++------------------------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/lisp/oc-basic.el b/lisp/oc-basic.el
index 1e18fc497..7ec580d71 100644
--- a/lisp/oc-basic.el
+++ b/lisp/oc-basic.el
@@ -875,37 +875,37 @@ (defun org-cite-basic-goto (datum _)
        (bibtex-search-entry key)))))
 
 (org-menu-define org-cite-basic-follow (citation-object)
-                 "Follow citations"
-                 [["Open"
-                   ("b" "bibliography entry" (org-cite-basic-goto !citation-object !prefix-argument))
-                   ("w" "Browse URL/DOI"
-                    (let ((url (org-cite-basic--get-url !citation-object))
-                          (doi (org-cite-basic--get-doi !citation-object)))
-                      (cond ((not (s-blank? url))
-                             (browse-url url))
-                            ((not (s-blank? doi))
-                             (if (string-match "^http" doi)
-                                 (browse-url doi)
-                               (browse-url (format "http://dx.doi.org/%s"; doi))))
-                            (t (user-error "No URL or DOI for `%s'"
-                                           (org-cite-basic--get-key !citation-object))))))]             
-                  ["Copy"
-                   ("d" "DOI"
-                    (let ((doi (org-cite-basic--get-doi !citation-object)))
-                      (if (not (s-blank? doi))
-                          (kill-new doi)
-                        (user-error "No DOI for `%s'" (org-cite-basic--get-key !citation-object)))))
-                   ("u" "URL"
-                    (let ((url (org-cite-basic--get-url !citation-object)))
-                      (if (not (s-blank? url))
-                          (kill-new url)
-                        (user-error "No URL for `%s'" (org-cite-basic--get-key !citation-object)))))]]
-                 (org-cite-basic-goto !citation-object !prefix-argument)
-                 (interactive
-                  (list (let ((obj (org-element-context)))
-                          (pcase (org-element-type obj)
-                            ((or 'citation 'citation-reference) obj)
-                            (_ (user-error "Wrong object type")))))))
+  "Follow citations"
+  [["Open"
+    ("b" "bibliography entry" (org-cite-basic-goto !citation-object !prefix-argument))
+    ("w" "Browse URL/DOI"
+     (let ((url (org-cite-basic--get-url !citation-object))
+           (doi (org-cite-basic--get-doi !citation-object)))
+       (cond ((org-string-nw-p url)
+              (browse-url url))
+             ((org-string-nw-p doi)
+              (if (string-match "^http" doi)
+                  (browse-url doi)
+                (browse-url (format "http://dx.doi.org/%s"; doi))))
+             (t (user-error "No URL or DOI for `%s'"
+                            (org-cite-basic--get-key !citation-object))))))]
+   ["Copy"
+    ("d" "DOI"
+     (let ((doi (org-cite-basic--get-doi !citation-object)))
+       (if (org-string-nw-p doi)
+           (kill-new doi)
+         (user-error "No DOI for `%s'" (org-cite-basic--get-key !citation-object)))))
+    ("u" "URL"
+     (let ((url (org-cite-basic--get-url !citation-object)))
+       (if (org-string-nw-p url)
+           (kill-new url)
+         (user-error "No URL for `%s'" (org-cite-basic--get-key !citation-object)))))]]
+  (org-cite-basic-goto !citation-object !prefix-argument)
+  (interactive
+   (list (let ((obj (org-element-context)))
+           (pcase (org-element-type obj)
+             ((or 'citation 'citation-reference) obj)
+             (_ (user-error "Wrong object type")))))))
 
 
 ;;; "Insert" capability
-- 
2.50.0

>From 32bdb4ae5073f77d1d957e53977003e446496aa1 Mon Sep 17 00:00:00 2001
Message-ID: <32bdb4ae5073f77d1d957e53977003e446496aa1.1751301583.git.yanta...@posteo.net>
In-Reply-To: <1dac8c8945965a3b6a492b121a74e206a6d875c8.1751301583.git.yanta...@posteo.net>
References: <1dac8c8945965a3b6a492b121a74e206a6d875c8.1751301583.git.yanta...@posteo.net>
From: Ihor Radchenko <yanta...@posteo.net>
Date: Mon, 30 Jun 2025 18:39:24 +0200
Subject: [PATCH 2/2] lisp/om.el: Modularize code

---
 lisp/om.el | 149 ++++++++++++++++++++++++++---------------------------
 1 file changed, 72 insertions(+), 77 deletions(-)

diff --git a/lisp/om.el b/lisp/om.el
index 5333407bc..762bd74dc 100644
--- a/lisp/om.el
+++ b/lisp/om.el
@@ -69,9 +69,9 @@ (define-minor-mode org-menu-mode
 
 The menu system used can be customized in `org-menu-system'.
 
-When org-menu-mode is active, it can be transiently deactivated by the 
-prefix argument specified in `org-menu-switch', and vice verse transiently
-activated when inactive."
+When `org-menu-mode' is active, it can be transiently deactivated by
+the prefix argument specified in `org-menu-switch', and vice verse
+transiently activated when inactive."
   :init-value nil
   :lighter " OM")
 
@@ -134,9 +134,9 @@ (defun org-menu--setup-children (name actions arglist)
 (defun org-menu--wrap-specification (specification arg-list)
   "Handle special syntax for `org-cite-basic-follow-actions'.
 
-In addition to the syntax described in 
-`(transient)Binding Suffix and Infix Commands', the names in arg-list,
-prefixed by `!', can be used to access those arguments."
+In addition to the syntax described in `(transient)Binding Suffix and
+Infix Commands', the names in arg-list, prefixed by `!', can be used
+to access those arguments."
   (pcase specification
     (`(,key ,desc (lambda ,args . ,fn-args) . ,other)
      `(,key ,desc
@@ -168,110 +168,105 @@ (defun org-menu--wrap-specification (specification arg-list)
     (other other)))
 
 
+(defmacro org-menu--defcustom-actions (menu-actions value menu-name)
+  "Define MENU-ACTIONS option for MENU-NAME with default VALUE."
+  `(defcustom ,menu-actions ,value
+     ,(concat "Actions in the `" (symbol-name menu-name) "' org 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 ARGUMENTS can be used to access those values.
+
+For example:
+
+[[\"Open\"
+  (\"b\" \"bibliography entry\"
+   (org-cite-basic-goto !citation-object !prefix-argument))]]
+
+will create an entry labeled \"bibliography entry\", activated with the
+b key, that calls `org-cite-basic-goto' with citation-object and
+prefix-argument as arguments.")
+     :group 'org-menu
+     :type 'sexp))
+
+(defmacro org-menu--defcustom-default-action
+    (default-action value menu-name arglist)
+  "Define DEFAULT-ACTION option for MENU-NAME with default VALUE.
+The action will accept ARGLIST arguments."
+  `(defcustom ,default-action ,value
+     ,(concat "Default action for `" (symbol-name menu-name) "'.
+This should be a function accepting the arguments\n"
+              (prin1-to-string arglist)
+              ".")
+     :group 'org-menu
+     :type 'sexp))
+
 ;;; Main macro definition
-(cl-defmacro org-menu-define (name
-                              arglist
-                              docstring
-                              contents
-                              default-action
-                              &body body)
-  "Define an org menu.
+(cl-defmacro org-menu-define
+    (name arglist docstring contents default-action &body body)
+  "Define an org menu NAME.
 
 A function called NAME will be created to activate the menu.
 
-ARGLIST is the name of the arguments given to this function. 
+ARGLIST is the name of the arguments given to this function.
 Unless it ends in prefix-argument, this will be appended.
 
-CONTENTS is the contents of the menu. It follows the syntax
+DOCSTRING is the menu docstring.
+
+CONTENTS is the contents of the menu.  It follows the syntax
 decribed in `(transient)Binding Suffix and Infix Commands',
 with the addition that the arguments in ARGLIST are accessible
-prefixed with !. For an example, see `org-cite-basic-follow'.
+prefixed with !.  For an example, see `org-cite-basic-follow'.
 
 DEFAULT-ACTION specifies the action to be taken, if org-menu is
 inactive (as determined by `org-menu-mode' and modified by a
 prefix argument set in `org-menu-switch'.
-It has the form of a function call, where the arguments in 
-ARGLIST are accessible prefixed by !. For example, the default action 
-of `org-cite-basic-follow', which is defined with n ARGLIST 
-(citation-object prefix-argument), has the form
-(org-cite-basic-goto !citation-object !prefix-argument).
+It has the form of a function call, where the arguments in
+ARGLIST are accessible prefixed by !.  For example, the default action
+of `org-cite-basic-follow', which is defined with n ARGLIST
+\\(citation-object prefix-argument), has the form
+\\(org-cite-basic-goto !citation-object !prefix-argument).
 
 BODY is optional and can be used to set up the interactive
 environemnt and validate arguments."
   (declare (indent defun))
-  (let ((menu-default-actions-name
-         (intern
-          (concat (symbol-name name)
-                  "-default-action")))
-        (menu-setup-children-name
-         (intern
-          (concat (symbol-name name)
-                  "--setup-children")))                
+  (let ((menu-default-action
+         (intern (concat (symbol-name name) "-default-action")))
         (menu-actions
-         (intern
-          (concat (symbol-name name)
-                  "-actions")))
+         (intern (concat (symbol-name name) "-actions")))
         (complete-arglist (if (member 'prefix-argument arglist)
                               arglist
                             `(,@arglist prefix-argument))))
     `(progn
-       (defcustom ,menu-actions ,contents
-         ,(concat "Actions in the `"
-                  (symbol-name name)
-                  "' org 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 ARGUMENTS can be used
-to access those values.
+       (org-menu--defcustom-actions
+        ,menu-actions ',contents ,name)
+       (org-menu--defcustom-default-action
+        ,menu-default-action ',default-action ,name ',complete-arglist)
 
-For example: 
-
-[[\"Open\" (\"b\" \"bibliography entry\" 
-(org-cite-basic-goto !citation-object !prefix-argument))]]
-
-will create an entry labeled \"bibliography entry\", activated with the 
-b key, that calls org-cite-basic-goto with citation-object and
-prefix-argument as arguments.")
-         :group 'org-menu
-         :type 'sexp)
-       
-       (defcustom ,menu-default-actions-name ',default-action
-         ,(concat "Default action for `"
-                  (symbol-name name)
-                  "'.
-This should be a function accepting the arguments
-"
-                  (prin1-to-string complete-arglist)
-                  ".")
-         :group 'org-menu
-         :type 'sexp)
-
-       (defun ,menu-setup-children-name (_)
-         ,(concat "Minimal wrapper to setup " (symbol-name name) ".")
-         (org-menu--setup-children ',name ',menu-actions ',complete-arglist))
-       
        (transient-define-prefix
          ,name (,@arglist &optional prefix-argument)
          ,docstring
          [:class
           transient-columns
           :setup-children
-          ,menu-setup-children-name
+          (lambda (_) (org-menu--setup-children
+                  ',name ',menu-actions ',complete-arglist))
           :pad-keys t]
          ;; Make sure we have an interactive body
          ,@(pcase body
-             (`((interactive . ,interactive-spec) . ,body)
-              `((interactive ,@interactive-spec) ,body))
+             (`((interactive . _) . _)
+              body)
              (_
-              `((interactive (list (org-element-context))) ,@body)))
+              `((interactive (list (org-element-context)))
+                ,@body)))
          ;; Should we display a menu? If so, how?
          (cond ((not (xor org-menu-mode
-                          (eq prefix-argument org-menu-switch)))
+                        (eq prefix-argument org-menu-switch)))
                 ;; Call the default action
                 (org-menu--with-arguments
                  ,complete-arglist
-                 (eval ,menu-default-actions-name)))
+                 (eval ,menu-default-action)))
                ((eq org-menu-system 'transient)
                 ;; Activate transient
                 (transient-setup
@@ -290,10 +285,10 @@        (defun ,menu-setup-children-name (_)
                  ,menu-actions
                  (list ,@(cl-mapcar (lambda (key value)
                                       `(list
-                                       ',(intern (concat "!" (symbol-name key)))
-                                       ,value))
-                                   complete-arglist
-                                   complete-arglist)))))))))
+                                        ',(intern (concat "!" (symbol-name key)))
+                                        ,value))
+                                    complete-arglist
+                                    complete-arglist)))))))))
 
 (provide 'om)
 ;;; om.el ends here
-- 
2.50.0

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

Reply via email to