Re: [Pre-PATCH v2] Add the capability to specify lexical scope in tangled files (was: Add new :lexical header argument)

2023-08-27 Thread Evgenii Klimov
Hi Ihor

On August 23, 2023 12:44:32 PM GMT+01:00, Ihor Radchenko  
wrote:
>Ihor Radchenko  writes:
>
>> What about generalizing the idea and providing a way to set Emacs
>> buffer-local variables in the tangled files?
>>
>> Can be something like:
>>
>> #+begin_src elisp :file-locals (lexical-binding t eval (line-number-mode))
>
>Over one month have passed since the last message in this thread.
>
>Evgenii, are you still interested to continue working on this?
>

I am busy for the next month and even after that generalizing the idea would 
take too much effort and time, since I'm not an advanced programmer. So 
probably the answer is no.



Re: [FR] Add an option to use ID links during tangling

2023-07-28 Thread Evgenii Klimov


Ihor Radchenko  writes:

> Evgenii Klimov  writes:
>
>> I see in the comment there the reason for that, but still would prefer
>> to use unique IDs in tangled files: the probability to overwrite wrong
>> source block under nonunique header overweights a side-effect of
>> creating new ID in Org file during tangling.
>
> Did you actually encounter such situation?
> `org-babel-detangle' is far from ideal in general.
> For example, detangling noweb references is pretty much guaranteed to
> create mess.

Yes, I did.  I keep my whole emacs configuration in an Org file and
tangle it after adjustments at Emacs startup (~org-babel-load-file~).
Recently I decided to split the tangled file and learned about
detangling.

And I have a lot of similar headers since my Org file looks like this:

#+begin_example
* package 1
** basic
** custom functions
** custom bindings
* package 2
** basic
** custom functions
** custom bindings
#+end_example

>> Can we do something with this?  Add another option or provide an even
>> eager value in =org-id-link-to-org-use-id=.
>
> I do not like the idea of creating side effects in the original Org
> document during tangling.
> We can, however, use (org-id-link-to-org-use-id 'use-existing) to use
> the already present IDs.

Understandable, with (org-id-link-to-org-use-id 'use-existing) I would
at least be able to manually add them where needed.

> Ideally, we should improve the detangling to understand the order of
> blocks better instead of searching the containing heading independently.

Maybe recent feature suggestion [1] will be of use here.

[1] 
https://list.orgmode.org/118435e8-0b20-46fd-af6a-88de8e19f...@app.fastmail.com



[FR] Add an option to use ID links during tangling

2023-07-27 Thread Evgenii Klimov
Hi, I noticed that links created during tangling back to the original
Org file doesn't respect custom =org-id-link-to-org-use-id= option in
~org-babel-tangle--unbracketed-link~.

I see in the comment there the reason for that, but still would prefer
to use unique IDs in tangled files: the probability to overwrite wrong
source block under nonunique header overweights a side-effect of
creating new ID in Org file during tangling.

Can we do something with this?  Add another option or provide an even
eager value in =org-id-link-to-org-use-id=.



[PATCH v5] ob-tangle.el: Blocks overwrite each other when grouping before tangling

2023-07-26 Thread Evgenii Klimov

Ihor Radchenko  writes:

>> +(ert-deftest ob-tangle/collect-blocks ()
>> +  "Test block collection into groups for tangling."
>> +  (org-test-with-temp-text-in-file
>> +  "* H1 with :tangle in properties
>> +:PROPERTIES:
>> +:header-args: :tangle relative.el
>> +:END:
>> 
>> +  ;; to the first header
>> +  (insert (format "#+begin_src emacs-lisp :tangle %s
>> +\"H1: absolute org-file.lang-ext :tangle %s\"
>> +#+end_src" el-file-abs el-file-abs))
>> +  (goto-char (point-max))
>
> This combination of pre-filled text and insertions is a bit
> disorienting. I understand why you need to insert some things only after
> we know the temporary Org file name, but I'd instead placed all the
> contents together via insert.

Rewrote.

>> +#+begin_src emacs-lisp :tangle %s
>> +\"H2: relative org-file.lang-ext :tangle %s\"
>> +#+end_src" el-file-rel el-file-rel))
>> +  (should (equal (funcall expected-targets-fn 4)
>> + (funcall collected-targets-fn 
>> (org-babel-tangle-collect-blocks
>
> When reading this code, I have no idea what it is trying to test.
> Probably something to do with function names not being descriptive.
> At least, a comment would help.
>
> And the magic numbers "4" and "5" have no obvious meaning.

Hope new version is cleaner.

>From f1bf00592b1ee2bb27148fe93316cc6c1a192179 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Fri, 21 Jul 2023 22:40:06 +0100
Subject: [PATCH v5 1/2] testing/lisp/test-ob-tangle.el: Test block collection
 into groups for tangling

* testing/lisp/test-ob-tangle.el (ob-tangle/collect-blocks): Test
block collection into groups for tangling.
---
 testing/lisp/test-ob-tangle.el | 116 +
 1 file changed, 116 insertions(+)

diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el
index 07e75f4d3..ad0e1c29c 100644
--- a/testing/lisp/test-ob-tangle.el
+++ b/testing/lisp/test-ob-tangle.el
@@ -569,6 +569,122 @@ another block
 (set-buffer-modified-p nil))
   (kill-buffer buffer
 
+(ert-deftest ob-tangle/collect-blocks ()
+  "Test block collection into groups for tangling."
+  (org-test-with-temp-text-in-file "" ; filled below, it depends on temp file name
+(let* ((org-file (buffer-file-name))
+   (test-dir (file-name-directory org-file))
+   (el-file-abs (concat (file-name-sans-extension org-file) ".el"))
+   (el-file-rel (file-name-nondirectory el-file-abs)))
+  (insert (format "* H1 with :tangle in properties
+:PROPERTIES:
+:header-args: :tangle relative.el
+:END:
+
+#+begin_src emacs-lisp
+\"H1: inherited :tangle relative.el in properties\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle yes
+\"H1: :tangle yes\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle no
+\"H1: should be ignored\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle %s
+\"H1: absolute org-file.lang-ext :tangle %s\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle relative.el
+\"H1: :tangle relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ./relative.el
+\"H1: :tangle ./relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle /tmp/absolute.el
+\"H1: :tangle /tmp/absolute.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el
+\"H1: :tangle ~/../../tmp/absolute.el\"
+#+end_src
+
+* H2 without :tangle in properties
+
+#+begin_src emacs-lisp
+\"H2: without :tangle\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle yes
+\"H2: :tangle yes\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle no
+\"H2: should be ignored\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle %s
+\"H2: relative org-file.lang-ext :tangle %s\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle relative.el
+\"H2: :tangle relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ./relative.el
+\"H2: :tangle ./relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle /tmp/absolute.el
+\"H2: :tangle /tmp/absolute.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el
+\"H2: :tangle ~/../../tmp/absolute.el\"
+#+end_src" el-file-abs el-file-abs el-file-rel el-file-rel))
+  (letrec ((sort-fn (lambda (lst) (seq-sort-by #'car #'string-lessp lst)))
+   (normalize-expected-targets-alist
+(lambda (blocks-per-target-alist)
+  "Convert to absolute file names and sort expected targets"
+  (funcall sort-fn
+   (map-apply (lambda (file nblocks)
+(cons (expand-file-name file test-dir) nblocks))
+  blocks-per-targe

[PATCH v4] ob-tangle.el: Blocks overwrite each other when grouping before tangling

2023-07-25 Thread Evgenii Klimov

Ihor Radchenko  writes:

[...]
> Thanks!
> The second patch is malformed. May you please resend?

Sorry, resend with rewritten test.

[...]
> If you can, please avoid using `org-test-at-id'. This is much less
> readable compared to explicit org-test-with-temp-text because one needs
> to reach out to another file in order to understand what the test is
> about.

Now it's less verbose, handles both cases
(with and without TARGET-FILE) and prints detailed ert explanation.

> Evgenii Klimov  writes:
[...]
>> It wasn't clear for me: will ":tangle yes" or explicit ":tangle no" be
>> affected by TARGET-FILE.  Maybe if we rephrase as follows it will be
>> clear for both of us:
>>
>> Optional argument TARGET-FILE can be used to overwrite a default
>> export file in `org-babel-default-header-args' for all source
>> blocks.
>
> In `org-babel-tangle', TARGET-FILE is set as fallback value for the
> blocks that have no :tangle value at all, including inherited; including
> :tangle yes.

This exactly idea I wanted to add to the docstring.

> The manual asserts
>
> ‘yes’
>  Export the code block to source file.  The file name for the source
>  file is derived from the name of the Org file, and the file
>  extension is derived from the source code language identifier.
>  Example: ‘:tangle yes’.
>
> So, "yes" should imply :tangle 
>
> `org-babel-tangle-collect-blocks' handles this by
>
> (unless (or (string= src-tfile "no")
> (and tangle-file (not (equal tangle-file src-tfile)))
> (and lang-re (not (string-match-p lang-re src-lang
>
> So, :tangle no is always excluded.
> When TANGLE-FILE is set and not equal to :tangle value (including
> "yes"), block is also excluded.

Indeed, but later

   ‘no’
The *default*.  Do not extract the code in a source code file.
Example: ‘:tangle no’.

in conjunction with TARGET-FILE's description in ~org-babel-tangle~
docstring:

   Optional argument TARGET-FILE can be used to specify a *default*
   export file for all source blocks.

made me feel doubt about TARGET-FILE's effect.

Anyway, probably it was my incorrect interpretation, so let's leave it
as it is.
>From a5b4faec9b58b8e56512c03e4f1a1fe295900d3f Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Fri, 21 Jul 2023 22:40:06 +0100
Subject: [PATCH v4 1/2] testing/lisp/test-ob-tangle.el: Test block collection
 into groups for tangling

* testing/lisp/test-ob-tangle.el (ob-tangle/collect-blocks): Test
block collection into groups for tangling.
---
 testing/lisp/test-ob-tangle.el | 111 +
 1 file changed, 111 insertions(+)

diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el
index 07e75f4d3..55e1f7aa3 100644
--- a/testing/lisp/test-ob-tangle.el
+++ b/testing/lisp/test-ob-tangle.el
@@ -569,6 +569,117 @@ another block
 (set-buffer-modified-p nil))
   (kill-buffer buffer
 
+(ert-deftest ob-tangle/collect-blocks ()
+  "Test block collection into groups for tangling."
+  (org-test-with-temp-text-in-file
+  "* H1 with :tangle in properties
+:PROPERTIES:
+:header-args: :tangle relative.el
+:END:
+
+#+begin_src emacs-lisp
+\"H1: inherited :tangle relative.el in properties\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle yes
+\"H1: :tangle yes\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle no
+\"H1: should be ignored\"
+#+end_src
+
+
+
+#+begin_src emacs-lisp :tangle relative.el
+\"H1: :tangle relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ./relative.el
+\"H1: :tangle ./relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle /tmp/absolute.el
+\"H1: :tangle /tmp/absolute.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el
+\"H1: :tangle ~/../../tmp/absolute.el\"
+#+end_src
+
+* H2 without :tangle in properties
+
+#+begin_src emacs-lisp
+\"H2: without :tangle\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle yes
+\"H2: :tangle yes\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle no
+\"H2: should be ignored\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle relative.el
+\"H2: :tangle relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ./relative.el
+\"H2: :tangle ./relative.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle /tmp/absolute.el
+\"H2: :tangle /tmp/absolute.el\"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ~/../../tmp/absolute.el
+\"H2: :tangle ~/../../tmp/absolute.el\"
+#+end_src
+"
+(letrec ((org-file (buffer-file-name))
+ (test-dir (file-name-directory org-file))
+ (el-file-abs (concat (file-name-sans-extension org-file) ".el"))
+   

[PATCH v3] ob-tangle.el: Blocks overwrite each other when grouping before tangling

2023-07-24 Thread Evgenii Klimov

Hi

Here are the new tests that demonstrate the bug in block grouping during
block collection, along with the patch to address the issue, taking your
previous remarks into account.

I split it into two patches so you can apply the tests first to see the
bug.  And probably tests should be rewritten as they look too complex
and mostly duplicate each other.  I'd appreciate your suggestions
on how to enhance them.

Ihor Radchenko  writes:

> Evgenii Klimov  writes:
>
>> In this version I just updated the docstrings for the relevant
>> functions, because prior to that it wasn't clear: does this "default
>> export file for *all* source blocks" influence blocks with :tangle
>> "yes"/FILENAME?
>
> Thanks for the patch, but we need to be careful changing things in
> ob-tangle. Not everything is well-documented there.
>
>>  Optional argument TARGET-FILE can be used to specify a default
>> -export file for all source blocks.
>> +export file for all source blocks without :tangle header
>> +argument.
>
> This is confusing.
> Is :tangle yes "without"?
> What about inheritance?
> What about default header args?

I just find current lack of details confusing as well and want to
express the place of TARGET-FILE in the lineage of :tangle in
~org-babel-get-src-block-info~:
1. org-babel-default-header-args
   1. TANGLE-FILE of ~org-babel-tangle~
2. org-babel-default-header-args:
3. org-babel-params-from-properties
4. org-element-property :parameters datum
5. org-element-property :header datum

It wasn't clear for me: will ":tangle yes" or explicit ":tangle no" be
affected by TARGET-FILE.  Maybe if we rephrase as follows it will be
clear for both of us:

Optional argument TARGET-FILE can be used to overwrite a default
export file in `org-babel-default-header-args' for all source
blocks.

> What if we have :tangle "/path/to/foo" and TARGET-FILE = "/path/to/foo"?
> What if they are :tangle "./foo" and TARGET-FILE = "/full/path/to/foo"?

See the new tests in the patch, I tried to take it into account.

