mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-13 04:03:16 +02:00
Rename pane → window title bar per reviewer feedback
- Rename all options from pane_title_* to window_title_*
- Use foreground/background instead of fg/bg in color option names
- Change color options to to_color_or_none defaulting to None,
falling back to corresponding tab bar colors
- Add bell_symbol, activity_symbol, progress_percent template vars
using existing bell_on_tab and tab_activity_symbol options
- Add custom script support via window_title_bar.py in config dir
(draw_window_title function exposed as {custom} in templates)
- Update C structs, Python references, and regenerate config files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1467,57 +1467,71 @@ actually resize the window itself, but instead, the layout row/column/slot, whic
|
||||
in multiple windows getting resized.
|
||||
''')
|
||||
|
||||
opt('pane_title_bar', 'none',
|
||||
opt('window_title_bar', 'none',
|
||||
choices=('none', 'top', 'bottom'),
|
||||
long_text='''
|
||||
Show a title bar for each window/pane when there are multiple windows in a tab.
|
||||
Show a title bar for each window when there are multiple windows in a tab.
|
||||
The title bar displays the window title and is hidden when only a single window
|
||||
is visible. The value controls the position of the title bar relative to the
|
||||
window content. Set to :code:`none` to disable.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('pane_title_template', '"{title}"',
|
||||
opt('window_title_template', '"{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.window}{progress_percent}{title}"',
|
||||
option_type='tab_title_template',
|
||||
long_text='''
|
||||
A template to render the pane title bar text. Uses the same template syntax as
|
||||
A template to render the window title bar text. Uses the same template syntax as
|
||||
:opt:`tab_title_template`. Available variables include: :code:`{title}`,
|
||||
:code:`{index}`, :code:`{layout_name}`, :code:`{num_windows}`,
|
||||
:code:`{num_window_groups}`, :code:`{tab.active_wd}`, etc.
|
||||
:code:`{bell_symbol}`, :code:`{activity_symbol}`, :code:`{progress_percent}`,
|
||||
:code:`{custom}`, :code:`{fmt}`, :code:`{is_active}`.
|
||||
You can also provide a custom :code:`draw_window_title(data)` function in
|
||||
:file:`window_title_bar.py` in the kitty config directory, exposed as :code:`{custom}`.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('active_pane_title_template', 'none',
|
||||
opt('active_window_title_template', 'none',
|
||||
option_type='tab_title_template',
|
||||
long_text='''
|
||||
Template to use for the active pane title bar. If not set (the value
|
||||
:code:`none`), the :opt:`pane_title_template` is used.
|
||||
Template to use for the active window title bar. If not set (the value
|
||||
:code:`none`), the :opt:`window_title_template` is used.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('pane_title_bar_active_fg', '#000000',
|
||||
option_type='to_color',
|
||||
long_text='Foreground color for the active pane title bar.'
|
||||
opt('window_title_bar_active_foreground', 'none',
|
||||
option_type='to_color_or_none', ctype='color_or_none_as_int',
|
||||
long_text='''
|
||||
Foreground color for the active window title bar. Defaults to
|
||||
:opt:`active_tab_foreground` when set to :code:`none`.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('pane_title_bar_active_bg', '#00ff00',
|
||||
option_type='to_color',
|
||||
long_text='Background color for the active pane title bar.'
|
||||
opt('window_title_bar_active_background', 'none',
|
||||
option_type='to_color_or_none', ctype='color_or_none_as_int',
|
||||
long_text='''
|
||||
Background color for the active window title bar. Defaults to
|
||||
:opt:`active_tab_background` when set to :code:`none`.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('pane_title_bar_inactive_fg', '#cccccc',
|
||||
option_type='to_color',
|
||||
long_text='Foreground color for inactive pane title bars.'
|
||||
opt('window_title_bar_inactive_foreground', 'none',
|
||||
option_type='to_color_or_none', ctype='color_or_none_as_int',
|
||||
long_text='''
|
||||
Foreground color for inactive window title bars. Defaults to
|
||||
:opt:`inactive_tab_foreground` when set to :code:`none`.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('pane_title_bar_inactive_bg', '#333333',
|
||||
option_type='to_color',
|
||||
long_text='Background color for inactive pane title bars.'
|
||||
opt('window_title_bar_inactive_background', 'none',
|
||||
option_type='to_color_or_none', ctype='color_or_none_as_int',
|
||||
long_text='''
|
||||
Background color for inactive window title bars. Defaults to
|
||||
:opt:`inactive_tab_background` when set to :code:`none`.
|
||||
'''
|
||||
)
|
||||
|
||||
opt('pane_title_bar_align', 'center',
|
||||
opt('window_title_bar_align', 'center',
|
||||
choices=('left', 'center', 'right'),
|
||||
long_text='Horizontal alignment of the text in pane title bars.'
|
||||
long_text='Horizontal alignment of the text in window title bars.'
|
||||
)
|
||||
egr() # }}}
|
||||
|
||||
|
||||
70
kitty/options/parse.py
generated
70
kitty/options/parse.py
generated
@@ -36,9 +36,6 @@ class Parser:
|
||||
def active_border_color(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['active_border_color'] = to_color_or_none(val)
|
||||
|
||||
def active_pane_title_template(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['active_pane_title_template'] = tab_title_template(val)
|
||||
|
||||
def active_tab_background(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['active_tab_background'] = to_color(val)
|
||||
|
||||
@@ -51,6 +48,9 @@ class Parser:
|
||||
def active_tab_title_template(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['active_tab_title_template'] = active_tab_title_template(val)
|
||||
|
||||
def active_window_title_template(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['active_window_title_template'] = tab_title_template(val)
|
||||
|
||||
def allow_cloning(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
val = val.lower()
|
||||
if val not in self.choices_for_allow_cloning:
|
||||
@@ -1168,37 +1168,6 @@ class Parser:
|
||||
def open_url_with(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['open_url_with'] = to_cmdline(val)
|
||||
|
||||
def pane_title_bar(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
val = val.lower()
|
||||
if val not in self.choices_for_pane_title_bar:
|
||||
raise ValueError(f"The value {val} is not a valid choice for pane_title_bar")
|
||||
ans["pane_title_bar"] = val
|
||||
|
||||
choices_for_pane_title_bar = frozenset(('none', 'top', 'bottom'))
|
||||
|
||||
def pane_title_bar_active_bg(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['pane_title_bar_active_bg'] = to_color(val)
|
||||
|
||||
def pane_title_bar_active_fg(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['pane_title_bar_active_fg'] = to_color(val)
|
||||
|
||||
def pane_title_bar_align(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
val = val.lower()
|
||||
if val not in self.choices_for_pane_title_bar_align:
|
||||
raise ValueError(f"The value {val} is not a valid choice for pane_title_bar_align")
|
||||
ans["pane_title_bar_align"] = val
|
||||
|
||||
choices_for_pane_title_bar_align = frozenset(('left', 'center', 'right'))
|
||||
|
||||
def pane_title_bar_inactive_bg(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['pane_title_bar_inactive_bg'] = to_color(val)
|
||||
|
||||
def pane_title_bar_inactive_fg(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['pane_title_bar_inactive_fg'] = to_color(val)
|
||||
|
||||
def pane_title_template(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['pane_title_template'] = tab_title_template(val)
|
||||
|
||||
def paste_actions(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['paste_actions'] = paste_actions(val)
|
||||
|
||||
@@ -1356,7 +1325,7 @@ class Parser:
|
||||
raise ValueError(f"The value {val} is not a valid choice for tab_bar_align")
|
||||
ans["tab_bar_align"] = val
|
||||
|
||||
choices_for_tab_bar_align = choices_for_pane_title_bar_align
|
||||
choices_for_tab_bar_align = frozenset(('left', 'center', 'right'))
|
||||
|
||||
def tab_bar_background(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['tab_bar_background'] = to_color_or_none(val)
|
||||
@@ -1538,6 +1507,37 @@ class Parser:
|
||||
def window_resize_step_lines(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_resize_step_lines'] = positive_int(val)
|
||||
|
||||
def window_title_bar(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
val = val.lower()
|
||||
if val not in self.choices_for_window_title_bar:
|
||||
raise ValueError(f"The value {val} is not a valid choice for window_title_bar")
|
||||
ans["window_title_bar"] = val
|
||||
|
||||
choices_for_window_title_bar = frozenset(('none', 'top', 'bottom'))
|
||||
|
||||
def window_title_bar_active_background(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_active_background'] = to_color_or_none(val)
|
||||
|
||||
def window_title_bar_active_foreground(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_active_foreground'] = to_color_or_none(val)
|
||||
|
||||
def window_title_bar_align(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
val = val.lower()
|
||||
if val not in self.choices_for_window_title_bar_align:
|
||||
raise ValueError(f"The value {val} is not a valid choice for window_title_bar_align")
|
||||
ans["window_title_bar_align"] = val
|
||||
|
||||
choices_for_window_title_bar_align = choices_for_tab_bar_align
|
||||
|
||||
def window_title_bar_inactive_background(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_inactive_background'] = to_color_or_none(val)
|
||||
|
||||
def window_title_bar_inactive_foreground(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_bar_inactive_foreground'] = to_color_or_none(val)
|
||||
|
||||
def window_title_template(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
ans['window_title_template'] = tab_title_template(val)
|
||||
|
||||
def x11_hide_window_decorations(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
deprecated_hide_window_decorations_aliases('x11_hide_window_decorations', val, ans)
|
||||
|
||||
|
||||
60
kitty/options/to-c-generated.h
generated
60
kitty/options/to-c-generated.h
generated
@@ -993,6 +993,58 @@ convert_from_opts_window_drag_tolerance(PyObject *py_opts, Options *opts) {
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_window_title_bar_active_foreground(PyObject *val, Options *opts) {
|
||||
opts->window_title_bar_active_foreground = color_or_none_as_int(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_window_title_bar_active_foreground(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "window_title_bar_active_foreground");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_window_title_bar_active_foreground(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_window_title_bar_active_background(PyObject *val, Options *opts) {
|
||||
opts->window_title_bar_active_background = color_or_none_as_int(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_window_title_bar_active_background(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "window_title_bar_active_background");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_window_title_bar_active_background(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_window_title_bar_inactive_foreground(PyObject *val, Options *opts) {
|
||||
opts->window_title_bar_inactive_foreground = color_or_none_as_int(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_window_title_bar_inactive_foreground(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "window_title_bar_inactive_foreground");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_window_title_bar_inactive_foreground(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_window_title_bar_inactive_background(PyObject *val, Options *opts) {
|
||||
opts->window_title_bar_inactive_background = color_or_none_as_int(val);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_opts_window_title_bar_inactive_background(PyObject *py_opts, Options *opts) {
|
||||
PyObject *ret = PyObject_GetAttrString(py_opts, "window_title_bar_inactive_background");
|
||||
if (ret == NULL) return;
|
||||
convert_from_python_window_title_bar_inactive_background(ret, opts);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
convert_from_python_tab_bar_edge(PyObject *val, Options *opts) {
|
||||
opts->tab_bar_edge = PyLong_AsLong(val);
|
||||
@@ -1550,6 +1602,14 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_window_drag_tolerance(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_window_title_bar_active_foreground(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_window_title_bar_active_background(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_window_title_bar_inactive_foreground(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_window_title_bar_inactive_background(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_tab_bar_edge(py_opts, opts);
|
||||
if (PyErr_Occurred()) return false;
|
||||
convert_from_opts_tab_bar_margin_height(py_opts, opts);
|
||||
|
||||
42
kitty/options/types.py
generated
42
kitty/options/types.py
generated
@@ -25,13 +25,11 @@ choices_for_default_pointer_shape = typing.Literal['arrow', 'beam', 'text', 'poi
|
||||
choices_for_linux_display_server = typing.Literal['auto', 'wayland', 'x11']
|
||||
choices_for_macos_colorspace = typing.Literal['srgb', 'default', 'displayp3']
|
||||
choices_for_macos_show_window_title_in = typing.Literal['all', 'menubar', 'none', 'window']
|
||||
choices_for_pane_title_bar = typing.Literal['none', 'top', 'bottom']
|
||||
choices_for_pane_title_bar_align = typing.Literal['left', 'center', 'right']
|
||||
choices_for_placement_strategy = typing.Literal['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right']
|
||||
choices_for_pointer_shape_when_grabbed = choices_for_default_pointer_shape
|
||||
choices_for_scrollbar = typing.Literal['scrolled', 'always', 'never', 'hovered', 'scrolled-and-hovered']
|
||||
choices_for_strip_trailing_spaces = typing.Literal['always', 'never', 'smart']
|
||||
choices_for_tab_bar_align = choices_for_pane_title_bar_align
|
||||
choices_for_tab_bar_align = typing.Literal['left', 'center', 'right']
|
||||
choices_for_tab_bar_style = typing.Literal['fade', 'hidden', 'powerline', 'separator', 'slant', 'custom']
|
||||
choices_for_tab_powerline_style = typing.Literal['angled', 'round', 'slanted']
|
||||
choices_for_tab_switch_strategy = typing.Literal['last', 'left', 'previous', 'right']
|
||||
@@ -39,15 +37,17 @@ choices_for_terminfo_type = typing.Literal['path', 'direct', 'none']
|
||||
choices_for_undercurl_style = typing.Literal['thin-sparse', 'thin-dense', 'thick-sparse', 'thick-dense']
|
||||
choices_for_underline_hyperlinks = typing.Literal['hover', 'always', 'never']
|
||||
choices_for_window_logo_position = choices_for_placement_strategy
|
||||
choices_for_window_title_bar = typing.Literal['none', 'top', 'bottom']
|
||||
choices_for_window_title_bar_align = choices_for_tab_bar_align
|
||||
|
||||
option_names = (
|
||||
'action_alias',
|
||||
'active_border_color',
|
||||
'active_pane_title_template',
|
||||
'active_tab_background',
|
||||
'active_tab_font_style',
|
||||
'active_tab_foreground',
|
||||
'active_tab_title_template',
|
||||
'active_window_title_template',
|
||||
'allow_cloning',
|
||||
'allow_hyperlinks',
|
||||
'allow_remote_control',
|
||||
@@ -408,13 +408,6 @@ option_names = (
|
||||
'narrow_symbols',
|
||||
'notify_on_cmd_finish',
|
||||
'open_url_with',
|
||||
'pane_title_bar',
|
||||
'pane_title_bar_active_bg',
|
||||
'pane_title_bar_active_fg',
|
||||
'pane_title_bar_align',
|
||||
'pane_title_bar_inactive_bg',
|
||||
'pane_title_bar_inactive_fg',
|
||||
'pane_title_template',
|
||||
'paste_actions',
|
||||
'pixel_scroll',
|
||||
'placement_strategy',
|
||||
@@ -507,16 +500,23 @@ option_names = (
|
||||
'window_padding_width',
|
||||
'window_resize_step_cells',
|
||||
'window_resize_step_lines',
|
||||
'window_title_bar',
|
||||
'window_title_bar_active_background',
|
||||
'window_title_bar_active_foreground',
|
||||
'window_title_bar_align',
|
||||
'window_title_bar_inactive_background',
|
||||
'window_title_bar_inactive_foreground',
|
||||
'window_title_template',
|
||||
)
|
||||
|
||||
|
||||
class Options:
|
||||
active_border_color: kitty.fast_data_types.Color | None = Color(0, 255, 0)
|
||||
active_pane_title_template: str = 'none'
|
||||
active_tab_background: Color = Color(238, 238, 238)
|
||||
active_tab_font_style: tuple[bool, bool] = (True, True)
|
||||
active_tab_foreground: Color = Color(0, 0, 0)
|
||||
active_tab_title_template: str | None = None
|
||||
active_window_title_template: str = 'none'
|
||||
allow_cloning: choices_for_allow_cloning = 'ask'
|
||||
allow_hyperlinks: int = 1
|
||||
allow_remote_control: choices_for_allow_remote_control = 'no'
|
||||
@@ -611,13 +611,6 @@ class Options:
|
||||
mouse_hide_wait: MouseHideWait = MouseHideWait(hide_wait=0.0, show_wait=0.0, show_threshold=40, scroll_show=True) if is_macos else MouseHideWait(hide_wait=3.0, show_wait=0.0, show_threshold=40, scroll_show=True)
|
||||
notify_on_cmd_finish: NotifyOnCmdFinish = NotifyOnCmdFinish(when='never', duration=5.0, action='notify', cmdline=(), clear_on=('focus', 'next'))
|
||||
open_url_with: list[str] = ['default']
|
||||
pane_title_bar: choices_for_pane_title_bar = 'none'
|
||||
pane_title_bar_active_bg: Color = Color(0, 255, 0)
|
||||
pane_title_bar_active_fg: Color = Color(0, 0, 0)
|
||||
pane_title_bar_align: choices_for_pane_title_bar_align = 'center'
|
||||
pane_title_bar_inactive_bg: Color = Color(51, 51, 51)
|
||||
pane_title_bar_inactive_fg: Color = Color(204, 204, 204)
|
||||
pane_title_template: str = '{title}'
|
||||
paste_actions: frozenset[str] = frozenset({'confirm', 'quote-urls-at-prompt'})
|
||||
pixel_scroll: bool = True
|
||||
placement_strategy: choices_for_placement_strategy = 'center'
|
||||
@@ -707,6 +700,13 @@ class Options:
|
||||
window_padding_width: FloatEdges = FloatEdges(left=0, top=0, right=0, bottom=0)
|
||||
window_resize_step_cells: int = 2
|
||||
window_resize_step_lines: int = 2
|
||||
window_title_bar: choices_for_window_title_bar = 'none'
|
||||
window_title_bar_active_background: kitty.fast_data_types.Color | None = None
|
||||
window_title_bar_active_foreground: kitty.fast_data_types.Color | None = None
|
||||
window_title_bar_align: choices_for_window_title_bar_align = 'center'
|
||||
window_title_bar_inactive_background: kitty.fast_data_types.Color | None = None
|
||||
window_title_bar_inactive_foreground: kitty.fast_data_types.Color | None = None
|
||||
window_title_template: str = '{fmt.fg.red}{bell_symbol}{activity_symbol}{fmt.fg.window}{progress_percent}{title}'
|
||||
action_alias: dict[str, str] = {}
|
||||
env: dict[str, str] = {}
|
||||
exe_search_path: dict[str, str] = {}
|
||||
@@ -1127,6 +1127,10 @@ nullable_colors = frozenset({
|
||||
'cursor_trail_color',
|
||||
'visual_bell_color',
|
||||
'active_border_color',
|
||||
'window_title_bar_active_foreground',
|
||||
'window_title_bar_active_background',
|
||||
'window_title_bar_inactive_foreground',
|
||||
'window_title_bar_inactive_background',
|
||||
'tab_bar_background',
|
||||
'tab_bar_margin_color',
|
||||
'selection_foreground',
|
||||
|
||||
Reference in New Issue
Block a user