diff --git a/README.md b/README.md index f51eb47..7b827b0 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ A plugin to name your tmux windows smartly, like IDE's. ## Dependencies * tmux (Tested on 3.0a) -* Python 3.6.8+ (Maybe can be lower, tested on 3.6.8) +* Python 3.7+ * pip * [libtmux](https://github.com/tmux-python/libtmux) >0.16 @@ -129,11 +129,6 @@ _**Note**_: Make sure you are using the `user` python and not `sudo` python or ` python3 -m pip install --user libtmux ``` -### Install dataclasses (for Python 3.6.X only) -```sh -python3 -m pip install dataclasses --user -``` - ### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended) Add plugin to the list of TPM plugins: diff --git a/scripts/path_utils.py b/scripts/path_utils.py index 878c258..a51f1c9 100644 --- a/scripts/path_utils.py +++ b/scripts/path_utils.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python3 +from __future__ import annotations from dataclasses import dataclass from pathlib import Path -from typing import List, Optional, Tuple from libtmux.pane import Pane as TmuxPane @@ -10,7 +9,7 @@ @dataclass class Pane: info: TmuxPane - program: Optional[str] # None when no program is running + program: str | None # None when no program is running @dataclass @@ -25,18 +24,20 @@ def from_pane(pane: Pane): return DisplayedPath(pane, path, Path(path.name)) -def get_uncommon_path(a: Path, b: Path) -> Tuple[Path, Path]: - """Get 2 uncommon path between paths +def get_uncommon_path(a: Path, b: Path) -> tuple[Path, Path]: + """ + Get 2 uncommon path between paths. Args: - a (Path): first path - b (Path): second path + a: first path + b: second path Returns: Tuple of uncommon paths - E.g: - a = 'a/dir1/c', b = 'b/dir2/c' -> ('dir1/c', 'dir2/c') + Examples: + >>> get_uncommon_path(Path('a/dir1/c'), Path('b/dir2/c')) + ('dir1/c', 'dir2/c') """ # Go from -1 to -Maximum length to check each part from the end # E.g: 'a/dir1/c', 'b/dir1/c' will go [:-1], [:-2] and stop @@ -51,14 +52,15 @@ def get_uncommon_path(a: Path, b: Path) -> Tuple[Path, Path]: return Path(*a.parts[x:]), Path(*b.parts[x:]) -def get_exclusive_paths(panes: List[Pane]) -> List[Tuple[Pane, Path]]: - """Get exclusive path for each pane (better explaining in the README) +def get_exclusive_paths(panes: list[Pane]) -> list[tuple[Pane, Path]]: + """ + Get exclusive path for each pane (better explaining in the README). Args: - panes (List[Pane]): list of the panes + panes: list of the panes Returns: - List of tuples with the original pane and display path + List of tuples with the original pane and display path. """ # Start all displays as the last dir (.name) exc_paths = [DisplayedPath.from_pane(pane) for pane in panes] diff --git a/scripts/rename_session_windows.py b/scripts/rename_session_windows.py index 13c6d80..f76046d 100755 --- a/scripts/rename_session_windows.py +++ b/scripts/rename_session_windows.py @@ -1,22 +1,22 @@ #!/usr/bin/env python3 +from __future__ import annotations import logging import logging.config -import tempfile -import subprocess import os import re -from dataclasses import dataclass, field -from pathlib import Path -from typing import Any, Iterator, List, Optional, Tuple +import subprocess +import tempfile from argparse import ArgumentParser from contextlib import contextmanager +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any, Iterator +from libtmux.pane import Pane as TmuxPane from libtmux.server import Server from libtmux.session import Session -from libtmux.pane import Pane as TmuxPane - -from path_utils import get_exclusive_paths, Pane +from path_utils import Pane, get_exclusive_paths OPTIONS_PREFIX = '@tmux_window_name_' HOOK_INDEX = 8921 @@ -37,12 +37,17 @@ def set_option(server: Server, option: str, val: str): server.cmd('set-option', '-g', f'{OPTIONS_PREFIX}{option}', val) -def get_window_option(server: Server, window_id: Optional[str], option: str, default: Any) -> Any: +def get_window_option(server: Server, window_id: str | None, option: str, default: Any) -> Any: return get_window_tmux_option(server, window_id, f'{OPTIONS_PREFIX}{option}', default, do_eval=True) def get_window_tmux_option( - server: Server, window_id: Optional[str], option: str, default: Any, do_eval: bool = False + server: Server, + window_id: str | None, + option: str, + default: Any, + *, + do_eval: bool = False, ) -> Any: arguments = ['show-option', '-wqv'] @@ -62,7 +67,7 @@ def get_window_tmux_option( return out[0] -def set_window_tmux_option(server: Server, window_id: Optional[str], option: str, value: str) -> Any: +def set_window_tmux_option(server: Server, window_id: str | None, option: str, value: str) -> Any: arguments = ['set-option', '-wq'] if window_id is not None: arguments.append('-t') @@ -128,12 +133,12 @@ def tmux_guard(server: Server) -> Iterator[bool]: @dataclass class Options: - shells: List[str] = field(default_factory=lambda: ['bash', 'fish', 'sh', 'zsh']) - dir_programs: List[str] = field(default_factory=lambda: ['nvim', 'vim', 'vi', 'git']) - ignored_programs: List[str] = field(default_factory=lambda: []) + shells: list[str] = field(default_factory=lambda: ['bash', 'fish', 'sh', 'zsh']) + dir_programs: list[str] = field(default_factory=lambda: ['nvim', 'vim', 'vi', 'git']) + ignored_programs: list[str] = field(default_factory=list) max_name_len: int = 20 use_tilde: bool = False - substitute_sets: List[Tuple] = field( + substitute_sets: list[tuple] = field( default_factory=lambda: [ (r'.+ipython([32])', r'ipython\g<1>'), USR_BIN_REMOVER, @@ -141,7 +146,7 @@ class Options: (r'.+poetry shell', 'poetry'), ] ) - dir_substitute_sets: List[Tuple] = field(default_factory=lambda: []) + dir_substitute_sets: list[tuple] = field(default_factory=list) show_program_args: bool = True log_level: str = 'WARNING' @@ -149,7 +154,7 @@ class Options: def from_options(server: Server): fields = Options.__dataclass_fields__ - def default_field_value(f: field): + def default_field_value(f): if callable(f.default_factory): return f.default_factory() return f.default @@ -161,7 +166,7 @@ def default_field_value(f: field): return Options(**fields_values) -def parse_shell_command(shell_cmd: List[bytes]) -> Optional[str]: +def parse_shell_command(shell_cmd: list[bytes]) -> str | None: # Only shell if len(shell_cmd) == 1: return None @@ -172,7 +177,7 @@ def parse_shell_command(shell_cmd: List[bytes]) -> Optional[str]: return ' '.join(shell_cmd_str[1:]) -def get_current_program(running_programs: List[bytes], pane: TmuxPane, options: Options) -> Optional[str]: +def get_current_program(running_programs: list[bytes], pane: TmuxPane, options: Options) -> str | None: if pane.pane_pid is None: raise ValueError(f'Pane id is none, pane: {pane}') @@ -210,7 +215,7 @@ def get_current_program(running_programs: List[bytes], pane: TmuxPane, options: return None -def get_program_if_dir(program_line: str, dir_programs: List[str]) -> Optional[str]: +def get_program_if_dir(program_line: str, dir_programs: list[str]) -> str | None: program = program_line.split() for p in dir_programs: @@ -242,7 +247,7 @@ def rename_window(server: Server, window_id: str, window_name: str, max_name_len ) # Turn on automatic-rename to make resurrect remeber the option -def get_panes_programs(session: Session, options: Options) -> List[Pane]: +def get_panes_programs(session: Session, options: Options) -> list[Pane]: session_active_panes = get_session_active_panes(session) try: running_programs = subprocess.check_output(['ps', '-a', '-oppid,command']).splitlines()[1:] @@ -324,7 +329,7 @@ def get_current_session(server: Server) -> Session: return Session(server, session_id=session_id) -def substitute_name(name: str, substitute_sets: List[Tuple]) -> str: +def substitute_name(name: str, substitute_sets: list[tuple]) -> str: logging.debug(f'substituting {name}') for pattern, replacement in substitute_sets: name = re.sub(pattern, replacement, name) @@ -347,9 +352,21 @@ def main(): server = Server() parser = ArgumentParser('Renames tmux session windows') - parser.add_argument('--print_programs', action='store_true', help='Prints full name of the programs in the session') - parser.add_argument('--enable_rename_hook', action='store_true', help='Enables rename hook, for internal use') - parser.add_argument('--disable_rename_hook', action='store_true', help='Enables rename hook, for internal use') + parser.add_argument( + '--print_programs', + action='store_true', + help='Prints full name of the programs in the session', + ) + parser.add_argument( + '--enable_rename_hook', + action='store_true', + help='Enables rename hook, for internal use', + ) + parser.add_argument( + '--disable_rename_hook', + action='store_true', + help='Enables rename hook, for internal use', + ) parser.add_argument( '--post_restore', action='store_true', @@ -368,9 +385,11 @@ def main(): ) log_level = logging._nameToLevel.get(options.log_level, logging.WARNING) - log_file = os.path.join(tempfile.gettempdir(), 'tmux-window-name') + log_file = Path(tempfile.gettempdir()) / 'tmux-window-name' logging.basicConfig( - level=log_level, filename=log_file, format='%(levelname)s - %(filename)s:%(lineno)d %(funcName)s() %(message)s' + level=log_level, + filename=log_file, + format='%(levelname)s - %(filename)s:%(lineno)d %(funcName)s() %(message)s', ) logging.debug(f'Args: {args}') logging.debug(f'Options: {options}') diff --git a/tests/test_exclusive_paths.py b/tests/test_exclusive_paths.py index ded6f6e..ff0113f 100644 --- a/tests/test_exclusive_paths.py +++ b/tests/test_exclusive_paths.py @@ -1,13 +1,12 @@ -#!/usr/bin/env python3 +from __future__ import annotations # I hate this but i don't want to make it a pip package, its a script. import sys -from typing import List, Optional, Tuple -from dataclasses import dataclass sys.path.append('scripts/') +from dataclasses import dataclass -from path_utils import get_exclusive_paths, Pane +from path_utils import Pane, get_exclusive_paths @dataclass @@ -15,15 +14,17 @@ class FakePane: pane_current_path: str | None -def _fake_pane(path: str, program: Optional[str]): +def _fake_pane(path: str, program: str | None): return Pane(FakePane(path), program) -def _check(expected: List[Tuple[str, Optional[str], str]]): - """check expected displayed paths +def _check(expected: list[tuple[str, str | None, str]]): + """ + Check expected displayed paths. Args: - expected (List[Tuple[str, Optional[str], str]]): list of (full_path, program, expected_display) + expected: list of (full_path, program, expected_display) + E.g: _check([ ('a/dir', 'p1', 'dir'), # Program p1 in a/dir will display dir (will be formated to p1:dir) diff --git a/tests/test_get_uncommon_path.py b/tests/test_get_uncommon_path.py index d329b1a..4dd6b07 100644 --- a/tests/test_get_uncommon_path.py +++ b/tests/test_get_uncommon_path.py @@ -1,11 +1,10 @@ -#!/usr/bin/env python3 - # I hate this but i don't want to make it a pip package, its a script. import sys sys.path.append('scripts/') from pathlib import Path + from path_utils import get_uncommon_path