phillbush / xmenu

a x11 menu utility
Other
296 stars 26 forks source link

[Enhancement] dmenu-like filtering of menus - typing the first several characters of a menu item would select that line #21

Closed vide0hanz closed 3 years ago

vide0hanz commented 3 years ago

Dunno if this is trivial or not, but in an effort to make xmenu more keyboard driven it would be nice to be able to start typing to navigate to a menu entry, for those with lots of items. Similar to how dmenu filters out items if they don't match what you have typed, or NNN file browser's type-to-nav functionality.

Using xmenu primarily with a keyboard feels really nice, this would be the icing on the cake.

This is a great project and has become a staple in my workflow. Keep up the great work!

phillbush commented 3 years ago

That is a nice, but non trivial, feature.
I will certainly implement that in the future (probably next week).

vide0hanz commented 3 years ago

Looking forward to testing it out.

Just some afterthoughts about a good way to implement it - how should this functionality be engaged? Ideally this feature probably shouldn't interfere with user-defined keybinds just for navigating the menu normally. If someone were to setup navigation keys to mimic vim, they probably wouldn't want the hjkl keys to trigger type to nav.

Perhaps holding down a special modifier key (Shift, maybe?) while typing would engage this feature. Or maybe it would just be simpler for an option like this to be switched on or off at compile time.

What do you think?

phillbush commented 3 years ago

I was thinking in xmenu to select items as the user types keys, without the need to use modifier keys.
I will make this feature optional (can be enabled/disabled with a command-line option, maybe?) to don't break the workflow of someone who mapped vim-like keys in config.h.

I already have the code for parsing keyboard input in another program of mine (xprompt), but I haven't touched its code for so long that I almost forgot how I coded it, so I am currently checking xprompt code (and doing some improvements in it while I'm there) in order to relearn how I did stuff.

phillbush commented 3 years ago

I added the type-to-select feature in the type branch.
I won't merge it into the master branch anytime soon, because I want to test this new feature (to see if there aren't bugs, for example), and I ask you be a tester ;-).

EDIT: The selection is case-insensitive, you just need to type a item in the current menu (it does not work in menus above or below the hierarchy) and it will select the first menu that matches the text you type as you type it. If you type a non-printable key (such as delete or backspace), the string in xmenu(1) memory will be rubbed out and you can type from beginning again. Also, selecting another item by other means (mouse, cursor keys, etc) also rub out the string in xmenu(1) memory.

I still need to do some changes in the code, as the run() function became a lot bigger than before, I may break it into other functions and do other tests. So expect more commits into this branch as I do more tests.

vide0hanz commented 3 years ago

Happy to help! Is there anything you can think of off hand that I should be on the lookout for, in terms of expected wonkiness?

Brief first impressions is that the feature works. As is, it appears to check against the first available match regardless of that pattern's placement in the menu. In other words, if you intend on navigating to an entry that begins with a certain string of letters, but there is an identical string of letters located within another word prior to the intended selection, it gets stuck on the first option and I don't believe there is a way to proceed to the next match.

I would think that maybe having an additional modifier key to hold which allows you to use your keybindings for jumping to the next and previous matches could be useful in this situation. Or perhaps more simply the tab key could act as a way to cycle between all possible matches as opposed to all entries if xmenu is used with this feature?

If you type a non-printable key (such as delete or backspace), the string in xmenu(1) memory will be rubbed out and you can type from beginning again.

Is there anything else going on which rubs the memory this way? Like if you type a pattern with no match does it auto reset similar to pressing one of the aforementioned keys? Just trying to understand :)

phillbush commented 3 years ago

Happy to help! Is there anything you can think of off hand that I should be on the lookout for, in terms of expected wonkiness?

I added support for Unicode characters and for input methods, so if your menu has weird Unicode characters or if you have set a compose key or other fancy input method, you can test that. My system only has dead keys and I have no idea of how other input methods work... Also, if you find how the type-to-select feature currently works wonky, just ask me for any change.

I would think that maybe having an additional modifier key to hold which allows you to use your keybindings for jumping to the next and previous matches could be useful in this situation. Or perhaps more simply the tab key could act as a way to cycle between all possible matches as opposed to all entries if xmenu is used with this feature?

Tab/Shift-Tab are already bound to cycle forward/backwards. But that is a good feature, I will make them cycle through the matched items if the memory is not empty, and work as before when the memory is empty.

Is there anything else going on which rubs the memory this way? Like if you type a pattern with no match does it auto reset similar to pressing one of the aforementioned keys? Just trying to understand :)

Yeah, I forgot to mention it. When you type a key whose character, when appended to the memory, does not match any item, the memory is rubbed out along with this new character. I think it would be better to rub out the memory first and then include this new character, what do you think?

Also, I need the opinion of xmenu users on two things:

vide0hanz commented 3 years ago

I think it would be better to rub out the memory first and then include this new character, what do you think?

Yes I think this would feel nicer. That was really the only thing which felt weird to me until I understood what was happening.

Should the type-to-select feature be always on? If not, should it be on by default or off by default?

Despite asking for this feature myself, I would think leaving it off by default would be preferable. I like your idea of enabling it with a launch flag, so that the user can decide how xmenu behaves on a per-script basis.

phillbush commented 3 years ago

Done!
With the last three commits, tab cycles through matched items when there is a string in memory; the memory is rubbed out first and then the new character is included, and the -t option was added to enable the type-to-select feature.

vide0hanz commented 3 years ago

Hey there, sorry for the late reply.

Latest commits feel much nicer! I personally think passing -t for type-to-nav is probably preferable but it does raise the question about what would happen if you source an xmenu script within another xmenu script that doesn't use it?

One example I can think of is you have a master script that acts as the parent menu, this one is just default xmenu which uses your desired keybinds to navigate the menus. What happens if you source the aforementioned launcher script from the master which uses xmenu -t? Would that effectively give the launcher menu type to nav but keep the parent menu normal?

I'm wondering if this could be used to fully customize which behavior you want for specific submenus.

phillbush commented 3 years ago

One example I can think of is you have a master script that acts as the parent menu, this one is just default xmenu which uses your desired keybinds to navigate the menus. What happens if you source the aforementioned launcher script from the master which uses xmenu -t?

The recommended way to use hierarchical menus is by indenting entries in the input, not by calling another xmenu instance (although that is also possible to do).

I will merge this branch into main to see how people will react to this change. I will make the type-to-select feature on by default (without a command-line option) for now.

Also, the keybindings that can be set in config.h override the type-to-select feature. So if one binds h/j/k/l to move the selection, typing those keys will not search for a item matching those characters.

phillbush commented 3 years ago

Done!
Version 4.5.0 released with type-to-select support and other additions.