bubbles
bubbles copied to clipboard
Support autocompletion of textinput
I build this for my current project. Thought it might be a feature that would make the textinput more glamorous.
It will enabled the setting of a value that the textinput can be autocompleted to by pushing the right arrow.
Hey! This is a really cool idea. If we were to add something like this it would likely need to be more customizable (i.e. Styling) and a little bit more flexible to support all the textinput use cases.
Just off the top of my head, I would imagine having something like a hook to allow the user to write some autocompletion logic:
// SuggestionFunc is a type of function that takes some text and returns suggestions for
// possible completions.
type SuggestionFunc func(s string) []string
And, then maybe on the model we would have
ShowSuggestions bool
GenerateSuggestions SuggestionFunc
We would also need some customization options:
SuggestionStyle lipgloss.Style
AcceptSuggestion key.Binding
It would likely be very similar to the Validation PR that was introduced recently.
That sounds reasonable. Should be easily doable.
But I guess SuggestionFunc would only every return a single string as a suggestion. Otherwise we'd have to have a UI for toggling between the suggestions...
In my head I was imagining perhaps a keybinding (ctrl-n / ctrl-p) that lets you cycle between the 1 or more suggestions but we don't need to display them all the the users. We can leave the UI as an exercise to the developer and then if it is heavily requested we can build a UI for it later on.
I think having the SuggestionFunc return multiple strings would allow for more flexibility in the future but for now we can pretty much only use the first suggestion and cycle / display them one at a time so that it is simpler for now and build upon it in the future. What do you think?
I see where you are coming from and it makes sense. Perhaps we could go with the most simple implementation first. So I'd try to build the Func, Styling and KeyBinding-solution. Multiple results and therefore additional key-bindings would be second. OK?
Sounds good! 👍 Let me know if I can help in any way :)
Hey @maaslalani - i started building this yesterday and remembered why my implementation was like this in the first place: Generating suggestions is something that would most likely be done asynchronously - at least is my use-case (e.g. from API calls or longer running commands)
That meant I must be able to set suggestions externally or at least trigger a refresh.
So I guess the simple callback-function for generating suggestions would not be enough in this case. We have to have a 'RefreshSuggestions' func to trigger that externally or make the generation of suggestions part of the ELM flow, so that suggestions are supplied via a message that could also be send externally.
What do you think?
That’s a good point @toadle. The API for this should probably be Msg-based (rather than function-based) so you can run completion asynchronously in a custom Cmd. And keep in mind that Cmds will always request repaints as long as they return a message (i.e. not nil).
func myCompletionCmd(options) tea.Msg {
return textarea.CompletionsMsg{
{"banana", "string", "99%"},
{"banana.Split", "function", "96%"},
{"banane", "French", "20%"},
}
}
I'm imagining the completions would want to be a [][]string so you could (optionally) include include metadata aligned in a tabular way, similar to how NeoVim does it. On that note, we could offer styling for those items too:
SuggestionStyle []lipgloss.Style
SelectedSuggestionStyle []lipgloss.Style
Of course, some of this could come later but API-wise it would be good to get it there on the first go.
So one more thought here (after talking with @maaslalani a bit): you could also offer a very simple API where the message remains a []string, per the original design, with no additional styling. Then, when we’re ready to implement more robust completion we simply create a new message type accordingly.
OK - sounds good. The only thing left on my question list is: What happens when there is two textinputs with different autocomplete-needs when using a Msg? Do we need some kind of ID?
Yeah, I believe we will need some sort of ID, there's an example of ID and Tag management in the cursor bubble here: https://github.com/charmbracelet/bubbles/blob/7cc578698457093a7ab8b2f293852acd52d7a8a9/cursor/cursor.go#L113-L116
@maaslalani @meowgorithm I'd suggest this for this for working implementation.
Playing around with it I'd say that multiple suggestion would have to be managed from outside the text-input. Which also makes the whole code inside and the styling-options much simpler.
The last thing that might become odd if the AcceptCompletionKey is not set to tea.KeyRight. Because in that case it might make sense to not check for the cursor being at the end of value. But when it actually IS tea.KeyRight it is not expected behaviour to complete from right in the middle of the string. Hard to describe. You'd have to try it out yourself.
BTW I used this to try it out: https://gist.github.com/toadle/be9321eefb689644ab35c0fbe8557530
Hey guys @maaslalani @meowgorithm , what do you say?
Hey! Taking a look now! Nice work @toadle.
Hey @maaslalani should we continue with this?
Hey @toadle, sorry I got totally distracted by something else. One piece of feedback is that I think we should make the default key to accept tab since I think that is the universally accepted completion key (imo).
@maaslalani finally came back to change the default key. Anything else?
Hey guys, can this be merged? I've been using autocompletion this way successfully in my project for quite some time now.
Sorry @toadle for not getting to this, been a bit busy with another project. I will take a look when I have some time, I haven't forgotten about this!
Heya! I'm halfway to poorly recreating a lot of this in a hacky workaround form for a project of mine. It'd be nice to get this finished up and merged the right way, but I'm not super familiar with the finer details of Git/Hub. Is it possible to pick up this branch/pull request myself and implement the suggested changes or would that just end up being a new pull request?
@different55 Hey there! Thanks for bringing this back to attention. Honestly: I lost interest, because my solution was working for my app and I didn't have time to implement the switching off multiple suggestions as @maaslalani suggested. Still I think this would be a great feature to add to textinput.
If you wanna help, you can check out my branch here: https://github.com/toadle/bubbles/tree/support_autocompletion I could add you as a collaborato otherwise you'd have to fork my repo and create a PR to my repo to add changes.
Yeah, if you could, that'd be great!
@different55 I just did. I also tried to rebase my changes onto the latest version of master. That didn't look to good. Much has changed in the textinput. I somehow have the feeling it'd be good to start a new branch based on the current version an implement the changes for autocomplete there.
@different55 I created a new branch based on the current master from upstream and migrated all work from my old branch here: https://github.com/toadle/bubbles/tree/autocomplete
I guess the suggested changes from @maaslalani should be done there. Then we could close this MR and open a new one. I'll see what I can do to implement the requested changes. Feel free to help.
@maaslalani @different55 OK, that was easier to implement than I thought. Let's continue here: https://github.com/charmbracelet/bubbles/pull/407