Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix subtree move (fixes #752) #753

Merged
merged 3 commits into from
Jun 13, 2024

Conversation

seflue
Copy link
Contributor

@seflue seflue commented Jun 10, 2024

Allows to move subtrees around smoothly (e.g. using Hydra.nvim, see #752). It also fixes the foldings after changing the subtree and preserves the folding state in the current subtree when moving it up or down.

@kristijanhusak
Copy link
Member

I think there is a simpler and shorter solution to this. We can just jump to the target line after moving.
This patch works ok for me:

diff --git a/lua/orgmode/org/mappings.lua b/lua/orgmode/org/mappings.lua
index 41d7c9f..7272f52 100644
--- a/lua/orgmode/org/mappings.lua
+++ b/lua/orgmode/org/mappings.lua
@@ -763,6 +763,7 @@ function OrgMappings:move_subtree_up()
   end
   local range = item:get_range()
   vim.cmd(string.format(':%d,%dmove %d', range.start_line, range.end_line, prev_headline:get_range().start_line - 1))
+  vim.fn.cursor(prev_headline:get_range().start_line, 1)
 end
 
 function OrgMappings:move_subtree_down()
@@ -773,6 +774,7 @@ function OrgMappings:move_subtree_down()
   end
   local range = item:get_range()
   vim.cmd(string.format(':%d,%dmove %d', range.start_line, range.end_line, next_headline:get_range().end_line))
+  vim.fn.cursor(next_headline:get_range().end_line - 2, 1)
 end
 
 function OrgMappings:show_help(type)

I'd prefer not to touch the folds with zx because that will recalculate everything and close other stuff that user might not want to be closed.

@seflue seflue force-pushed the fix_subtree_move branch from fe18581 to 9a3cfc9 Compare June 11, 2024 11:21
@seflue
Copy link
Contributor Author

seflue commented Jun 11, 2024

Would it be ok for you, if I add a configuration variable, which is false by default, but if set to true, will fix the foldings? Because I find myself pressing zx all the time and it would make my workflow much more convenient, if Orgmode would do that for me.

@kristijanhusak
Copy link
Member

We can fire an event similar to what we do for promote/demote (example:

EventManager.dispatch(events.HeadlineDemoted:new(self.files:get_closest_headline(), old_level))
), and then you can listen for that in your config to do whatever you want.
You can call the events HeadlineMovedUp and HeadlineMovedDown

@seflue seflue force-pushed the fix_subtree_move branch 4 times, most recently from ef5c441 to d862fb5 Compare June 13, 2024 17:07
- repeated move
- evaluate cursor position after move
@seflue
Copy link
Contributor Author

seflue commented Jun 13, 2024

HeadlineDemoted

Two questions:

First, should we distinguish between up and down? Is there a difference or is just "HeadlineMoved" sufficient? My feeling is, that one event is enough, because it does not make much of a difference from perspective of a user. At least I currently cannot imagine a use case, where it makes a difference.

Second, is there some example code, how the events can be used from the config? A fast search over the help file didn't get any results.

For now I will just remove the fold fixes and would like to get the PR merged as it is and would open another to add the events.

@seflue seflue force-pushed the fix_subtree_move branch from d862fb5 to 57de752 Compare June 13, 2024 17:22
seflue added 2 commits June 13, 2024 19:31
To allow for repetition of moving a subtree, the cursor must stay on the
headline.
To be consistent with promotion and demotion commands, we preserve the
folding state also when moving a subtree.
@seflue seflue force-pushed the fix_subtree_move branch from 57de752 to 4d869da Compare June 13, 2024 17:32
@seflue
Copy link
Contributor Author

seflue commented Jun 13, 2024

I think there is a simpler and shorter solution to this. We can just jump to the target line after moving. This patch works ok for me:

diff --git a/lua/orgmode/org/mappings.lua b/lua/orgmode/org/mappings.lua
index 41d7c9f..7272f52 100644
--- a/lua/orgmode/org/mappings.lua
+++ b/lua/orgmode/org/mappings.lua
@@ -763,6 +763,7 @@ function OrgMappings:move_subtree_up()
   end
   local range = item:get_range()
   vim.cmd(string.format(':%d,%dmove %d', range.start_line, range.end_line, prev_headline:get_range().start_line - 1))
+  vim.fn.cursor(prev_headline:get_range().start_line, 1)
 end
 
 function OrgMappings:move_subtree_down()
@@ -773,6 +774,7 @@ function OrgMappings:move_subtree_down()
   end
   local range = item:get_range()
   vim.cmd(string.format(':%d,%dmove %d', range.start_line, range.end_line, next_headline:get_range().end_line))
+  vim.fn.cursor(next_headline:get_range().end_line - 2, 1)
 end
 
 function OrgMappings:show_help(type)

I'd prefer not to touch the folds with zx because that will recalculate everything and close other stuff that user might not want to be closed.

vim.fn.cursor(prev_headline:get_range().start_line, 1)

Your patch does not work for me, at least not for moving the headline down. I backed everything with tests, with my code they succeed, with yours they fail. I simplified the code anyway though. Hope that works for you.

@kristijanhusak
Copy link
Member

kristijanhusak commented Jun 13, 2024

First, should we distinguish between up and down? Is there a difference or is just "HeadlineMoved" sufficient?

You're right, one event is enough. Just provide an argument to the event which way it went.

Second, is there some example code, how the events can be used from the config? A fast search over the help file didn't get any results.

There isn't since I wanted to keep it internal, and expose it only through the api. For now, you can do something like this (Example with TodoChanged event):

  local eventManager = require('orgmode.events')

  eventManager.listen(eventManager.event.TodoChanged, function()
    print('todo changed')
  end)

Your patch does not work for me, at least not for moving the headline down

I'll take another look. I tested with the example from the issue you reported.

@seflue
Copy link
Contributor Author

seflue commented Jun 13, 2024

First, should we distinguish between up and down? Is there a difference or is just "HeadlineMoved" sufficient?

You're right, one event is enough. Just provide an argument to the event which way it went.

Second, is there some example code, how the events can be used from the config? A fast search over the help file didn't get any results.

There isn't since I wanted to keep it internal, and expose it only through the api. For now, you can do something like this (Example with TodoChanged event):

  local eventManager = require('orgmode.events')
  local eventTypes = require('orgmode.events.types')

  eventManager.listen(eventTypes.TodoChanged, function()
    print('todo changed')
  end)

Thanks for the insight, will try that out - but as I said, in an upcomping PR.

Your patch does not work for me, at least not for moving the headline down

I'll take another look. I tested with the example from the issue you reported.

I mean, it's quite simple math: If you move a subtree of arbitrary length in the file down, then this arbitrary length has to be somehow included in the calculation of the new cursor position, because moving the current subtree down does basically mean, pulling the next subtree this arbitrary length up. So to calculate the new cursor position after the move from a line number before the move has to subtract the number of lines of our moving subtree.
Determining the cursor position after moving the subtree up is much simpler though, because the target line has the same line number before and after the move.

Copy link
Member

@kristijanhusak kristijanhusak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok yeah I didn't test all the cases. Looks good, thanks!

@kristijanhusak kristijanhusak merged commit cf261f7 into nvim-orgmode:master Jun 13, 2024
6 checks passed
@seflue seflue deleted the fix_subtree_move branch June 13, 2024 21:46
SlayerOfTheBad pushed a commit to SlayerOfTheBad/orgmode that referenced this pull request Aug 16, 2024
* tests: improve test cases for subtree move

- repeated move
- evaluate cursor position after move

* fix: cursor position after moving subtree

To allow for repetition of moving a subtree, the cursor must stay on the
headline.

* fix: preserve folding when moving subtree

To be consistent with promotion and demotion commands, we preserve the
folding state also when moving a subtree.

---------

Co-authored-by: Sebastian Flügge <seflue@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants