proteanthread / vim

Automatically exported from code.google.com/p/vim
0 stars 0 forks source link

Dot operator doesn't work with user-defined insert functions #202

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I'm trying to write a new (repeatable) operator that goes into insert mode with 
a movement, similar to the built-in 'c'. But (as far as I know) it can't be 
done without using feedkeys() or startinsert, both of which modify the effect 
of the dot operator. 'normal! i' (or any command that enters insert mode) 
doesn't work because the function doesn't wait for your input before it 
terminates.

As a result it's not actually possible to recreate the functionality of an 
operator like 'c' without it already existing as a primitive operator.

Another, related issue is with insert mode's <C-o>; whatever text you inserted 
before using <C-o> isn't repeated by the dot operator. Ideally the dot operator 
would insert the text before <C-o>, redo whatever action was performed with 
<C-o>, and then insert the text after if there is any. But it doesn't seem like 
the current behavior should be the expected one.

Original issue reported on code.google.com by HoweJ...@gmail.com on 5 Mar 2014 at 3:17

GoogleCodeExporter commented 9 years ago
Can you be more specific? Can you share some code that we can talk about?

What you're trying to do should be possible since there are already good 
frameworks that let you create arbitrary custom operators.

- http://www.vim.org/scripts/script.php?script_id=2692
- http://www.vim.org/scripts/script.php?script_id=2782

Original comment by 676c7...@gmail.com on 5 Mar 2014 at 6:30

GoogleCodeExporter commented 9 years ago
Sure, sorry. I actually tried using vim-operator-user (as well as 
github.com/neitanod/vim-sade), but it breaks for this particular use-case.

I actually had a discussion about this with the creator of vim-sade here: 
https://github.com/neitanod/vim-sade/issues/3#issuecomment-36698860

The code is in that post, but I'll post it here too. Basically, I want to call 
an operator that takes a motion and then moves to a specified side of that 
motion (e.g. for `ip` it would either go before the paragraph or after the 
paragraph depending on the operator used). It then starts insert mode at that 
location. The idea being you could use the dot operator to apply the entered 
text to one side of the text object you're using. Even better would be to be 
able to do `{the operator}+.` to apply the text to the side you want, without 
having to retype the text. But that's a stretch goal right now.

This is what I wanted to write (I posted in the linked issue a failed attempt 
at a workaround; this is what I wanted to do)

```Vim
function! SadeAppend()
    exe "normal! \<esc>`>"
    call feedkeys('a', 'n')
endfunction

function! SadeInsert()
    exe "normal! \<esc>`<"
    call feedkeys('i', 'n')
endfunction

call sade#Func('(', 'SadeInsert')
call sade#Func(')', 'SadeAppend')

Unfortunately I don't really know the internals of sade very well so I can't tell you exactly how this looks when you expand the sade#Funcs, but according to the developer it won't work anyway because feedkeys/startinsert overwrites the repeat record. A similar issue occurred when I tried implementing this operation with kana/vim-operator-user. The syntax is almost identical anyway (replace sade#func with operator#user#define and change the arguments). I also tried using Tim Pope's repeat.vim, but it still came up against the same issue.

The operator works perfectly if the text to be added is hard-coded. The issue arises only when text is entered interactively at the time of the operator call. Like I said before, it's because feedkeys (or startinsert) is seen as a distinct "action" to Vim. Feedkeys (and startinsert) is by design called after the function ends, so this behavior makes sense. However, it's not what I want. And there is no version of feedkeys that works from within the function

I tried another workaround where I used a one-time autocommand to call a "postamble" function on InsertLeave. Combining that with repeat.vim, I managed to repeat the original function call instead of the text insertion. So it would perform the motion and then leave the cursor in insert mode. However, the cursor location was fixed to wherever the original call went, meaning pressing . on a different paragraph would put you at the corresponding location in the original paragraph. In addition, InsertLeave is not triggered if the user types to escape, so there's no guarantee the postamble will even be called.


Original comment by `HoweJ...@gmail.com` on 5 Mar 2014 at 7:12
GoogleCodeExporter commented 9 years ago
>no version of feedkeys that works from within the function

Sorry, that part was a little imprecise. I meant to say there's no way to enter 
insert mode interactively from within the function. Feedkeys can do more than 
just enter insert mode, and for 99% of actions you can emulate them from within 
the function with `normal! foo`. It's just that you can't emulate entering 
insertmode interactively.

Original comment by HoweJ...@gmail.com on 5 Mar 2014 at 7:18

GoogleCodeExporter commented 9 years ago
Is it possible to edit the post title after submitting? I didn't mean to 
suggest dot repeating couldn't be done with custom operators in general, I just 
meant it couldn't be done in this specific case.

Original comment by HoweJ...@gmail.com on 6 Mar 2014 at 11:43

GoogleCodeExporter commented 9 years ago
I think I can see the problem now. But are you sure a custom operator is
the right tool for the job? The purpose of an operator is to *act* on
some text object. Delete it, change it, make it upper case, surround it
with quotes, etc.

Allowing the user to do arbitrary insert mode editing and somehow have
that be part of the operator isn't possible and I think that's ok.
Alternatives where already mentioned in the other thread (getchar(),
InsertLeave). I don't think this is something that needs fixing in Vim.
Fortunately for you I have no power here :). Good luck!

Original comment by 676c7...@gmail.com on 7 Mar 2014 at 12:55

GoogleCodeExporter commented 9 years ago
Sorry, I reread your first message and now it clicked. You can't recreate the
'c' operator as a custom operator. I agree with you that it seems that should
be possible. Sorry for the interference.

Original comment by 676c7...@gmail.com on 7 Mar 2014 at 1:07

GoogleCodeExporter commented 9 years ago
No problem! Thank you for your input.

Original comment by HoweJ...@gmail.com on 7 Mar 2014 at 11:37

GoogleCodeExporter commented 9 years ago
I would love to see some new options to finally achieve this.

Original comment by grign...@gmail.com on 14 Dec 2014 at 5:53

GoogleCodeExporter commented 9 years ago
feedkeys should now be able to handle the '.' operator  correctly as of vim 
7.4.601.
Closing.

Original comment by chrisbr...@googlemail.com on 27 Jan 2015 at 8:20