From 52816a7693fda5c8ab1d121ccb27c586747cfc3a Mon Sep 17 00:00:00 2001 From: AL Bashkir <41126916+al-bashkir@users.noreply.github.com> Date: Mon, 4 May 2026 17:53:01 +0300 Subject: [PATCH 1/2] Feat/uv support (#1) * feat: add PEP 723 inline script metadata for uv Allows running rename_session_windows.py via 'uv run --script' so libtmux is provisioned automatically. Block is a comment for plain python3, behaviour is unchanged on that path. Refs #56 * feat: auto-detect uv in tmux entrypoint If 'uv' is on PATH, route all rename_session_windows.py invocations through 'uv run --script' so libtmux is resolved from PEP 723 metadata. Otherwise fall back to the existing python3 + libtmux import check. Zero config; existing users unaffected. Refs #56 * docs: document uv auto-detect path in README Tell users uv is auto-detected and pip-install of libtmux is not required when uv is present. Refs #56 * fix: route after-rename-window hook through uv launcher enable_user_rename_hook() registered a tmux hook with the bare script path, relying on the python3 shebang. Under the uv adoption path, that bypasses uv and tries system python3 + libtmux, which silently fails when libtmux is not installed system-wide. Pass the launcher through env var TMUX_WINDOW_NAME_LAUNCHER from the .tmux entrypoint, and prefix the hook's run-shell command with it. The pre-existing unbalanced quotes around run-shell's path also broke once the path contained spaces ("uv run --script /path"); use properly escaped \"...\" so tmux parses the run-shell argument as a single quoted token. Refs #56 --------- --- README.md | 13 +++++++++++++ scripts/rename_session_windows.py | 12 ++++++++++-- tmux_window_name.tmux | 22 ++++++++++++++-------- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 135a49c..ee1e2c8 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,19 @@ To make the shortest path as possible the plugin finds the shortest not common p ## Installation +### Recommended: install [uv](https://docs.astral.sh/uv/) + +If `uv` is on your `PATH`, the plugin auto-detects it and runs the script via `uv run --script`. `libtmux` is resolved from inline script metadata; the steps below for `pip install libtmux` and `dataclasses` are **not needed** in this case. + +Install uv: +```sh +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +If `uv` is not present, the plugin falls back to `python3` and requires `libtmux` to be installed manually — see the next section. + +--- + ### Install libtmux (must) _**Note**_: Make sure you are using the `user` python and not `sudo` python or `virutalenv` python! diff --git a/scripts/rename_session_windows.py b/scripts/rename_session_windows.py index 5896377..0a5d167 100755 --- a/scripts/rename_session_windows.py +++ b/scripts/rename_session_windows.py @@ -1,4 +1,10 @@ #!/usr/bin/env python3 +# /// script +# requires-python = ">=3.7" +# dependencies = [ +# "libtmux", +# ] +# /// import logging import logging.config @@ -132,11 +138,13 @@ def enable_user_rename_hook(server: Server): Indicator if we should rename the window or not """ current_file = Path(__file__).absolute() + launcher = os.environ.get('TMUX_WINDOW_NAME_LAUNCHER', '').strip() + invocation = f'{launcher} {current_file}' if launcher else str(current_file) server.cmd( 'set-hook', '-g', f'after-rename-window[{HOOK_INDEX}]', - f'if-shell "[ #{{n:window_name}} -gt 0 ]" "set -w @tmux_window_name_enabled 0" "set -w @tmux_window_name_enabled 1; run-shell "{current_file}"', + f'if-shell "[ #{{n:window_name}} -gt 0 ]" "set -w @tmux_window_name_enabled 0" "set -w @tmux_window_name_enabled 1; run-shell \\"{invocation}\\""', ) @@ -499,4 +507,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/tmux_window_name.tmux b/tmux_window_name.tmux index 1ec3502..7328cf6 100755 --- a/tmux_window_name.tmux +++ b/tmux_window_name.tmux @@ -2,22 +2,28 @@ CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -LIBTMUX_AVAILABLE=$(python -c "import importlib.util; print(importlib.util.find_spec('libtmux') is not None)" 2>/dev/null) -if [ "$LIBTMUX_AVAILABLE" = "False" ]; then - tmux display "ERROR: tmux-window-name - Python dependency libtmux not found (Check the README)" - exit 0 +if command -v uv >/dev/null 2>&1; then + LAUNCHER="uv run --script" +else + LAUNCHER="python3" + LIBTMUX_AVAILABLE=$(python3 -c "import importlib.util; print(importlib.util.find_spec('libtmux') is not None)" 2>/dev/null) + if [ "$LIBTMUX_AVAILABLE" = "False" ]; then + tmux display "ERROR: tmux-window-name - Python dependency libtmux not found (Check the README)" + exit 0 + fi fi +export TMUX_WINDOW_NAME_LAUNCHER="$LAUNCHER" tmux set -g automatic-rename on # Set automatic-rename on to make #{automatic-rename} be on when a new window is been open without a name tmux set-hook -g 'after-new-window[8921]' 'set -wF @tmux_window_name_enabled \#\{automatic-rename\} ; set -w automatic-rename off' -tmux set-hook -g 'after-select-window[8921]' "run-shell -b ""$CURRENT_DIR""/scripts/rename_session_windows.py" +tmux set-hook -g 'after-select-window[8921]' "run-shell -b \"$LAUNCHER $CURRENT_DIR/scripts/rename_session_windows.py\"" ############################################################################################ ### Hacks for preserving users custom window names, read more at enable_user_rename_hook ### ############################################################################################ -"$CURRENT_DIR"/scripts/rename_session_windows.py --enable_rename_hook +$LAUNCHER "$CURRENT_DIR"/scripts/rename_session_windows.py --enable_rename_hook # Disabling rename hooks when tmux-ressurect restores the sessions -tmux set -g @resurrect-hook-pre-restore-all ""$CURRENT_DIR"/scripts/rename_session_windows.py --disable_rename_hook" -tmux set -g @resurrect-hook-post-restore-all ""$CURRENT_DIR"/scripts/rename_session_windows.py --post_restore" +tmux set -g @resurrect-hook-pre-restore-all "$LAUNCHER $CURRENT_DIR/scripts/rename_session_windows.py --disable_rename_hook" +tmux set -g @resurrect-hook-post-restore-all "$LAUNCHER $CURRENT_DIR/scripts/rename_session_windows.py --post_restore" From 6b06cd93e840ef377aaed0e641eb5088aa979420 Mon Sep 17 00:00:00 2001 From: Al Bashkir <41126916+al-bashkir@users.noreply.github.com> Date: Mon, 4 May 2026 18:02:47 +0300 Subject: [PATCH 2/2] docs: add uv run --script variants to runtime snippets The nvim Lua autocmd, vim job_start, and zsh chpwd snippets all invoked the script via its python3 shebang, which fails when libtmux is not installed system-wide (the uv path skips that install). Add a parallel 'uv run --script' variant under each snippet so users on the uv path can pick the one that works for them. Original direct-shebang snippets are kept as-is. Refs #56 --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index ee1e2c8..e2cf935 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,20 @@ vim.api.nvim_create_autocmd({ 'VimEnter', 'VimLeave' }, { }) ``` +Or via `uv run --script` (resolves `libtmux` from PEP 723 metadata, no system install needed): +```lua +local loop = vim.uv + +vim.api.nvim_create_autocmd({ 'VimEnter', 'VimLeave' }, { + callback = function() + if vim.env.TMUX_PLUGIN_MANAGER_PATH then + local script = vim.env.TMUX_PLUGIN_MANAGER_PATH .. '/tmux-window-name/scripts/rename_session_windows.py' + loop.spawn('uv', { args = { 'run', '--script', script } }) + end + end, +}) +``` + ### Vim Script autocmd example ```vim " update the script path based on your setup @@ -95,6 +109,13 @@ if !empty($TMUX) && has('job') endif ``` +Or via `uv run --script`: +```vim +if !empty($TMUX) && has('job') + autocmd VimEnter,VimLeave * call job_start('uv run --script ' . expand('$HOME/.config/tmux/plugins/tmux-window-name/scripts/rename_session_windows.py')) +endif +``` + ### Automatic rename after changing dir By default `tmux-window-name` hooks `after-select-window` which trigged when switching windows, you can add hook in your `.shellrc` to execute `tmux-window-name` ##### .zshrc @@ -106,6 +127,15 @@ tmux-window-name() { add-zsh-hook chpwd tmux-window-name ``` +Or via `uv run --script`: +```bash +tmux-window-name() { + (uv run --script $TMUX_PLUGIN_MANAGER_PATH/tmux-window-name/scripts/rename_session_windows.py &) +} + +add-zsh-hook chpwd tmux-window-name +``` + #### Hooks Used Make sure the hooks that used aren't overridden. * @resurrect-hook-pre-restore-all