emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Startup option to separate macros arguments with an alternat


From: Juan Manuel Macías
Subject: Re: [PATCH] Startup option to separate macros arguments with an alternative string
Date: Wed, 21 Apr 2021 16:01:35 +0000

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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]