JumpForward & JumpBackward triggers defined only during snippet expansion

Bug #1231677 reported by mMontu
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
UltiSnips
Fix Committed
Wishlist
Unassigned

Bug Description

When using the default configuration the keys <c-k> and <c-j> are mapped to jump between the placeholders. But as these mappings are always defined, they interfere with the normal function of these keys.

For instance, in insert mode the dictionary completion (:h i_CTRL-X_CTRL-K) doesn't work due to the <c-k> mapping created after a snippet is expanded.

Of course changing the value of g:UltiSnipsJumpBackwardTrigger would solve this problme, but I find these mappings very intuitive so I'd prefer to avoid this approach.

Instead it would be nice if the mappings are defined only when expanding the snippet. I've tried to do this with the following functions:

function! UltiSnips_MapInnerKeys()
    " TODO: use maparg() to save current mapping (if any) to these keys, which
    " can be restored on UltiSnips_RestoreInnerKeys
    if g:UltiSnipsExpandTrigger != g:UltiSnipsJumpForwardTrigger
        exec "inoremap <silent> " . g:UltiSnipsJumpForwardTrigger . " <C-R>=UltiSnips_JumpForwards()<cr>"
        exec "snoremap <silent> " . g:UltiSnipsJumpForwardTrigger . " <Esc>:call UltiSnips_JumpForwards()<cr>"
    endif
    exec "inoremap <silent> " . g:UltiSnipsJumpBackwardTrigger . " <C-R>=UltiSnips_JumpBackwards()<cr>"
    exec "snoremap <silent> " . g:UltiSnipsJumpBackwardTrigger . " <Esc>:call UltiSnips_JumpBackwards()<cr>"
endf

function! UltiSnips_RestoreInnerKeys()
    if g:UltiSnipsExpandTrigger != g:UltiSnipsJumpForwardTrigger
        exec "iunmap " . g:UltiSnipsJumpForwardTrigger
        exec "sunmap " . g:UltiSnipsJumpForwardTrigger
    endif
    exec "iunmap " . g:UltiSnipsJumpBackwardTrigger
    exec "sunmap " . g:UltiSnipsJumpBackwardTrigger
endf

Removing the mappings definition from UltiSnips_MapKeys() and placing calls to function UltiSnips_MapInnerKeys() on the start of UltiSnips_ExpandSnippet()/UltiSnips_ExpandSnippetOrJump() works as expected, but due to my limited knowledge of Python I was unable to find the point to insert the call to remove (and possible restore) these mappings:

      _vim.command("call UltiSnips_RestoreInnerKeys()")

Is it possible? Do you see any downsides on this approach or a better solution?

Revision history for this message
SirVer (sirver) wrote :

I think it should be possible to do that. Vim users are also used to modes - so they might take to this idea naturally. However I personally would hate to try to use the feauture my muscle memory expects from this key just to realize that it now jumps forward inside - instead of doing that other thing that it does outside of the snippet.

So in general I am not very fond of the idea. If you provide and implementation including good test coverage I will include it into UltiSnips though - it is optional for users - people like myself will just map to keys that are not overloaded, others might use this feature without even realizing.

Changed in ultisnips:
status: New → Incomplete
Revision history for this message
mMontu (mmontu) wrote :

"I personally would hate to try to use the feauture my muscle memory expects from this key just to realize that it now jumps forward inside"

I'm actually going the other way around: my muscle memory expects that hitting Ctrl-x Ctrl-k would trigger the default functionality of Vim, and was used to have Tab and Shift+Tab (in snipmate) move between placeholders. But I like the idea of using Ctrl-j and Ctrl-k to do this, because I think Tab is used by too many plugins and by the recommendation on 98a. of https://github.com/MarcWeber/ultisnips/blob/master/doc/UltiSnips-Quickstart.txt.

"If you provide and implementation" - as I mentioned above, I got a partially working implementation, but lack the necessary knowledge of python to understand the plugin flow and insert the _vim.command("call UltiSnips_RestoreInnerKeys()"). I've spent some time by trial and error , but I'm unsure if is there a point of code that is executed every time the outermost snippet expansion ends.

Thus I'll consider learning python or using a different mapping.
Thanks!

Revision history for this message
SirVer (sirver) wrote :

> .... https://github.com/MarcWeber/ultisnips/blob/master/doc/UltiSnips-Quickstart.txt.

Urgl. Note that this inofficial fork of UltiSnips has some bugs that the master version has not - And is unsupported by me. Please do not report bugs against this version, instead ask Marc. Or just use master, please.

> some time by trial and error , but I'm unsure if is there a point of code that is executed every time the outermost snippet expansion ends.

this method: https://github.com/SirVer/ultisnips/blob/master/plugin/UltiSnips/__init__.py#L764 is called whenever a snippet exits, as soon as the list is empty, the other most snippet is done too and you should restore the keymappings. Please also add a test to test.py.

Revision history for this message
Launchpad Janitor (janitor) wrote :

[Expired for UltiSnips because there has been no activity for 60 days.]

Changed in ultisnips:
status: Incomplete → Expired
Revision history for this message
SirVer (sirver) wrote :

setting to inprogress. The ball is in my court - i need to review the pull request, but I am currently a bit overloaded.

Changed in ultisnips:
status: Expired → In Progress
Revision history for this message
SirVer (sirver) wrote :

The pull request has been merged.

Changed in ultisnips:
importance: Undecided → Wishlist
status: In Progress → Fix Committed
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.