Allow using templates with text formatting for tab_activity_symbol

Fixes #4507
This commit is contained in:
Kovid Goyal 2022-01-14 08:18:04 +05:30
parent ecf4fcdeb0
commit 017da1159c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 62 additions and 42 deletions

View File

@ -79,6 +79,9 @@ Detailed list of changes
- macOS: Allow opening text files, images and directories with kitty when - macOS: Allow opening text files, images and directories with kitty when
launched using "Open with" in Finder (:iss:`4460`) launched using "Open with" in Finder (:iss:`4460`)
- Allow using templates with text formatting for :opt:`tab_activity_symbol`
(:pull:`4507`)
- macOS: Persist "Secure Keyboard Entry" across restarts to match the behavior - macOS: Persist "Secure Keyboard Entry" across restarts to match the behavior
of Terminal.app (:iss:`4471`) of Terminal.app (:iss:`4471`)

View File

@ -1054,7 +1054,8 @@
long_text=''' long_text='''
Some text or a unicode symbol to show on the tab if a window in the tab that Some text or a unicode symbol to show on the tab if a window in the tab that
does not have focus has some activity. If you want to use leading or trailing spaces does not have focus has some activity. If you want to use leading or trailing spaces
surround the text with quotes. surround the text with quotes. You can also use text formatting via the same templating
system as for :opt:`tab_title_template`.
''' '''
) )

View File

@ -4,7 +4,7 @@
import os import os
from functools import lru_cache, partial, wraps from functools import lru_cache, partial, wraps
from typing import ( from typing import (
Any, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple, Union Any, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple, Union, TYPE_CHECKING
) )
from .borders import Border, BorderColor from .borders import Border, BorderColor
@ -20,6 +20,10 @@
from .utils import color_as_int, log_error from .utils import color_as_int, log_error
if TYPE_CHECKING:
import re
class TabBarData(NamedTuple): class TabBarData(NamedTuple):
title: str title: str
is_active: bool is_active: bool
@ -152,22 +156,24 @@ class ExtraData:
next_tab: Optional[TabBarData] = None next_tab: Optional[TabBarData] = None
def draw_title(draw_data: DrawData, screen: Screen, tab: TabBarData, index: int) -> None: @run_once
if tab.needs_attention and draw_data.bell_on_tab: def attributed_string_pat() -> 're.Pattern[str]':
fg = screen.cursor.fg import re
screen.cursor.fg = draw_data.bell_fg return re.compile('(\x1b\\[[^m]*m)')
screen.draw('🔔 ')
screen.cursor.fg = fg
if tab.has_activity_since_last_focus and draw_data.tab_activity_symbol:
fg = screen.cursor.fg
screen.cursor.fg = draw_data.bell_fg
screen.draw(draw_data.tab_activity_symbol)
screen.cursor.fg = fg
template = draw_data.title_template
if tab.is_active and draw_data.active_title_template is not None: def draw_attributed_string(title: str, screen: Screen) -> None:
template = draw_data.active_title_template if '\x1b' in title:
try: for x in attributed_string_pat().split(title):
if x.startswith('\x1b') and x.endswith('m'):
screen.apply_sgr(x[2:-1])
else:
screen.draw(x)
else:
screen.draw(title)
def draw_title(draw_data: DrawData, screen: Screen, tab: TabBarData, index: int) -> None:
data = { data = {
'index': index, 'index': index,
'layout_name': tab.layout_name, 'layout_name': tab.layout_name,
@ -187,19 +193,29 @@ def draw_title(draw_data: DrawData, screen: Screen, tab: TabBarData, index: int)
'sup': SupSub(data), 'sup': SupSub(data),
'sub': SupSub(data, True), 'sub': SupSub(data, True),
} }
if tab.needs_attention and draw_data.bell_on_tab:
fg = screen.cursor.fg
screen.cursor.fg = draw_data.bell_fg
screen.draw('🔔 ')
screen.cursor.fg = fg
if tab.has_activity_since_last_focus and draw_data.tab_activity_symbol:
template = draw_data.tab_activity_symbol
try:
text = eval(compile_template(template), {'__builtins__': {}}, eval_locals)
except Exception as e:
report_template_failure(template, str(e))
else:
draw_attributed_string(text, screen)
template = draw_data.title_template
if tab.is_active and draw_data.active_title_template is not None:
template = draw_data.active_title_template
try:
title = eval(compile_template(template), {'__builtins__': {}}, eval_locals) title = eval(compile_template(template), {'__builtins__': {}}, eval_locals)
except Exception as e: except Exception as e:
report_template_failure(template, str(e)) report_template_failure(template, str(e))
title = tab.title title = tab.title
if '\x1b' in title: draw_attributed_string(title, screen)
import re
for x in re.split('(\x1b\\[[^m]*m)', title):
if x.startswith('\x1b') and x.endswith('m'):
screen.apply_sgr(x[2:-1])
else:
screen.draw(x)
else:
screen.draw(title)
DrawTabFunc = Callable[[DrawData, Screen, TabBarData, int, int, int, bool, ExtraData], int] DrawTabFunc = Callable[[DrawData, Screen, TabBarData, int, int, int, bool, ExtraData], int]