wez / wezterm

A GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust
https://wezfurlong.org/wezterm/
Other
17.87k stars 801 forks source link

Tmux Like Status Bar #500

Closed rrpolanco closed 3 years ago

rrpolanco commented 3 years ago

I just came across this project and like it so far. Are there any plans to add a status bar a la to Tmux's status bar?

wez commented 3 years ago

I'm always open for new feature ideas!

I've had some thoughts on allowing the existing tab bar to specified via some kind of template definition, so it's not just tabs and a new tab button.

The tmux status bar does a lot, and I'd rather avoid simply copying it exactly. I'd prefer to understand specifically which parts of its functionality are most important so that effort can be focused on building things that are immediately useful.

So, could you list out the things in the tmux status bar that you use to help me prioritize and design this feature?

rrpolanco commented 3 years ago

I'm not a Tmux power user but I primarily like the status bar for information such as the time, tmux windows (along with the command that is executing) and specifically to my uses case, the kubernetes context via kube-tmux.

wez commented 3 years ago

I've pushed what I think is probably the bare minimum support for something like this; it's not fully documented because I anticipate changes based on feedback.

You can set something like this in your config:


local wezterm = require 'wezterm';

wezterm.on("update-right-status", function(window, pane)
      -- demonstrates shelling out to get some external status.
      -- wezterm will parse escape sequences output by the
      -- child process and include them in the status area, too.
      local success, date, stderr = wezterm.run_child_process({"date"});

     -- However, if all you need is to format the date/time, then:
     date = wezterm.strftime("%Y-%m-%d %H:%M:%S");

      -- Make it italic and underlined
      window:set_right_status(wezterm.format({
        {Attribute={Underline="Single"}},
        {Attribute={Italic=true}},
        {Text="Hello "..date},
    }));
end);

return {}

The update-right-status event is triggered once per second, starting 1 second after the window first appears (I plan to make the initial call happen sooner, later).

The right status text is right aligned and clipped into the space remaining to the right of the new tab + button in the tab bar.

I can see it being useful to add options for:

Additional information:

image

prabirshrestha commented 3 years ago

Since using tiling managers I have stoped using tmux status bar. But few suggestions and ideas in case others want to use it.

cxiao commented 3 years ago

Just chiming in to say I'm pretty happy with how the status bar is right now. Here's my "powerline" status bar which just shows current working directory, date and time, and hostname. For me, this information is all that I used the tmux status bar for.

wezterm-status-bar

Config:

wezterm.on("update-right-status", function(window, pane)
    local cwd = " "..pane:get_current_working_dir():sub(8).." "; -- remove file:// uri prefix
    local date = wezterm.strftime(" %I:%M %p  %A  %B %-d ");
    local hostname = " "..wezterm.hostname().." ";

    window:set_right_status(
        wezterm.format({
            {Foreground={Color="#ffffff"}},
            {Background={Color="#005f5f"}},
            {Text=cwd},
        })..
        wezterm.format({
            {Foreground={Color="#00875f"}},
            {Background={Color="#005f5f"}},
            {Text=""},
        })..
        wezterm.format({
            {Foreground={Color="#ffffff"}},
            {Background={Color="#00875f"}},
            {Text=date},
        })..
        wezterm.format({
            {Foreground={Color="#00af87"}},
            {Background={Color="#00875f"}},
            {Text=""},
        })..
        wezterm.format({
            {Foreground={Color="#ffffff"}},
            {Background={Color="#00af87"}},
            {Text=hostname},
        })
    );
end);
wez commented 3 years ago

Looks great! FWIW, you can simplify the formatting:

                wezterm.format({
            {Foreground={Color="#ffffff"}},
            {Background={Color="#005f5f"}},
            {Text=cwd},
            {Foreground={Color="#00875f"}},
            {Background={Color="#005f5f"}},
            {Text=""},
            {Foreground={Color="#ffffff"}},
            {Background={Color="#00875f"}},
            {Text=date},
            {Foreground={Color="#00af87"}},
            {Background={Color="#00875f"}},
            {Text=""},
            {Foreground={Color="#ffffff"}},
            {Background={Color="#00af87"}},
            {Text=hostname},
        })
wez commented 3 years ago

I cooked up this so far; it does the heavy lifting to figure out the powerline fade bit, and lets you focus on adding the cell text.

It also extracts the cwd and hostname from the cwd for the current pane. That way it can potentially pick up the remote hostname if your remote shell session is using OSC 7

image

wezterm.on("update-right-status", function(window, pane)
  -- Each element holds the text for a cell in a "powerline" style << fade
  local cells = {};

  -- Figure out the cwd and host of the current pane.
  -- This will pick up the hostname for the remote host if your
  -- shell is using OSC 7 on the remote host.
  local cwd_uri = pane:get_current_working_dir()
  if cwd_uri then
    cwd_uri = cwd_uri:sub(8);
    local slash = cwd_uri:find("/")
    local cwd = ""
    local hostname = ""
    if slash then
      hostname = cwd_uri:sub(1, slash-1)
      -- Remove the domain name portion of the hostname
      local dot = hostname:find("[.]")
      if dot then
        hostname = hostname:sub(1, dot-1)
      end
      -- and extract the cwd from the uri
      cwd = cwd_uri:sub(slash)

      table.insert(cells, cwd);
      table.insert(cells, hostname);
    end
  end

  -- I like my date/time in this style: "Wed Mar 3 08:14"
  local date = wezterm.strftime("%a %b %-d %H:%M");
  table.insert(cells, date);

  -- An entry for each battery (typically 0 or 1 battery)
  for _, b in ipairs(wezterm.battery_info()) do
    table.insert(cells, string.format("%.0f%%", b.state_of_charge * 100))
  end

  -- The powerline < symbol
  local LEFT_ARROW = utf8.char(0xe0b3);
  -- The filled in variant of the < symbol
  local SOLID_LEFT_ARROW = utf8.char(0xe0b2)

  -- Color palette for the backgrounds of each cell
  local colors = {
    "#3c1361",
    "#52307c",
    "#663a82",
    "#7c5295",
    "#b491c8",
  };

  -- Foreground color for the text across the fade
  local text_fg = "#c0c0c0";

  -- The elements to be formatted
  local elements = {};
  -- How many cells have been formatted
  local num_cells = 0;

  -- Translate a cell into elements
  function push(text, is_last)
    local cell_no = num_cells + 1
    table.insert(elements, {Foreground={Color=text_fg}})
    table.insert(elements, {Background={Color=colors[cell_no]}})
    table.insert(elements, {Text=" "..text.." "})
    if not is_last then
      table.insert(elements, {Foreground={Color=colors[cell_no+1]}})
      table.insert(elements, {Text=SOLID_LEFT_ARROW})
    end
    num_cells = num_cells + 1
  end

  while #cells > 0 do
    local cell = table.remove(cells, 1)
    push(cell, #cells == 0)
  end

  window:set_right_status(wezterm.format(elements));
end);
cxiao commented 3 years ago

This is awesome, thanks for taking the time to write that (and for the tip about consuming OSC 7), wez!

github-actions[bot] commented 1 year ago

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.