-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Autocomplete as you type #15
Conversation
The idea here is simply that the completion popup be triggered while you're typing? What would be the criteria for bringing it up? |
@Shadowfiend : Like in many other editors (Sublime/VisualStudio), as you type characters (longer that X) it searches open documents (or some other configurable index) for words that begin with that prefix, and pops up the completions below. Vim's famous ACP.vim plugin does this in a way that's similar to Sublime. (Emacs has a plugin as well.) If an open document contains: "Hello There". |
So in your mind typing a 2-letter prefix would be what sets it off? I've used editors with autocomplete before, just trying to get a feel for when we bring it up at all. |
Yes, two letters is usually a great way to quickly filter out a huge number of possibilities. One letter is usually overkill. The key is that it should be two characters after any word break (like punctuation etc). A lot of this could/should be configurable IMHO. |
Yeah. This is definitely a larger feature; if anyone wants to take up the gauntlet, that would be cool. I've got a few other big features I want to take care of first, so it might be a while before I can look at this. Before all of that I'm going to try and clear out some of the issues that have already been filed here, though. Most have been pending for a tad too long. |
Understandable - thanks for continuing development on this very promising editor. I feel the auto-complete-as-you-type feature is one of the reasons may people are using Sublime and I'd love to see Vico gain traction. |
Sublime's completion algorithm is also a little more complex than Vico's atm, I think. Still, definitely worth working on (Vico's completion's been annoying me a little lately and I think I have some ideas on how to improve prioritization and such). |
@Shadowfiend: Can you see a way to get the autocompletion to pop up as you type? I tried to implement this by simply creating a plugin, but the plugin system isn't powerful enough to trigger the popup window. It definitely required some modifications to the core of Vico. |
I'll try and have a look over the next few days to see if I can find an easy fix. |
Everything about the completion popup currently works as it did before.
Before we only highlighted your typing as you went in the completion popup, now the text also properly appears in the text view.
We're not all the way there, but most of the time the caret ends up at either where it should be if the completions are ultimately ignored, or it ends up at the end of the completed text when the completion is accepted.
Inserting as snippets was having some very bizarre side-effects at times when space was being hit. More to come on that front, I think. However, it didn't seem like snippet insertion was being used anywhere at the moment anyway, as in no snippets were ever suggested.
The real culprit was that space accepted the completion instead of ignoring it, which doesn't make sense as you type. For now, removing space as an accept action.
I've been doing some work on this (work so far is in the completion-as-you-type branch), but it looks more difficult than originally expected. Because the completion popup is currently something that runs modally, keeping up the typing in the main window is not particularly straightforward. So I'm going to have to rework the completion popup to work non-modally, which is going to be a little bit of work. I'll see what I can do tonight. |
Awesome. Could you help me understand how you would get it to work non-modally? Would you paint it directly on top of the text in the save text view (full disclaimer, I haven't done iOS programming in a long time). If so, maybe we could also think about ways to let plugins (or other features) do other types of painting on top of the text. I'd love to get inline compile/lint errors highlighted directly on top of the text (though I imagine there's a much easier way to do that). |
I saw this error when
|
Er… That looks odd. Try re-making? May also want to make sure you've updated the sparkle submodule or whatever… I forget what the crazy git syntax for that is. As for getting it to work non-modally—what I'm thinking is that we'd let the The biggest problem right now is that the text view and completion stuff aren't just used in the regular text views, they're also used in the command box. That's where things get hairy, because we may not necessarily want the two to behave the same. The options there get nasty, because they basically involve using a separate subclass of |
We're going to try a proper implementation of complete as you type, which will involve slightly differing behaviors for the completion popup depending on which mode it's invoked in, so we need this preference in place.
We missed a spot, so depending on the path you took the completion controller could still aggressively choose to close the window based on only having 1 completion, even if completion was initiated in a non-aggressive way.
We pass in the text view's key manager when initializing the completion controller, and it goes on to pass keystrokes back to the text view. This way, we're updating the contents of the text view as the user types, in addition to filtering the completion view itself. This replaces the old completionController:appendedStringWithoutCompleting: hack, which was totally broken anyway.
We also only trigger it once at a time. So if the completion window is already up, we don't try to bring it back up, which will reset its state. Instead, we track if we've currently got a window up (which is easy since it runs modally) and don't try again until it's gone.
We now check in the central presentCompletionsOf: method instead of checking only when checking the autocomplete trigger, since we've changed how completions work in general. We also update the flag in presentCompletionsOf: as well.
We add a selector, accept_if_not_autocompleting:, to the completion controller. When invoked via autocomplete, the completion controller gets a C option, which we check for and then set on an instance variable. That variable is then checked when invoking accept_if_not_autocompleting: to see if the selected entry should be accepted or not. The effect of this is that invoking autocomplete via C-N will accept on space, since you explicitly asked for the completion popup, while if it pops up via autocomplete it will only accept on enter/tab. The additional effect is that this is customizable behavior -- the relevant keys can simply be remapped to accept: or accept_if_not_autocompleting: as desired.
Now that we're filling in keys to the text view as they're being procesed by the completion controller as well, we need the range to reflect the fact that all prefix/filter text in the completion controller needs to be replaced with whatever completion was selected.
Because all keys are sent to the text view anyway, there's no reason at all to handle the terminating key after the completion popup goes away, as it's already been handled.
For now, we would end up with bad completions anyway because we always use a ViWordCompletion when autocompleting.
When we complete aggressively, we go through a separate return flow if there is only one completion available. We weren't setting up the range properly for that situation.
That first issue issue was definitely related to my key mappings. I'm still having trouble having escape and closing the completion window using a single press of escape (when it popped up automatically). I've disable every line in my site.nu file. Any other suggestions? There's also a strange behavior when completing at the beginning of a word. I really like how you still allow completions at the beginning of text (Sublime gets this wrong - vim's ACP gets this right - this plugin gets it right too). If you have:
Then typing |
Heh, frankly, I haven't tested the behavior at the beginning of a word at all, and it's more accidental than intentional. That implies we'd want the current word to be considered whatever the current word is up to the cursor. If you don't mind, I'd rather fix the snippet issue, consider this particular feature complete, and then consider that change in behavior as a separate issue. |
It does seem like you're right about escape. I could have sworn I had that working, but apparently it was too late and my mind was fooling me. More to come. |
Sounds fine! |
This ensures anyone else who relies on it in the rest of the input handling chain (which is blocked by the completion popup's modality) will have the right value. In this case, we can just set final_location to the caret, since the completion popup method takes care of updating the caret appropriately when/if the text insertion step wraps up.
This ensures we don't cancel the current snippet when we're autocompleting while inside one, but it also ensures we don't do the same when we explicitly invoke the completion box, which was an existing bug.
Before, when the user cancelled the completion popup during autocomplete, we tried to pass on the cancellation key combo to the existing key manager. Unfortunately we did this after the completion controller had been reset, which meant there was no key manager to send it to. We now save the key manager before resetting and then pass it the keys after we run the reset. This is so that the key manager receives the keys after the completion controller is fully dismissed.
Ok, I think the snippet issue is fixed. I also think the escape-while-autocompleting issues are actually legitimately fixed -.- |
We were passing the keys that cancelled the popup to the existing key manager in situations where we were running accept_if_not_autocompleting: and the completion popup *was* autocompleting. This typically meant we'd get two spaces instead of just one when we'd hit space, which should cancel the popup but not accept the top completion when autocompleting.
Fixed a couple of more bugs. However, the |
virtualInput indicates input that is not part of a macro or dot replay that is still not being inputted directly from the keyboard. Initially, we'll be using this to input the completion from the completion popup in a way that allows the dot command to work properly. The autocompletion popup doesn't trigger when virtualInput is set to YES, much like it won't trigger when replayingInput is set to YES. However, we WILL record keys inputted virtually when virtualInput is set to YES (whereas we do not when replayingInput is set to YES).
Completions are now inserted by virtually playing the keys that the completion would add to the current text as actual keys typed by the user. We set virtualInput to YES while we do this. This allows the keys to be recorded for the dot command to replay, which fixes dot commands with autocomplete.
Breakthrough. Completely redid how completions are inserted, which fixes the |
Trying now! |
I would definitely be proud of your I just tried some more testing and all the issues seem to be ironed out except for the snippets. One question: |
w00t. Good to hear. What exactly is the issue with the snippets? I didn't get a chance to test it, but it's possible the new completion logic that fixes As for the logic, it's currently very much structured around the fact that the popup window is modal. That said, the core functionality doesn't rely on it; with some rearrangement, it could be done differently. I agree it's a serious annoyance that the popup is modal for a variety of reasons; the reason it's done that way seems to be essentially so that the completion popup is the one getting the keystrokes, so that it can have its own key mappings. Modifying that will be interesting. |
We were passing an non-updated range for partial completions, which could lead to odd behavior when running partial completions e.g. in the ex field.
We were still doing the old replaceRange-based completion insertion; this switches it to the new virtual input insertion style.
Here's a repro of the snippets issue: Open a .js file. |
Because the completion dialog is modal, processing for that particular keystroke stops until the completion popup goes away in the situation where we show the completion popup. This means we never get a chance to show that the caret moved to after the currently inserted character. We now update the caret explicitly before showing the completion popup so that it updates correctly in the UI. This fixes a couple of other bugs with snippets, as well.
Before we completed partially in that situation, but that meant the popup would never go away if there were multiple matches for the current completion with the same length. That made triggering a snippet when typing if in a file where both if and IF were being used, for example, completely impossible
I'm currently running the code with the couple of changes that I've pushed in the last hour, which were addressing some issues directly and indirectly related to snippets, so maybe give that a whirl in case that changed things. As it is, following your steps, I get a menu prompting me for two different for loop variants and after I choose one things seem to work as expected, with tab moving among the appropriate things. If you tell me what behavior you're seeing and what behavior you expect to see instead, maybe I can get a better idea of what might be happening. |
It seems like something in your last update has fixed the snippets behavior! I can't see any glaring issues with this (though I've only given a few minutes). |
Sweet! I'm messing around with some stuff and running this branch merged with a couple of others, so I'll probably keep using it for a couple of days and if everything is still feeling good, merge it in. With that in mind, please let me know if you run into any serious problems with it so I can reset that process :) |
Autocomplete as you type There is now an option, "Complete as you type", that can be set in Editing options. This means it can be set per-file-type, as well. It runs word-based completion as currently triggered by C-N after two characters of a word have been typed. This also implements completion so that typing while a completion popup comes up also goes into the editor window, which did not used to happen.
Vim's ACP has this, and Sublime has this. I would love to see this in Vico. I've tried to implement it using Nu, but I hit a wall. Now that we have the source, it's likely much easier.