[-- Attachment #1: Type: text/plain, Size: 1065 bytes --] Hi, I would like to propose this (possible) patch. With `#+STARTUP: macro-arg-sep-other' the macros arguments can be separated by a string other than comma, whose value is defined in `org-macro-arg-sep-other' (by default it is "'@"). Rationale for this patch: There are many contexts where the comma character can be inappropriate as an argument separator, since it has to be escaped many times. If the patch is relevant, I can take care of writing the documentation and docstrings. Example: #+begin_src org ,#+STARTUP: macro-arg-sep-other ,#+MACRO: lg (eval (if (org-export-derived-backend-p org-export-current-backend 'latex) (concat "@@latex:\\foreignlanguage{@@" $1 "@@latex:}{@@" "\u200B" $2 "\u200B" "@@latex:}@@") $2)) {{{lg(latin'@Lorem ipsum dolor sit amet, consectetuer adipiscing elit, donec hendrerit tempor tellus, donec pretium posuere tellus, proin quam nisl, tincidunt et, mattis eget, convallis nec, purus.)}}} With the escaped character: {{{lg(latin'@Lorem ipsum dolor sit amet \'@)}}} #+end_src Best regards, Juan Manuel [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: org-macro-arg-sep.patch --] [-- Type: text/x-patch, Size: 2302 bytes --] diff --git a/lisp/org-macro.el b/lisp/org-macro.el index f914a33d6..311eaf9a5 100644 --- a/lisp/org-macro.el +++ b/lisp/org-macro.el @@ -82,6 +82,8 @@ directly, use instead: #+MACRO: name template") +(defvar org-macro-arg-sep-other "'@") + ;;; Functions (defun org-macro--set-template (name value templates) @@ -277,15 +279,19 @@ Return a list of arguments, as strings. This is the opposite of `org-macro-escape-arguments'." ;; Do not use `org-split-string' since empty strings are ;; meaningful here. + (let ((sep (cond ((eq org-startup-macro-arg-sep 'comma) + ",") + ((eq org-startup-macro-arg-sep 'other) + org-macro-arg-sep-other)))) (split-string (replace-regexp-in-string - "\\(\\\\*\\)," + (format "\\(\\\\*\\)%s" sep) (lambda (str) (let ((len (length (match-string 1 str)))) (concat (make-string (/ len 2) ?\\) - (if (zerop (mod len 2)) "\000" ",")))) + (if (zerop (mod len 2)) "\000" (format "%s" sep))))) s nil t) - "\000")) + "\000"))) \f ;;; Helper functions and variables for internal macros diff --git a/lisp/org.el b/lisp/org.el index 7d8733448..a51893ed3 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -974,6 +974,15 @@ case it is too late to set the variable `org-startup-truncated'." :group 'org-startup :type 'boolean) +(defcustom org-startup-macro-arg-sep 'comma + "TODO" + :group 'org-startup + :package-version '(Org . "9.0") + :version "26.1" + :type '(choice + (const :tag "comma" comma) + (const :tag "other" other))) + (defcustom org-startup-indented nil "Non-nil means turn on `org-indent-mode' on startup. This can also be configured on a per-file basis by adding one of @@ -4187,7 +4196,8 @@ After a match, the following groups carry important information: ("nohideblocks" org-hide-block-startup nil) ("beamer" org-startup-with-beamer-mode t) ("entitiespretty" org-pretty-entities t) - ("entitiesplain" org-pretty-entities nil)) + ("entitiesplain" org-pretty-entities nil) + ("macro-arg-sep-other" org-startup-macro-arg-sep other)) "Variable associated with STARTUP options for Org. Each element is a list of three items: the startup options (as written in the #+STARTUP line), the corresponding variable, and the value to set
Hello, Juan Manuel Macías <maciaschain@posteo.net> writes: > I would like to propose this (possible) patch. > > With `#+STARTUP: macro-arg-sep-other' the macros arguments can be > separated by a string other than comma, whose value is defined in > `org-macro-arg-sep-other' (by default it is "'@"). Even though Org syntax partly is, I don't think parameterizable syntax is a way to go. I'd rather have less variables controlling it. (I'm looking at you `org-list-allow-alphabetical', and `org-plain-list-ordered-item-terminator'.) That being said, we can discuss syntax that is not depending upon some variable. For example macro names are written with a limited set of characters (alphanumeric, dash, underscore). We might allow the optional argument separator to be located right before the opening parenthesis, e.g., {{{macroname@(latin@Lorem ipsum dolor sit amet, ...)}}} {{{macroname|(latin|Lorem ipsum dolor sit amet, ...)}}} But see below. > Rationale for this patch: There are many contexts where the comma character can be > inappropriate as an argument separator, since it has to be escaped > many times. That's true. But I wonder if you're hitting a limit of replacement macros use case. IMO, macros are good for short text. For bigger ones, you may want to use some Babel code, in the language of your choice. WDYT? Regards, -- Nicolas Goaziou
Hi Nicolas Nicolas Goaziou writes: > Even though Org syntax partly is, I don't think parameterizable syntax > is a way to go. I'd rather have less variables controlling it. (I'm > looking at you `org-list-allow-alphabetical', and > `org-plain-list-ordered-item-terminator'.) Thanks for your explanations. I understand that the use of variables here is perhaps not the happiest solution. Naturally, I speak of 'solution' assuming there is a 'problem', the choice of the comma as an argument separator; but I also assume that what is a problem for me, it doesn't have to be for other users, as here everything is subjective. Anyway, I couldn't think of another way to respect the original comma (and backward compatibility), but leaving the user some freedom to choose a different separator. I also understand that implementing that can lead to confusion. >> Rationale for this patch: There are many contexts where the comma character can be >> inappropriate as an argument separator, since it has to be escaped >> many times. > > That's true. But I wonder if you're hitting a limit of replacement > macros use case. IMO, macros are good for short text. For bigger ones, > you may want to use some Babel code, in the language of your choice. > WDYT? I think replacement macros have huge potential, that I often explore in my daily work and (I admit) wearing the things to the limit, which means struggling with resistance to the material ;-) Perhaps that emerging potential was not originally foreseen ... Of course, the scenario is always in short texts, I agree. But even in those scenarios, the comma as an argument separator is somewhat uncomfortable and confusing. That is, macros have great potential (IMHO) in contrast to an "ugly" syntax. But at this point it has a difficult solution... A typical use case for macros (for me) can be to export to LaTeX with the command \foreignlanguage{lang}{short text} in multilingual documents (see this screenshot: https://gnutas.juanmanuelmacias.com/images/macros-sample.png). I can't think of another way to do (easily) something like that (with the plus of being able to evaluate some Elisp in there and add a conditional for the backend, etc.). Best regards, Juan Manuel
Hello again.
I forgot to answer this question on your previous message, sorry...
Nicolas Goaziou writes:
> That being said, we can discuss syntax that is not depending upon some
> variable. For example macro names are written with a limited set of
> characters (alphanumeric, dash, underscore). We might allow the optional
> argument separator to be located right before the opening parenthesis,
> e.g.,
>
> {{{macroname@(latin@Lorem ipsum dolor sit amet, ...)}}}
> {{{macroname|(latin|Lorem ipsum dolor sit amet, ...)}}}
I think it's a very interesting idea. I've made this sketch (at least
as a proof of concept), what do you think of the approach?
Example (and code below):
#+macro: foo (eval (format "%s and %s" $1 $2))
{{{foo(xxx,zzz\, yyy)}}}
{{{foo|(xxx|zzz, aaa)}}}
{{{foo@(xxx@zzz, sss)}}}
{{{foo|(xxx|zzz\| aaa)}}}
{{{foo@(xxx@zzz\@ sss)}}}
#+begin_src emacs-lisp
(defun org-macro-extract-arguments (sep s)
"Extract macro arguments from string S.
S is a string containing comma separated values properly escaped.
Return a list of arguments, as strings. This is the opposite of
`org-macro-escape-arguments'."
;; Do not use `org-split-string' since empty strings are
;; meaningful here.
(split-string
(replace-regexp-in-string
(format "\\(\\\\*\\)%s" sep)
(lambda (str)
(let ((len (length (match-string 1 str))))
(concat (make-string (/ len 2) ?\\)
(if (zerop (mod len 2)) "\000" (format "%s" sep)))))
s nil t)
"\000"))
(defun org-element-macro-parser ()
"Parse macro at point, if any.
When at a macro, return a list whose car is `macro' and cdr
a plist with `:key', `:args', `:begin', `:end', `:value' and
`:post-blank' as keywords. Otherwise, return nil.
Assume point is at the macro."
(save-excursion
(when (looking-at "{{{\\([a-zA-Z][-a-zA-Z0-9_]*\\)\\([^a-zA-Z]*[^-a-zA-Z0-9_]*\\)\\((\\([^\000]*?\\))\\)?}}}")
(let ((begin (point))
(key (downcase (match-string-no-properties 1)))
(value (match-string-no-properties 0))
(post-blank (progn (goto-char (match-end 0))
(skip-chars-forward " \t")))
(end (point))
(args (pcase (match-string-no-properties 4)
(`nil nil)
(a (org-macro-extract-arguments
(if (not (equal (match-string-no-properties 2) ""))
(match-string-no-properties 2)
",")
(replace-regexp-in-string
"[ \t\r\n]+" " " (org-trim a)))))))
(list 'macro
(list :key key
:value value
:args args
:begin begin
:end end
:post-blank post-blank))))))
(defun org-macro-extract-arguments (sep s)
"Extract macro arguments from string S.
S is a string containing comma separated values properly escaped.
Return a list of arguments, as strings. This is the opposite of
`org-macro-escape-arguments'."
;; Do not use `org-split-string' since empty strings are
;; meaningful here.
(split-string
(replace-regexp-in-string
(format "\\(\\\\*\\)%s" sep)
(lambda (str)
(let ((len (length (match-string 1 str))))
(concat (make-string (/ len 2) ?\\)
(if (zerop (mod len 2)) "\000" (format "%s" sep)))))
s nil t)
"\000"))
#+end_src
Hello, Juan Manuel Macías <maciaschain@posteo.net> writes: > I think it's a very interesting idea. I've made this sketch (at least > as a proof of concept), what do you think of the approach? I think there are a few things to fix. For example, the separator may need to be stored in the properties of the macro. Otherwise, interpreting data back would return to comma-separated arguments, which may not be desirable, although correct. Also, I would limit separator to a single character. You also need to exclude space characters. > Example (and code below): > > #+macro: foo (eval (format "%s and %s" $1 $2)) > > {{{foo(xxx,zzz\, yyy)}}} > > {{{foo|(xxx|zzz, aaa)}}} > > {{{foo@(xxx@zzz, sss)}}} > > {{{foo|(xxx|zzz\| aaa)}}} > > {{{foo@(xxx@zzz\@ sss)}}} This change will need to be tested extensively in "test-org-element.el" and "test-org-macro.el". However, as a start, I suggest starting a new thread about a suggested change in the syntax, with a clear title, examples, and code. Then we can leave time for users to react to it. Do you want to take care of it? Regards, -- Nicolas Goaziou
Hi Nicolas,
Thank you very much for your suggestions.
Nicolas Goaziou writes:
> This change will need to be tested extensively in "test-org-element.el"
> and "test-org-macro.el".
>
> However, as a start, I suggest starting a new thread about a suggested
> change in the syntax, with a clear title, examples, and code. Then we
> can leave time for users to react to it.
>
> Do you want to take care of it?
Ok, I agree. Next week I will start a new thread for submit this new
proposal.
Best regards,
Juan Manuel
As you have said you'll start a new thread for your revised proposal,
I'll mark this as closed on updates.orgmode.org via the X-Woof-Patch
header.
Juan Manuel Macías <maciaschain@posteo.net> writes:
> Ok, I agree. Next week I will start a new thread for submit this new
> proposal.
>
> Best regards,
>
> Juan Manuel