A new option to draw the tab bar centered or right

Fixes #3946
This commit is contained in:
Kovid Goyal 2021-08-18 07:35:04 +05:30
parent 868626c79c
commit a82bc6738c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 38 additions and 1 deletions

View File

@ -7,6 +7,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
0.23.2 [future] 0.23.2 [future]
---------------------- ----------------------
- A new option :option:`tab_bar_align` to draw the tab bar centered or right
aligned (:iss:`3946`)
- Allow the user to supply a custom Python function to draw tab bar. See - Allow the user to supply a custom Python function to draw tab bar. See
:option:`tab_bar_style` :option:`tab_bar_style`

View File

@ -1058,6 +1058,9 @@ class Screen:
def has_activity_since_last_focus(self) -> bool: def has_activity_since_last_focus(self) -> bool:
pass pass
def insert_characters(self, num: int) -> None:
pass
def set_tab_bar_render_data( def set_tab_bar_render_data(
os_window_id: int, xstart: float, ystart: float, dx: float, dy: float, os_window_id: int, xstart: float, ystart: float, dx: float, dy: float,

View File

@ -907,6 +907,8 @@ The tab bar style, can be one of:
''' '''
) )
opt('tab_bar_align', 'left', choices=('left', 'center', 'right'), long_text='The horizontal alignment of the tab bar')
opt('tab_bar_min_tabs', '2', opt('tab_bar_min_tabs', '2',
option_type='tab_bar_min_tabs', ctype='uint', option_type='tab_bar_min_tabs', ctype='uint',
long_text='The minimum number of tabs that must exist before the tab bar is shown' long_text='The minimum number of tabs that must exist before the tab bar is shown'

View File

@ -1152,6 +1152,14 @@ class Parser:
def tab_activity_symbol(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: def tab_activity_symbol(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['tab_activity_symbol'] = tab_activity_symbol(val) ans['tab_activity_symbol'] = tab_activity_symbol(val)
def tab_bar_align(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
val = val.lower()
if val not in self.choices_for_tab_bar_align:
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 = frozenset(('left', 'center', 'right'))
def tab_bar_background(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: def tab_bar_background(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
ans['tab_bar_background'] = to_color_or_none(val) ans['tab_bar_background'] = to_color_or_none(val)

View File

@ -23,6 +23,7 @@ if typing.TYPE_CHECKING:
choices_for_pointer_shape_when_dragging = typing.Literal['arrow', 'beam', 'hand'] choices_for_pointer_shape_when_dragging = typing.Literal['arrow', 'beam', 'hand']
choices_for_pointer_shape_when_grabbed = typing.Literal['arrow', 'beam', 'hand'] choices_for_pointer_shape_when_grabbed = typing.Literal['arrow', 'beam', 'hand']
choices_for_strip_trailing_spaces = typing.Literal['always', 'never', 'smart'] choices_for_strip_trailing_spaces = typing.Literal['always', 'never', 'smart']
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_bar_style = typing.Literal['fade', 'hidden', 'powerline', 'separator', 'slant', 'custom']
choices_for_tab_powerline_style = typing.Literal['angled', 'round', 'slanted'] choices_for_tab_powerline_style = typing.Literal['angled', 'round', 'slanted']
choices_for_tab_switch_strategy = typing.Literal['last', 'left', 'previous', 'right'] choices_for_tab_switch_strategy = typing.Literal['last', 'left', 'previous', 'right']
@ -35,6 +36,7 @@ else:
choices_for_pointer_shape_when_dragging = str choices_for_pointer_shape_when_dragging = str
choices_for_pointer_shape_when_grabbed = str choices_for_pointer_shape_when_grabbed = str
choices_for_strip_trailing_spaces = str choices_for_strip_trailing_spaces = str
choices_for_tab_bar_align = str
choices_for_tab_bar_style = str choices_for_tab_bar_style = str
choices_for_tab_powerline_style = str choices_for_tab_powerline_style = str
choices_for_tab_switch_strategy = str choices_for_tab_switch_strategy = str
@ -404,6 +406,7 @@ option_names = ( # {{{
'symbol_map', 'symbol_map',
'sync_to_monitor', 'sync_to_monitor',
'tab_activity_symbol', 'tab_activity_symbol',
'tab_bar_align',
'tab_bar_background', 'tab_bar_background',
'tab_bar_edge', 'tab_bar_edge',
'tab_bar_margin_height', 'tab_bar_margin_height',
@ -536,6 +539,7 @@ class Options:
strip_trailing_spaces: choices_for_strip_trailing_spaces = 'never' strip_trailing_spaces: choices_for_strip_trailing_spaces = 'never'
sync_to_monitor: bool = True sync_to_monitor: bool = True
tab_activity_symbol: typing.Optional[str] = None tab_activity_symbol: typing.Optional[str] = None
tab_bar_align: choices_for_tab_bar_align = 'left'
tab_bar_background: typing.Optional[kitty.rgb.Color] = None tab_bar_background: typing.Optional[kitty.rgb.Color] = None
tab_bar_edge: int = 3 tab_bar_edge: int = 3
tab_bar_margin_height: TabBarMarginHeight = TabBarMarginHeight(outer=0, inner=0) tab_bar_margin_height: TabBarMarginHeight = TabBarMarginHeight(outer=0, inner=0)

View File

@ -3,7 +3,7 @@
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
import os import os
from functools import lru_cache, wraps from functools import lru_cache, partial, wraps
from typing import ( from typing import (
Any, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple Any, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple
) )
@ -415,6 +415,12 @@ class TabBar:
self.draw_func = load_custom_draw_tab() self.draw_func = load_custom_draw_tab()
else: else:
self.draw_func = draw_tab_with_fade self.draw_func = draw_tab_with_fade
if opts.tab_bar_align == 'center':
self.align: Callable[[], None] = partial(self.align_with_factor, 2)
elif opts.tab_bar_align == 'right':
self.align = self.align_with_factor
else:
self.align = lambda: None
def patch_colors(self, spec: Dict[str, Any]) -> None: def patch_colors(self, spec: Dict[str, Any]) -> None:
if 'active_tab_foreground' in spec: if 'active_tab_foreground' in spec:
@ -497,6 +503,17 @@ class TabBar:
break break
s.erase_in_line(0, False) # Ensure no long titles bleed after the last tab s.erase_in_line(0, False) # Ensure no long titles bleed after the last tab
self.cell_ranges = cr self.cell_ranges = cr
self.align()
def align_with_factor(self, factor: int = 1) -> None:
if not self.cell_ranges:
return
end = self.cell_ranges[-1][1]
if end < self.screen.columns - 1:
shift = (self.screen.columns - end) // factor
self.screen.cursor.x = 0
self.screen.insert_characters(shift)
self.cell_ranges = [(s + shift, e + shift) for (s, e) in self.cell_ranges]
def destroy(self) -> None: def destroy(self) -> None:
self.screen.reset_callbacks() self.screen.reset_callbacks()