Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
When available, use complete() and TextChangedP rather than completefunc
Recently there has been quite a lot of flicker and noticable redraw latency, ostensibly caused by our auto-triggering approach. Historically our approach was as follows: * set completefunc to our CompleteFunc (see later) * On InsertCharPre, close the popup menu if it is visible * On TextChangedI, trigger user-defined completion (to re-show the now closed popup menu), request completion async and start polling * When the completion request is done store the result and, trigger user-deinfed completion using ctrl-x, ctrl-u (and ctrl-p to prevent selecting the top entry) * In our CompleteFunc, supply the completions stored completion data. The reason for the closing the popup menu in InsertCharPre was that TextChangedI is _not_ fired while the popup menu is visible. So we do this dance. However, more recent Vims have provided TextChangedP - basically TextChangedI but triggered while the pum is visible. In addition, the following new features are useful: complete() - a function to basically start insert-mode completion with the supplied data, and completeopt=noselect, which prevents automatically selecting the first completion. Nice. But there is one snag. TextChangedP is _also_ triggers when a completion is selected (e.g. using Ctrl-n or Tab). This is irksome, because it means that we end up filtering the completions based on the newly-inserted text. This is not what we want - the user didn't type that text (they selected it) so we should continue to show all of the most recent matches. There's no _good_ way to solve this, so we solve it by recording whether or not the last imput came from a user or not. We do this using InsertCharPre (setting it to true) and CompleteDone (setting it to false). The former is when a user types some characters and the latter when an entry in the menu is selected. This isn't perfect. As previously mentioned, InsertCharPre is not triggered when the completion menu is visible, so there is a scenario which breaks: User tabs to an entry, then adds some more characters. However, this seems niche enough that the benefits of the new system in terms of redraw and flicker outweigh this (essentially unfixable) bug. So the new approach is: * In InsertCharPre, set the flag to true * In TextChangedI/TextChangedP, if it's TextChangedP and the flag is false, ignore the event. * Otherwise, in TextChangedI/TextChangedP, call complete() with the latest completion response, and fire off another one, staring the poll .timer * When the response is received, just call complete() with the new data. The only remaining wrinkle is the omnicompleter. complete() cannot be called from the TextChangedI/TextChangedP autocommand handlers synchronously (for some reason) - it causes vim to get messed up. This is reasonable, as complete() is supposed to be used async. So we workaround that by polling for completion in a 0ms timer, rather than in athe autocommand handler. Finally, this commit adds a bunch more tests for completion that test both the new and the old mechanism. We keep the old mechanism because the new stuff is too new for our "supported" Vim version.
- Loading branch information