3

First of all I want to say that I know and use delimitmate and surround-vim.

And while they work pretty well, there is room for improvement. I'll explain what I mean.

Suppose I'm writing the code

foo = bar() # some comment

And what I need is to wrap bar function call in another function call.

foo = baz(bar()) # some comment

The best option I know right now is to use surround-vim. So suppose cursor is at the start of bar. I press v w l l shift+S shift+( (then I type bar, but that's not relevant). Let's count, this is 6 key presses and two of them with Shift, which is harder than without it, right?

So I'm imagining another solution to this problem.

What if when I'm pressing ( (or some other key) the editor would detect that and propose some place to place the ) and I would choose that. The most effective way of doing that could be observed in easy-motion plugin.

The editor could mark the choices with colored letters and the user would choose by pressing letter with pressed Ctrl or something. This would be just two key presses (one with ctrl though) - 3 times less!

If such a plugin doesn't exist (and I think it doesn't) I'm willing to write one myself, but I don't know where to start.

For example, how do I detect that ( was pressed? And how do I mark choices with colored letters?

EDIT1. I know about surround's ys mapping, and I'm using it. But let's look at how many key presses you need to make with it:

ysiWf baz <cr>

Six key presses. And with my (proposed) plugin it's still only two. Notice the fact that with my plugin you don't need to think about what motion to use, I believe it's much better because of this. But let's make things more interesting. Let's imagine I need to transform this.

foo = bar(), baz(), goo()

into this

foo = boo(bar(), baz()), goo()

So I would need to press something ys4ff bar <cr>. It's still 6 key presses, but I would need to count parenthesis and this gets messy quite soon with more complicated expressions.

Also I believe that it's less natural to do it that way. Because I don't know about you, but at first I think about what function I need to use for wrapping and the next natural action is to type its name, not thinking about what motion I need to use to surround something.

1
  • How would your plugin choose the suitable places that the ) could go? I think that problem is way harder than anything related to implementing it in VimScript.
    – tommcdo
    Mar 19, 2016 at 12:51

2 Answers 2

5

You can use surround's ys operator with the iW motion. Using the f surrounding prompts for a function name.

ysiWfbaz<cr>

For more help see:

:h surround-mappings
:h iW
:h text-objects
2
  • Well, thanks for trying to help, but I know about ys operator and vim text objects. What I didn't know is that I can press f to prompt to function name. Still, my proposed plugin is much better handles this task I believe. Have you noticed, that even in this very simple case with surround I would need the press 6 keys? And with my plugin is only two. What's even more important is that it's less thought work. I don't need to think about what text-object I need to use. Mar 18, 2016 at 7:53
  • 3
    When working every day with vim, learning to use the text-objects is not a waste of time. Mar 18, 2016 at 9:45
3

viW( with lh-brackets, or vf(%( if you want something more robust... Something similar is certainly possible with surround without using the interactive visual mode.

Anyway, you need first to do a nnoremap on ( in normal mode I guess to enter in your mode. Then, you'll have to look at how easymotion handles its motion to do the same. And if you validate your action, then you can apply the actual surrounding, either with S (that messes up registers, which is to be avoided in plugins : we can never know what register the end user is already using, and for what), either with the usual '>astuff-to-append<esc>'<istuff-to-prepend<esc>.

It may be best to start as a extension to Easymotion

11
  • Okay, why I need to do normap on ( in normal mode, If the plugin should work in insert mode? Mar 18, 2016 at 8:18
  • 1
    Sorry it should be nnoremap, I fix the answer. Otherwise, I doubt you want to surround anything in insert mode when you just hit (. The default behaviour shall be to insert at least the opening bracket, and maybe the closing one. It the plugin waits for another input just to know where the closing bracket shall go, you'll quickly grow tired with this behaviour. Mar 18, 2016 at 9:44
  • well of course it would insert opening paren, why wouldn't it?. And if you will press closing paren it would insert it as if nothing happened naturally. That's why if I would use imap ( to my plugin function I would insert ( first thing in this function. But I don't think that mapping paren in insert mode to something is would be good idea at all. Because that way other plugins probably wouldn't work properly. I wonder how delimitmate detects the presses of parens etc. I've tried to understand it, but couldn't. Mar 18, 2016 at 10:15
  • nnoremap wouldn't work in insert mode, right? If so, It's not what I wan't. Mar 18, 2016 at 10:16
  • oh, and of course plugin should be smart enough to know, that for example if there is nothing further in the current line, then it doesn't need to show anything at all and just close open param automatically or leave this work to delimitmate. It would be configurable. Mar 18, 2016 at 10:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.