Replies: 46 comments 74 replies
-
Thanks for sharing. You can use typo: lenght -> length Previous Discussion: how to implement tab drawing in python? # 4366 |
Beta Was this translation helpful? Give feedback.
-
kitty.conf
tar_bar.pyfrom kitty.fast_data_types import Screen
from kitty.tab_bar import DrawData, ExtraData, TabBarData, draw_title
def draw_tab(
draw_data: DrawData, screen: Screen, tab: TabBarData,
before: int, max_title_length: int, index: int, is_last: bool,
extra_data: ExtraData
) -> int:
orig_fg = screen.cursor.fg
orig_bg = screen.cursor.bg
left_sep, right_sep = ('', '')
def draw_sep(which: str) -> None:
screen.cursor.bg = draw_data.default_bg
screen.cursor.fg = orig_bg
screen.draw(which)
screen.cursor.bg = orig_bg
screen.cursor.fg = orig_fg
if max_title_length <= 1:
screen.draw('…')
elif max_title_length == 2:
screen.draw('…|')
elif max_title_length < 6:
draw_sep(left_sep)
screen.draw((' ' if max_title_length == 5 else '') + '…' + (' ' if max_title_length >= 4 else ''))
draw_sep(right_sep)
else:
draw_sep(left_sep)
screen.draw(' ')
draw_title(draw_data, screen, tab, index)
extra = screen.cursor.x - before - max_title_length
print("extra:%d" %(extra))
if extra >= 0:
screen.cursor.x -= extra + 3
screen.draw('…')
elif extra == -1:
screen.cursor.x -= 2
screen.draw('…')
screen.draw(' ')
draw_sep(right_sep)
draw_sep(' ')
return screen.cursor.x Diff Relative to
|
Beta Was this translation helpful? Give feedback.
-
Hi, is there a way to update the time in the tab bar when there's no activity in the terminal ? |
Beta Was this translation helpful? Give feedback.
-
On Mon, Jan 10, 2022 at 06:40:53AM -0800, Pascal Hubrecht wrote:
Hi, is there a way to update the time in the tab bar when there's no activity in the terminal ?
The tab bar is redrawn only when a tab title is changed or the
number of tabs is changed. So in your custom python function you can use
add_timer to force a redraw of it.
the timer would need to call a function like
def redraw_tab_bar():
tm = get_boss().active_tab_manager
if tm is not None:
tm.mark_tab_bar_dirty()
|
Beta Was this translation helpful? Give feedback.
-
I'm having a play with extending the tab bar to include some small status notifications on the right of the tab bar, and I'm trying to reuse the [Edit: Sorry, I just used you as a rubber duck! Now I have the screenshots side by side, I can clearly see that they are different fonts! The new Eg, the original powerline: When rendered by my custom tab function:
See post below for my finished tab config. |
Beta Was this translation helpful? Give feedback.
-
My tabs, based on powerline rounded: The code: import datetime
import json
import subprocess
from collections import defaultdict
from kitty.boss import get_boss
from kitty.fast_data_types import Screen, add_timer
from kitty.tab_bar import (
DrawData,
ExtraData,
Formatter,
TabBarData,
as_rgb,
draw_attributed_string,
draw_tab_with_powerline,
)
timer_id = None
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
global timer_id
# if timer_id is None:
# timer_id = add_timer(_redraw_tab_bar, 2.0, True)
draw_tab_with_powerline(
draw_data, screen, tab, before, max_title_length, index, is_last, extra_data
)
if is_last:
draw_right_status(draw_data, screen)
return screen.cursor.x
def draw_right_status(draw_data: DrawData, screen: Screen) -> None:
# The tabs may have left some formats enabled. Disable them now.
draw_attributed_string(Formatter.reset, screen)
cells = create_cells()
# Drop cells that wont fit
while True:
if not cells:
return
padding = screen.columns - screen.cursor.x - sum(len(c) + 3 for c in cells)
if padding >= 0:
break
cells = cells[1:]
if padding:
screen.draw(" " * padding)
tab_bg = as_rgb(int(draw_data.inactive_bg))
tab_fg = as_rgb(int(draw_data.inactive_fg))
default_bg = as_rgb(int(draw_data.default_bg))
for cell in cells:
# Draw the separator
if cell == cells[0]:
screen.cursor.fg = tab_bg
screen.draw("")
else:
screen.cursor.fg = default_bg
screen.cursor.bg = tab_bg
screen.draw("")
screen.cursor.fg = tab_fg
screen.cursor.bg = tab_bg
screen.draw(f" {cell} ")
def create_cells() -> list[str]:
now = datetime.datetime.now()
return [
currently_playing(),
get_headphone_battery_status(),
now.strftime("%d %b"),
now.strftime("%H:%M"),
]
def get_headphone_battery_status():
try:
battery_pct = int(subprocess.getoutput("headsetcontrol -b -c"))
except Exception:
status = ""
else:
if battery_pct < 0:
status = ""
else:
status = f"{battery_pct}% {''[battery_pct // 10]}"
return f" {status}"
STATE = defaultdict(lambda: "", {"Paused": "", "Playing": ""})
def currently_playing():
# TODO: Work out how to add python libraries so that I can query dbus directly
# For now, implemented in a separate python project: dbus-player-status
status = " "
data = {}
try:
data = json.loads(subprocess.getoutput("dbus-player-status"))
except ValueError:
pass
if data:
if "state" in data:
status = f"{status} {STATE[data['state']]}"
if "title" in data:
status = f"{status} {data['title']}"
if "artist" in data:
status = f"{status} - {data['artist']}"
else:
status = ""
return status
def _redraw_tab_bar(timer_id):
for tm in get_boss().all_tab_managers:
tm.mark_tab_bar_dirty()
## Tab bar
tab_bar_edge bottom
tab_bar_margin_height 5.0 0.0
tab_bar_style custom
tab_powerline_style round
tab_bar_background #003747
tab_title_template "{fmt.fg.default}{index}"
|
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Taking some of the solid work by others, I'm replicating my tmux statusline configs and migrating to kitty (hoping to move to kitty and ditch tmux at some point).
Here's my full kitty config: I'm definitely still working through a ton of stuff; really hoping to build out "sessions" of some sort to flip between (really they correspond to different projects that I'm working on for work or personal). In addition, I'm adding support for kitty overlays to a lot of my tmux-popup based fzf scripts (bin/ftm and bin/slack are the two main ones -- also for weechat, updating weechat-fzf to support kitty as well). |
Beta Was this translation helpful? Give feedback.
-
Is it possible to get the current directory of a given tab in the tab_bar.py? The following doesn't work for a number of reasons. The title changes, based on what is open in the tab, though the cwd does show up in the title occasionally so it must be available def get_active_branch_name(tab: TabBarData):
...
return tab.title.split(...)[1].split(...) # This doesn't work obviously Is there something like Thanks for the work on Kitty and the previous posts examples of their tab bars! |
Beta Was this translation helpful? Give feedback.
-
I've only done some basics tab bar rendering similar to those shared in this thread (adding a clock, etc). Is there any way to hook clicking in the tab bar? I'd like to create some nerd-font/emoji "widgets" or per-tab close/other action buttons. I seem to recall kitty being pretty hard wired for that, but this thread seems a good place to ask before diving in my own implementation or filing an enhancement Issue. |
Beta Was this translation helpful? Give feedback.
-
Replace |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
What I changedI began my tab_bar.py by copying @megalithic , but didn't like the fact that color values were hardcoded into the script. Instead, I now read colors directly from the kitty.conf file. How to configure this thingThe default configuration assumes that your terminal is configured to use Nerd Font patched fonts. The codeThis code assumes you have Kitty configured to use Nerd Fonts and have color16 set in your kitty.conf # pyright: reportMissingImports=false
from datetime import datetime
from kitty.boss import get_boss
from kitty.fast_data_types import Screen, add_timer, get_options
from kitty.utils import color_as_int
from kitty.tab_bar import (
DrawData,
ExtraData,
Formatter,
TabBarData,
as_rgb,
draw_attributed_string,
draw_title,
)
opts = get_options()
icon_fg = as_rgb(color_as_int(opts.color16))
icon_bg = as_rgb(color_as_int(opts.color8))
bat_text_color = as_rgb(color_as_int(opts.color15))
clock_color = as_rgb(color_as_int(opts.color15))
date_color = as_rgb(color_as_int(opts.color8))
SEPARATOR_SYMBOL, SOFT_SEPARATOR_SYMBOL = ("", "")
RIGHT_MARGIN = 1
REFRESH_TIME = 1
ICON = " "
UNPLUGGED_ICONS = {
10: "",
20: "",
30: "",
40: "",
50: "",
60: "",
70: "",
80: "",
90: "",
100: "",
}
PLUGGED_ICONS = {
1: "",
}
UNPLUGGED_COLORS = {
15: as_rgb(color_as_int(opts.color1)),
16: as_rgb(color_as_int(opts.color15)),
}
PLUGGED_COLORS = {
15: as_rgb(color_as_int(opts.color1)),
16: as_rgb(color_as_int(opts.color6)),
99: as_rgb(color_as_int(opts.color6)),
100: as_rgb(color_as_int(opts.color2)),
}
def _draw_icon(screen: Screen, index: int) -> int:
if index != 1:
return 0
fg, bg = screen.cursor.fg, screen.cursor.bg
screen.cursor.fg = icon_fg
screen.cursor.bg = icon_bg
screen.draw(ICON)
screen.cursor.fg, screen.cursor.bg = fg, bg
screen.cursor.x = len(ICON)
return screen.cursor.x
def _draw_left_status(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
if screen.cursor.x >= screen.columns - right_status_length:
return screen.cursor.x
tab_bg = screen.cursor.bg
tab_fg = screen.cursor.fg
default_bg = as_rgb(int(draw_data.default_bg))
if extra_data.next_tab:
next_tab_bg = as_rgb(draw_data.tab_bg(extra_data.next_tab))
needs_soft_separator = next_tab_bg == tab_bg
else:
next_tab_bg = default_bg
needs_soft_separator = False
if screen.cursor.x <= len(ICON):
screen.cursor.x = len(ICON)
screen.draw(" ")
screen.cursor.bg = tab_bg
draw_title(draw_data, screen, tab, index)
if not needs_soft_separator:
screen.draw(" ")
screen.cursor.fg = tab_bg
screen.cursor.bg = next_tab_bg
screen.draw(SEPARATOR_SYMBOL)
else:
prev_fg = screen.cursor.fg
if tab_bg == tab_fg:
screen.cursor.fg = default_bg
elif tab_bg != default_bg:
c1 = draw_data.inactive_bg.contrast(draw_data.default_bg)
c2 = draw_data.inactive_bg.contrast(draw_data.inactive_fg)
if c1 < c2:
screen.cursor.fg = default_bg
screen.draw(" " + SOFT_SEPARATOR_SYMBOL)
screen.cursor.fg = prev_fg
end = screen.cursor.x
return end
def _draw_right_status(screen: Screen, is_last: bool, cells: list) -> int:
if not is_last:
return 0
draw_attributed_string(Formatter.reset, screen)
screen.cursor.x = screen.columns - right_status_length
screen.cursor.fg = 0
for color, status in cells:
screen.cursor.fg = color
screen.draw(status)
screen.cursor.bg = 0
return screen.cursor.x
def _redraw_tab_bar(_):
tm = get_boss().active_tab_manager
if tm is not None:
tm.mark_tab_bar_dirty()
def get_battery_cells() -> list:
try:
with open("/sys/class/power_supply/BAT0/status", "r") as f:
status = f.read()
with open("/sys/class/power_supply/BAT0/capacity", "r") as f:
percent = int(f.read())
if status == "Discharging\n":
# TODO: declare the lambda once and don't repeat the code
icon_color = UNPLUGGED_COLORS[
min(UNPLUGGED_COLORS.keys(), key=lambda x: abs(x - percent))
]
icon = UNPLUGGED_ICONS[
min(UNPLUGGED_ICONS.keys(), key=lambda x: abs(x - percent))
]
elif status == "Not charging\n":
icon_color = UNPLUGGED_COLORS[
min(UNPLUGGED_COLORS.keys(), key=lambda x: abs(x - percent))
]
icon = PLUGGED_ICONS[
min(PLUGGED_ICONS.keys(), key=lambda x: abs(x - percent))
]
else:
icon_color = PLUGGED_COLORS[
min(PLUGGED_COLORS.keys(), key=lambda x: abs(x - percent))
]
icon = PLUGGED_ICONS[
min(PLUGGED_ICONS.keys(), key=lambda x: abs(x - percent))
]
percent_cell = (bat_text_color, str(percent) + "% ")
icon_cell = (icon_color, icon)
return [percent_cell, icon_cell]
except FileNotFoundError:
return []
timer_id = None
right_status_length = -1
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
global timer_id
global right_status_length
if timer_id is None:
timer_id = add_timer(_redraw_tab_bar, REFRESH_TIME, True)
clock = datetime.now().strftime(" %H:%M")
date = datetime.now().strftime(" %d.%m.%Y")
cells = get_battery_cells()
cells.append((clock_color, clock))
cells.append((date_color, date))
right_status_length = RIGHT_MARGIN
for cell in cells:
right_status_length += len(str(cell[1]))
_draw_icon(screen, index)
_draw_left_status(
draw_data,
screen,
tab,
before,
max_title_length,
index,
is_last,
extra_data,
)
_draw_right_status(
screen,
is_last,
cells,
)
return screen.cursor.x Relevant kitty.conf changes
|
Beta Was this translation helpful? Give feedback.
-
Wow... All of these looks so good. I am trying to implement equal width tabs on mine , but I have absolutely no idea how to even begin doing it .. anyone has any ideas on how i should go about doing it . Any help would be great... |
Beta Was this translation helpful? Give feedback.
-
I am met with the error message: Errors in kitty.conf when trying to use the tab bar of @megalithic. I have put tab_bar.py in /home/user/.config/kitty. Am I supposed to move the file somewhere else, or am I doing something else wrong? |
Beta Was this translation helpful? Give feedback.
-
On Thu, Mar 14, 2024 at 03:20:19AM -0700, Jen Stehlik wrote:
Hi, I'm using https://github.com/typicode/bg.nvim to set the background color of kitty to match my neovim theme. Can I somehow read the current background color of the tab? I want to change the tab bar colors depending on the background of each tab. :)
Tabs dont have background colors, ever window in a tab can have a different background color.
The best you can do is the background color of the active window in the tab, which you can get
from the tab_id. Use the boss object to get the tab object, gets its
active window and get the active window's background color.
get_boss().all_tabs + tab_id to get tab
then,
tab.active_window.screen.color_profile.default_bg
|
Beta Was this translation helpful? Give feedback.
-
I recently switched from tmux+Kitty to just Kitty, so my goal was to emulate the the most important parts of my tmux setup. I display all windows in the currently active tab, as I use kitty tabs almost like tmux sessions and kitty windows like tmux windows/panes (toggling between stack/tall layouts). I also have a project switcher set up, (originally from kitty-meow) to make opening projects faster. Many thanks to @wochap, @0rphee & everyone for sharing your setups! tab_bar.py"""draw kitty tab"""
# pyright: reportMissingImports=false
# pylint: disable=E0401,C0116,C0103,W0603,R0913
from kitty.boss import get_boss
from kitty.fast_data_types import Screen, get_options
from kitty.tab_bar import (
DrawData,
ExtraData,
TabBarData,
as_rgb,
draw_title,
)
from kitty.utils import color_as_int
opts = get_options()
# colors
# MAGENTA_1 = as_rgb(color_as_int(opts.color5))
TABBAR_BG = as_rgb(color_as_int(opts.tab_bar_background or opts.color0))
ACTIVE_BG = as_rgb(color_as_int(opts.active_tab_background or opts.color8))
ACTIVE_FG = as_rgb(color_as_int(opts.active_tab_foreground or opts.color4))
INACTIVE_BG = as_rgb(color_as_int(
opts.inactive_tab_background or opts.color12))
INACTIVE_FG = as_rgb(color_as_int(opts.inactive_tab_foreground or opts.color7))
ACTIVE_WINDOW_BG = as_rgb(color_as_int(opts.color6))
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
_draw_left_status(
draw_data, screen, tab, before, max_title_length, index, is_last, extra_data
)
if is_last:
_draw_right_status(screen)
return screen.cursor.x
def _draw_right_status(screen: Screen) -> int:
tab_manager = get_boss().active_tab_manager
cells = []
LOWER_RIGHT_TRIANGLE = ''
FORWARD_SLASH = ''
if tab_manager is not None:
windows = tab_manager.active_tab.windows.all_windows
if windows is not None:
for i, window in enumerate(windows):
is_active = window.id == tab_manager.active_window.id
is_first = i == 0
is_prev_active = windows[i -
1].id == tab_manager.active_window.id if not is_first else False
sup = to_sup(str(i + 1))
window_fg = ACTIVE_FG if is_active else INACTIVE_FG
window_bg = ACTIVE_WINDOW_BG if is_active else INACTIVE_BG
if is_first:
sep = LOWER_RIGHT_TRIANGLE
sep_bg = TABBAR_BG
sep_fg = INACTIVE_BG if not is_active else ACTIVE_WINDOW_BG
elif is_active:
sep = LOWER_RIGHT_TRIANGLE
sep_bg = INACTIVE_BG
sep_fg = ACTIVE_WINDOW_BG
elif is_prev_active:
sep = LOWER_RIGHT_TRIANGLE
sep_bg = ACTIVE_WINDOW_BG
sep_fg = INACTIVE_BG
else:
sep = FORWARD_SLASH
sep_bg = INACTIVE_BG
sep_fg = INACTIVE_FG
cells.insert(
i*2, (window_fg, window_bg, f" {sup} {window.title} "))
cells.insert(
i*2, (sep_fg, sep_bg, sep))
# calculate leading spaces to separate tabs from right status
right_status_length = 0
for _, _, cell in cells:
right_status_length += len(cell)
# calculate leading spaces
leading_spaces = 0
leading_spaces = screen.columns - screen.cursor.x - right_status_length
# draw leading spaces
if leading_spaces > 0:
screen.draw(" " * leading_spaces)
# draw right status
for fg, bg, cell in cells:
screen.cursor.fg = fg
screen.cursor.bg = bg
screen.draw(cell)
screen.cursor.fg = 0
screen.cursor.bg = 0
# update cursor position
screen.cursor.x = max(
screen.cursor.x, screen.columns - right_status_length)
return screen.cursor.x
SEPARATOR_SYMBOL, SOFT_SEPARATOR_SYMBOL = ("", "")
ICON = " "
def _draw_left_status(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
# if screen.cursor.x >= screen.columns - right_status_length:
# return screen.cursor.x
tab_bg = screen.cursor.bg
tab_fg = screen.cursor.fg
default_bg = as_rgb(int(draw_data.default_bg))
if extra_data.next_tab:
next_tab_bg = as_rgb(draw_data.tab_bg(extra_data.next_tab))
needs_soft_separator = next_tab_bg == tab_bg
else:
next_tab_bg = default_bg
needs_soft_separator = False
# if screen.cursor.x <= len(ICON):
# screen.cursor.x = len(ICON)
# screen.draw(" ")
screen.cursor.bg = tab_bg
draw_title(draw_data, screen, tab, index)
if not needs_soft_separator:
screen.draw(" ")
screen.cursor.fg = tab_bg
screen.cursor.bg = next_tab_bg
screen.draw(SEPARATOR_SYMBOL)
else:
prev_fg = screen.cursor.fg
if tab_bg == tab_fg:
screen.cursor.fg = default_bg
elif tab_bg != default_bg:
c1 = draw_data.inactive_bg.contrast(draw_data.default_bg)
c2 = draw_data.inactive_bg.contrast(draw_data.inactive_fg)
if c1 < c2:
screen.cursor.fg = default_bg
screen.cursor.fg = prev_fg # separator_fg
screen.draw(" " + SOFT_SEPARATOR_SYMBOL)
end = screen.cursor.x
return end
def to_sup(s):
sups = {u'0': u'\u2070',
u'1': u'\xb9',
u'2': u'\xb2',
u'3': u'\xb3',
u'4': u'\u2074',
u'5': u'\u2075',
u'6': u'\u2076',
u'7': u'\u2077',
u'8': u'\u2078',
u'9': u'\u2079'}
return ''.join(sups.get(char, char) for char in s) kitty.conf
|
Beta Was this translation helpful? Give feedback.
-
A powerline based custom tab bar, icon-centric, requires Nerd fonts. It draws:
Note that original titles (except the Neovim's) are not altered at the shell level, so they look usual in other terminal emulators. |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
import datetime
import json
import subprocess
from collections import defaultdict
from kitty.boss import get_boss
from kitty.fast_data_types import Screen, add_timer, get_options
from kitty.rgb import to_color
from kitty.tab_bar import (
DrawData,
ExtraData,
Formatter,
TabBarData,
as_rgb,
draw_attributed_string,
draw_tab_with_powerline,
)
timer_id = None
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
global timer_id
if timer_id is None:
timer_id = add_timer(_redraw_tab_bar, 2.0, True)
draw_tab_with_powerline(
draw_data, screen, tab, before, max_title_length, index, is_last, extra_data
)
if is_last: draw_right_status(draw_data, screen)
return screen.cursor.x
def draw_right_status(draw_data: DrawData, screen: Screen) -> None:
# The tabs may have left some formats enabled. Disable them now.
draw_attributed_string(Formatter.reset, screen)
tab_bg = as_rgb(int(draw_data.inactive_bg))
tab_fg = as_rgb(int(draw_data.inactive_fg))
default_bg = as_rgb(int(draw_data.default_bg))
cells = create_cells()
# Drop cells that wont fit
while True:
if not cells:
return
padding = screen.columns - screen.cursor.x - sum(len(" ".join([c.get("icon", ""), c["text"]])) + 2 for c in cells)
if padding >= 0:
break
cells = cells[1:]
if padding: screen.draw(" " * padding)
for c in cells:
screen.cursor.bg = default_bg
icon = c.get("icon")
if icon:
fg = to_color(c.get("color")) if c.get("color") else tab_fg
screen.cursor.fg = as_rgb(int(fg))
screen.draw(f" {icon}")
screen.cursor.fg = tab_fg
text = c["text"]
screen.draw(f" {text} ")
def create_cells():
cells = [
get_todo(),
get_date(),
get_time()
]
return [c for c in cells if c is not None]
def get_time():
now = datetime.datetime.now().strftime("%H:%M")
return { "icon": " ", "color": "#669bbc", "text": now }
def get_date():
today = datetime.date.today()
if today.weekday() < 5:
return { "icon": " ", "color": "#2a9d8f", "text": today.strftime("%b %e") }
else:
return { "icon": " ", "color": "#f2e8cf", "text": today.strftime("%b %e") }
def get_todo():
out = subprocess.getoutput("/opt/homebrew/bin/rg -m 1 --pcre2 -N '^(?!@done).*@today' ~/workspace/doc/main.taskpaper |sed 's:^.*- ::;s:@today::'")
if len(out) > 0:
return { "icon": " ", "color": "#e76f51", "text": out }
else:
return None
def _redraw_tab_bar(timer_id):
for tm in get_boss().all_tab_managers:
tm.mark_tab_bar_dirty() kitty.conf
|
Beta Was this translation helpful? Give feedback.
-
👀 Here is a Pac-Man styled tab bar! You guys can take it from 👻 here. |
Beta Was this translation helpful? Give feedback.
-
@kovidgoyal so look at this: λ ~/.config/kitty/ main* tree
.
├── current-theme.conf
├── kitty.conf
└── tab_bar.py
1 directory, 3 files but my custom tab bar is not activated? kitty.conf:
tab_bar.py: """draw kitty tab"""
# pyright: reportMissingImports=false
# pylint: disable=E0401,C0116,C0103,W0603,R0913
import datetime
from kitty.fast_data_types import Screen, get_options
from kitty.tab_bar import (DrawData, ExtraData, TabBarData, as_rgb,
draw_tab_with_powerline, draw_title)
from kitty.utils import color_as_int
opts = get_options()
ICON: str = " LEI "
ICON_LENGTH: int = len(ICON)
ICON_FG: int = as_rgb(color_as_int(opts.color16))
ICON_BG: int = as_rgb(color_as_int(opts.color8))
CLOCK_FG = 0
CLOCK_BG = as_rgb(color_as_int(opts.color15))
DATE_FG = 0
DATE_BG = as_rgb(color_as_int(opts.color8))
def _draw_icon(screen: Screen, index: int) -> int:
if index != 1:
return screen.cursor.x
fg, bg, bold, italic = (
screen.cursor.fg,
screen.cursor.bg,
screen.cursor.bold,
screen.cursor.italic,
)
screen.cursor.bold, screen.cursor.italic, screen.cursor.fg, screen.cursor.bg = (
True,
False,
ICON_FG,
ICON_BG,
)
screen.draw(ICON)
# set cursor position
screen.cursor.x = ICON_LENGTH
# restore color style
screen.cursor.fg, screen.cursor.bg, screen.cursor.bold, screen.cursor.italic = (
fg,
bg,
bold,
italic,
)
return screen.cursor.x
def _draw_left_status(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
use_kitty_render_function: bool = False,
) -> int:
if use_kitty_render_function:
# Use `kitty` function render tab
end = draw_tab_with_powerline(
draw_data, screen, tab, before, max_title_length, index, is_last, extra_data
)
return end
if draw_data.leading_spaces:
screen.draw(" " * draw_data.leading_spaces)
# draw tab title
draw_title(draw_data, screen, tab, index)
trailing_spaces = min(max_title_length - 1, draw_data.trailing_spaces)
max_title_length -= trailing_spaces
extra = screen.cursor.x - before - max_title_length
if extra > 0:
screen.cursor.x -= extra + 1
# Don't change `ICON`
screen.cursor.x = max(screen.cursor.x, ICON_LENGTH)
screen.draw("…")
if trailing_spaces:
screen.draw(" " * trailing_spaces)
screen.cursor.bold = screen.cursor.italic = False
screen.cursor.fg = 0
if not is_last:
screen.cursor.bg = as_rgb(color_as_int(draw_data.inactive_bg))
screen.draw(draw_data.sep)
screen.cursor.bg = 0
return screen.cursor.x
def _draw_right_status(screen: Screen, is_last: bool) -> int:
if not is_last:
return screen.cursor.x
cells = [
(CLOCK_FG, CLOCK_BG, datetime.datetime.now().strftime(" %H:%M ")),
(DATE_FG, DATE_BG, datetime.datetime.now().strftime(" %Y/%m/%d ")),
]
right_status_length = 0
for _, _, cell in cells:
right_status_length += len(cell)
draw_spaces = screen.columns - screen.cursor.x - right_status_length
if draw_spaces > 0:
screen.draw(" " * draw_spaces)
for fg, bg, cell in cells:
screen.cursor.fg = fg
screen.cursor.bg = bg
screen.draw(cell)
screen.cursor.fg = 0
screen.cursor.bg = 0
screen.cursor.x = max(screen.cursor.x, screen.columns - right_status_length)
return screen.cursor.x
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
_draw_icon(screen, index)
# Set cursor to where `left_status` ends, instead `right_status`,
# to enable `open new tab` feature
end = _draw_left_status(
draw_data,
screen,
tab,
before,
max_title_length,
index,
is_last,
extra_data,
use_kitty_render_function=False,
)
_draw_right_status(
screen,
is_last,
)
return end |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Hello. |
Beta Was this translation helpful? Give feedback.
-
Make Kitty tab bar theme match my VIM's and TMUX's, it looks better 😄 kitty.conf
tab_bar.py from kitty.rgb import Color
from kitty.utils import color_as_int
from kitty.fast_data_types import Screen
from kitty.tab_bar import (
as_rgb,
draw_title,
DrawData,
ExtraData,
Formatter,
TabBarData
)
ICON = " "
ICON_FG = as_rgb(color_as_int(Color(78, 81, 82)))
ICON_BG = as_rgb(color_as_int(Color(157, 205, 105)))
LEFT_SEP = ""
RIGHT_SEP = ""
ICON_SEP_COLOR_FG = as_rgb(color_as_int(Color(157, 205, 105)))
ICON_SEP_COLOR_BG = as_rgb(color_as_int(Color(16, 16, 16)))
def __draw_icon(screen: Screen, index: int) -> int:
if index != 1:
return 0
icon_fg, icon_bg = screen.cursor.fg, screen.cursor.bg
screen.cursor.fg = ICON_FG
screen.cursor.bg = ICON_BG
screen.draw(ICON)
screen.cursor.fg = ICON_SEP_COLOR_FG
screen.cursor.bg = ICON_SEP_COLOR_BG
screen.draw(RIGHT_SEP)
screen.cursor.fg, screen.cursor.bg = icon_fg, icon_bg
end = screen.cursor.x
return end
def __draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
max_tab_length: int,
index: int,
extra_data: ExtraData
) -> int:
tab_bg = screen.cursor.bg
default_bg = as_rgb(int(draw_data.default_bg))
if extra_data.next_tab:
next_tab_bg = as_rgb(draw_data.tab_bg(extra_data.next_tab))
else:
next_tab_bg = default_bg
screen.cursor.fg = default_bg
screen.draw(RIGHT_SEP)
draw_title(draw_data, screen, tab, index, max_tab_length)
screen.cursor.fg = tab_bg
screen.cursor.bg = default_bg
screen.draw(RIGHT_SEP)
screen.cursor.fg = tab_bg
screen.cursor.bg = next_tab_bg
end = screen.cursor.x
return end
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
__draw_icon(screen, index)
end = __draw_tab(draw_data, screen, tab, max_title_length, index, extra_data)
return end |
Beta Was this translation helpful? Give feedback.
-
On Fri, Aug 23, 2024 at 02:45:34PM -0700, Alex S. wrote:
Sorry, I don't think, I fully understand you. In my experience, when I have a default tabs config in _kitty.conf_, the empty space inside the tab-bar indeed follows the theme bg-color, but, say, the color of the active tab (the button with the title of the tab) always stays the same: _rgb: 238, 238, 238_.
That color is controlled by active_tab_foreground and
active_tab_background both of which can be set by color themes.
|
Beta Was this translation helpful? Give feedback.
-
On Fri, Aug 23, 2024 at 07:41:32PM -0700, Alex S. wrote:
You mean, `active_tab_foreground` and `active_tab_background` can be set within the theme file?
yes
|
Beta Was this translation helpful? Give feedback.
-
Hello... Simple and pretty... from kitty.fast_data_types import Screen
from kitty.tab_bar import (DrawData, ExtraData, TabBarData, draw_title)
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_title_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
BG_TRANSPARENT = 0
BG_TAB = screen.cursor.bg
screen.cursor.bg = BG_TRANSPARENT
screen.cursor.fg = BG_TAB
if index == 1:
screen.draw(" ")
screen.draw("")
screen.cursor.bg = BG_TAB
draw_title(draw_data, screen, tab, index)
screen.cursor.bg = BG_TRANSPARENT
screen.cursor.fg = BG_TAB
screen.draw("")
if not is_last:
screen.draw(" ")
screen.cursor.bg = BG_TAB
return screen.cursor.x |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
This is my 👇
screenshot:
kitty.conf:
tar_bar.py:
Old
detail
This is my 👇screenshot:
kitty.conf:
tar_bar.py:
Beta Was this translation helpful? Give feedback.
All reactions