tmux_styler.Styler

Styler object for styling tmux.

  1"""
  2Styler object for styling tmux.
  3"""
  4
  5import json
  6import os
  7from typing import Dict, List
  8from enum import Enum
  9
 10from .ContextVars import ContextVar
 11from .Statusbar.Statusbar import *
 12
 13
 14class PaneBorder(Enum):
 15    OFF = "off"
 16    TOP = "top"
 17    BOTTOM = "bottom"
 18
 19    def __str__(self):
 20        return self.value
 21
 22
 23class PaneBorderLineStyle(Enum):
 24    """
 25    Pane border type/style.
 26
 27    - SINGLE: single lines using ACS or UTF-8 characters
 28    - DOUBLE: double lines using UTF-8 characters
 29    - HEAVY: heavy lines using UTF-8 characters
 30    - SIMPLE: simple ASCII characters
 31    - NUMBER: the pane number
 32
 33    DOUBLE and HEAVY will fall back to standard ACS line
 34    drawing when UTF-8 is not supported.
 35    """
 36    SINGLE = "single"
 37    DOUBLE = "double"
 38    HEAVY = "heavy"
 39    SIMPLE = "simple"
 40    NUMBER = "number"
 41
 42    def __str__(self):
 43        return self.value
 44
 45
 46class Styler:
 47    """
 48    Styler for tmux.
 49    """
 50
 51    status_bar: Statusbar | None = None
 52    """
 53    Statusbar object for styling the status bar.
 54    """
 55
 56    renumber_windows: bool = True
 57    """
 58    Whether to renumber windows automatically when a window is closed. Defaults to True.
 59    """
 60
 61    auto_rename_window: bool = True
 62    """
 63    Whether to automatically rename windows. Defaults to True.
 64    """
 65
 66    _auto_rename_window_content: str = str(ContextVar.PANE_CURRENT_COMMAND)
 67
 68    @property
 69    def auto_rename_window_content(cls) -> str | ContextVar | List[ContextVar | str]:
 70        """
 71        What to rename windows to. Defaults to `ContextVar.PANE_CURRENT_COMMAND`.
 72        """
 73        return cls._auto_rename_window_content
 74
 75    @auto_rename_window_content.setter
 76    def auto_rename_window_content(cls, value: str | ContextVar | List[ContextVar | str]):
 77        if isinstance(value, List):
 78            cls._auto_rename_window_content = "".join(map(str, value))
 79        else:
 80            cls._auto_rename_window_content = str(value)
 81
 82    pane_border: PaneBorder = PaneBorder.TOP
 83    """
 84    Pane border position or off. Defaults to `PaneBorder.TOP`.
 85    """
 86
 87    pane_border_line_style: PaneBorderLineStyle = PaneBorderLineStyle.SINGLE
 88    """
 89    Pane border line type/style. Defaults to `PaneBorderLineStyle.SINGLE`.
 90    """
 91
 92    pane_border_content: str | ContextVar | List[ContextVar | str] = [
 93        ContextVar.PANE_INDEX, " ", ContextVar.PANE_CURRENT_COMMAND]
 94    """
 95    Pane border content. Defaults to `[ContextVar.PANE_INDEX, " ", ContextVar.PANE_CURRENT_COMMAND]`,
 96    which will display the pane index, a space, and the currently running command e.g. "1 nvim".
 97    """
 98
 99    current_command_max_depth: int = 1
