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

Text objects and motions for headings, subtrees and etc #48

Closed
petRUShka opened this issue Jul 15, 2021 · 44 comments
Closed

Text objects and motions for headings, subtrees and etc #48

petRUShka opened this issue Jul 15, 2021 · 44 comments
Labels
core-feature Feature is in orgmode core

Comments

@petRUShka
Copy link

petRUShka commented Jul 15, 2021

Does this feature exist in Emacs orgmode?
N/A

If answer to first question is "No", elaborate on how this feature is valuable and what problem does it solve.

One cool feature of jceb/vim-orgmode is text objects for orgmode. It allows to combine power of orgmode and Vim ideas. Quotation:

Vim offers a mighty feature called |text-objects|. A text object is bound to
a certain character sequence that can be used in combination with all kinds
of editing and selection tasks.

vim-orgmode implements a number of text objects to make editing org files
easier:

  ih                    inner heading, referring to the current heading
                        excluding the heading level characters (*)
  ah                    a heading, referring to the current heading including
                        everything
  ir                    inner subtree, starting with the current heading
  ar                    a subtree, starting with the current heading
  Oh                    inner outer heading, referring to the parent
  Or                    inner outer heading, including subtree, referring to
                        the parent
  OH                    an outer heading
  OT                    an outer subtree

Motions can be used like text objects as well. See |orgguide-motion|.

I thinks it is a very good idea to use powerful Vim features to interact with Org content.

Additional context
P.S. Having motions should be also very useful.

@petRUShka petRUShka added the core-feature Feature is in orgmode core label Jul 15, 2021
@kristijanhusak
Copy link
Member

I added support for motions. Check docs from here https://github.com/kristijanhusak/orgmode.nvim/blob/master/DOCS.md#org_next_visible_heading.

I'll add text objects separately.
I tested those text objects in vim-orgmode, but they don't behave so well for me.

I plan to add these (v, <, > and ^ marks the cursor):

  • ih - select everything inside a heading except asterisks. By heading I mean the first line:
  v---------------------v
* TODO some text  :MYTAG:
  Some content
  • ah - select everything inside a heading, including asterisks.
v-----------------------v
* TODO some text  :MYTAG:
  Some content
  • ic - select all content of the subtree
* TODO some text  :MYTAG:
> DEADLINE: <2021-07-16 Fri>
  Some content <
  • ir - select everything inside a subtree except asterisks:
  v
* TODO some text  :MYTAG:
  Some Content <
  • ar - select everything inside a subtree including asterisks:
v  
* TODO some text  :MYTAG:
  Some Content <

Do you have some additional suggestions?

@petRUShka
Copy link
Author

Looks like a great start!

I'm personally pretty happy with this objects but I think it nice to have full list implemented in vim-orgmode.

@kristijanhusak
Copy link
Member

Could you give me some detailed breakdown what's the difference between some of these? I installed vim-orgmode and some of these behaved completely same to me, like ih and ah did the same, and ir also did the same thing like ih and ah. Maybe I'm missing something.

@petRUShka
Copy link
Author

I've tested all the text-objects.

ih:

2021-07-22-005805_253x173_scrot

ah:

2021-07-22-005817_265x186_scrot

ir:

2021-07-22-005927_264x202_scrot

ar:

2021-07-22-005950_262x189_scrot

Oh:

2021-07-22-010038_245x177_scrot

Or:

2021-07-22-010108_275x194_scrot

OH:

2021-07-22-010132_261x210_scrot

OT doesn't work at all.

@petRUShka
Copy link
Author

test file:

* Header
** TODO task1
testh 
*** header 3
** TODO task2
* Header #2

@kristijanhusak
Copy link
Member

Thanks @petRUShka , this is really helpful!

@petRUShka
Copy link
Author

@kristijanhusak, please tell me, do you have plan on this issue? Actually it is the only issue that stopping me from migrating to this plugin. So for me it would be great to have this functionality implemented!

P.S. I use it to bind hotkeys for selecting and moving TODO item between files, headers within file and etc. Very useful and one of the key features.

@kristijanhusak
Copy link
Member

@petRUShka I plan to implement this, but it's not on my high priority list. Are you using tree-sitter branch? When I implement it, it will most likely be there, since I'm pushing all of the new features there, to avoid doubling the work.

@petRUShka
Copy link
Author

@kristijanhusak, right now I'm on jceb/vim-orgmode because it's the only org-mode plugin with text-object feature.

So I'm looking forward to have this feature!

@kristijanhusak
Copy link
Member

@petRUShka I pushed a commit with support for these motions on tree-sitter branch. I just didn't document them yet, but they work the same way as you described in your #48 (comment). I also added additional 0R which does same what 0r does + selects stars, like all uppercase ones does. Let me know what you think.

@kristijanhusak
Copy link
Member

I added documentation around them and made them configurable.
Let me know what you think once you give it a try.

@petRUShka
Copy link
Author

petRUShka commented Oct 11, 2021

@kristijanhusak, thanks a lot! It's a huge step! But It seems that ar and ar work not as expected. Instead of selecting till next heading on same level It selects all content till end of file (or sometimes added not all file but just next heading).

ih and ah work well.

OH works randomly (stops in the middle of the heading), but sometimes works well.

Or just doesn't work in my case.

@petRUShka
Copy link
Author

Example file: https://gist.github.com/petRUShka/cdf772db1fcbc1c2aa8318511609450b

var works badly on line 20 (inside header 2). Same for vir.

vOH works not as expected on line 38 for example.

vOr and vOh don't work at all.

@kristijanhusak
Copy link
Member

@petRUShka could you show me what you get and what's the expectation?

Here's var on line 20:
var-line-20

v0H on line 38
v0H-line-38

v0r on line 37
v0r-line-37

v0h on line 37
v0h-line-37

From what I understood (from the screenshots in your previous comment):

  • vir selects current headline and all of it's children, without the stars
  • v0H selects current headline to it's root headline, with the stars
  • v0r selects everything from the root healdine
  • v0h selects everything from the current headline to the root headline

Can you give more detailed explanation how these should work?

Also, did you test your first example #48 (comment) ?

@petRUShka
Copy link
Author

petRUShka commented Oct 13, 2021

On test file from #48 (comment)

  • var and vir are working as on screenshot;
  • vah and vih are the same;
  • vOh doesn't work at all, instead v0h works (zero char works but not O char);
  • vOr doesn't work at all, instead v0r works;
  • v0H works;
  • vOH works strange, it doesn't select all I want
    2021-10-13-222641_255x170_scrot

What do you think on changing from 0 to O? It should looks more vim-style when it is command: visual select Outer Heading.

@petRUShka
Copy link
Author

petRUShka commented Oct 13, 2021

But in case of bigger file from comment var for example doesn't work well:

2021-10-13-224415_1484x831_scrot

One can see that when I run var with cursor on line 20 it selects all file from line 9 (which is correct) till last line (which isn't).

You can compar behavior with vim-orgmode's:

2021-10-13-224429_1902x787_scrot

It selects text till line 35 which is the line of next header of level 1.

@petRUShka
Copy link
Author

petRUShka commented Oct 13, 2021

I've tested it with same as in previous comment result also with nvim -u vimrc_minimal. Where vimrc_minimal is:

set nocompatible
set runtimepath^=~/.vim runtimepath+=~/.vim/after
call plug#begin('~/.vim/plugged')
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}
Plug 'kristijanhusak/orgmode.nvim', { 'branch': 'tree-sitter' }
call plug#end()

filetype plugin indent on
syntax enable

lua << EOF
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
parser_config.org = {
    install_info = {
        url = 'https://github.com/milisims/tree-sitter-org',
        revision = 'main',
        files = {'src/parser.c', 'src/scanner.cc'},
        },
    filetype = 'org',
    }

require'nvim-treesitter.configs'.setup {
    -- If TS highlights are not enabled at all, or disabled via `disable` prop, highlighting will fallback to default Vim syntax highlighting
    highlight = {
    enable = true,
    disable = {'org'}, -- Remove this to use TS highlighter for some of the highlights (Experimental)
    additional_vim_regex_highlighting = {'org'}, -- Required since TS highlighter doesn't support all syntax features (conceal)
    },
  ensure_installed = {'org'}, -- Or run :TSUpdate org
  }

require('orgmode').setup({
org_agenda_files = {'~/Dropbox/org/*'},
org_default_notes_file = '~/Dropbox/org/test.org',
})
EOF

@kristijanhusak
Copy link
Member

Folds were the issue. I didn't account for those. Pull latest tree-sitter branch and give it a test.

I tried vim-orgmode for some of these, and in certain situations it behaves differently, like when cursor is on an empty line, vah selects the stars, but if cursor is on a line with text, it doesn't. I'm not doing that, since it seems like a bug to me.

@petRUShka
Copy link
Author

It works much better, thanks!

But sometimes var it works strange:

2021-10-14-232504_394x267_scrot

I've added several copies of line 32 and did var. It selected more than one heading.

These behavior isn't repeated. I've seen it several times on several files (including real one and test one), but suddenly it stops behave like this.

@kristijanhusak
Copy link
Member

I think this issue is the same issue as this one. Treesitter tree is not properly refreshed when some changes are done to the document, which causes all content to be treated as child of the first entry. I'm looking at that issue now.

@petRUShka
Copy link
Author

It somehow triggered by dar.

Steps to reproduce:

  1. Open updated test.org
  2. Place cursor on 35 line
  3. Do dar and u (undo) several times
  4. Watch number of deleted lines increases from step to step.
    Updated test.org: https://gist.github.com/902ab1946aaf98cc633b3bd081514d8a

@kristijanhusak
Copy link
Member

Can you try doing this and see if it still happens?

@kristijanhusak
Copy link
Member

@petRUShka I just pushed a fix for the parsing issue. Try using latest tree-sitter branch. No need to do what I said in last comment.

@petRUShka
Copy link
Author

It looks like you've fixed this issue. Thanks a lot!

@kristijanhusak
Copy link
Member

Awesome, thanks for your help! Can we close this?

@petRUShka
Copy link
Author

So what do you think on changing 0 to O in keybindings (for example vOr instead of v0r) to make things:

  • compatible with vim-orgmode,
  • more vim-like?

@petRUShka
Copy link
Author

Please look at #48 (comment) for details.

@kristijanhusak
Copy link
Member

Oooh, that's o. It looked like zero to me. Makes much more sense now. I'll update it today.

@kristijanhusak
Copy link
Member

I updated it to be O instead of 0.

@petRUShka
Copy link
Author

Great! Thanks a lot

@petRUShka
Copy link
Author

petRUShka commented Oct 25, 2021

There is one annoying difference between vim-orgmode ar behaviour and orgmode.nvim one.

vim-orgmode selects text including newline, whereas orgmode.nvim doesn't include newline.

Suppose we have:

** TODO Heading 1
** TODO Heading 1

dar on second line in vim-orgmode:

|** TODO Heading 1

where | is a position of a cursor.

and in orgmode.nvim it would be:

** TODO Heading 1
|

Which isn't what you naturally expect.

@petRUShka petRUShka reopened this Oct 25, 2021
@kristijanhusak
Copy link
Member

To me vim-orgmode functionality doesn't seem natural.r stands for subtree, which is basically headline and all of it's children. In this case, subtree is only ** TODO Heading 1.
Let's take for example Vim's built in way to delete around html tags. Having this html (| is cursor):

<div>First div</div>
<div>Second| div</div>

and doing dat will delete the second div and put cursor at the beginning of the 2nd line. I don't know why would cursor go to the beginning of the previous line, it doesn't really make sense.

@petRUShka
Copy link
Author

Another core-vim example is deleting line:

["x]dd			Delete [count] lines [into register x] |linewise|.

Line deletes completely as there is was line at all, so no new line left, cursor goes to beginning of a first line which seems kind of natural for me.

If you want to delete heading do you want to have extra line after deletion? I believe you don't in most of the cases.

@kristijanhusak
Copy link
Member

The issue happens only on the last subtree, and I figured out what's exactly the issue. I pushed a change, should be working as expected now.

@petRUShka
Copy link
Author

It's working well right now, thanks!

@petRUShka
Copy link
Author

var selects heading but last line. Suppose we have file:

** TODO Heading
- 1
- 2
- 3
- 4

var selects like this:

2021-10-26-185222_282x132_scrot

@petRUShka petRUShka reopened this Oct 26, 2021
@kristijanhusak
Copy link
Member

This seems like an issue with treesitter. It happens only on last line:

bug

no-bug

Strange thing is that section range is not different with or without something at the end.

I'll investigate this further.

@kristijanhusak
Copy link
Member

@petRUShka can you pull latest changes and test everything all over again? I fixed this issue, but I changed how things are generally calculated, so I want to be sure I didn't break anything.

@kristijanhusak
Copy link
Member

@petRUShka any updates on this?

@petRUShka
Copy link
Author

Now it seems to work fine. I'll put my eye on it!

@Maltimore
Copy link
Contributor

This may be slightly off-topic, but is there a reason why the character for "subtree" is r in the textobjects, but for instance in promote/demote heading it is s? If there's a good reason, I could make a documentation PR where I explain it.

@kristijanhusak
Copy link
Member

@Maltimore s is used for built in operator motion for sentences. For example, cis is "change inside sentence". If we would use s, we would break that.
On the other side, >s is not an operator mapping so it's perfectly fine to use it there.

@Maltimore
Copy link
Contributor

I think this issue could be closed then? Everything seems to be addressed.
I created a continuation of this issue (of sorts), for addition of more textobjects: #332

@kristijanhusak
Copy link
Member

Yeah I think we are ok with closing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core-feature Feature is in orgmode core
Projects
None yet
Development

No branches or pull requests

3 participants