Home

Awesome

Tmux-Menus

Popup menus to help with managing your environment.

For tmux < 3.0 whiptail will be used, since the tmux feature display-menu is not available.

Not too hard to adapt to fit your needs. Items that some might find slightly redundant are included, easier to remove excess for more experienced users, then add more for newbies.

<details> <summary>Recent Changes</summary> <br> </details> <details> <summary>Purpose</summary> <br>

Some basic popup menus come as the default (See Configuration for how to disable them)

Rather lacking and since they're written as hard-to-read one-liners, a more integrated approach with navigation and adaptability seemed the way to go, also covering more than panes and windows.

Not solely meant for beginners, I use it myself all the time:

</details> <details> <summary>Usage</summary> <br>

Once installed, hit the trigger to get the main menu to pop up. The default is <prefix> \ see Configuration below for how to change it.

</details> <details> <summary>Screenshots of some menus</summary> <br>

The grey one is generated with whiptail, as can be seen whiptail menus use a lot more screen real estate. The rest are generated by the tmux built-in display-menu

help-summary main pane missing_keys sessions sessions-wt

</details> <details> <summary>Dependencies & Compatibility</summary>

Dependencies

If tmux >= 3.0 is used, whiptail is not needed

Linux

In most cases whiptail is installed by default on Linux distros. If not, install it using your package manager. One gotcha is that in the Red Hat universe the package is not called whiptail, the package containing whiptail is called newt.

MacOS

MacOS does not come with whiptail, but it is available in Homebrew

Compatability

VersionNotice
3.2Fully compatible
3.0 - 3.1cMenu centering is not supported, it's displayed top left if C is selected.
1.9 - 2.9aNeeds whiptail. Menu location setting ignored.
1.7 - 1.8tpm is not available, so the plugin needs to be initialized by running [path to tmux-menus]/menus.tmux directly from the conf file

The above table covers compatibility for the general tool. Some items has a min tmux version set, if the running tmux doesn't match this, that item will be skipped, this is by no means perfect, so if you find I set incorrect limits on some feature, please let me know!

</details> <details> <summary>Installing</summary>

Via TPM (recommended)

The easiest way to install tmux-menus is via the Tmux Plugin Manager.

  1. Add plugin to the list of TPM plugins in .tmux.conf:

    set -g @plugin 'jaclu/tmux-menus'
    
  2. Hit <prefix> + I to install the plugin and activate it. You should now be able to use the plugin.

Manual Installation

  1. Clone the repository

    git clone https://github.com/jaclu/tmux-menus ~/clone/path
    
  2. Add this line to the bottom of .tmux.conf

    run-shell ~/clone/path/menus.tmux
    
  3. Reload the tmux environment

    # type this inside tmux
    $ tmux source-file ~/.tmux.conf
    

You should now be able to use tmux-menus immediately.

</details> <details> <summary>Whiptail</summary> <br>

These menus can also be displayed using Whiptail, be aware that in order to run whiptail dialogs via a shortcut, the current (if any) task is suspended, dialogs are run, and when done the suspended task is reactivated.

The downside of this is that if no current tasks were running in the active pane, you will see fg: no current job being printed when the dialog is exited. This can be ignored.

The menu system works the same using Whiptail, however the menu shortcuts are not as convenient, since Whiptail does not differentiate between upper and lower case letters, and does not at all support special keys like 'Left' or 'Home'

If tmux is < 3.0 whiptail will automatically be used. If you want to use Whiptail on modern tmuxes set this env variable outside tmux, or in tmux conf: export FORCE_WHIPTAIL_MENUS=1

</details> <details> <summary>Configuration</summary>

Changing the key bindings for this plugin

The default trigger is <prefix> \ The trigger is configured like this:

set -g @menus_trigger F9

Please note that non-standard keys, like the default backslash need to be prefixed with an \ in order not to confuse tmux.

If you want to trigger menus without first hitting <prefix>

set -g @menus_without_prefix Yes

This param can be either Yes/true or No/false (the default)

Menu location

The default locations are: C for tmux >= 3.2 P otherwise. If whiptail is used, menu location is ignored

set -g @menus_location_x W
set -g @menus_location_y S

For all location options see the tmux man page, search for display-menu. The basic options are:

ValueFlagMeaning
CBothThe centre of the terminal (tmux 3.2 or newer)
R-xThe right side of the terminal
PBothThe bottom left of the pane
MBothThe mouse position
WBothThe window position on the status line
S-yThe line above or below the status line

Disable caching

By default menu items are cached, set this to No to disable all caching.

set -g @menus_use_cache No

