Hello Rudy,

sorry for the long time it took.

I haven't created a patch yet but thought I would just send the code so you can 
have a look at it.
I have some comments inside which I would remove for the final patch.

I tried to keep it close to what you suggested (using rx, only have a single 
match function etc.) but I changed your code to some extend based on heavy 
testing and checking again how the plantuml cli converts the code into an image.

Main changes to your code are:
- I also handle code that doesn't contain @start... @end... (we fall back then 
to @startuml and @enduml, identical to how plantuml cli would handle the code)
- I changed the regex in some ways (I changed the greedy/non-greedy behavior a 
bit so it matches not the first @start... but the last @startuml... just in 
case someone has @start multiple times in the code - which of course never 
should happen but now we handle it like plantuml cli would handle it)
- I simplified the regex to some extend and use a backref so we assure we match 
exactly the same keyword type that has been found in the @start<KEYWORD-TYPE> 
regex

I tested it thoroughly and couldn't find any issues with this code.

Would appreciate your feedback but I believe it is quite clean.

If you like we could of course move the whole (rx ...) part directly into the 
(_ (string-match regex body)) part so we don't define a variable regex... but 
other than that I wouldn't change much.

Best
Tim


(defun org-babel-plantuml-make-body (body params)
  "..."
  (let* ((regex (rx
                 ;; 1️⃣  Anything before the block (captured)
                 (group (zero-or-more anything))        ; 1: pre-body

                 ;; 2️⃣  Start of the line that contains “@start…”
                 line-start
                 (zero-or-more blank)
                 "@start"
                 (group (one-or-more (not whitespace))) ; 2: start-keyword-type
                 (zero-or-more blank)
                 line-end
                 (zero-or-one whitespace)

                 ;; 3️⃣  The body that follows the @start line (captured)
                 (group (zero-or-more anychar))         ; 3: inner-body

                 ;; 4️⃣  Start of the line that contains “@end…”
                 line-start
                 (zero-or-more blank)
                 "@end"
                 (backref 2)                            ; repeat the tag name 
captured in #2
                 (zero-or-more blank)
                 line-end
                 (group (zero-or-more anything))))      ; 4: post-body
         (_ (string-match regex body))
         (pre-body      (string-trim (or (match-string 1 body) "")))
         (keyword-type  (or (match-string 2 body) "uml")) ; fallback (@startuml 
/ @enduml)
         (inner-body    (string-trim (or (match-string 3 body) body)))
         (post-body     (string-trim (or (match-string 4 body) ""))))

    (string-join
     (remove ""
             (list pre-body
                   (string-join (list "@start" keyword-type))
                   (org-babel-expand-body:generic
                    inner-body
                    params
                    (org-babel-variable-assignments:plantuml params))
                   (string-join (list "@end" keyword-type))
                   post-body))
     "\n")))



On 9 Oct 2025, at 12:09, Rudolf Adamkovič wrote:

> Tim Hansinger <[email protected]> writes:
>
>> Hello Rudy,
>
> Tim, hi!
>
>> please find here the latest patch.
>>
>> I tried to implement the changes request. This one is now simplified.
>
> The new patch is *much* simplified, to the point even I can read it. :)
>
> Better and better!
>
>> I think this is very clean. If you have anything to change please
>> provide me with complete alternative code. I hope however this one
>> works for you.
>
> It works but is still tiny bit too complex. :)
>
> Below, I include "complete alternative code" you asked for.
>
> - It matches the regular language of the input body *exactly once*.
> - It contains *exactly one* invocation of `org-babel-expand-body:...'.
> - It contains *exactly one* invocation of 
> `org-babel-variable-assignments:...'.
> - It uses `rx' for readability, as I am trying to learn it. :)
>
> Please test it thoroughly; I just tried it once. *ducks*
>
> P.S. We could also extract a `defcustom' for those default "@startuml"
> and "@enduml", e.g. `org-babel-plantuml-default-diagram-type' containing
> the string "uml".
>
> P.P.S. Great work, Tim!
>
> (defun org-babel-plantuml-make-body (body params)
>   "..."
>   (let ((match (string-match
>                 (rx (zero-or-more (or whitespace control))
>                     (group (minimal-match (zero-or-more anything)))
>                     line-start
>                     (zero-or-more blank)
>                     (group "@start" (group (one-or-more (any "a-zA-Z"))))
>                     (zero-or-more blank)
>                     line-end
>                     (group (zero-or-more anything))
>                     line-start
>                     (zero-or-more blank)
>                     (group "@end" (group (one-or-more (any "a-zA-Z"))))
>                     (zero-or-more blank)
>                     line-end
>                     (group (minimal-match (zero-or-more anything)))
>                     (zero-or-more (or whitespace control)))
>                 body)))
>     (pcase-let ((`(,pre-body
>                    ,start-keyword
>                    ,start-keyword-type
>                    ,inner-body
>                    ,end-keyword
>                    ,end-keyword-type
>                    ,post-body)
>                  (mapcar (lambda (group)
>                            (if match (match-string group body)))
>                          (number-sequence 1 7))))
>       (unless (string= start-keyword-type end-keyword-type)
>         (user-error "Incompatible PlantUML start/end keywords: %s, %s"
>                     start-keyword end-keyword))
>       (string-join
>        (remove "" (list (or pre-body "")
>                         (or start-keyword "@startuml")
>                         (org-babel-expand-body:generic
>                          (or inner-body body)
>                          params
>                          (org-babel-variable-assignments:plantuml params))
>                         (or end-keyword "@enduml")
>                         (or post-body "")))
>        "\n"))))
>
> Rudy
> --
> "All of humanity's problems stem from man's inability to sit quietly in
> a room alone."  --- Blaise Pascal, Pensées, 1670
>
> Rudolf Adamkovič <[email protected]> [he/him]
> http://adamkovic.org


Reply via email to