emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Ihor Radchenko <yantar92@posteo.net>
To: gerard.vermeulen@posteo.net
Cc: Emacs orgmode <emacs-orgmode@gnu.org>
Subject: Re: [PATCH] org-babel-demarcate-block: split using org-element instead of  regexp
Date: Wed, 03 Jan 2024 15:11:06 +0000	[thread overview]
Message-ID: <87v88a78qd.fsf@localhost> (raw)
In-Reply-To: <e0252d664af25728243734d67432ad64@posteo.net>

[-- Attachment #1: Type: text/plain, Size: 1470 bytes --]

gerard.vermeulen@posteo.net writes:

> Attached you'll find a new patch trying to implement your suggestions.
> Interactive splitting by demarcation seems to work quite well (see the
> before and after splitting snippets in the PS).

Thanks!

> However, I cannot run the test because org-babel-demarcate-block
> always errors "org-element--cache: Emergency exit" while the same
> input works interactively. Could there be a problem of cache
> synchronization or something like that? Is there something I can do?

This was a bug in `org-element-copy'. Fixed, on main now.
https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=dfeff03c5

> I also did not yet look into how to propagate a switch like -n10.

-n10 is not a valid switch, AFAIK. We demand space: -n 10.
See 12.6 Literal Examples section of the manual.

I made some adjustments to the patch, making use of org-element API.
See the attached updated version of the patch.

I am not yet merging it as I found some weirdness with indentation.
Consider the following (indentation is important):

            #+BEGIN_SRC emacs-lisp -n 20
              ;; This exports with line number 20.
<point>       (message "This is line 21")
            #+END_SRC

After M-x org-babel-demarcate-block, I am getting

            #+BEGIN_SRC emacs-lisp -n 20
              ;; This exports with line number 20.
              #+END_SRC
              
#+begin_src emacs-lisp -n 20
  (message "This is line 21")
#+end_src


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-org-babel-demarcate-block-split-using-org-element-in.patch --]
[-- Type: text/x-patch, Size: 6409 bytes --]

From f5b9a6862cdb71ab33b7a291386221fff6648d53 Mon Sep 17 00:00:00 2001
Message-ID: <f5b9a6862cdb71ab33b7a291386221fff6648d53.1704294360.git.yantar92@posteo.net>
From: Gerard Vermeulen <gerard.vermeulen@posteo.net>
Date: Sat, 30 Dec 2023 19:25:25 +0100
Subject: [PATCH] org-babel-demarcate-block: split using org-element instead of
 regexp

* lisp/ob-babel.el (org-babel-demarcate-block): Delete the caption and
the name from a copy of (org-element-at-point) and set its value to
the body inside the source block after point.  Delete all superfluous
text after point from the current Emacs buffer and add a proper
sentinel to the upper source block.  Insert the lower block by
applying `org-element-interpret-data' to the modified copy.  Leave
point in a convenient position.
* testing/lisp/test-ob.el (test-ob/demarcate-block-split): New test
for block splitting by demarcation.  It checks also that the language,
switches, and header arguments are duplicated.
---
 lisp/ob-core.el         | 38 ++++++++++++++------------------------
 testing/lisp/test-ob.el | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index f7e4e255f..300747dae 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -73,6 +73,7 @@ (declare-function org-element-contents-end "org-element" (node))
 (declare-function org-element-parent "org-element-ast" (node))
 (declare-function org-element-type "org-element-ast" (node &optional anonymous))
 (declare-function org-element-type-p "org-element-ast" (node &optional types))
+(declare-function org-element-interpret-data "org-element" (data))
 (declare-function org-entry-get "org" (pom property &optional inherit literal-nil))
 (declare-function org-escape-code-in-region "org-src" (beg end))
 (declare-function org-forward-heading-same-level "org" (arg &optional invisible-ok))
@@ -2067,35 +2068,24 @@ (defun org-babel-demarcate-block (&optional arg)
 	 (start (org-babel-where-is-src-block-head))
          ;; `start' will be nil when within space lines after src block.
 	 (block (and start (match-string 0)))
-	 (headers (and start (match-string 4)))
 	 (stars (concat (make-string (or (org-current-level) 1) ?*) " "))
 	 (upper-case-p (and block
 			    (let (case-fold-search)
 			      (string-match-p "#\\+BEGIN_SRC" block)))))
     (if (and info start) ;; At src block, but not within blank lines after it.
-        (mapc
-         (lambda (place)
-           (save-excursion
-             (goto-char place)
-             (let ((lang (nth 0 info))
-                   (indent (make-string (org-current-text-indentation) ?\s)))
-	       (when (string-match "^[[:space:]]*$"
-                                   (buffer-substring (line-beginning-position)
-                                                     (line-end-position)))
-                 (delete-region (line-beginning-position) (line-end-position)))
-               (insert (concat
-		        (if (looking-at "^") "" "\n")
-		        indent (if upper-case-p "#+END_SRC\n" "#+end_src\n")
-		        (if arg stars indent) "\n"
-		        indent (if upper-case-p "#+BEGIN_SRC " "#+begin_src ")
-		        lang
-		        (if (> (length headers) 1)
-			    (concat " " headers) headers)
-		        (if (looking-at "[\n\r]")
-			    ""
-			  (concat "\n" (make-string (current-column) ? )))))))
-	   (move-end-of-line 2))
-         (sort (if (org-region-active-p) (list (mark) (point)) (list (point))) #'>))
+        (let* ((body-end (match-end 5))
+               (copy (org-element-copy (org-element-at-point)))
+               (end (org-element-end copy))
+               (indent (make-string (org-current-text-indentation) ?\s)))
+          (org-element-put-property copy :caption nil)
+          (org-element-put-property copy :name nil)
+          (org-element-put-property copy :value (buffer-substring (point) body-end))
+          (delete-region (point) end)
+          (insert (concat indent (if upper-case-p "#+END_SRC\n" "#+end_src\n")
+                          (if arg stars indent) "\n"))
+          (insert (org-element-interpret-data copy))
+          ;; Go back to the lower source block for `org-narrow-to-element':
+          (re-search-backward (rx bol (1+ nonl))))
       (let ((start (point))
 	    (lang (or (car info) ; Reuse language from previous block.
                       (completing-read
diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el
index 42c77ca56..e57edfa22 100644
--- a/testing/lisp/test-ob.el
+++ b/testing/lisp/test-ob.el
@@ -26,6 +26,41 @@ (require 'ob-ref)
 (require 'org-table)
 (eval-and-compile (require 'cl-lib))
 
+(ert-deftest test-ob/demarcate-block-split ()
+  "Test duplication of headers and switches in demarcation block splitting."
+  (org-test-with-temp-text "
+#+header: :var edge=\"also duplicated\"
+#+header: :wrap \"src any-spanish -n\"
+#+begin_src emacs-lisp -i -n :var here=\"duplicated\" :wrap \"src any-english -n\"
+
+'above-split
+<point>
+'below-split
+
+#+end_src
+"
+    (let ((wrap-val "src any-spanish -n") above below avars bvars)
+      (org-babel-demarcate-block)
+      (setq above (org-babel-get-src-block-info))
+      (setq avars (org-babel--get-vars (nth 2 above)))
+      (org-babel-next-src-block)
+      (setq below (org-babel-get-src-block-info))
+      (setq bvars (org-babel--get-vars (nth 2 below)))
+      ;; duplicated multi-line header arguments:
+      (should (string= "also duplicated" (cdr (assq 'edge avars))))
+      (should (string= "also duplicated" (cdr (assq 'edge bvars))))
+      (should (string= wrap-val (cdr (assq :wrap (nth 2 above)))))
+      (should (string= wrap-val (cdr (assq :wrap (nth 2 below)))))
+      ;; duplicated language, other header arguments, and switches:
+      (should (string= "emacs-lisp" (nth 0 above)))
+      (should (string= "emacs-lisp" (nth 0 below)))
+      (should (string= "'above-split" (org-trim (nth 1 above))))
+      (should (string= "'below-split" (org-trim (nth 1 below))))
+      (should (string= "duplicated" (cdr (assq 'here avars))))
+      (should (string= "duplicated" (cdr (assq 'here bvars))))
+      (should (string= "-i -n" (nth 3 above)))
+      (should (string= "-i -n" (nth 3 below))))))
+
 (ert-deftest test-ob/indented-cached-org-bracket-link ()
   "When the result of a source block is a cached indented link it
 should still return the link."
-- 
2.42.0


[-- Attachment #3: Type: text/plain, Size: 224 bytes --]


-- 
Ihor Radchenko // yantar92,
Org mode contributor,
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	other threads:[~2024-01-03 15:09 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-30 19:13 [PATCH] org-babel-demarcate-block: duplicate switches too gerard.vermeulen
2023-12-31 14:28 ` Ihor Radchenko
2024-01-01 12:52   ` gerard.vermeulen
2024-01-02 10:48     ` Ihor Radchenko
2024-01-02 20:20       ` [PATCH] org-babel-demarcate-block: split using org-element instead of regexp gerard.vermeulen
2024-01-03 15:11         ` Ihor Radchenko [this message]
2024-01-04  8:59           ` gerard.vermeulen
2024-01-04 14:43             ` Ihor Radchenko
2024-01-07 18:49               ` [PATCH] org-babel-demarcate-block: split using element API gerard.vermeulen
2024-01-08 12:08                 ` Ihor Radchenko
2024-01-08 20:25                   ` gerard.vermeulen
2024-01-09  7:49                     ` gerard.vermeulen
2024-01-09 10:50                       ` gerard.vermeulen
2024-01-09 14:49                         ` Ihor Radchenko
2024-01-13 14:04                           ` gerard.vermeulen
2024-01-13 15:17                             ` Ihor Radchenko
2024-01-13 20:16                               ` gerard.vermeulen
2024-01-14 10:53                                 ` gerard.vermeulen
2024-01-14 12:16                                   ` Ihor Radchenko
2024-01-14 19:18                                     ` gerard.vermeulen
2024-01-15  9:37                                       ` gerard.vermeulen
2024-01-16 13:34                                         ` Ihor Radchenko
2024-02-19  9:46                                           ` Ihor Radchenko
2024-02-19 13:01                                             ` gerard.vermeulen
2024-02-21  9:40                                               ` Ihor Radchenko
2024-02-21 18:19                                                 ` gerard.vermeulen
2024-02-22 16:28                                                   ` gerard.vermeulen
2024-02-23 13:43                                                     ` Ihor Radchenko
2024-02-25 12:06                                                       ` gerard.vermeulen
2024-02-25 12:21                                                         ` Ihor Radchenko
2024-02-26  8:51                                                           ` gerard.vermeulen
2024-02-28 11:54                                                             ` Ihor Radchenko
2024-02-29  9:50                                                               ` gerard.vermeulen
2024-02-29 11:56                                                                 ` Ihor Radchenko
2024-02-29 17:33                                                                   ` gerard.vermeulen
2024-03-03 13:08                                                                     ` Ihor Radchenko
2024-03-03 15:45                                                                       ` gerard.vermeulen
2024-03-04 10:12                                                                         ` Ihor Radchenko
2024-03-04 11:40                                                                           ` gerard.vermeulen
2024-03-04 11:51                                                                             ` Ihor Radchenko
2024-02-26  9:06                                                           ` gerard.vermeulen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87v88a78qd.fsf@localhost \
    --to=yantar92@posteo.net \
    --cc=emacs-orgmode@gnu.org \
    --cc=gerard.vermeulen@posteo.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).