Skip to content

Instantly share code, notes, and snippets.

@kevinkenny
Forked from alexpls/appearance.lua
Created August 12, 2024 21:15
Show Gist options
  • Save kevinkenny/a82cf5e188049216c6b5936fc94ca2e2 to your computer and use it in GitHub Desktop.
Save kevinkenny/a82cf5e188049216c6b5936fc94ca2e2 to your computer and use it in GitHub Desktop.

Revisions

  1. @alexpls alexpls revised this gist Aug 10, 2024. No changes.
  2. @alexpls alexpls revised this gist Aug 9, 2024. No changes.
  3. @alexpls alexpls created this gist Aug 9, 2024.
    23 changes: 23 additions & 0 deletions appearance.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    -- vim: tabstop=2 shiftwidth=2 expandtab

    -- We almost always start by importing the wezterm module
    local wezterm = require 'wezterm'
    -- Define a lua table to hold _our_ module's functions
    local module = {}

    -- Returns a bool based on whether the host operating system's
    -- appearance is light or dark.
    function module.is_dark()
    -- wezterm.gui is not always available, depending on what
    -- environment wezterm is operating in. Just return true
    -- if it's not defined.
    if wezterm.gui then
    -- Some systems report appearance like "Dark High Contrast"
    -- so let's just look for the string "Dark" and if we find
    -- it assume appearance is dark.
    return wezterm.gui.get_appearance():find("Dark")
    end
    return true
    end

    return module
    52 changes: 52 additions & 0 deletions projects.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    -- vim: tabstop=2 shiftwidth=2 expandtab

    local wezterm = require 'wezterm'
    local module = {}

    local project_dir = wezterm.home_dir .. "/Projects"

    local function project_dirs()
    -- Start with your home directory as a project, 'cause you might want
    -- to jump straight to it sometimes.
    local projects = { wezterm.home_dir }

    -- WezTerm comes with a glob function! Let's use it to get a lua table
    -- containing all subdirectories of your project folder.
    for _, dir in ipairs(wezterm.glob(project_dir .. '/*')) do
    -- ... and add them to the projects table.
    table.insert(projects, dir)
    end

    return projects
    end

    function module.choose_project()
    local choices = {}
    for _, value in ipairs(project_dirs()) do
    table.insert(choices, { label = value })
    end

    return wezterm.action.InputSelector {
    title = "Projects",
    choices = choices,
    fuzzy = true,
    action = wezterm.action_callback(function(child_window, child_pane, id, label)
    -- "label" may be empty if nothing was selected. Don't bother doing anything
    -- when that happens.
    if not label then return end

    -- The SwitchToWorkspace action will switch us to a workspace if it already exists,
    -- otherwise it will create it for us.
    child_window:perform_action(wezterm.action.SwitchToWorkspace {
    -- We'll give our new workspace a nice name, like the last path segment
    -- of the directory we're opening up.
    name = label:match("([^/]+)$"),
    -- Here's the meat. We'll spawn a new terminal with the current working
    -- directory set to the directory that was picked.
    spawn = { cwd = label },
    }, child_pane)
    end),
    }
    end

    return module
    213 changes: 213 additions & 0 deletions wezterm.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,213 @@
    -- vim: tabstop=2 shiftwidth=2 expandtab

    local wezterm = require 'wezterm'
    local config = wezterm.config_builder()
    local appearance = require 'appearance'
    local projects = require 'projects'

    config.set_environment_variables = {
    PATH = '/opt/homebrew/bin:' .. os.getenv('PATH')
    }

    if appearance.is_dark() then
    config.color_scheme = 'Tokyo Night'
    else
    config.color_scheme = 'Tokyo Night Day'
    end

    -- Slightly transparent and blurred background
    config.window_background_opacity = 0.9
    config.macos_window_background_blur = 30
    -- Removes the title bar, leaving only the tab bar. Keeps
    -- the ability to resize by dragging the window's edges.
    -- On macOS, 'RESIZE|INTEGRATED_BUTTONS' also looks nice if
    -- you want to keep the window controls visible and integrate
    -- them into the tab bar.
    config.window_decorations = 'RESIZE'
    -- Sets the font for the window frame (tab bar)
    config.window_frame = {
    -- Berkeley Mono for me again, though an idea could be to try a
    -- serif font here instead of monospace for a nicer look?
    font = wezterm.font({ family = 'Berkeley Mono', weight = 'Bold' }),
    font_size = 11,
    }


    local function segments_for_right_status(window)
    return {
    window:active_workspace(),
    wezterm.strftime('%a %b %-d %H:%M'),
    wezterm.hostname(),
    }
    end

    wezterm.on('update-status', function(window, _)
    local SOLID_LEFT_ARROW = utf8.char(0xe0b2)
    local segments = segments_for_right_status(window)

    local color_scheme = window:effective_config().resolved_palette
    -- Note the use of wezterm.color.parse here, this returns
    -- a Color object, which comes with functionality for lightening
    -- or darkening the colour (amongst other things).
    local bg = wezterm.color.parse(color_scheme.background)
    local fg = color_scheme.foreground

    -- Each powerline segment is going to be coloured progressively
    -- darker/lighter depending on whether we're on a dark/light colour
    -- scheme. Let's establish the "from" and "to" bounds of our gradient.
    local gradient_to, gradient_from = bg
    if appearance.is_dark() then
    gradient_from = gradient_to:lighten(0.2)
    else
    gradient_from = gradient_to:darken(0.2)
    end

    -- Yes, WezTerm supports creating gradients, because why not?! Although
    -- they'd usually be used for setting high fidelity gradients on your terminal's
    -- background, we'll use them here to give us a sample of the powerline segment
    -- colours we need.
    local gradient = wezterm.color.gradient(
    {
    orientation = 'Horizontal',
    colors = { gradient_from, gradient_to },
    },
    #segments -- only gives us as many colours as we have segments.
    )

    -- We'll build up the elements to send to wezterm.format in this table.
    local elements = {}

    for i, seg in ipairs(segments) do
    local is_first = i == 1

    if is_first then
    table.insert(elements, { Background = { Color = 'none' } })
    end
    table.insert(elements, { Foreground = { Color = gradient[i] } })
    table.insert(elements, { Text = SOLID_LEFT_ARROW })

    table.insert(elements, { Foreground = { Color = fg } })
    table.insert(elements, { Background = { Color = gradient[i] } })
    table.insert(elements, { Text = ' ' .. seg .. ' ' })
    end

    window:set_right_status(wezterm.format(elements))
    end)

    local function move_pane(key, direction)
    return {
    key = key,
    mods = 'LEADER',
    action = wezterm.action.ActivatePaneDirection(direction),
    }
    end

    local function resize_pane(key, direction)
    return {
    key = key,
    action = wezterm.action.AdjustPaneSize { direction, 3 }
    }
    end

    -- If you're using emacs you probably wanna choose a different leader here,
    -- since we're gonna be making it a bit harder to CTRL + A for jumping to
    -- the start of a line
    config.leader = { key = 'a', mods = 'CTRL', timeout_milliseconds = 1000 }

    -- Table mapping keypresses to actions
    config.keys = {
    -- Sends ESC + b and ESC + f sequence, which is used
    -- for telling your shell to jump back/forward.
    {
    -- When the left arrow is pressed
    key = 'LeftArrow',
    -- With the "Option" key modifier held down
    mods = 'OPT',
    -- Perform this action, in this case - sending ESC + B
    -- to the terminal
    action = wezterm.action.SendString '\x1bb',
    },
    {
    key = 'RightArrow',
    mods = 'OPT',
    action = wezterm.action.SendString '\x1bf',
    },

    {
    key = ',',
    mods = 'SUPER',
    action = wezterm.action.SpawnCommandInNewTab {
    cwd = wezterm.home_dir,
    args = { 'nvim', wezterm.config_file },
    },
    },

    {
    -- I'm used to tmux bindings, so am using the quotes (") key to
    -- split horizontally, and the percent (%) key to split vertically.
    key = '"',
    -- Note that instead of a key modifier mapped to a key on your keyboard
    -- like CTRL or ALT, we can use the LEADER modifier instead.
    -- This means that this binding will be invoked when you press the leader
    -- (CTRL + A), quickly followed by quotes (").
    mods = 'LEADER',
    action = wezterm.action.SplitHorizontal { domain = 'CurrentPaneDomain' },
    },
    {
    key = '%',
    mods = 'LEADER',
    action = wezterm.action.SplitVertical { domain = 'CurrentPaneDomain' },
    },

    {
    key = 'a',
    -- When we're in leader mode _and_ CTRL + A is pressed...
    mods = 'LEADER|CTRL',
    -- Actually send CTRL + A key to the terminal
    action = wezterm.action.SendKey { key = 'a', mods = 'CTRL' },
    },

    move_pane('j', 'Down'),
    move_pane('k', 'Up'),
    move_pane('h', 'Left'),
    move_pane('l', 'Right'),

    {
    -- When we push LEADER + R...
    key = 'r',
    mods = 'LEADER',
    -- Activate the `resize_panes` keytable
    action = wezterm.action.ActivateKeyTable {
    name = 'resize_panes',
    -- Ensures the keytable stays active after it handles its
    -- first keypress.
    one_shot = false,
    -- Deactivate the keytable after a timeout.
    timeout_milliseconds = 1000,
    }
    },

    {
    key = 'p',
    mods = 'LEADER',
    -- Present in to our project picker
    action = projects.choose_project(),
    },
    {
    key = 'f',
    mods = 'LEADER',
    -- Present a list of existing workspaces
    action = wezterm.action.ShowLauncherArgs { flags = 'FUZZY|WORKSPACES' },
    },
    }

    config.key_tables = {
    resize_panes = {
    resize_pane('j', 'Down'),
    resize_pane('k', 'Up'),
    resize_pane('h', 'Left'),
    resize_pane('l', 'Right'),
    },
    }

    return config