Re: [PATCH] org-babel-demarcate-block: split using org-element instead of regexp

2024-01-04 Thread Ihor Radchenko
gerard.vermeu...@posteo.net writes:

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

Thanks! See my comments inline.

> I have tried to clean up the code.  I have also tried to get `body-beg' 
> and
> `body-end' marking the text between the #+begin_src and #+end_src lines
> from the element API, but I failed and had to fall back to
> `org-babel-where-is-src-block-head'.  But only for that.

org-element API does not provide this information for now. Maybe it is a
good opportunity to alter the parser, so that code boundaries are
provided... 

>  (defun org-babel-demarcate-block ( arg)
> ...
> -When called within blank lines after a code block, create a new code
> -block of the same language with the previous."

Is there any reason why you dropped this feature?

When I try

#+begin_src emacs-lisp
(+ 1 2)
#+end_src


M-x org-babel-demacrate-block throws an error with your patch.
It creates a new block with the same language before your patch.

> +  (let ((copy (org-element-copy (org-element-at-point)))
> +(stars (concat (make-string (or (org-current-level) 1) ?*) " ")))
> +(if (eq 'src-block (car copy))

You can instead use `org-element-type-p'

> +;; Keep this branch in sync with test-ob/demarcate-block-split.
> +;; _start is never nil, since there is a source block element at 
> point.

May you elaborate what you mean by "keep in sync"?

> +(let* ((_start (org-babel-where-is-src-block-head))

Are you using (org-babel-where-is-src-block-head) for side effect of
modifying the match data? If so, please do it outside let, with
appropriate comment.

> +  (if (not org-adapt-indentation)
> +  ;; Move point to the left of the lower block line #+begin_src.
> +  (org-previous-block 1)
> +;; Adapt the indentation: upper block first and lower block 
> second.
> +(org-previous-block 2)
> +(org-indent-block)
> +;; Move point to the left of the lower block line #+begin_src.
> +(org-next-block 1)
> +(org-indent-block)))

`org-indent-block' should honor `org-adapt-indentation'. You do not need
to call it conditionally. Re-indenting unconditionally should be better
here.

>(let ((start (point))
> - (lang (or (car info) ; Reuse language from previous block.
> -  (completing-read
> -"Lang: "
> -(mapcar #'symbol-name
> -(delete-dups
> - (append (mapcar #'car org-babel-load-languages)
> - (mapcar (lambda (el) (intern (car el)))
> - org-src-lang-modes)))
> +;; (org-babel-get-src-block-info 'no-eval) returns nil,
> +;; since there is no source block at point.  Therefore, this
> +;; cannot be used to get the language of a neighbour block.

Why nil? The condition was

  (and info start) ;; At src block, but not within blank lines after it.

So, this branch of the if used to be INFO - non-nil, and START nil ->
re-use the information. And if INFO were nil, query.

> +;; Deleted code indicated that this may have worked in the past.
> +;; I have removed upper-case-p, since it could never be true 
> here.

The idea of UPPER-CASE-P is to keep user preference for keyword style
(upper case or lower case). There is no reason to remove this feature.
Although, since we are using `org-element-interpret-data', it might be a
good idea to extend org-element parser to preserve the keyword case
information.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at .
Support Org development at ,
or support my work at 



Re: [PATCH] org-babel-demarcate-block: split using org-element instead of regexp

2024-01-04 Thread gerard . vermeulen



On 03.01.2024 16:11, Ihor Radchenko wrote:

gerard.vermeu...@posteo.net writes:


[...]
Attached you'll find a new patch that seems to solve the block 
indentation

problem that you have pointed out, see PS or attached patch-demo.org.

test-ob/demarcate-block-split passes.


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 did not yet pull your change.  Nevertheless, the Emergency exit errors
have disappeared.



[...]


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

This patch is heavily edited and I think I did not forget any of your 
changes.


I have tried to clean up the code.  I have also tried to get `body-beg' 
and

`body-end' marking the text between the #+begin_src and #+end_src lines
from the element API, but I failed and had to fall back to
`org-babel-where-is-src-block-head'.  But only for that.


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.
   (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

See PS or patch-demo.org: PS (hope you read it with a mono-spaced font):
#+begin_src emacs-lisp :results silent
  (setopt org-adapt-indentation t
  org-src-preserve-indentation nil
  org-edit-src-content-indentation 2)
#+end_src

 before C-u org-babel-demarcate-block splitting

 I put point at the left of the last line in this block before 
splitting

 #+BEGIN_SRC emacs-lisp -n 20
   ;; this exports with line number 20
(message "This exports with line number 21")
 #+END_SRC
 C-u C-c C-v d gets the stars right and the indentation

 after C-u org-babel-demarcate-block splitting

 I put point at the left of the last line in this block before 
splitting

 #+begin_src emacs-lisp -n 20
   ;; this exports with line number 20
 #+end_src

 #+begin_src emacs-lisp -n 20
   (message "This exports with line number 21")
 #+end_src
 C-u C-c C-v d gets the stars right and the indentation



0001-org-babel-demarcate-block-split-using-org-element-in.patch
Description: Binary data


patch-demo.org
Description: Binary data


Re: [PATCH] org-babel-demarcate-block: split using org-element instead of regexp

2024-01-03 Thread Ihor Radchenko
gerard.vermeu...@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.
   (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

>From f5b9a6862cdb71ab33b7a291386221fff6648d53 Mon Sep 17 00:00:00 2001
Message-ID: 
From: Gerard Vermeulen 
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  anonymous))
 (declare-function org-element-type-p "org-element-ast" (node  types))
+(declare-function org-element-interpret-data "org-element" (data))
 (declare-function org-entry-get "org" (pom property  inherit literal-nil))
 (declare-function org-escape-code-in-region "org-src" (beg end))
 (declare-function org-forward-heading-same-level "org" (arg  invisible-ok))
@@ -2067,35 +2068,24 @@ (defun org-babel-demarcate-block ( 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 

Re: [PATCH] org-babel-demarcate-block: split using org-element instead of regexp

2024-01-02 Thread gerard . vermeulen



On 02.01.2024 11:48, Ihor Radchenko wrote:

gerard.vermeu...@posteo.net writes:


[...]


IMHO, this is a bug.
The current approach with regexp matching in 
`org-babel-demarcate-block'

is clearly not accurate. What would be more robust is using
org-element-at-point + org-element-copy + set :value +
org-element-interpret-data to carry over all the affiliated keywords 
and

header arguments.


[...]


(org-babel--get-vars (nth 2 (org-babel-get-src-block-info)))


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).

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?

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

PS:
# begin before splitting snippet
#+caption[Demarcation splitting test]:
#+caption: Demarcation splitting test.
#+header: :var edge="also copied"
#+header: :wrap "src any-spanish -n"
#+name: lst:test
#+begin_src python -i -n :var here="copied" :wrap "src any-english -n"

# above-split

# below-split

#+end_src
# end before splitting snippet

# begin after splitting snippet
#+caption[Demarcation splitting test]:
#+caption: Demarcation splitting test.
#+header: :var edge="also copied"
#+header: :wrap "src any-spanish -n"
#+name: lst:test
#+begin_src python -i -n :var here="copied" :wrap "src any-english -n"

# above-split
#+end_src

#+header: :var edge="also copied"
#+header: :wrap "src any-spanish -n"
#+begin_src python -i -n :var here="copied" :wrap "src any-english -n"

# below-split
#+end_src
# end after splitting snippet


0001-org-babel-demarcate-block-split-using-org-element-in.patch
Description: Binary data