ultisnips icon indicating copy to clipboard operation
ultisnips copied to clipboard

Saving visual selection gets stuck when selecting big texts

Open SirVer opened this issue 10 years ago • 8 comments

First of all, I'd like to say a big THANKS for this plugin that I discovered yesterday. It's really easy to use, documentation is precise and quite exhaustive, and the plugin itself is very powerful. Great job !

Well, my problem is that when selecting a quite big amount of text and pressing to reuse it in a snippet, vim gets stuck in the UltiSnips_SaveLastVisualSelection() function for a while. I don't exactly know what the _visual_content.conserve() function is doing, but an optimization would be welcomed :-).

My use-case is the following very simple C snippet, wrapping the selected text into a vim fold:

snippet fold "Add a new vim fold" !b
/*{{{ ${1:topic} */

${0:${VISUAL}}

/*}}} */
endsnippet

When working on a big C file (> 5k lines) without folds, and that I want to add some with this snippet... well I just can't :-D.

Launchpad Details: #LP1178643 LpZ_squall - 2013-05-10 13:46:39 +0200

SirVer avatar Feb 15 '14 11:02 SirVer

Well, this is not related to visual, it is related to big edits inside a snippet. The problem is here:

https://github.com/SirVer/ultisnips/blob/master/plugin/UltiSnips/init.py#L686

The issue is that Vim is not reporting what changed in a buffer when the cursor moved. But UltiSnips needs this information to update its text objects. So it first tries a bunch of heuristics to figure this out - e.g. if the cursor is on the next line, but further to the left it is likely that the user inserted a newline. But if those heuristic fail, we need to do a full diff of the snippet area before and after - unfortunately this is a very costly operation and very slow as well (both the implementation and python). This is the notable freeze you see.

Unfortunately I have no idea how to improve the situation - if you have any suggestions, shoot.

Launchpad Details: #LPC SirVer - 2013-05-10 21:17:06 +0200

SirVer avatar Feb 15 '14 11:02 SirVer

OK, thank you for the explanation.

I'm a C developper and I don't know Python, so if you don't know how to improve the situation, then I probably won't be able to do anything, but I'll may have a look one day...

Launchpad Details: #LPC LpZ_squall - 2013-05-12 23:32:10 +0200

SirVer avatar Feb 15 '14 11:02 SirVer

Is there a way for us to disable UltiSnips manually before inserting long line? Or let vim to disable UltiSnips when inserting long line? Probably disabling plugin is out of question in vim, but I just curious to know if it can.

kenng avatar Sep 06 '16 03:09 kenng

@kenng: The only workaround so far is to jump out of snippet (e.g. hit <C-J> until you will encounter last placeholder) and then paste text wherever you want.

seletskiy avatar Sep 06 '16 08:09 seletskiy

I have some suggestions maybe?

  • could you use difflib instead of implementing a manual diff algorithm by hand?
  • could you abort snippet expansion logic if the edit is too large according to some criterion (simple length, or cost reaching a high value, or simply time.time() reaching some timeout value since the beginning of the computation)?

mgedmin avatar Apr 12 '19 16:04 mgedmin

BTW Vim 8.1.1321 added the listener_add() API that lets you register a callback and be informed about every change the user makes.

mgedmin avatar Oct 21 '19 06:10 mgedmin

@mgedmin This looks perfect, I believe this can be used to solve this problem once and for all.

SirVer avatar Oct 21 '19 19:10 SirVer

I looked into using listener_add, and unfortunately that API is not exposing all information necessary for UltiSnips. It misses what edits have been taken place (i.e. if there are deletions insertions or changes), so this will not help us here.

Other suggestions like terminating the diffing on a time criteria are of course possible, but a lot of work.

SirVer avatar Dec 29 '19 15:12 SirVer