bubble-table icon indicating copy to clipboard operation
bubble-table copied to clipboard

Feature Request: Extend 'table.KeyMap' to fulfil 'bubbles/help' KeyMap interface

Open MaximilianSoerenPollak opened this issue 1 year ago • 4 comments

This feature would integrate it further into the BubbleTea ecosystem.

It would allow someone to define a KeyMap themselvs and then using bubbles/help they could render the Keymaps wherever they wish as the help wants you to fulfil the KeyMap interface which is defined like the following, in this source file

type KeyMap interface {
	// ShortHelp returns a slice of bindings to be displayed in the short
	// version of the help. The help bubble will render help in the order in
	// which the help items are returned here.
	ShortHelp() []key.Binding

	// FullHelp returns an extended group of help items, grouped by columns.
	// The help bubble will render the help in the order in which the help
	// items are returned here.
	FullHelp() [][]key.Binding
}

One way to solve this is to include key.WithHelp(...) in the defined keys like so for example:

func DefaultKeyMap() KeyMap {
	return KeyMap{
		RowDown: key.NewBinding(
			key.WithKeys("down", "j"),
			key.WithHelp("↓/j", "move down"),
		),
		RowUp: key.NewBinding(
			key.WithKeys("up", "k"),
			key.WithHelp("↑/k", "move up"),
		),
		RowSelectToggle: key.NewBinding(
			key.WithKeys(" ", "enter"),
			key.WithHelp("<space>/enter", "select row"),
		),
		Filter: key.NewBinding(
			key.WithKeys("/"),
			key.WithHelp("/", "filter"),
		),

And then let the user in their own model struct define two more things:

type YourModel struct {
      ...
     keys table.Keys
     help help.Model // From bubbles/help 
 }

Then implement ShortHelp & FullHelp according to the definitions and then you can render the help easily with m.help.View(m)

See an implementation of ShortHelp and FullHelp here bubbles/list

Only thing I think that then would be missing to make it maybe nicer would be to add Keybinds? Not sure what the best way for that would be, probably a different issue I guess.

MaximilianSoerenPollak avatar Oct 02 '24 05:10 MaximilianSoerenPollak

To clarify, would the user need to supply their own help.Model or would we be able to handle that by implementing FullHelp() and ShortHelp() in our keymap? I'm also a little confused about what's different between the linked bubbles/list keymap and ours, as I don't see where they're implementing those two functions.

The short version is I'm very open to this being implemented, I'm just unfamiliar with the best way to go about it. Adding the key.WithHelp to each bind seems to be an easy win to start, though I'd then wonder the best way to attach help text to custom keybinds... maybe hooking into https://github.com/Evertras/bubble-table/blob/main/table/options.go#L86 and applying help there? :thinking:

Evertras avatar Oct 02 '24 13:10 Evertras

Currently on vacation, but have sometime in a couple days.

The difference in fulfilling the interface is literally just the Full help and Short help methods on the struct.

There is two approaches that's. Can think of. Will work them out and describe them more clearly once I got my laptop and a bit of time.

We could either provide the methods to fulfill the interface and then also provide maybe a function where you can add own keys to your registered ones so that they show up in the help. Making them work with the model would then be manual work through the update function everyone has to do themselves.

Other way is you just document how the user can setup the interface. Although that might then be a worse experience.

Let me know which way you prefer for your project.

MaximilianSoerenPollak avatar Oct 03 '24 09:10 MaximilianSoerenPollak

Oh and the help.Model I have to look into it. All it is used for is basically the help rendering. So I think it could be supplied by us or the user.

And then the user can just render it maybe with "WithHelpText(true)" or something.

But can also keep it simple and just let the user provide that so they can also do styling etc on top. And just document that it needs to be there.

MaximilianSoerenPollak avatar Oct 03 '24 09:10 MaximilianSoerenPollak

What do you think of this proposal.

We implement a 'basic' version so it fullfills the interface and the user can use it with the help model. But we then also implement a way to add custom bindings to the keymap help, maybe via a method or so. As anything that isn´t specified in the KeyMap itself won´t be handled by the package and the user has to handle the 'workings' itself anyway so if we just make a way for them to easily add it to the help view (short or full) and then they just as they normally would implement the functionality via the update method I think that could work quite nicely.

So:

  • Extend KeyMap to fullfill help.Model interface via making 'ShortHelp' & 'FullHelp' methods
  • Enabling the user to extend short/full Help with custom keybinds as well (only the HELP view/display. Functionality has to be implemented by the user) - Doing this via two methods on KeyMap. 'AddBindingToShortHelp', 'AddBindingToFullHelp' ?
  • Extending the README to showcase that new functionality / how to implement it.

I will work on a draft PR so it's easier to understand what I mean and you can have a look at it :)

Let me know if you'd like to change anything of that, but I'm fully open to implement it any which way. :)

MaximilianSoerenPollak avatar Oct 09 '24 10:10 MaximilianSoerenPollak

Released as v0.17.1, we can tweak from there if needed. Thanks for the PR! I'll let you close this one if you confirm the released version works as you expect.

Evertras avatar Oct 31 '24 13:10 Evertras

In my own project I have opted a different way as I want to share a keymap over all models not just the bubble-table one. But the implementation should work as expected for anyone that uses it imo.

Maybe could add an Example or so as well, can take a look at that in the coming days.

MaximilianSoerenPollak avatar Oct 31 '24 20:10 MaximilianSoerenPollak