>>  (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile)
>> -  "Return effective tangled filename of a source-code block.
>> +  "Return effective tangled absolute filename of a source-code block.
>
> This will likely cause breakage.
> There are two callers of `org-babel-effective-tangled-filename:
> 1. `org-babel-tangle-collect-blocks'
> 2. `org-babel-tangle-single-block'
>
> `org-babel-tangle-single-block' passes (nth 1 result) as BUFFER-FN.
> Its value is
>
> (if org-babel-tangle-use-relative-file-links
>   (file-relative-name file)
> file)
>
> So,
>
>> +  (let* ((fnd (file-name-directory (buffer-file-name
>> +(get-buffer buffer-fn
>
> will fail when FILE contains file path.
> And it does: (file (buffer-file-name (buffer-base-buffer)))

Thanks, fixed: both `org-babel-tangle-single-block' and
`org-babel-tangle-collect-blocks' now pass absolute value to
`org-babel-effective-tangled-filename'.

>From 7235bf0306d12f6644838ad8542ac8822bcde258 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Fri, 21 Jul 2023 22:40:06 +0100
Subject: [PATCH v3 1/2] testing/lisp/test-ob-tangle.el: Test block collection
 into groups for tangling

* testing/lisp/test-ob-tangle.el (ob-tangle/collect-blocks): Test
block collection into groups for tangling.
(ob-tangle/collect-blocks-with-target-file): The same but with
TARGET-FILE.
---
 testing/examples/babel.org | 75 ++
 testing/lisp/test-ob-tangle.el | 60 +++
 2 files changed, 135 insertions(+)

diff --git a/testing/examples/babel.org b/testing/examples/babel.org
index d46afeb5e..2d7b39d4e 100644
--- a/testing/examples/babel.org
+++ b/testing/examples/babel.org
@@ -490,3 +490,78 @@ The =[[= causes a false positive which ~org-babel-detangle~ should handle proper
 :END:
 #+begin_src emacs-lisp :tangle yes :comments link
 #+end_src
+* tangle collect blocks
+:PROPERTIES:
+:ID:   fae6bb5b-555a-4d68-9658-a30ac5d1b2ba
+:END:
+** with :tangle in properties
+:PROPERTIES:
+:ID:   b2021d51-253c-4b26-9988-dac9193eb00b
+:header-args: :tangle relative.el
+:END:
+#+begin_src emacs-lisp
+"H1: no :tangle, but :tangle relative.el in properties"
+#+end_src
+
+#+begin_src emacs-lisp :tangle yes
+"H1: :tangle yes (to babel.el)"
+#+end_src
+
+#+begin_src emacs-lisp :tangle no
+"H1: should be ignored"
+#+end_src
+
+#+begin_src emacs-lisp :tangle ./babel.el
+"H1: :tangle ./babel.el"
+#+end_src
+
+#+begin_src emacs-lisp :tangle relative.el
+"H1: :tangle relative.el"
+#+end_src
+
+#+begin_src emacs-lisp :tangle 

Re: [BUG] [PATCH] Avoid interaction in test ~ob-tangle/detangle-false-positive~

2023-07-21 Thread Evgenii Klimov


Ihor Radchenko  writes:

> Bastien Guerry  writes:
>
 Copyright assignment is complete.
>>>
>>> Bastien, may you confirm?
>>
>> Yes I do!  Thanks for the heads up.
>
> Thanks!
> Recorded.
> https://git.sr.ht/~bzg/worg/commit/daaa35a9

Thanks, what about the patch itself?



Re: [BUG] [PATCH] Avoid interaction in test ~ob-tangle/detangle-false-positive~

2023-07-20 Thread Evgenii Klimov


Ihor Radchenko  writes:

> Evgenii Klimov  writes:
>
>> Test ~ob-tangle/detangle-false-positive~ asks for confirmation to kill
>> the buffer, connected to testing/examples/babel.org file, that is
>> modified during the couse of the test.
>>
>> Way to reproduce the bug (from projects main dir):
>
> Thanks!
> Waiting for your copyright assignment before applying.

Copyright assignment is complete.



Re: Unable to unfold a folded block having point directly after the folded block

2023-07-20 Thread Evgenii Klimov


Hi

Vlastimil Vondra  writes:

> Perfect, org-reveal is working as well, haven't known about that! But it 
> would be good that org-reveal is called automatically before org-cycle, 
> because when
> going through the task list, I'm just expanding by tab. It is not really 
> convenient to use tab and when reaching error (or no unfold) then hitting C-c 
> C-r.
> Maybe it's just me.
[...]

Can't you move the point at the beginning of the line before starting to
expand by tab? That way =org-speed-commands= will be available for you
and moving/expanding will be even faster.



Re: [BUG] [PATCH] Avoid interaction in test ~ob-tangle/detangle-false-positive~

2023-07-17 Thread Evgenii Klimov


Ihor Radchenko  writes:

> Evgenii Klimov  writes:
>
>> Test ~ob-tangle/detangle-false-positive~ asks for confirmation to kill
>> the buffer, connected to testing/examples/babel.org file, that is
>> modified during the couse of the test.
>>
>> Way to reproduce the bug (from projects main dir):
>
> Thanks!
> Waiting for your copyright assignment before applying.

Thanks, responsible person from FSF just returned from vacation.

While it's not applied, may I also ask: I noticed that non-default value
'other-frame of =org-src-window-setup= variable in my init.el leads to
creation of multiple frames during interactive testing.

I understand that testing should be done on ~emacs -Q~ etc, but since
it's an option to quickly test interactively in the current process
during development, would you accept the patch where
=org-src-window-setup= would be set to default value inside the test?

It took me some time to figure it out, so further developers in the
similar situation could benefit from it.



[BUG] [PATCH] Avoid interaction in test ~ob-tangle/detangle-false-positive~

2023-07-16 Thread Evgenii Klimov
Test ~ob-tangle/detangle-false-positive~ asks for confirmation to kill
the buffer, connected to testing/examples/babel.org file, that is
modified during the couse of the test.

Way to reproduce the bug (from projects main dir):

#+BEGIN_SRC sh :dir (expand-file-name ".")
emacs -Q \
  -L lisp/ -L testing/ -L testing/lisp -l lisp/org.el \
  -l lisp/org-id.el -l testing/org-test.el -l 
testing/lisp/test-ob-tangle.el \
  --eval "(progn (org-reload) (setq org-confirm-babel-evaluate nil) \
  (org-babel-do-load-languages 'org-babel-load-languages \
  '((emacs-lisp . t) (shell . t) (org . t" \
  --eval '(ert "ob-tangle/detangle-false-positive")'
#+END_SRC

>From 5905e37a581d4cf2a4a517593c91730d836b6471 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Sun, 16 Jul 2023 13:14:38 +0100
Subject: [PATCH] testing/lisp/test-ob-tangle.el: Avoid interaction in test

* testing/lisp/test-ob-tangle.el (ob-tangle/detangle-false-positive):
Unset modification flag from buffer to kill
(testing/examples/babel.org) in tear down step of test to avoid Emacs
asking for confirmation during interactive testing from within Emacs.
---
 testing/lisp/test-ob-tangle.el | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/testing/lisp/test-ob-tangle.el b/testing/lisp/test-ob-tangle.el
index b1b0a0a53..07e75f4d3 100644
--- a/testing/lisp/test-ob-tangle.el
+++ b/testing/lisp/test-ob-tangle.el
@@ -565,6 +565,8 @@ another block
 	(should (equal (string-trim (org-element-property
 	 :value (org-element-at-point)))
 			   ";; detangle changes"
+  (with-current-buffer buffer
+(set-buffer-modified-p nil))
   (kill-buffer buffer
 
 (provide 'test-ob-tangle)
-- 
2.34.1



[PATCH worg] Fix broken link

2023-07-14 Thread Evgenii Klimov
>From ed39640d75df231c8826191f2576fcfd6a5aa723 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Sat, 15 Jul 2023 00:34:58 +0100
Subject: [PATCH] org-contrib/babel/languages/index.org: Fix broken link

---
 org-contrib/babel/languages/index.org | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/org-contrib/babel/languages/index.org b/org-contrib/babel/languages/index.org
index a72db778..0dc6f2f8 100644
--- a/org-contrib/babel/languages/index.org
+++ b/org-contrib/babel/languages/index.org
@@ -257,7 +257,7 @@ To fetch a copy of this file, please clone Worg:
 
 You should find =org-contrib/babel/ob-template.el=.
 
-Developers are encouraged to read the [[file:../../org-contribute.org][Org-mode contribution
+Developers are encouraged to read the [[file:../../../org-contribute.org][Org-mode contribution
 instructions]] in the hope that the language support can be added to the
 Org-mode core.
 
-- 
2.34.1




Re: [Pre-PATCH v2] Add the capability to specify lexical scope in tangled files (was: Add new :lexical header argument)

2023-07-14 Thread Evgenii Klimov


No Wayman  writes:

[...]
> I, and others, have been surprised to find that the tangled file does
> not have lexical binding enabled when :lexical blocks are tangled.

Am I correct that language-specific header arguments are not yet covered
in the manual?  I can't find any reference of "lexical" there.



[Pre-PATCH] Add new :lexical header argument

2023-07-13 Thread Evgenii Klimov
Hi, here I propose new header argument to enable scope change
(lexical/dynamic binding) of the tangled file.  We have :shebang header
argument and the new one behaves similarly.

If you like the idea I think we should discuss the following:
- should we allow to set it for non-elisp blocks?  e.g. :shebang is not
  restricted and `elisp-enable-lexical-binding' is smart enough to use
  the comment symbol appropriate to the context. 
- should it be :lexical or :scope.  :lexical is long to type, but boolean
  and clear; scope is shorter, but the user will have to type
  "dynamic/lexical" or "dyn/lex".
- should we add the third option of the argument to explicitly forbid
  lexical binding?  E.g. if we a have source block that rely on the
  dynamic binding but it could be used in another block with lexical
  binding via noweb. I'm not sure that it's worth the effort.
- which default value to choose?  Currently if you tangle it would be
  dynamic, but lexical binding is the future.

After all I'll add tests and update Changelog/Docs if needed.

>From 3ad56137cb709182dc1bc242cd80a1474078cb95 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Thu, 13 Jul 2023 18:16:08 +0100
Subject: [PATCH] ob-tangle.el: Add new :lexical header argument

* lisp/ob-tangle.el (org-babel-tangle-use-lexical-binding): Add
new customization variable.
(org-babel-tangle): Add ability to enable lexical binding in
tangled file.

* lisp/ob-core.el (org-babel-common-header-args-w-values): Add new
:lexical header argument.

Previously one could achieve this manually, but 1) had to keep in mind
to hold this source block top-most, 2) couldn't use comment header
argument, as `lexical-binding' variable must be set in the first line
of a file.
---
 lisp/ob-core.el   |  1 +
 lisp/ob-tangle.el | 15 +--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/lisp/ob-core.el b/lisp/ob-core.el
index 47410b53f..c1801a677 100644
--- a/lisp/ob-core.el
+++ b/lisp/ob-core.el
@@ -437,6 +437,7 @@ then run `org-babel-switch-to-session'."
 (sep	. :any)
 (session	. :any)
 (shebang	. :any)
+(lexical. ((yes no)))
 (tangle	. ((tangle yes no :any)))
 (tangle-mode . ((#o755 #o555 #o444 :any)))
 (var	. :any)
diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 1274d0db7..916dd8489 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -76,6 +76,11 @@ then the name of the language is used."
   :group 'org-babel-tangle
   :type 'boolean)
 
+(defcustom org-babel-tangle-use-lexical-binding nil
+  "Enable lexical binding in tangled file by default."
+  :group 'org-babel-tangle
+  :type 'boolean)
+
 (defcustom org-babel-post-tangle-hook nil
   "Hook run in code files tangled by `org-babel-tangle'."
   :group 'org-babel-tangle
@@ -262,7 +267,7 @@ expression."
 	 (when file-name
(let ((lspecs (cdr by-fn))
 		 (fnd (file-name-directory file-name))
-		 modes make-dir she-banged lang)
+		 modes make-dir she-banged scoped lang)
 	 ;; drop source-blocks to file
 	 ;; We avoid append-to-file as it does not work with tramp.
 	 (with-temp-buffer
@@ -273,6 +278,9 @@ expression."
 			 (get-spec (lambda (name) (cdr (assq name (nth 4 spec)
 			 (she-bang (let ((sheb (funcall get-spec :shebang)))
  (when (> (length sheb) 0) sheb)))
+ (lexicalp (or (string-equal (funcall get-spec :lexical)
+ "yes")
+   org-babel-tangle-use-lexical-binding))
 			 (tangle-mode (funcall get-spec :tangle-mode)))
 		(unless (string-equal block-lang lang)
 			  (setq lang block-lang)
@@ -294,7 +302,10 @@ expression."
 		(when (and she-bang (not she-banged))
 			  (insert (concat she-bang "\n"))
 			  (setq she-banged t))
-		(org-babel-spec-to-string spec)
+(org-babel-spec-to-string spec)
+		(when (and lexicalp (not scoped))
+			  (save-excursion (elisp-enable-lexical-binding))
+			  (setq scoped t))
 		(setq block-counter (+ 1 block-counter
 		lspecs)
 		   (when make-dir
-- 
2.34.1



[PATCH v2] ob-tangle.el: Blocks overwrite each other when grouping before tangling

2023-07-13 Thread Evgenii Klimov
In this version I just updated the docstrings for the relevant
functions, because prior to that it wasn't clear: does this "default
export file for *all* source blocks" influence blocks with :tangle
"yes"/FILENAME?

>From 1a4f76960cf11fb192f2bee2cdc8778c7b897f1a Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Wed, 12 Jul 2023 19:24:48 +0100
Subject: [PATCH v2] ob-tangle.el: Avoid relative file names when grouping
 blocks to tangle

* lisp/ob-tangle.el (org-babel-effective-tangled-filename): Avoid
using relative file names that could cause one block to overwrite the
others in `org-babel-tangle-collect-blocks' if they have the same
target file but in different formats.
(org-babel-tangle-file, org-babel-tangle): Clarify the meaning of the
TARGET-FILE argument.
---
 lisp/ob-tangle.el | 34 +-
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 25129616f..1274d0db7 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -194,11 +194,12 @@ evaluating BODY."
 
 ;;;###autoload
 (defun org-babel-tangle-file (file  target-file lang-re)
-  "Extract the bodies of source code blocks in FILE.
+  "Extract the bodies of source code blocks from FILE.
 Source code blocks are extracted with `org-babel-tangle'.
 
 Optional argument TARGET-FILE can be used to specify a default
-export file for all source blocks.
+export file for all source blocks without :tangle header
+argument.
 
 Optional argument LANG-RE can be used to limit the exported
 source code blocks by languages matching a regular expression.
@@ -230,9 +231,10 @@ With one universal prefix argument, only tangle the block at point.
 When two universal prefix arguments, only tangle blocks for the
 tangle file of the block at point.
 Optional argument TARGET-FILE can be used to specify a default
-export file for all source blocks.  Optional argument LANG-RE can
-be used to limit the exported source code blocks by languages
-matching a regular expression."
+export file for all source blocks without :tangle header
+argument.  Optional argument LANG-RE can be used to limit the
+exported source code blocks by languages matching a regular
+expression."
   (interactive "P")
   (run-hooks 'org-babel-pre-tangle-hook)
   ;; Possibly Restrict the buffer to the current code block
@@ -427,17 +429,23 @@ that the appropriate major-mode is set.  SPEC has the form:
 		org-babel-tangle-comment-format-end link-data)
 
 (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile)
-  "Return effective tangled filename of a source-code block.
+  "Return effective tangled absolute filename of a source-code block.
 BUFFER-FN is the name of the buffer, SRC-LANG the language of the
 block and SRC-TFILE is the value of the :tangle header argument,
 as computed by `org-babel-tangle-single-block'."
-  (let ((base-name (cond
-((string= "yes" src-tfile)
- ;; Use the buffer name
- (file-name-sans-extension buffer-fn))
-((string= "no" src-tfile) nil)
-((> (length src-tfile) 0) src-tfile)))
-(ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang)))
+  (let* ((fnd (file-name-directory (buffer-file-name
+(get-buffer buffer-fn
+ (base-name (cond
+ ((string= "yes" src-tfile)
+  ;; Use the buffer name
+  (file-name-concat fnd
+(file-name-sans-extension buffer-fn)))
+ ((string= "no" src-tfile) nil)
+ ((> (length src-tfile) 0)
+  (if (file-name-directory src-tfile)
+  src-tfile
+(file-name-concat fnd src-tfile)
+ (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang)))
 (when base-name
   ;; decide if we want to add ext to base-name
   (if (and ext (string= "yes" src-tfile))
-- 
2.34.1



[PATCH] ob-tangle.el: Blocks overwrite each other when grouping before tangling

2023-07-12 Thread Evgenii Klimov
And here's the patch to fix it.
>From 2695d48f265a4100a9fc25c4dd278ab2b4b89ba5 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Wed, 12 Jul 2023 19:24:48 +0100
Subject: [PATCH] ob-tangle.el: Avoid relative file names when grouping blocks
 to tangle

* lisp/ob-tangle.el (org-babel-effective-tangled-filename): Avoid
using relative file names that could cause one block to overwrite the
others in `org-babel-tangle-collect-blocks' if they have the same
target file but in different formats.
---
 lisp/ob-tangle.el | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el
index 25129616f..4aab453e3 100644
--- a/lisp/ob-tangle.el
+++ b/lisp/ob-tangle.el
@@ -427,17 +427,23 @@ that the appropriate major-mode is set.  SPEC has the form:
 		org-babel-tangle-comment-format-end link-data)
 
 (defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile)
-  "Return effective tangled filename of a source-code block.
+  "Return effective tangled absolute filename of a source-code block.
 BUFFER-FN is the name of the buffer, SRC-LANG the language of the
 block and SRC-TFILE is the value of the :tangle header argument,
 as computed by `org-babel-tangle-single-block'."
-  (let ((base-name (cond
-((string= "yes" src-tfile)
- ;; Use the buffer name
- (file-name-sans-extension buffer-fn))
-((string= "no" src-tfile) nil)
-((> (length src-tfile) 0) src-tfile)))
-(ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang)))
+  (let* ((fnd (file-name-directory (buffer-file-name
+(get-buffer buffer-fn
+ (base-name (cond
+ ((string= "yes" src-tfile)
+  ;; Use the buffer name
+  (file-name-concat fnd
+(file-name-sans-extension buffer-fn)))
+ ((string= "no" src-tfile) nil)
+ ((> (length src-tfile) 0)
+  (if (file-name-directory src-tfile)
+  src-tfile
+(file-name-concat fnd src-tfile)
+ (ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang)))
 (when base-name
   ;; decide if we want to add ext to base-name
   (if (and ext (string= "yes" src-tfile))
-- 
2.34.1



[BUG] ob-tangle.el: Blocks overwrite each other when grouping before tangling

2023-07-12 Thread Evgenii Klimov
Hi, I noticed that during grouping of blocks to tangle some of them can
overwrite each other if they have the same target file, but in different
format (relative vs absolute).

Consider this example (part of example.org file in the attachment):

  * 1st explicit :tangle yes
  #+begin_src emacs-lisp :tangle yes
"1st explicit :tangle yes"
  #+end_src
  * 1st implicit default
  #+begin_src emacs-lisp
"1st implicit :tangle no"
  #+end_src

If we call `org-babel-tangle-file' with target-file arg equal to
"/path/to/example.el" (e.g. `org-babel-load-file' does that), then
target file name for the first block will be "example.el" and
"/path/to/example.el" for the second block. It appears to be crucial in
`org-babel-tangle-collect-blocks' [1]:

  ;; `org-babel-map-src-blocks' runs this part on each source block
  (let* ((block (org-babel-tangle-single-block counter))
 (src-tfile (cdr (assq :tangle (nth 4 block
 (file-name (org-babel-effective-tangled-filename
 (nth 1 block) src-lang src-tfile))
 (by-fn (assoc file-name blocks)))
(if by-fn (setcdr by-fn (cons (cons src-lang block) (cdr by-fn)))
  (push (cons file-name (list (cons src-lang block))) blocks)))

Current implementation of `org-babel-effective-tangled-filename' returns
relative file name if :tangle is "yes" or relative FILENAME. But if
:tangle happened to be absolute (as `org-babel-load-file' does), then
blocks with the same file name but one name is relative while the other is
absolute, will be treated as different and won't be group (see last tree
lines of code above).

As a result when blocks are returned to `org-babel-tangle' [2] one group
will overwrite the previous one, since their absolute file names are
equal.

I noticed two scenarious where such things happen (e.g. if running
`org-babel-tangle-file'):
- if target-file arg is equal to one of :tangle FILENAMEs and some
  blocks don't have :tangle argument, while other have :tangle
  FILENAME. As a result one of these groups will be lost.
- if target-file arg is equal to tangled original Org file and some
  blocks don't have :tangle argument, while other have :tangle
  "yes". As a result one of these groups will also be lost.

I attach example Org file and scratch code to reproduce both scenarious.

[1] [[file:lisp/ob-tangle.el::(file-name 
(org-babel-effective-tangled-filename][target file-name]]

[2] [[file:lisp/ob-tangle.el::org-babel-tangle-collect-blocks lang-re 
tangle-file))][blocks return]]

* 1st explicit :tangle yes
#+begin_src emacs-lisp :tangle yes
  "1st explicit :tangle yes"
#+end_src
* 1st explicit :tangle filename.el
#+begin_src emacs-lisp :tangle filename.el
  "1st explicit :tangle filename.el"
#+end_src
* 1st implicit default
#+begin_src emacs-lisp
  "1st implicit :tangle no"
#+end_src
* 2nd explicit :tangle yes
#+begin_src emacs-lisp :tangle yes
  "2nd explicit :tangle yes"
#+end_src
* explicit :tangle no
#+begin_src emacs-lisp :tangle no
  "explicit :tangle no"
#+end_src
* 2nd explicit :tangle filename.el
#+begin_src emacs-lisp :tangle filename.el
  "2nd explicit :tangle filename.el"
#+end_src
* 2nd implicit default
#+begin_src emacs-lisp
  "2nd implicit :tangle no"
#+end_src


scratch.el
Description: scratch code to reproduce the bug


Re: [PATCH] org.el: Remove undefined dynamic variable `org-log-states' from example

2023-07-12 Thread Evgenii Klimov


Ihor Radchenko  writes:

> It looks like 5 working days have passed since your email to FSF. If so,
> please follow up once and wait another 5 working days.

I've got papers from FSF, signed it and sent it back. It was 6 working
days ago. 5 days that you mention is for the first response from them, I
guess?



[PATCH] org.el: Remove undefined dynamic variable `org-log-states' from example

2023-07-10 Thread Evgenii Klimov
I added `org-summary-todo' example function, that are advertized in
`org-after-todo-statistics-hook', to my init file (with
lexical-binding: t) and got a compilation warning:

  Warning (bytecomp): Unused lexical variable `org-log-states'

since this variable is undefined. The command:

  git log -G 'org-log-states[^-]' --patch -- lisp/

shows its first appearance in commit
2c0812caf14e674d938d80d05678576c0cefcc83 but only in docstring.

Running ~find~ also didn't show its definition:

  find -H . -type f -exec grep --color=auto -i -nH --null \
-e org-log-states\[\^-\] \{\} +

But there are =org-log-states-order-reversed=, but it doesn't seem to
be relevant.

PS: I didn't add TINYCHANGE since I have reached the contribution
limit but FSF didn't respond yet.

>From a3e50c5799acb216ccb2c1ae6883d73ac36e4291 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Mon, 10 Jul 2023 23:00:41 +0100
Subject: [PATCH] org.el: Remove undefined dynamic variable `org-log-states'
 from example

* lisp/org.el (org-after-todo-statistics-hook): Remove undefined
dynamic variable `org-log-states' from docstring example.

* doc/org-manual.org (Breaking Down Tasks into Subtasks): The same
thing in doc example.

`org-log-states' was never defined throughout the whole repo history,
its removal helps to avoid compilation warning.
---
 doc/org-manual.org | 2 +-
 lisp/org.el| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index 987a29354..8a58bb31e 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -4648,7 +4648,7 @@ all children are done, you can use the following setup:
 #+begin_src emacs-lisp
 (defun org-summary-todo (n-done n-not-done)
   "Switch entry to DONE when all subentries are done, to TODO otherwise."
-  (let (org-log-done org-log-states)   ; turn off logging
+  (let (org-log-done)   ; turn off logging
 (org-todo (if (= n-not-done 0) "DONE" "TODO"
 
 (add-hook 'org-after-todo-statistics-hook #'org-summary-todo)
diff --git a/lisp/org.el b/lisp/org.el
index 62278ec77..9df56c700 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9755,7 +9755,7 @@ when there is a statistics cookie in the headline!
 
  (defun org-summary-todo (n-done n-not-done)
\"Switch entry to DONE when all subentries are done, to TODO otherwise.\"
-   (let (org-log-done org-log-states)   ; turn off logging
+   (let (org-log-done)   ; turn off logging
  (org-todo (if (= n-not-done 0) \"DONE\" \"TODO\"")
 
 (defvar org-todo-statistics-hook nil
-- 
2.34.1



Re: [PATCH v3] lisp/org.el: Add final hooks to S-/M-/S-M-cursor commands

2023-07-05 Thread Evgenii Klimov


Ihor Radchenko  writes:

[...]
>
> Thanks!
> Applied, onto main.

Thanks, it's a great pleasure!

> Note that you have reached the contribution limit allowed without FSF
> copyright assignment. If you want to contribute further, please consider
> signing copyright paperwork. See
> https://orgmode.org/worg/org-contribute.html#copyright

Paperwork in process.



[PATCH v3] lisp/org.el: Add final hooks to S-/M-/S-M-cursor commands

2023-07-04 Thread Evgenii Klimov

Ihor Radchenko  writes:

> Evgenii Klimov  writes:
[...]
> Few comments.
>
> First, please add Changelog entry for etc/ORG-NEWS.

Done.

>> +(defvar org-metaleft-final-hook nil
>> +  "Hook for functions attaching themselves to `M-left'.
>> +See `org-ctrl-c-ctrl-c-hook' for more information.")
>
> Note that unlike the docstring your added, `org-shiftup-final-hook'
> specifies when the hook is executed:
>
> (defvar org-shiftup-final-hook nil
>   "Hook for functions attaching themselves to `S-up'.
> This one runs after all other options except shift-select have been excluded.
> See `org-ctrl-c-ctrl-c-hook' for more information.")
>
> It is better to follow the pattern and clarify the purpose of the hook
> better instead of leaving docstrings for both the -final and other hook
> same.

Done.

>> +individual commands for more information.
>> +
>> +This function runs the hook `org-shiftmetaleft-hook' as a first
>> +step, `org-shiftmetaleft-final-hook' as the penultimate step, and
>> +returns at first non-nil value."
>
> Upon looking closer, I realized that you also defined return value of
> the function here.  Is there any particular reason for this? The return
> value is currently not defined and supposed to be discarded.

> Apparently the original wording is quite confusing.
> What it is supposed to say is:
> 
> This function runs the functions in `org-metaleft-hook' one by one
> as a first step, and exits immediately if a function from the hook
> returns non-nil.

Reworded as we discussed. Also for commands that support
`shift-select-mode' (i.e. org-shift{up,down,right,left}) mentioned it
and `org-support-shift-select'.

>From b27b95efbad7645d7bd4870becd112abc25c9840 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Thu, 29 Jun 2023 20:06:33 +0100
Subject: [PATCH v3] lisp/org.el: Add final hooks to S-/M-/S-M-cursor commands

* lisp/org.el (org-metaleft-final-hook, org-metaright-final-hook,
org-metaup-final-hook, org-metadown-final-hook): Define final hooks
for S-cursor commands.
(org-metaleft, org-metaright, org-metaup, org-metadown): Add final
hooks to M-commands and document them in the docstring.

* lisp/org.el (org-shiftup, org-shiftdown, org-shiftright,
org-shiftleft): Document hooks for S-cursor commands in the docstring.

* lisp/org.el (org-shiftmetaleft-final-hook,
org-shiftmetaright-final-hook, org-shiftmetaup-final-hook,
org-shiftmetadown-final-hook): Define final hooks for the S-M-cursor
commands.
(org-shiftmetaleft, org-shiftmetaright, org-shiftmetaup,
org-shiftmetadown): Add final hooks to the S-M-cursor commands and
document hooks in the docstring.

* etc/ORG-NEWS (New final hooks for Modifier-Cursor keys): Document
new hooks.

TINYCHANGE
---
 etc/ORG-NEWS |  17 ++
 lisp/org.el  | 155 +--
 2 files changed, 156 insertions(+), 16 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index d04e92275..973a97a2f 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -437,6 +437,23 @@ Currently implemented options are:
   iCalendar programs support this usage.
 
 ** New features
+*** New final hooks for Modifier-Cursor keys
+
+Final hooks are added to the following commands:
+- ~org-metaleft-final-hook~ to ~org-metaleft~ (bound to =M-=).
+- ~org-metaright-final-hook~ to ~org-metaright~ (bound to
+  =M-=).
+- ~org-metaup-final-hook~ to ~org-metaup~ (bound to =M-=).
+- ~org-metadown-final-hook~ to ~org-metadown~ (bound to =M-=).
+- ~org-shiftmetaleft-final-hook~ to ~org-shiftmetaleft~ (bound to
+  =M-S-=).
+- ~org-shiftmetaright-final-hook~ to ~org-shiftmetaright~ (bound to
+  =M-S-=).
+- ~org-shiftmetaup-final-hook~ to ~org-shiftmetaup~ (bound to
+  =M-S-=).
+- ~org-shiftmetadown-final-hook~ to ~org-shiftmetadown~ (bound to
+  =M-S-=).
+
 *** ~org-insert-todo-heading-respect-content~ now accepts prefix arguments
 
 The prefix arguments are passed to ~org-insert-todo-heading~.
diff --git a/lisp/org.el b/lisp/org.el
index 36235322d..57d8082e5 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -16658,27 +16658,63 @@ before indentation and \t insertion takes place.")
 (defvar org-metaleft-hook nil
   "Hook for functions attaching themselves to `M-left'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaleft-final-hook nil
+  "Hook for functions attaching themselves to `M-left'.
+This one runs after all options have been excluded.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metaright-hook nil
   "Hook for functions attaching themselves to `M-right'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaright-final-hook nil
+  "Hook for functions attaching themselves to `M-right'.
+This one runs after all options have been excluded.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defv

Re: [PATCH v2] Keep the link if the command was cancelled

2023-07-03 Thread Evgenii Klimov

Ihor Radchenko  writes:

> Evgenii Klimov  writes:
>
[...]
>> -(when (funcall (if (equal complete-file '(64)) 'not 'identity)
>> -   (not org-link-keep-stored-after-insertion))
>> -  (setq org-stored-links (delq (assoc link org-stored-links)
>> -   org-stored-links)))
>> -
>>  (when (and (string-match org-link-plain-re link)
>> (not (string-match org-ts-regexp link)))
>>;; URL-like link, normalize the use of angular brackets.
>> @@ -1995,6 +1990,10 @@ Use TAB to complete link prefixes, then RET for 
>> type-specific completion support
>>   (read-string "Description: " initial-input)
>> initial-input)))
>
> The code below the removed form can modify `link' variable. If such
> modification does happen, your patch will fail to remove the link from
> `org-stored-links' - (assoc link org-stored-links) will no longer return
> non-nil.

I added `link-original' variable to keep it intact until we want to
remove the link from `org-stored-links'.

>From a5ff8d4fe27fd503a6ddb719a622a980a73789a7 Mon Sep 17 00:00:00 2001
From: Evgenii Klimov 
Date: Fri, 30 Jun 2023 22:56:39 +0100
Subject: [PATCH] Keep the link if it was not inserted

* lisp/ol.el (org-insert-link): Keep the link in `org-stored-links' if
the command was interrupted by the user during the reading of a
description from the minibuffer.
---
 lisp/ol.el | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lisp/ol.el b/lisp/ol.el
index e2bf90acd..1490bde86 100644
--- a/lisp/ol.el
+++ b/lisp/ol.el
@@ -1820,7 +1820,7 @@ non-interactively, don't allow to edit the default description."
 	 (all-prefixes (append (mapcar #'car abbrevs)
 			   (mapcar #'car org-link-abbrev-alist)
 			   (org-link-types)))
- entry)
+ entry link-original)
 (cond
  (link-location)		  ; specified by arg, just use it.
  ((org-in-regexp org-link-bracket-re 1)
@@ -1896,11 +1896,7 @@ Use TAB to complete link prefixes, then RET for type-specific completion support
   (or entry (push link org-link--insert-history))
   (setq desc (or desc (nth 1 entry)
 
-(when (funcall (if (equal complete-file '(64)) 'not 'identity)
-		   (not org-link-keep-stored-after-insertion))
-  (setq org-stored-links (delq (assoc link org-stored-links)
-   org-stored-links)))
-
+(setq link-original link)
 (when (and (string-match org-link-plain-re link)
 	   (not (string-match org-ts-regexp link)))
   ;; URL-like link, normalize the use of angular brackets.
@@ -1995,6 +1991,10 @@ Use TAB to complete link prefixes, then RET for type-specific completion support
  (read-string "Description: " initial-input)
initial-input)))
 
+(when (funcall (if (equal complete-file '(64)) 'not 'identity)
+   (not org-link-keep-stored-after-insertion))
+  (setq org-stored-links (delq (assoc link-original org-stored-links)
+   org-stored-links)))
 (unless (org-string-nw-p desc) (setq desc nil))
 (when remove (apply #'delete-region remove))
 (insert (org-link-make-string link desc))
-- 
2.34.1



Re: [PATCH v2] lisp/org.el: Add final hooks to S-/M-/S-M-cursor commands

2023-07-03 Thread Evgenii Klimov


Ihor Radchenko  writes:

[...]
>> +individual commands for more information.
>> +
>> +This function runs the hook `org-shiftmetaleft-hook' as a first
>> +step, `org-shiftmetaleft-final-hook' as the penultimate step, and
>> +returns at first non-nil value."
>
> Upon looking closer, I realized that you also defined return value of
> the function here.  Is there any particular reason for this? The return
> value is currently not defined and supposed to be discarded.

Maybe I got it wrong, but I tried to follow the docstring for
`org-metaleft'. And I don't see here the use of the return value either:

#+begin_example
  (defun org-metaleft ( _arg)
"...
This function runs the hook `org-metaleft-hook' as a first step,
and returns at first non-nil value."
...)
#+end_example

Should I keep it like this?
  This function runs the hook `org-shiftmetaleft-hook' as a first
  step, and `org-shiftmetaleft-final-hook' as the penultimate step.



Re: [PATCH] Keep the link if the command was cancelled

2023-07-03 Thread Evgenii Klimov


Ihor Radchenko  writes:

> Max Nikulin  writes:
[...]
>> I had it in mind when I was writing my message. I had even tried to find 
>> another command that allows to remove stored links.
>
> If necessary, removing stored links without inserting can be made as an
> effect of negative prefix argument in `org-insert-link' or in
> `org-insert-all-links'.

I tried `org-insert-link' with the negative prefix argument, but the
link was inserted though.

And this behaviour is not mentioned in the docstring.



Re: [PATCH] Keep the link if the command was cancelled

2023-07-03 Thread Evgenii Klimov


Ihor Radchenko  writes:
> Evgenii Klimov  writes:
>> ...
>
> This makes sense, but the patch may break removing stored link in
> certain scenarios.

Thanks for response, I'll look into this issue and try to avoid this
breakage.



[PATCH v2] lisp/org.el: Add final hooks to S-/M-/S-M-cursor commands

2023-07-03 Thread Evgenii Klimov
* lisp/org.el (org-metaleft-final-hook, org-metaright-final-hook,
org-metaup-final-hook, org-metadown-final-hook): Define final hooks
for S-cursor commands.
(org-metaleft, org-metaright, org-metaup, org-metadown): Add final
hooks to M-commands and document them in the docstring.

* lisp/org.el (org-shiftup, org-shiftdown, org-shiftright,
org-shiftleft): Document hooks for S-cursor commands in the docstring.

* lisp/org.el (org-shiftmetaleft-final-hook,
org-shiftmetaright-final-hook, org-shiftmetaup-final-hook,
org-shiftmetadown-final-hook): Define final hooks for the S-M-cursor
commands.
(org-shiftmetaleft, org-shiftmetaright, org-shiftmetaup,
org-shiftmetadown): Add final hooks to the S-M-cursor commands and
document hooks in the docstring.

TINYCHANGE
---
Probably you are right and there's no need to add the final hook to
`org-meta-return'. Previously, I thought that the last condition fully
simulate C-RET, but the latter turned out to be
`org-insert-heading-respect-content'.

 etc/ORG-NEWS | 17 +
 lisp/org.el  | 98 +---
 2 files changed, 103 insertions(+), 12 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index cb4bc632b..f88e3df3d 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -249,6 +249,23 @@ Currently implemented options are:
   iCalendar programs support this usage.
 
 ** New features
+*** New final hooks for Modifier-Cursor keys
+
+Final hooks are added to the following commands:
+- ~org-metaleft-final-hook~ to ~org-metaleft~ (bound to =M-=).
+- ~org-metaright-final-hook~ to ~org-metaright~ (bound to
+  =M-=).
+- ~org-metaup-final-hook~ to ~org-metaup~ (bound to =M-=).
+- ~org-metadown-final-hook~ to ~org-metadown~ (bound to =M-=).
+- ~org-shiftmetaleft-final-hook~ to ~org-shiftmetaleft~ (bound to
+  =M-S-=).
+- ~org-shiftmetaright-final-hook~ to ~org-shiftmetaright~ (bound to
+  =M-S-=).
+- ~org-shiftmetaup-final-hook~ to ~org-shiftmetaup~ (bound to
+  =M-S-=).
+- ~org-shiftmetadown-final-hook~ to ~org-shiftmetadown~ (bound to
+  =M-S-=).
+
 *** ~org-insert-todo-heading-respect-content~ now accepts prefix arguments
 
 The prefix arguments are passed to ~org-insert-todo-heading~.
diff --git a/lisp/org.el b/lisp/org.el
index fdb920864..052c592ed 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -16831,27 +16831,51 @@ before indentation and \t insertion takes place.")
 (defvar org-metaleft-hook nil
   "Hook for functions attaching themselves to `M-left'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaleft-final-hook nil
+  "Hook for functions attaching themselves to `M-left'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metaright-hook nil
   "Hook for functions attaching themselves to `M-right'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaright-final-hook nil
+  "Hook for functions attaching themselves to `M-right'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metaup-hook nil
   "Hook for functions attaching themselves to `M-up'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaup-final-hook nil
+  "Hook for functions attaching themselves to `M-up'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metadown-hook nil
   "Hook for functions attaching themselves to `M-down'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metadown-final-hook nil
+  "Hook for functions attaching themselves to `M-down'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetaleft-hook nil
   "Hook for functions attaching themselves to `M-S-left'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetaleft-final-hook nil
+  "Hook for functions attaching themselves to `M-S-left'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetaright-hook nil
   "Hook for functions attaching themselves to `M-S-right'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetaright-final-hook nil
+  "Hook for functions attaching themselves to `M-S-right'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetaup-hook nil
   "Hook for functions attaching themselves to `M-S-up'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetaup-final-hook nil
+  "Hook for functions attaching themselves to `M-S-up'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetadown-hook nil
   "Hook for functions attaching themselves to `M-S-down'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetadown-final-hook nil
+  "Hook for functions attaching themselves to `M-S-down'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metareturn-hook nil
   "Hook for functions attaching themselves to `M-RET'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
@@ -16919,7 +16943,11 @@ When ARG is a numeric prefix, show contents of this 
level."
   "Promote subtree or 

Re: Add final hooks to S-/M-/S-M-cursor commands

2023-07-03 Thread Evgenii Klimov



On July 1, 2023 11:40:07 AM GMT+01:00, Ihor Radchenko  
wrote:
>Thanks for the patch!
>May you please squash it into one
>

Don't you mind if I also add the final hook to `org-meta-return'? I
didn't do it right away because it requires a little bit of refactoring:
everything after the initial hook is currently run with
`call-interactively'.



[PATCH] Keep the link if the command was cancelled

2023-07-03 Thread Evgenii Klimov
* lisp/ol.el (org-insert-link): Keep the link in `org-stored-links' if
the command was interrupted by the user during the reading of a
description from the minibuffer.
---
Currently the link is lost if the user chooses the link but cancells
the comand while writing the description.

 lisp/ol.el | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/lisp/ol.el b/lisp/ol.el
index e2bf90acd..e48138ef9 100644
--- a/lisp/ol.el
+++ b/lisp/ol.el
@@ -1896,11 +1896,6 @@ Use TAB to complete link prefixes, then RET for 
type-specific completion support
   (or entry (push link org-link--insert-history))
   (setq desc (or desc (nth 1 entry)
 
-(when (funcall (if (equal complete-file '(64)) 'not 'identity)
-  (not org-link-keep-stored-after-insertion))
-  (setq org-stored-links (delq (assoc link org-stored-links)
-  org-stored-links)))
-
 (when (and (string-match org-link-plain-re link)
   (not (string-match org-ts-regexp link)))
   ;; URL-like link, normalize the use of angular brackets.
@@ -1995,6 +1990,10 @@ Use TAB to complete link prefixes, then RET for 
type-specific completion support
  (read-string "Description: " initial-input)
initial-input)))
 
+(when (funcall (if (equal complete-file '(64)) 'not 'identity)
+   (not org-link-keep-stored-after-insertion))
+  (setq org-stored-links (delq (assoc link org-stored-links)
+   org-stored-links)))
 (unless (org-string-nw-p desc) (setq desc nil))
 (when remove (apply #'delete-region remove))
 (insert (org-link-make-string link desc))
-- 
2.34.1




[PATCH 2/3] lisp/org.el: Fix docstring for S-cursor commands

2023-06-30 Thread Evgenii Klimov
* lisp/org.el (org-shiftup, org-shiftdown, org-shiftright,
org-shiftleft): Document hooks for S-cursor commands in the docstring.
---
 lisp/org.el | 24 
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index b396456a2..bf61062b1 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -17121,7 +17121,11 @@ first non-nil value."
   "Act on current element according to context.
 Call `org-timestamp-up' or `org-priority-up', or
 `org-previous-item', or `org-table-move-cell-up'.  See the
-individual commands for more information."
+individual commands for more information.
+
+This function runs the hook `org-shiftup-hook' as a first step,
+`org-shiftup-final-hook' as the penultimate step, and returns at
+first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-shiftup-hook))
@@ -17149,7 +17153,11 @@ individual commands for more information."
   "Act on current element according to context.
 Call `org-timestamp-down' or `org-priority-down', or
 `org-next-item', or `org-table-move-cell-down'.  See the
-individual commands for more information."
+individual commands for more information.
+
+This function runs the hook `org-shiftdown-hook' as a first step,
+`org-shiftdown-final-hook' as the penultimate step, and returns
+at first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-shiftdown-hook))
@@ -17182,7 +17190,11 @@ This does one of the following:
 - on an item, switch entire list to the next bullet type
 - on a property line, switch to the next allowed value
 - on a clocktable definition line, move time block into the future
-- in a table, move a single cell right"
+- in a table, move a single cell right
+
+This function runs the hook `org-shiftright-hook' as a first
+step, `org-shiftright-final-hook' as the penultimate step, and
+returns at first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-shiftright-hook))
@@ -17222,7 +17234,11 @@ This does one of the following:
 - on an item, switch entire list to the previous bullet type
 - on a property line, switch to the previous allowed value
 - on a clocktable definition line, move time block into the past
-- in a table, move a single cell left"
+- in a table, move a single cell left
+
+This function runs the hook `org-shiftleft-hook' as a first step,
+`org-shiftleft-final-hook' as the penultimate step, and returns
+at first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-shiftleft-hook))
-- 
2.34.1




Add final hooks to S-/M-/S-M-cursor commands

2023-06-30 Thread Evgenii Klimov
`org-shiftup' and other S-cursor commands not only provide initial
hooks but also final hooks, while M-cursor and S-M-cursor commands
lack them. These patches add final hooks to all of these commands and
document both hooks in the docstring if they are not already present.





[PATCH 3/3] lisp/org.el: Add final hooks to the S-M-cursor commands

2023-06-30 Thread Evgenii Klimov
* lisp/org.el (org-shiftmetaleft-final-hook,
org-shiftmetaright-final-hook, org-shiftmetaup-final-hook,
org-shiftmetadown-final-hook): Define final hooks for the S-M-cursor
commands.
(org-shiftmetaleft, org-shiftmetaright, org-shiftmetaup,
org-shiftmetadown): Add final hooks to the S-M-cursor commands and
document hooks in the docstring.
---
 lisp/org.el | 40 
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index bf61062b1..326d3eed9 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -16738,15 +16738,27 @@ See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetaleft-hook nil
   "Hook for functions attaching themselves to `M-S-left'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetaleft-final-hook nil
+  "Hook for functions attaching themselves to `M-S-left'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetaright-hook nil
   "Hook for functions attaching themselves to `M-S-right'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetaright-final-hook nil
+  "Hook for functions attaching themselves to `M-S-right'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetaup-hook nil
   "Hook for functions attaching themselves to `M-S-up'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetaup-final-hook nil
+  "Hook for functions attaching themselves to `M-S-up'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetadown-hook nil
   "Hook for functions attaching themselves to `M-S-down'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-shiftmetadown-final-hook nil
+  "Hook for functions attaching themselves to `M-S-down'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metareturn-hook nil
   "Hook for functions attaching themselves to `M-RET'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
@@ -16814,7 +16826,11 @@ When ARG is a numeric prefix, show contents of this 
level."
   "Promote subtree or delete table column.
 Calls `org-promote-subtree', `org-outdent-item-tree', or
 `org-table-delete-column', depending on context.  See the
-individual commands for more information."
+individual commands for more information.
+
+This function runs the hook `org-shiftmetaleft-hook' as a first
+step, `org-shiftmetaleft-final-hook' as the penultimate step, and
+returns at first non-nil value."
   (interactive)
   (cond
((and (eq system-type 'darwin)
@@ -16828,13 +16844,18 @@ individual commands for more information."
   (save-excursion (goto-char (region-beginning))
  (org-at-item-p)))
 (call-interactively 'org-outdent-item-tree))
+   ((run-hook-with-args-until-success 'org-shiftmetaleft-final-hook))
(t (org-modifier-cursor-error
 
 (defun org-shiftmetaright ()
   "Demote subtree or insert table column.
 Calls `org-demote-subtree', `org-indent-item-tree', or
 `org-table-insert-column', depending on context.  See the
-individual commands for more information."
+individual commands for more information.
+
+This function runs the hook `org-shiftmetaright-hook' as a first
+step, `org-shiftmetaright-final-hook' as the penultimate step,
+and returns at first non-nil value."
   (interactive)
   (cond
((and (eq system-type 'darwin)
@@ -16848,6 +16869,7 @@ individual commands for more information."
   (save-excursion (goto-char (region-beginning))
  (org-at-item-p)))
 (call-interactively 'org-indent-item-tree))
+   ((run-hook-with-args-until-success 'org-shiftmetaright-final-hook))
(t (org-modifier-cursor-error
 
 (defun org-shiftmetaup ( _arg)
@@ -16855,13 +16877,18 @@ individual commands for more information."
 In a table, kill the current row.
 On a clock timestamp, update the value of the timestamp like `S-'
 but also adjust the previous clocked item in the clock history.
-Everywhere else, drag the line at point up."
+Everywhere else, drag the line at point up.
+
+This function runs the hook `org-shiftmetaup-hook' as a first
+step, `org-shiftmetaup-final-hook' as the penultimate step, and
+returns at first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-shiftmetaup-hook))
((org-at-table-p) (call-interactively 'org-table-kill-row))
((org-at-clock-log-p) (let ((org-clock-adjust-closest t))
   (call-interactively 'org-timestamp-up)))
+   ((run-hook-with-args-until-success 'org-shiftmetaup-final-hook))
(t (call-interactively 'org-drag-line-backward
 
 (defun org-shiftmetadown ( _arg)
@@ -16869,13 +16896,18 @@ Everywhere else, drag the line at point up."
 In a table, insert an empty row at the current line.
 On a clock timestamp, update the value of the timestamp like `S-'
 but also adjust the previous clocked item in the clock history.
-Everywhere else, drag the line at point down."
+Everywhere 

[PATCH 1/3] lisp/org.el: Add final hooks to the M-cursor commands

2023-06-30 Thread Evgenii Klimov
* lisp/org.el (org-metaleft-final-hook, org-metaright-final-hook,
org-metaup-final-hook, org-metadown-final-hook): Define final hooks
for S-cursor commands.
(org-metaleft, org-metaright, org-metaup, org-metadown): Add final
hooks to M-commands and document them in the docstring.
---
 lisp/org.el | 34 ++
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 4063ba98f..b396456a2 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -16714,15 +16714,27 @@ before indentation and \t insertion takes place.")
 (defvar org-metaleft-hook nil
   "Hook for functions attaching themselves to `M-left'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaleft-final-hook nil
+  "Hook for functions attaching themselves to `M-left'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metaright-hook nil
   "Hook for functions attaching themselves to `M-right'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaright-final-hook nil
+  "Hook for functions attaching themselves to `M-right'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metaup-hook nil
   "Hook for functions attaching themselves to `M-up'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metaup-final-hook nil
+  "Hook for functions attaching themselves to `M-up'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-metadown-hook nil
   "Hook for functions attaching themselves to `M-down'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
+(defvar org-metadown-final-hook nil
+  "Hook for functions attaching themselves to `M-down'.
+See `org-ctrl-c-ctrl-c-hook' for more information.")
 (defvar org-shiftmetaleft-hook nil
   "Hook for functions attaching themselves to `M-S-left'.
 See `org-ctrl-c-ctrl-c-hook' for more information.")
@@ -16879,7 +16891,8 @@ default `backward-word'.  See the individual commands 
for more
 information.
 
 This function runs the hook `org-metaleft-hook' as a first step,
-and returns at first non-nil value."
+`org-metaleft-final-hook' as the penultimate step, and returns at
+first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-metaleft-hook))
@@ -16902,6 +16915,7 @@ and returns at first non-nil value."
   (org-at-item-p
 (when (org-check-for-hidden 'items) (org-hidden-tree-error))
 (call-interactively 'org-outdent-item))
+   ((run-hook-with-args-until-success 'org-metaleft-final-hook))
(t (call-interactively 'backward-word
 
 (defun org-metaright ( _arg)
@@ -16915,7 +16929,8 @@ With no specific context, calls the Emacs default 
`forward-word'.
 See the individual commands for more information.
 
 This function runs the hook `org-metaright-hook' as a first step,
-and returns at first non-nil value."
+`org-metaright-final-hook' as the penultimate step, and returns
+at first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-metaright-hook))
@@ -16940,6 +16955,7 @@ and returns at first non-nil value."
   (org-at-item-p
 (when (org-check-for-hidden 'items) (org-hidden-tree-error))
 (call-interactively 'org-indent-item))
+   ((run-hook-with-args-until-success 'org-metaright-final-hook))
(t (call-interactively 'forward-word
 
 (defun org-check-for-hidden (what)
@@ -16973,7 +16989,11 @@ this function returns t, nil otherwise."
   "Move subtree up or move table row up.
 Calls `org-move-subtree-up' or `org-table-move-row' or
 `org-move-item-up', depending on context.  See the individual commands
-for more information."
+for more information.
+
+This function runs the hook `org-metaup-hook' as a first step,
+`org-metaup-final-hook' as the penultimate step, and returns at
+first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-metaup-hook))
@@ -17030,13 +17050,18 @@ for more information."
 (org-drag-element-backward))
((org-at-heading-p) (call-interactively 'org-move-subtree-up))
((org-at-item-p) (call-interactively 'org-move-item-up))
+   ((run-hook-with-args-until-success 'org-metaup-final-hook))
(t (org-drag-element-backward
 
 (defun org-metadown ( _arg)
   "Move subtree down or move table row down.
 Calls `org-move-subtree-down' or `org-table-move-row' or
 `org-move-item-down', depending on context.  See the individual
-commands for more information."
+commands for more information.
+
+This function runs the hook `org-metadown-hook' as a first step,
+`org-metadown-final-hook' as the penultimate step, and returns at
+first non-nil value."
   (interactive "P")
   (cond
((run-hook-with-args-until-success 'org-metadown-hook))
@@ -17089,6 +17114,7 @@ commands for more information."
 (org-drag-element-forward))
((org-at-heading-p) (call-interactively 'org-move-subtree-down))
((org-at-item-p) (call-interactively 'org-move-item-down))
+