To be more precise, items listed inside static_content() are cached. Some items need to be freshly generated each time a menu is displayed, those items are defines in dynamic_content() see scripts/panes.sh for an example of this. In that case, the label changes between Zoom and Un-Zoom for the zooming action.

The plugin remmebers what tmux version you used last time. If another version is detected as the plugin is initialized, the entire cache is dropped, so that the right version dependant items can be selected as the cache is re-populated. Same if a menu script is changed, if the script is newer than the cache, that cache item is regenerated.

Pointer to the config file

set -g @menus_config_file '~/.configs/tmux.conf'

In the main menu, you can request the config file to be reloaded. The defaults for this are:

  1. @menus_config_file - if this is defined in the tmux config file, it will be used.
  2. $TMUX_CONF - if this is present in the environment, it will be used.
  3. $XDG_CONFIG_HOME/tmux/tmux.conf - if $XDG_CONFIG_HOME is defined.
  4. ~/.tmux.conf - Default if none of the above are set.

When a reload is requested, the conf file will be prompted for, defaulting to the above. It can be manually changed.

Logging

Per default logging is disabled. If you want to use it, provide a log file name like this

set -g @menus_log_file '~/tmp/tmux-menus.log'
</details> <details> <summary>Screen might be too small</summary> <br>

tmux does not give any error if a menu doesn't fit the available screen. The only hint is that the menu is terminated instantaneously. Since this test is far from perfect, and some computers are really slow, the current assumption is that if it was displayed < 0.5 seconds (on most modern computers it will be below 0.03), it was likely due to screen size. And this error will be displayed on the status-bar:

tmux-menus ERROR: Screen might be too small

It will also be displayed if the menu is closed right away intentionally or unintentionally, so there will no doubt sometimes be false positives. If it doesen't happen the next time the menu is attempted, it can be ignored.

</details> <details> <summary>Modifications</summary> <br>

Each menu is a script, so you can edit a menu script, and once saved, the new content is displayed the next time you trigger that menu.

Rapid development with minimal fuzz.

If you are struggling with a menu edit, run that menu item in a pane of the tmux session you are working on, something like

./items/sessions.sh

This directly triggers that menu and displays any syntax errors on the command line.

If @menus_log_file is defined, you can use logging like this:

log_it "foo is now [$foo]"

If you are triggering a menu from the command line, you can use direct echo, but then you need to remove it before using it via the trigger, since tmux sees any script output as a potential error and display it in a scroll-back buffer.

</details> <details> <summary>Menu building</summary> <br>

Each item consists of at least two params

Item types and their parameters

Sample script

#!/bin/sh

#
#  This script is assumed to have been placed in the items folder of
#  this repo, if not, you will need to change the s to the support
#  scripts below.
#
static_content() {
  menu_name="Simple Test"

  #
  # Be aware:
  #   The first 'set' to define a new menu segment should not use
  #   'set -- "@" \', if that is done, it will just continue to build on
  #   what was defined in the previous menu segment!
  #   'set -- \' creates a new set of parameters for menu_generate_part
  #
  set -- \
    0.0 M Left "Back to Main menu  <==" "main.sh" \
    0.0 S \
    0.0 T "Example of a line extending action" \
    2.0 C "\$" "<P> Rename this session" "command-prompt -I '#S' \
        'rename-session -- \"%%\"'" \
    0.0 S \
    0.0 T "Example of action reloading the menu" \
    1.8 C z "<P> Zoom pane toggle" "resize-pane -Z $menu_reload"

  menu_generate_part 1 "$@"
}

#===============================================================
#
#   Main
#
#===============================================================

#  Full path to tmux-menux plugin
D_TM_BASE_="$(realpath "$(dirname -- "$(dirname -- "$0")")")"

# shellcheck source=scripts/dialog_handling.sh
. "$D_TM_BASE_PATH"/scripts/dialog_handling.sh

Complex param building for menu items

If whilst building the dialog, you need to take a break and check some condition, you just pause the set -- param assignments, do the check and then resume param assignment using set -- "$@"

Something like this:

...
    1.8 C z "<P> Zoom pane toggle" "resize-pane -Z $menu_reload"

if tmux display-message -p '#{pane_marked_set}' | grep -q '1'; then
    set -- "$@" \
        2.1 C s "Swap current pane with marked" "swap-pane $menu_reload"
fi

set -- "$@" \
    1.7 C "{" "<P> Swap pane with prev" "swap-pane -U $menu_reload" \
...
</details> <details> <summary>Contributions</summary> <br>

Contributions are welcome, and they're appreciated. Every little bit helps, and credit is always given.

The best way to send feedback is to file an issue

</details>

Thanks to

License

MIT