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

Add text objects that include surrounding whitespace #24

Open
padde opened this issue Jan 12, 2016 · 11 comments
Open

Add text objects that include surrounding whitespace #24

padde opened this issue Jan 12, 2016 · 11 comments

Comments

@padde
Copy link

padde commented Jan 12, 2016

Similar to the way aw, ap etc. also include the surrounding whitespace. This would be useful to delete an entire block e.g. daR without having to delete the remaining empty lines manually. For example:

test do
  foo do
    bar
  end

  baz do
    quux
  end
end

putting the cursor within the first nested block and pressing dar results in:

test do

  baz do
    quux
  end
end

pressing daR should then result in:

test do
  baz do
    quux
  end
end

Analogously, pressing daR when the cursor is in the second nested block should result in:

test do
  baz do
    quux
  end
end

So the included surrounding whitespace should be:

  • All empty lines and whitespace after the block
  • BUT: All empty lines and whitespace before the block, if there is none before
  • This is also analogous to what vaw does, for example

This is also helpful when integrating with the expand-region plugin. It is important here that we have the surrounding whitespace included so that a repeated application of alternating vir and vaR will continue to bubble up to the topmost block. This way the selection will hopefully correctly expand up the hierarchy. Currently it is a big annoyance for me that this does not work properly.

I'd love to give it a shot and make a PR, however I'd first like to hear your opinion on whether I missed anything and whether this is deemed useful. Cheers!

@nelstrom
Copy link
Owner

I like this idea. I'm glad that you suggested creating a separate text-object as aR, rather than changing the behaviour of the existing ar. What do you think should happen when you use iR?

In Practical Vim, I came up with the names delimited and bounded to differentiate between the two styles of text object.

delimited-text-objects

bounded-text-objects

The existing ir and ar match the delimited text object behaviour, while the aR object you're proposing follows the bounded text object behaviour.

@nelstrom
Copy link
Owner

I'm afraid that I've rather neglected this plugin in recent years, so I'm not too sure where you should start. The plugin has tests, implemented with vspec. Writing a failing test would be a good start...

@padde
Copy link
Author

padde commented Jan 12, 2016

Thanks for your comments.

Actually I was thinking about suggesting the change to ar, but I figured that this might annoy some existing users. For me personally the bounded style seems like the natural choice for ruby blocks, probably because they feel like "paragraphs". After all, it's just a matter of remapping the keys so I really don't care very much what the "official" mapping is.

In think iR should do the same thing as ir. I would include it just for symmetry, although it would not add any new functionality. Maybe it could also select blocks including the do and end keywords (but nothing more) or something like that, but I'd find that kind of surprising. Do you have any other ideas or plans regarding iR?

@nelstrom
Copy link
Owner

Yeah, it's fine with me if ir and iR do the same thing.

@nelstrom
Copy link
Owner

@padde are you aware of the am and aM text objects that ship with the vim-ruby package? They also follow the bounded text object style.

The current implementation of textobj-rubyblock is not great. I've often thought that it would be worthwhile rewriting it, using the implementation of am and aM as a reference.

@padde
Copy link
Author

padde commented Jan 12, 2016

Oh I see... you meant one could argue that iR should behave like ar, right? Something like:

  • iR - (entire) Current Ruby block
  • aR - (entire) Current Ruby block plus surrounding blanks

Now I am confused what the right thing would be ;-)

By the way: bounded text object will not just match one additional space/blank line but actually all of them up to the first non-blank character (or EOF).

@padde
Copy link
Author

padde commented Jan 12, 2016

@padde are you aware of the am and aM text objects that ship with the vim-ruby package? They also follow the bounded text object style.

No, I did not! They look nice but for me they feel to specialized. Why restrict myself to selecting just methods and classes when I can have all blocks? However, I really like that they check the syntax groups to find the right boundaries for the text objects.

The current implementation of textobj-rubyblock is not great. I've often thought that it would be worthwhile rewriting it, using the implementation of am and aM as a reference.

Don't be so hard on yourself. I've used it daily for quite some time and it works great for me ;-) There's probably some room for refactoring, especially when new very similar text objects are added.

I'm however not convinced that the implementation could be improved much without adding a dependency to vim-ruby and using the syntax groups from there. Is that what you are planning to do?

@nelstrom
Copy link
Owner

one could argue that iR should behave like ar, right?

I suppose one could, but I never said that 😉

By the way: bounded text object will not just match one additional space/blank line but actually all of them up to the first non-blank character (or EOF).

Sounds good. I think that's how the am and aM text objects work too.

@nelstrom
Copy link
Owner

They look nice but for me they feel to specialized. Why restrict myself to selecting just methods and classes when I can have all blocks?

I like to think of textobj-rubyblock as being a useful catchall, but I'm keen on the more specialized text objects too. I use dam often, to delete a method. When writing rspec tests, I often wish that I had specialized text objects for selecting the current it block, or the describe block, or the context block. I haven't bothered to create these specialized text objects, because textobj-rubyblock works well enough, but I still think about creating those text objects!

@nelstrom
Copy link
Owner

I'm however not convinced that the implementation could be improved much without adding a dependency to vim-ruby and using the syntax groups from there. Is that what you are planning to do?

I hadn't thought it through that far. At the moment, textobj-rubyblock has a dependency on matchit.vim, which is included by default, but usually not enabled by default. On the other hand, vim-ruby is usually bundled with Vim distributions, and you don't have to do anything to enable it. So it might be the less awkward of two dependencies.

Alternatively, we could copy the syntax groups into the textobj-rubyblock plugin and scope them to this plugin's scripts, so as to avoid conflict.

@padde
Copy link
Author

padde commented Jan 12, 2016

I suppose one could, but I never said that 😉

Alright, I still think mapping iR to the same as ir is the least surprising thing to do.

I haven't bothered to create these specialized text objects, because textobj-rubyblock works well enough, but I still think about creating those text objects!

This sounds exactly like the problem I am trying to solve by integrating textobj-rubyblock with expand-region. I've been recently playing around with Emacs a bit (he said the "E" word!) and was really impressed with the expand-region package. I'm not sold on Emacs for other reasons though, so I am looking for a way to make this work in Vim.

In case you're not familiar with the concept of expand-region: it allows you to expand (and also contract) a visual selection by repeatedly extending it to the next bigger matching text object. So if you want to select an it block, you would simply place the cursor somewhere inside it and then expand until the entire block is selected. If you map this to a single key it's fairly efficient and you don't have to remember multiple mappings. Of course one might be faster with specialized text objects, but for me it works really well.

vim-ruby is usually bundled with Vim distributions, and you don't have to do anything to enable it.

Fair enough, this should not be a big problem then. Anyway, looks like there's quite some work ahead ;-)

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

No branches or pull requests

2 participants