Skip to content

Instantly share code, notes, and snippets.

@codemedic
Last active July 30, 2024 17:13
Show Gist options
  • Select an option

  • Save codemedic/fac3684bde0a4f7161e60deea9e0a887 to your computer and use it in GitHub Desktop.

Select an option

Save codemedic/fac3684bde0a4f7161e60deea9e0a887 to your computer and use it in GitHub Desktop.

Revisions

  1. codemedic revised this gist Jul 30, 2024. 2 changed files with 95 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    Lua module for `wezterm` to convert `tmux` stylised text into Lua tables compatible with [`wezterm.format()`](https://wezfurlong.org/wezterm/config/lua/wezterm/format.html).

    See https://github.com/wez/wezterm/issues/5848 for details.

    In addition to the `tmux` styles, it also supports [`wezterm.nerdfonts`](https://wezfurlong.org/wezterm/config/lua/wezterm/nerdfonts.html),
    allowing the use of any symbol name supported by `wezterm`.

    [Gitmux](https://github.com/arl/gitmux) is an example of `tmux` utility that can be used with `wezterm`. See `gitmux.yml` for example config.
    87 changes: 87 additions & 0 deletions gitmux.yml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,87 @@
    tmux:
    # The symbols section defines the symbols printed before specific elements
    # of Git status displayed in tmux status string.
    symbols:
    # current branch name.
    branch: "#[nf=dev_git_branch] "
    # Git SHA1 hash (in 'detached' state).
    hashprefix: ":"
    # 'ahead count' when local and remote branch diverged.
    ahead: "#[nf=md_arrow_up_bold] "
    # 'behind count' when local and remote branch diverged.
    behind: "#[nf=md_arrow_down_bold] "
    # count of files in the staging area.
    staged: "#[nf=oct_file_added] "
    # count of files in conflicts.
    conflict: "#[nf=cod_error] "
    # count of modified files.
    modified: "#[nf=oct_file_diff] "
    # count of untracked files.
    untracked: "#[nf=oct_diff_ignored] "
    # count of stash entries.
    stashed: "#[nf=md_snowflake] "
    # count of inserted lines (stats section).
    insertions: "+"
    # count of deleted lines (stats section).
    deletions: "-"
    # Shown when the working tree is clean.
    clean: "#[nf=fa_check] "

    # Styles are tmux format strings used to specify text colors and attributes
    # of Git status elements. See the STYLES section of tmux man page.
    # https://man7.org/linux/man-pages/man1/tmux.1.html#STYLES.
    styles:
    # Clear previous style.
    clear: "#[none]"
    # Special tree state strings such as [rebase], [merge], etc.
    state: "#[fg=red,bold]"
    # Local branch name
    branch: "#[fg=#7B6823]"
    # Remote branch name
    remote: "#[fg=cyan]"
    # 'divergence' counts
    divergence: "#[fg=yellow]"
    # 'staged' count
    staged: "#[fg=green,bold]"
    # 'conflicts' count
    conflict: "#[fg=red,bold]"
    # 'modified' count
    modified: "#[fg=red,bold]"
    # 'untracked' count
    untracked: "#[fg=magenta,bold]"
    # 'stash' count
    stashed: "#[fg=cyan,bold]"
    # 'insertions' count
    insertions: "#[fg=green]"
    # 'deletions' count
    deletions: "#[fg=red]"
    # 'clean' symbol
    clean: "#[fg=green,bold]"

    # The layout section defines what components gitmux shows and the order in
    # which they appear on tmux status bar.
    #
    # Allowed components:
    # - branch: local branch name. Examples: `⎇ main`, `⎇ :345e7a0` or `[rebase]`
    # - remote-branch: remote branch name, for example: `origin/main`.
    # - divergence: divergence between local and remote branch, if any. Example: `↓·2↑·1`
    # - remote: alias for `remote-branch` followed by `divergence`, for example: `origin/main ↓·2↑·1`
    # - flags: symbols representing the working tree state, for example `✚ 1 ⚑ 1 … 2`
    # - stats: insertions/deletions (lines), for example`Σ56 Δ21`
    # - some string `foo`: any other character of string is directly shown, for example `foo` or `|`
    layout: [branch, divergence, " ", flags, stats]

    # Additional configuration options.
    options:
    # Maximum displayed length for local and remote branch names.
    branch_max_len: 50
    # Trim left, right or from the center of the branch (`right`, `left` or `center`).
    branch_trim: center
    # Character indicating whether and where a branch was truncated.
    ellipsis:
    # Hides the clean flag
    hide_clean: false
    # Swaps order of behind & ahead upstream counts - "↓·1↑·1" -> "↑·1↓·1".
    swap_divergence: false
    # Add a space between behind & ahead upstream counts.
    divergence_space: false
  2. codemedic revised this gist Jul 30, 2024. 1 changed file with 16 additions and 0 deletions.
    16 changes: 16 additions & 0 deletions tmux-status.lua
    Original file line number Diff line number Diff line change
    @@ -46,6 +46,20 @@ local function BackgroundColour(colour)
    return make_single_table('Background', make_single_table('Color', colour))
    end

    local function NerdFont(text)
    local wezterm = require 'wezterm'
    local ok, nf = pcall(function()
    return wezterm.nerdfonts[text]
    end)
    if ok then
    return Text(nf)
    else
    wezterm.log_info(wezterm.to_string(nf))
    end

    return nil
    end

    local function MakeFormat(f)
    f = f:sub(3, -2)
    local ret = {}
    @@ -56,6 +70,8 @@ local function MakeFormat(f)
    table.insert(ret, ForegroundColour(ff:sub(4)))
    elseif ff:match '^bg=' then
    table.insert(ret, BackgroundColour(ff:sub(4)))
    elseif ff:match '^nf=' then
    table.insert(ret, NerdFont(ff:sub(4)))
    elseif ff == 'bright' or ff == 'bold' then
    table.insert(ret, Intensity 'Bold')
    elseif ff == 'dim' then
  3. codemedic created this gist Jul 24, 2024.
    122 changes: 122 additions & 0 deletions tmux-status.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,122 @@
    function string:split(pat)
    pat = pat or '%s+'
    local st, g = 1, self:gmatch('()(' .. pat .. ')')
    local function getter(segs, seps, sep, cap1, ...)
    st = sep and seps + #sep
    return self:sub(segs, (seps or 0) - 1), cap1 or sep, ...
    end
    return function()
    if st then
    return getter(st, g())
    end
    end
    end

    local function Text(text)
    return { Text = text }
    end

    local function make_single_table(name, value)
    local ret = {}
    ret[name] = value
    return ret
    end

    local function Attribute(name, value)
    return make_single_table('Attribute', make_single_table(name, value))
    end

    local function Underline(type)
    return Attribute('Underline', type)
    end

    local function Intensity(level)
    return Attribute('Intensity', level)
    end

    local function Italic(on)
    return Attribute('Italic', on)
    end

    local function ForegroundColour(colour)
    return make_single_table('Foreground', make_single_table('Color', colour))
    end

    local function BackgroundColour(colour)
    return make_single_table('Background', make_single_table('Color', colour))
    end

    local function MakeFormat(f)
    f = f:sub(3, -2)
    local ret = {}
    for ff in f:split ',' do
    if ff == 'none' then
    table.insert(ret, 'ResetAttributes')
    elseif ff:match '^fg=' then
    table.insert(ret, ForegroundColour(ff:sub(4)))
    elseif ff:match '^bg=' then
    table.insert(ret, BackgroundColour(ff:sub(4)))
    elseif ff == 'bright' or ff == 'bold' then
    table.insert(ret, Intensity 'Bold')
    elseif ff == 'dim' then
    table.insert(ret, Intensity 'Half')
    elseif ff == 'italics' then
    table.insert(ret, Italic(true))
    elseif ff == 'underscore' then
    table.insert(ret, Underline 'Single')
    elseif ff == 'double-underscore' then
    table.insert(ret, Underline 'Double')
    elseif ff == 'curly-underscore' then
    table.insert(ret, Underline 'Curly')
    elseif ff == 'dotted-underscore' then
    table.insert(ret, Underline 'Dotted')
    elseif ff == 'dashed-underscore' then
    table.insert(ret, Underline 'Dashed')
    end
    end
    return ret
    end

    M = {}

    function M.status_to_wezterm_format(text)
    local rx = '(#%b[])'

    local tokens = {}

    -- Extract all formatting notations into tokens table as plain text
    local pass1 = string.gsub(text, rx, function(f)
    table.insert(tokens, f)
    return '`'
    end)

    -- Capture all text, which remains in pass1 result, as Text objects
    local i = 1
    for ticks, txt in string.gmatch(pass1, '(`*)([^`]+)') do
    i = i + ticks:len()
    if txt:len() > 0 then
    table.insert(tokens, i, Text(txt))
    i = i + 1
    end
    end

    -- Finalise wezterm.format input
    local ret = {}
    for _, v in pairs(tokens) do
    if type(v) == 'table' then
    table.insert(ret, v)
    goto continue
    end

    local formats = MakeFormat(v)
    for _, f in ipairs(formats) do
    table.insert(ret, f)
    end

    ::continue::
    end

    return ret
    end

    return M