100    """
101    Whenever `ContextVar.PANE_CURRENT_COMMAND` is used, this is the maximum depth to search for the
102    currently running command in the process tree. Defaults to 1.
103
104    Useful to change when you are commonly running processes/commands that spawn other processes
105    e.g. you use fig for terminal command completion, tmux given a depth of 1 only looks at 
106    first process spawned by a pane's root process. In this case tmux will see fig at depth 0
107    and report it's child process, which would just be a shell (zsh/bash/etc), so tmux will always 
108    show the shell as the current command. Setting this to 2 will show the command/process below 
109    the shell e.g. python or node or an editor.
110
111    If you aren't using fig than a depth of 1 is probably fine as the "root" process tmux sees will
112    be the shell and the child process will be the command you are currently running.
113    """
114
115    current_command_glyph: bool = True
116    """
117    Whether to show a glyph corresponding to the current command whenever `ContextVar.PANE_CURRENT_COMMAND`
118    is used. Requires a Nerd Font/Patched Font. Defaults to True.
119    """
120
121    current_command_glyphs: Dict[str, str] | None = None
122    """
123    Add or change glyphs for `ContextVar.PANE_CURRENT_COMMAND`. Common processes are already included by default.
124    common editors (vim/neovim, emacs), common language interpreters/runtimes/compilers (clang/gcc, python, 
125    node, rust, go, etc.), common tools (git, less, docker), shells (bash, zsh, fish, etc.) and many more.
126
127    If you want to add a glyph for a process or change a default, pass a dictionary mapping process names to glyphs.
128
129    e.g. if you want to use a different icon for "node":
130    ```python
131    styler = Styler()
132    styler.current_command_glyphs = {"node": "󰇷"}
133    ```
134    """
135
136    def style(self):
137        """
138        Style tmux. Call at the end of your config file to style tmux.
139        """
140        current_dir = os.path.dirname(os.path.abspath(__file__))
141        path = os.path.join(current_dir, ".user")
142        # create the .user directory if it doesn't exist
143        if not os.path.exists(path):
144            os.mkdir(path)
145
146        # Save the segment data as JSON
147        if self.status_bar:
148            with open(os.path.join(path, "segment_data.json"), "w") as f:
149                f.write(json.dumps(self.status_bar.segment_data))
150
151        # Pickle the statusbar object
152        if self.status_bar:
153            with open(os.path.join(path, "statusbar.pickle"), "wb") as f:
154                f.write(self.status_bar._Statusbar__pickle())
155
156        # Save the current command glyphs/settings as JSON
157        if self.current_command_max_depth < 1:
158            self.current_command_max_depth = 1
159        with open(os.path.join(path, "command_settings.json"), "w") as f:
160            f.write(json.dumps({
161                "glyphs": self.current_command_glyphs,
162                "glyph": self.current_command_glyph,
163                "max_depth": self.current_command_max_depth,
164            }))
165
166        #  Pane border content to string
167        if isinstance(self.pane_border_content, List):
168            self.pane_border_content = "".join(
169                map(str, self.pane_border_content))
170        else:
171            self.pane_border_content = str(self.pane_border_content)
172        self.pane_border_content = f" {self.pane_border_content} "
173
174        commands = [
175            # Load commands for the statusbar
176            *self.status_bar._Statusbar__commands(),
177
178            # Auto rename windows
179            f'tmux set -g automatic-rename {"on" if self.auto_rename_window else "off"}',
180            # Renumber windows
181            f'tmux set -g renumber-windows {"on" if self.renumber_windows else "off"}',
182            # Auto rename format
183            f'tmux set -g automatic-rename-format "{self._auto_rename_window_content}"',
184
185            # Pane border
186            f'tmux set -g pane-border-status "{self.pane_border}"',
187            # Pane border style
188            f'tmux set -g pane-border-line "{self.pane_border_line_style}"',
189            # Pane border content
190            f'tmux set -g pane-border-format "{self.pane_border_content}"',
191
192            # Term Colors
193            'tmux set -g default-terminal "screen-256color"',
194        ]
195
196        for command in commands:
197            proc = subprocess.Popen(command, shell=True,
198                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
199            proc.wait()
200            proc.terminate()
class PaneBorder(enum.Enum):
15class PaneBorder(Enum):
16    OFF = "off"
17    TOP = "top"
18    BOTTOM = "bottom"
19
20    def __str__(self):
21        return self.value

An enumeration.

OFF = <PaneBorder.OFF: 'off'>
TOP = <PaneBorder.TOP: 'top'>
BOTTOM = <PaneBorder.BOTTOM: 'bottom'>
Inherited Members
enum.Enum
name
value
class PaneBorderLineStyle(enum.Enum):
24class PaneBorderLineStyle(Enum):
25    """
26    Pane border type/style.
27
28    - SINGLE: single lines using ACS or UTF-8 characters
29    - DOUBLE: double lines using UTF-8 characters
30    - HEAVY: heavy lines using UTF-8 characters
31    - SIMPLE: simple ASCII characters
32    - NUMBER: the pane number
33
34    DOUBLE and HEAVY will fall back to standard ACS line
35    drawing when UTF-8 is not supported.
36    """
37    SINGLE = "single"
38    DOUBLE = "double"
39    HEAVY = "heavy"
40    SIMPLE = "simple"
41    NUMBER = "number"
42
43    def __str__(self):
44        return self.value

Pane border type/style.

  • SINGLE: single lines using ACS or UTF-8 characters
  • DOUBLE: double lines using UTF-8 characters
  • HEAVY: heavy lines using UTF-8 characters
  • SIMPLE: simple ASCII characters
  • NUMBER: the pane number

DOUBLE and HEAVY will fall back to standard ACS line drawing when UTF-8 is not supported.

SINGLE = <PaneBorderLineStyle.SINGLE: 'single'>
DOUBLE = <PaneBorderLineStyle.DOUBLE: 'double'>
HEAVY = <PaneBorderLineStyle.HEAVY: 'heavy'>
SIMPLE = <PaneBorderLineStyle.SIMPLE: 'simple'>
NUMBER = <PaneBorderLineStyle.NUMBER: 'number'>
Inherited Members
enum.Enum
name
value
class Styler:
 47class Styler:
 48    """
 49    Styler for tmux.
 50    """
 51
 52    status_bar: Statusbar | None = None
 53    """
 54    Statusbar object for styling the status bar.
 55    """
 56
 57    renumber_windows: bool = True
 58    """
 59    Whether to renumber windows automatically when a window is closed. Defaults to True.
 60    """
 61
 62    auto_rename_window: bool = True
 63    """
 64    Whether to automatically rename windows. Defaults to True.
 65    """
 66
 67    _auto_rename_window_content: str = str(ContextVar.PANE_CURRENT_COMMAND)
 68
 69    @property
 70    def auto_rename_window_content(cls) -> str | ContextVar | List[ContextVar | str]:
 71        """
 72        What to rename windows to. Defaults to `ContextVar.PANE_CURRENT_COMMAND`.
 73        """
 74        return cls._auto_rename_window_content
 75
 76    @auto_rename_window_content.setter
 77    def auto_rename_window_content(cls, value: str | ContextVar | List[ContextVar | str]):
 78        if isinstance(value, List):
 79            cls._auto_rename_window_content = "".join(map(str, value))
 80        else:
 81            cls._auto_rename_window_content = str(value)
 82
 83    pane_border: PaneBorder = PaneBorder.TOP
 84    """
 85    Pane border position or off. Defaults to `PaneBorder.TOP`.
 86    """
 87
 88    pane_border_line_style: PaneBorderLineStyle = PaneBorderLineStyle.SINGLE
 89    """
 90    Pane border line type/style. Defaults to `PaneBorderLineStyle.SINGLE`.
 91    """
 92
 93    pane_border_content: str | ContextVar | List[ContextVar | str] = [
 94        ContextVar.PANE_INDEX, " ", ContextVar.PANE_CURRENT_COMMAND]
 95    """
 96    Pane border content. Defaults to `[ContextVar.PANE_INDEX, " ", ContextVar.PANE_CURRENT_COMMAND]`,
 97    which will display the pane index, a space, and the currently running command e.g. "1 nvim".
 98    """
 99
100    current_command_max_depth: int = 1
101    """
102    Whenever `ContextVar.PANE_CURRENT_COMMAND` is used, this is the maximum depth to search for the
103    currently running command in the process tree. Defaults to 1.
104
105    Useful to change when you are commonly running processes/commands that spawn other processes
106    e.g. you use fig for terminal command completion, tmux given a depth of 1 only looks at 
107    first process spawned by a pane's root process. In this case tmux will see fig at depth 0
108    and report it's child process, which would just be a shell (zsh/bash/etc), so tmux will always 
109    show the shell as the current command. Setting this to 2 will show the command/process below 
110    the shell e.g. python or node or an editor.
111
112    If you aren't using fig than a depth of 1 is probably fine as the "root" process tmux sees will
113    be the shell and the child process will be the command you are currently running.
114    """
115
116    current_command_glyph: bool = True
117    """
118    Whether to show a glyph corresponding to the current command whenever `ContextVar.PANE_CURRENT_COMMAND`
119    is used. Requires a Nerd Font/Patched Font. Defaults to True.
120    """
121
122    current_command_glyphs: Dict[str, str] | None = None
123    """
124    Add or change glyphs for `ContextVar.PANE_CURRENT_COMMAND`. Common processes are already included by default.
125    common editors (vim/neovim, emacs), common language interpreters/runtimes/compilers (clang/gcc, python, 
126    node, rust, go, etc.), common tools (git, less, docker), shells (bash, zsh, fish, etc.) and many more.
127
128    If you want to add a glyph for a process or change a default, pass a dictionary mapping process names to glyphs.
129
130    e.g. if you want to use a different icon for "node":
131    ```python
132    styler = Styler()
133    styler.current_command_glyphs = {"node": "󰇷"}
134    ```
135    """
136
137    def style(self):
138        """
139        Style tmux. Call at the end of your config file to style tmux.
140        """
141        current_dir = os.path.dirname(os.path.abspath(__file__))
142        path = os.path.join(current_dir, ".user")
143        # create the .user directory if it doesn't exist
144        if not os.path.exists(path):
145            os.mkdir(path)
146
147        # Save the segment data as JSON
148        if self.status_bar:
149            with open(os.path.join(path, "segment_data.json"), "w") as f:
150                f.write(json.dumps(self.status_bar.segment_data))
151
152        # Pickle the statusbar object
153        if self.status_bar:
154            with open(os.path.join(path, "statusbar.pickle"), "wb") as f:
155                f.write(self.status_bar._Statusbar__pickle())
156
157        # Save the current command glyphs/settings as JSON
158        if self.current_command_max_depth < 1:
159            self.current_command_max_depth = 1
160        with open(os.path.join(path, "command_settings.json"), "w") as f:
161            f.write(json.dumps({
162                "glyphs": self.current_command_glyphs,
163                "glyph": self.current_command_glyph,
164                "max_depth": self.current_command_max_depth,
165            }))
166
167        #  Pane border content to string
168        if isinstance(self.pane_border_content, List):
169            self.pane_border_content = "".join(
170                map(str, self.pane_border_content))
171        else:
172            self.pane_border_content = str(self.pane_border_content)
173        self.pane_border_content = f" {self.pane_border_content} "
174
175        commands = [
176            # Load commands for the statusbar
177            *self.status_bar._Statusbar__commands(),
178
179            # Auto rename windows
180            f'tmux set -g automatic-rename {"on" if self.auto_rename_window else "off"}',
181            # Renumber windows
182            f'tmux set -g renumber-windows {"on" if self.renumber_windows else "off"}',
183            # Auto rename format
184            f'tmux set -g automatic-rename-format "{self._auto_rename_window_content}"',
185
186            # Pane border
187            f'tmux set -g pane-border-status "{self.pane_border}"',
188            # Pane border style
189            f'tmux set -g pane-border-line "{self.pane_border_line_style}"',
190            # Pane border content
191            f'tmux set -g pane-border-format "{self.pane_border_content}"',
192
193            # Term Colors
194            'tmux set -g default-terminal "screen-256color"',
195        ]
196
197        for command in commands:
198            proc = subprocess.Popen(command, shell=True,
199                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
200            proc.wait()
201            proc.terminate()

Styler for tmux.

status_bar: tmux_styler.Statusbar.Statusbar.Statusbar | None = None

Statusbar object for styling the status bar.

renumber_windows: bool = True

Whether to renumber windows automatically when a window is closed. Defaults to True.

auto_rename_window: bool = True

Whether to automatically rename windows. Defaults to True.

auto_rename_window_content: Union[str, tmux_styler.ContextVars.ContextVar, List[tmux_styler.ContextVars.ContextVar | str]]
69    @property
70    def auto_rename_window_content(cls) -> str | ContextVar | List[ContextVar | str]:
71        """
72        What to rename windows to. Defaults to `ContextVar.PANE_CURRENT_COMMAND`.
73        """
74        return cls._auto_rename_window_content

What to rename windows to. Defaults to ContextVar.PANE_CURRENT_COMMAND.

pane_border: PaneBorder = <PaneBorder.TOP: 'top'>

Pane border position or off. Defaults to PaneBorder.TOP.

pane_border_line_style: PaneBorderLineStyle = <PaneBorderLineStyle.SINGLE: 'single'>

Pane border line type/style. Defaults to PaneBorderLineStyle.SINGLE.

pane_border_content: Union[str, tmux_styler.ContextVars.ContextVar, List[tmux_styler.ContextVars.ContextVar | str]] = [<ContextVar.PANE_INDEX: 'pane_index'>, ' ', <ContextVar.PANE_CURRENT_COMMAND: 'pane_current_command'>]

Pane border content. Defaults to [ContextVar.PANE_INDEX, " ", ContextVar.PANE_CURRENT_COMMAND], which will display the pane index, a space, and the currently running command e.g. "1 nvim".

current_command_max_depth: int = 1

Whenever ContextVar.PANE_CURRENT_COMMAND is used, this is the maximum depth to search for the currently running command in the process tree. Defaults to 1.

Useful to change when you are commonly running processes/commands that spawn other processes e.g. you use fig for terminal command completion, tmux given a depth of 1 only looks at first process spawned by a pane's root process. In this case tmux will see fig at depth 0 and report it's child process, which would just be a shell (zsh/bash/etc), so tmux will always show the shell as the current command. Setting this to 2 will show the command/process below the shell e.g. python or node or an editor.

If you aren't using fig than a depth of 1 is probably fine as the "root" process tmux sees will be the shell and the child process will be the command you are currently running.

current_command_glyph: bool = True

Whether to show a glyph corresponding to the current command whenever ContextVar.PANE_CURRENT_COMMAND is used. Requires a Nerd Font/Patched Font. Defaults to True.

current_command_glyphs: Optional[Dict[str, str]] = None

Add or change glyphs for ContextVar.PANE_CURRENT_COMMAND. Common processes are already included by default. common editors (vim/neovim, emacs), common language interpreters/runtimes/compilers (clang/gcc, python, node, rust, go, etc.), common tools (git, less, docker), shells (bash, zsh, fish, etc.) and many more.

If you want to add a glyph for a process or change a default, pass a dictionary mapping process names to glyphs.

e.g. if you want to use a different icon for "node":

styler = Styler()
styler.current_command_glyphs = {"node": "󰇷"}
def style(self):
137    def style(self):
138        """
139        Style tmux. Call at the end of your config file to style tmux.
140        """
141        current_dir = os.path.dirname(os.path.abspath(__file__))
142        path = os.path.join(current_dir, ".user")
143        # create the .user directory if it doesn't exist
144        if not os.path.exists(path):
145            os.mkdir(path)
146
147        # Save the segment data as JSON
148        if self.status_bar:
149            with open(os.path.join(path, "segment_data.json"), "w") as f:
150                f.write(json.dumps(self.status_bar.segment_data))
151
152        # Pickle the statusbar object
153        if self.status_bar:
154            with open(os.path.join(path, "statusbar.pickle"), "wb") as f:
155                f.write(self.status_bar._Statusbar__pickle())
156
157        # Save the current command glyphs/settings as JSON
158        if self.current_command_max_depth < 1:
159            self.current_command_max_depth = 1
160        with open(os.path.join(path, "command_settings.json"), "w") as f:
161            f.write(json.dumps({
162                "glyphs": self.current_command_glyphs,
163                "glyph": self.current_command_glyph,
164                "max_depth": self.current_command_max_depth,
165            }))
166
167        #  Pane border content to string
168        if isinstance(self.pane_border_content, List):
169            self.pane_border_content = "".join(
170                map(str, self.pane_border_content))
171        else:
172            self.pane_border_content = str(self.pane_border_content)
173        self.pane_border_content = f" {self.pane_border_content} "
174
175        commands = [
176            # Load commands for the statusbar
177            *self.status_bar._Statusbar__commands(),
178
179            # Auto rename windows
180            f'tmux set -g automatic-rename {"on" if self.auto_rename_window else "off"}',
181            # Renumber windows
182            f'tmux set -g renumber-windows {"on" if self.renumber_windows else "off"}',
183            # Auto rename format
184            f'tmux set -g automatic-rename-format "{self._auto_rename_window_content}"',
185
186            # Pane border
187            f'tmux set -g pane-border-status "{self.pane_border}"',
188            # Pane border style
189            f'tmux set -g pane-border-line "{self.pane_border_line_style}"',
190            # Pane border content
191            f'tmux set -g pane-border-format "{self.pane_border_content}"',
192
193            # Term Colors
194            'tmux set -g default-terminal "screen-256color"',
195        ]
196
197        for command in commands:
198            proc = subprocess.Popen(command, shell=True,
199                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
200            proc.wait()
201            proc.terminate()

Style tmux. Call at the end of your config file to style tmux.