Closed jankatins closed 3 years ago
Tab title would not completely work: the title is set before the command is run, so in my usecase, it would not work as only after pressing enter within the new environment, it would show the correct thing. See #711 where you can see the empty prompts which I used to let the title show the right char.
nightly builds now have a format-tab-title event that you can use to format individual tab titles using the same FormatItem
syntax used in wezterm.format.
@wez Works as intended, thank you! :-)
Is there any way to get an environment variable from the current active pane when in format-tab-title?
inspecting the environment doesn't have a defined interface; the pane may not be local and the foreground process may not be the one that the terminal started. If you know that everything is local you could potentially snoop around in something like the proc filesystem if you're on linux.
There's an escape sequence that iTerm2 defined that wezterm is technically able to parse, but doesn't do anything with:
https://github.com/wez/wezterm/blob/main/termwiz/src/escape/osc.rs#L821-L825
I haven't done anything with these so far, but it seems like this might be the thing you need for your use-case; you could have your shell emit something like this, but derived from the environment that you want to act upon:
printf "\e]1337;SetUserVar=%s=%s\a" NAME $(echo VALUE | base64)
then wezterm could add the dictionary of user vars as an available item in PaneInformation
Another thing: if you do a different color on hover, this cannot be done from the current format-tab-title, as it misses the hover information. E.g.
return {
...
-- You can configure some alternate styling when the mouse pointer
-- moves over inactive tabs
inactive_tab_hover = {
bg_color = "#3c1361",
fg_color = "#909090",
--italic = true,
intensity = "Bold",
underline = "Single",
}
wezterm.on("format-tab-title", function(tab, tabs, panes, config)
if tab.is_active then
--return "! " .. tab.active_pane.title
return {
{Background={Color="red"}},
{Text="! " .. tab.active_pane.title},
}
end
return {
{Background={Color="green"}},
{Text="* " .. tab.active_pane.title},
}
end)
-> will show the inactive part green, but on hover will switch to underlined text, but not to the purple-ly colors defined in inactive_tab_hover.
I was hoping you wouldn't ask about hover :-p. To support that, we'll need to call the event one extra time for the hovered tab. I'll add that :)
then wezterm could add the dictionary of user vars as an available item in PaneInformation
This sounds amazing! (I would add a postcmd to zsh, which would send this :-))
Re hover: actually I'm fine with the current state (my hoover is only making it underline), but just wanted to state it for completeness :-)
One more comment: it seems strange that the tab_bar_style
thingies are drawn around a format-tab-title
which contains format information. The result is something like this:
I can work around that, by basically making all old values be nothing and really do everything in the event, but this looks a bit messy.
-> maybe don't use the tab-bar-style if the returned value is a table (=has formatting) or expose the default formatting via the "old" mechanism as a lua functions so one could call that as a fallback (and the default format-tab-title
would be just delegating it to this func)?
There also seems something in the code which adds spaces to too short tab titles, which again use the old mechanism.
re: the tab bar style decoration, my thinking was that more casual users would like to focus on having format-tab-title
produce just the label portion. If you want more precise control, I think setting the relevant pieces of tab_bar_style
to empty strings is reasonable.
If we think that most people using format-tab-style
just don't want tab_bar_style
, then maybe a simpler end state is to remove tab_bar_style
and have folks migrate to format-tab-title
instead?
With the most recent commit you can do:
printf "\e]1337;SetUserVar=%s=%s\a" foo $(echo -n value | base64)
wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover)
local foo = tab.active_pane.user_vars.foo or "";
return {
{Text=foo..tab.active_pane.title},
}
end)
Nice, I have now converted my setup to this (will add more colors for toolbox + hover later, my style foo is weak...):
-- https://wezfurlong.org/wezterm/config/
local wezterm = require 'wezterm';
-- The powerline </> symbol
local LEFT_ARROW = utf8.char(0xe0b3);
local SOLID_LEFT_ARROW = utf8.char(0xe0b2);
local SOLID_RIGHT_ARROW = utf8.char(0xe0b0);
local color_tabbar_background = "#0b0022"
-- background, forground, intensity, underline
local color_tab_inactive={"#3c1361", "#808080", "Bold", "None"};
local color_tab_hoover={"#3c1361", "#909090", "Bold", "Single"};
local color_tab_active={"#52307c", "#c0c0c0", "Bold", "None"};
-- meh: chars and width are only broadly related...
local tab_max_width = 50
local tab_max_chars = 30
wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover)
local tab_is_toolbox = (tab.active_pane.user_vars.in_toolbox or "false") == "true";
local tab_is_hover = hover;
local tab_is_active = tab.is_active;
if tab_is_active then
c = color_tab_active;
elseif tab_is_hover then
c=color_tab_hoover;
else
c=color_tab_inactive;
end
bg=c[1]
fg=c[2]
b=c[3]
u=c[4]
title = tab.active_pane.title;
-- we can at maximum only display some predefined chars and have to add
-- the numbering ("xx: ", 4 chars) and maybe a dot + space (3 chars))
available_chars = tab_max_chars - 4 - 3;
title_chars = string.len(title)
if title_chars > available_chars then
title = "…" .. string.sub(title, title_chars - available_chars) ;
end
if tab_is_toolbox then
title = "🔴 " .. title
end
if #tabs > 1 then
title = string.format("%d: %s", tab.tab_index + 1, title);
end
return {
{Background={Color=color_tabbar_background}},
{Foreground={Color=bg}},
{Text=SOLID_LEFT_ARROW},
{Background={Color=bg}},
{Foreground={Color=fg}},
{Text=" "},
{Attribute={Underline=u}},
{Attribute={Intensity=b}},
{Text=title},
{Attribute={Intensity="Normal"}},
{Attribute={Underline="None"}},
{Text=" "},
{Background={Color=color_tabbar_background}},
{Foreground={Color=bg}},
{Text=SOLID_RIGHT_ARROW},
}
end)
local empty = ""
return {
...
tab_max_width = tab_max_width,
-- intentionally both empty as we use the title bar function
tab_bar_style = {
active_tab_left = empty,
active_tab_right = empty,
inactive_tab_left = empty,
inactive_tab_right = empty,
inactive_tab_hover_left = empty,
inactive_tab_hover_right = empty,
},
colors = {
tab_bar = {},
}
}
And in my zshrc i have:
export IN_TOOLBOX="false"
# Toolbox specific things
if [[ -f /run/.containerenv && -f /run/.toolboxenv ]]; then
# If we are inside a toolbox...
IN_TOOLBOX="true"
fi
# copied and adapted from https://github.com/starship/starship/blob/master/src/init/starship.zsh
# Will be run before every prompt draw
toolbox_wezterm_precmd() {
# makes this available in the pane info of wezterm
printf "\e]1337;SetUserVar=%s=%s\a" in_toolbox $(echo -n ${IN_TOOLBOX} | base64)
}
(( ! ${+precmd_functions} )) && precmd_functions=()
if [[ -z ${precmd_functions[(re)toolbox_wezterm_precmd]} ]]; then
precmd_functions+=(toolbox_wezterm_precmd)
fi
Works nicely! Thanks a lot for implementing this!
Re old-sytle styling vs new event/func: It does feel a bit clumsy to explicitly disable all old-style styling via some empty string/table. The + icon also still needs to be styled the old way, but that's also fine, just a bit inconsistent.
It's also a bit strange that the "tab title shortner" is basically now some heuristic, as the real string width is not available in lua. If this heuristic is wrong, it removes the powerline >
endings in my case:
.
But apart from making a string_width function available in lua, I wouldn't know a better way (e.g. in my case, I would want the title to be shortened between the red ball and the original title...). So to be honest: it's good enough for me, I will just set the width do much bigger than the char length will always catch it earlier :-)
Oh, and you still need to press enter twice for some reason: going into the toolbox -> new prompt has the decoaration, but tab not yet -> enter -> both prompt and tab have the toolbox decoration. Might be a timing issue between when the precmd thingies are run and when the pane info is computed?
On the other hand: exiting the toolbox (and therfore sending the false state) will imidiately remove the dot and manually overriding it will not work at all (flicker, but directly back to the old state).
So it sounds like a couple of things need to be tidied up:
unicode_column_width
function to lua to help with reasoning about how a string maps to columnswezterm.truncate_to_width and the new max_width
parameter should help manage the tab titles; there's an example of this at the bottom of https://wezfurlong.org/wezterm/config/lua/window-events/format-tab-title.html
Any chance to truncate at the beginning? In paths, the end is the important part and that is was is displayed most if the time in my case.
BTW: just realized that the title is also not set (or only set after one more ENTER) as oh-my-zsh is setting it in precmd (https://github.com/ohmyzsh/ohmyzsh/blob/master/lib/termsupport.zsh). Unfortunately, I cannot record, as my gif recorder does not work on wayland anymore :-(
Basically:
~
, wezterm shows "wezterm"~
in the tab titleRunning wezterm 20210501-112939-faaf6dea, and I noticed that tab titles are really short somehow.
I traced that down that I somehow get two different tab title max_width passed in somehow:
I've set my tab width to 40 and when I use the following tab function:
wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover, max_width)
wezterm.log_warn(string.format("%s , %s, %s, %s", tab.active_pane.title, max_width, hover, tabs));
...
Log looks like this (two tabs) -> two runs for each tab!
2021-05-01T23:00:21.473Z WARN config::lua > lua: ~ , 40, false, table: 0x555ffe90f800
2021-05-01T23:00:21.474Z WARN config::lua > lua: wezterm , 40, false, table: 0x555ffe92bd00
2021-05-01T23:00:21.474Z WARN config::lua > lua: ~ , 14, false, table: 0x555ffde34120
2021-05-01T23:00:21.475Z WARN config::lua > lua: wezterm , 14, false, table: 0x555ffe8938b0
I'm not quite sure why sometimes I only see short titles and sometimes longer. I also saw that when the title is different than "wezterm" or "~", I get higher numbers passed in. E.g. this is what I get as output for a single tab in a different folder:
2021-05-01T23:08:04.412Z WARN config::lua > lua: /var/lib/AccountsService , 40, false, table: 0x555ffec18a00
2021-05-01T23:08:04.413Z WARN config::lua > lua: /var/lib/AccountsService , 31, false, table: 0x555ffe8b0540
It's expected that there are two passes; it does one first with config-specified size to see what the ideal tab width might be. If the ideal width won't fit, it takes the available width, less some space for the new tab button, then divides it by the number of tabs to get the equal width per tab that will fit.
Then a second pass is made with this adjusted max and whether we're hovering in the now-known width of that tab.
Is there something about the width of the window or the table that is being generated and returned that correlates with the weird widths?
One more thing: the truncate thingy would benefit from a "truncate marker" (I'm really bad with names): I've this pattern and it seems redundant given what truncate has to compute:
if wezterm.column_width(title) > available_width then
title = "…" .. wezterm.truncate_left(title, available_width-2);
end
and a big thanks for the refactoring: this looks much cleaner than munching it together :-) .. and also for the explanation: it was surprising: seems I missed that when I read the docs, but rereading it, the behaviour makes total sense.
Just realized that there is a small gap here between the (foreground) edge and the (background) title:
Relevant code should be this:
return {
{Background={Color=color_tabbar_background}},
{Foreground={Color=bg}},
{Text=SOLID_LEFT_ARROW},
{Background={Color=bg}},
{Foreground={Color=fg}},
{Text=" "},
{Attribute={Underline=u}},
{Attribute={Intensity=b}},
{Text=title},
{Attribute={Intensity="Normal"}},
{Attribute={Underline="None"}},
{Text=" "},
{Background={Color=color_tabbar_background}},
{Foreground={Color=bg}},
{Text=SOLID_RIGHT_ARROW},
}
The gaps are due to a font hinting bug in freetype. https://github.com/wez/wezterm/issues/584 and https://github.com/wez/wezterm/pull/588 are relevant. The latter is a PR that seems to have stalled.
I think this is complete now; are there any outstanding issues?
2 more requests related to current discussion. But if you want, I can open a new issue.
| Tab1 | Tab2 | + | <remaining space> | <right status> |
| Tab1 | Tab2 | + | <right status> |
This issue has been automatically closed because there has been no response to the request for more information from the original author. With only the information that is currently in the issue, there isn't enough information to take further action. Please reach out if you have or find the answers we need so that we can investigate further.
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Is your feature request related to a problem? Please describe.
I use toolbox to run certain things at work and it looks more or less the same as my regular account. I do use starship to change the prompt, but it would be amazing if the tab could also indicate that this tab runs in toolbox.
Describe the solution you'd like It would be amazing if wezterm could change to color/add a prefix of the tab based on the tab title or an env variable or a file or so (the actual flag is the existence of a file but I think I can set a env variable or use a title command to change the tab title).
Describe alternatives you've considered As far as I understand the config (https://wezfurlong.org/wezterm/config/lua/config/tab_bar_style.html) does not allow for context based styling of specific panes.
One alternative is using the right status, as
pane:get_title()
exists. But that doesn't show non-active tab(s) which run in that environment.