-
Notifications
You must be signed in to change notification settings - Fork 12
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
Have menus adapt to user's customized bindings #48
Comments
I always apreciate suggestions, but Im not sure what you mean in this case. Previously I tried to always list the default key-bindings for items when there was one, but in the end it made the menus a bit bloated, so I recently dropped it. |
Including all the default key bindings would bloat the menus for sure! In real-world use, most people use about 20% of the keybindings 80% of the time. Which key bindings vary between people. Around 10% of those keybindings are common across all people. People's workflows are different. Their preferred custom bindings are different for the same functions. There are potentially three ways to build the menus taking people's preferences into consideration:
IMO, No. 1 is important to cater to people's custom key bindings already in place, but they could use a visual menu to remind them. No. 1 reduces friction from the user to use the plugin, i.e., it just works and fits in with their current workflow. |
Scenario 1 seems to trigger the issue I mentioned, if the user defined shortcut is used as the menu shortcut it would indeed make sense, but sooner or later somebody will happen to use a shortcut colliding with something already used in that menu, adding a pre-parse stage to first extract user preferences, then ensure all other items get unused shortcuts - sure not to hard to do, but adds processing time, so will make the menus slower to appear on slower systems |
Agreed on the additional processing time. One option is to cache the menu and give the user the option, i.e., a menu item to refresh the cache. For most people, unless they are experimenting, their custom key bindings won't change much. |
Regarding using yaml to define menus, sure could be done, but not sure if it would make things more convenient when defining dynamic items like the Panes menu, using shell script gives a fairly simplistic menu design, and allows normal script logic when examining states deciding dynamic items. I have mostly used yaml when doing docker and ansible, so perhaps scripting can be included without too much over head? |
The YAML idea was a brainstorming suggestion. Most people who are smart enough to use tmux and nvim will likely be able to modify shell scripts and mess up those shell scripts as well :) From the customer experience perspective, people enjoy a solution that offers low friction, is easy to use, and provides value and "magic." |
Im not arguing against the low friction perspective, and I would agree that yaml would make sense from a pure menu design perspective. |
but sure i you think my menu design concept is hard to understand, that might need to be adressed |
GPT suggested that tmux conditionals could be done something like this: menus:
- name: "My Tmux Menu"
items:
- label: "Do Action If Pane Marked"
command: |
if-shell 'tmux list-panes -F "#{?pane_marked,1,0}" | grep -q 1' \
'tmux display-message "A pane is marked!"' \
'tmux display-message "No pane is marked."'
- label: "Other Action"
command: "tmux split-window" No entirely sure that could be seen as less confusing :) - any thoughts? |
Another idea is to set this plugin's config and layout the menu within
|
It's slightly less confusing but the difference is negligible :) |
about to board a plane, you had some interesting inputs - much apreciated, will look into it more tomorrow! |
Have a safe flight! |
Having this plugin's configuration settings and menus defined like above in the #!/bin/bash
# Extract the value of @catppuccin_flavor from tmux
catppuccin_flavor=$(tmux show-options -g | grep '@catppuccin_flavor' | awk '{print $2}')
# Use the extracted value
echo "The current Catppuccin flavor is: $catppuccin_flavor"
# Example usage: Apply the theme based on the flavor
if [ "$catppuccin_flavor" == "mocha" ]; then
echo "Applying the Mocha theme..."
# Add commands to apply the Mocha theme
else
echo "Unknown Catppuccin flavor: $catppuccin_flavor"
fi Your shell scripts to handle the menus look good. You could use the existing code for that and leverage the Take the menu item "Rename window" for example. Your default setup uses set -g @tmux_menus_rename_window 'r' Now if I happen to prefer to use set -g @tmux_menus_rename_window ',' or use the value of the variable as shell commands to pull the custom keybinding: set -g @tmux_menus_rename_window "tmux list-keys -N | rg '^[a-zA-Z0-9-]+\s+(\S+)\s+Rename current window$' -r '$1''' # uses ripgrep so it's consistent across all OSes or use the description of each key binding from set -g @tmux_menus_rename_window "Rename current window" Then in your shell scripts to build the menu, use "Rename current window" as a key to access the bash hash map to get the custom keybinding. One way to build that key binding hash map is to use #!/bin/bash
# Ensure we're using an associative array
declare -A my_map
# Capture the output and check if rg processes it correctly
output=$(tmux list-keys -N | rg '^([a-zA-Z0-9-]+)\s+(\S+)\s+(.*)$' -r $'$3\t$2')
# Use a here string to avoid subshells
while IFS=$'\t' read -r key value; do
# Strip leading and trailing whitespace
key=$(echo "$key" | xargs)
value=$(echo "$value" | xargs)
# Set the key-value pair in the hash map
if [[ -n "$key" && -n "$value" ]]; then
my_map["$key"]="$value"
# Print the key and value immediately after adding to the hash map
echo "Added to my_map: Key: '$key', Value: '${my_map[$key]}'"
fi
done <<< "$output"
# Check if my_map is populated and print the contents
if [[ ${#my_map[@]} -eq 0 ]]; then
echo "my_map is empty."
else
echo -e "\nFinal key-value pairs in my_map:"
for key in "${!my_map[@]}"; do
echo "Key: '$key', Value: '${my_map[$key]}'"
done
fi
That key binding hash map can be loaded once for all the submenus to find their keys/values. Here is a sample output from the script above: Final key-value pairs in my_map:
Key: 'Toggle the marked pane', Value: 'm'
Key: 'Resize the pane right by 5', Value: 'M-Right'
Key: 'List all paste buffers', Value: '#'
Key: 'Rotate through the panes in reverse', Value: 'M-o'
Key: 'Spread panes out evenly', Value: 'E'
Key: 'Select the previous window with an alert', Value: 'M-p'
Key: 'Customize options', Value: 'C'
Key: 'Display pane numbers', Value: 'q'
Key: 'Resize the pane left by 5', Value: 'M-Left'
Key: 'Show messages', Value: '~'
Key: 'Select the pane below the active pane', Value: 'Down'
Key: 'Zoom the active pane', Value: 'z'
Key: 'Switch to the last client', Value: 'L'
Key: 'Choose a session from a list', Value: 's'
Key: 'Set the main-vertical layout', Value: 'M-4'
Key: 'Set the even-horizontal layout', Value: 'M-1'
... The prefix keys can be retrieved using the ❯ tmux show-options -g prefix | rg '^prefix (.+)$' -r '$1'
C-Space
❯ tmux show-options -g prefix2 | rg '^prefix2 (.+)$' -r '$1'
None |
By using a variation of your bash script where i instead filter using tmux list-keys | grep 'prefix' | sed 's/.*prefix *//' and tmux list-keys | grep 'root' | sed 's/.*root *//' I could get two lists defininng user binds. But it doesnt really work out in practice, for instance the menu items/split_view.sh uses several versions of split-window, most of them with multiple options. Checking for a matching user bind via list-keys quickly collapses, for instance "Split Window-Left" internally uses So this makes finding a user bind that matches pretty resource intensive, since first all options would need to be expanded into single option items in alphabetical order, and then all options in each menu would also need the same option expansion treatment to ensure source and dest is using the same notation. Finally all options that can be ignored in a specific context needs to be filtered out. And after all that is done, there is still the risk of when overriding the menu shortcut with the user defined bind, it would collide with an already used shortcut. Each such override needs to be cross checked with all other shortcuts in that menu, and change any found duplicate in the menu definition to something else. I certainly agree that it would be a desirable feature, but I just cant come up with a reasonable way to implement such a feature. If you can come up with a solution that can both handle identical but differently formulated options, and find a way to remap predefined colliding menu shortcuts that would be epic and I would gladly accept any such PR! |
This plugin is already nicely over-engineered. Why not take it to the next level of over-engineering? :)
Currently, the menus are hardcoded with certain keybindings that could be different than the user's settings. Having the menu "read" (
tmux list-keys
,tmux show-keys
, and/or other ways) the user key bindings and display those in the menus would help reinforce memory and give them the menu as another access point. This is a major reason for nvim's which-key success.For example, part of my
tmux.conf
include:The text was updated successfully, but these errors were encountered: