Skip to content

WezTerm Integration

David Moberg edited this page May 12, 2023 · 11 revisions

There are 2 examples of wezterm integrations below,

  1. "get_foreground_process_name" (Does not work if vim is started from somewhere else than the commandline)
  2. "get_tty_name" (More robust version that understands vim is the fg process if started via tig, git commit, git jump, chezmoi edit etc. - Only tested on Ubuntu)

1.

Add the following snippet to your configuration file. You can change the following keybindings as you may prefer.

local wezterm = require('wezterm')
local act = wezterm.action

local function isViProcess(pane) 
    -- get_foreground_process_name On Linux, macOS and Windows, 
    -- the process can be queried to determine this path. Other operating systems 
    -- (notably, FreeBSD and other unix systems) are not currently supported
    return pane:get_foreground_process_name():find('n?vim') ~= nil
    -- return pane:get_title():find("n?vim") ~= nil
end

local function conditionalActivatePane(window, pane, pane_direction, vim_direction)
    if isViProcess(pane) then
        window:perform_action(
            -- This should match the keybinds you set in Neovim.
            act.SendKey({ key = vim_direction, mods = 'ALT' }),
            pane
        )
    else
        window:perform_action(act.ActivatePaneDirection(pane_direction), pane)
    end
end

wezterm.on('ActivatePaneDirection-right', function(window, pane)
    conditionalActivatePane(window, pane, 'Right', 'l')
end)
wezterm.on('ActivatePaneDirection-left', function(window, pane)
    conditionalActivatePane(window, pane, 'Left', 'h')
end)
wezterm.on('ActivatePaneDirection-up', function(window, pane)
    conditionalActivatePane(window, pane, 'Up', 'k')
end)
wezterm.on('ActivatePaneDirection-down', function(window, pane)
    conditionalActivatePane(window, pane, 'Down', 'j')
end)

return {
    -- ...your settings ...
    keys = {
        { key = 'h', mods = 'ALT', action = act.EmitEvent('ActivatePaneDirection-left') },
        { key = 'j', mods = 'ALT', action = act.EmitEvent('ActivatePaneDirection-down') },
        { key = 'k', mods = 'ALT', action = act.EmitEvent('ActivatePaneDirection-up') },
        { key = 'l', mods = 'ALT', action = act.EmitEvent('ActivatePaneDirection-right') },
    },
}

2. A more robust way determining foreground process on Linux

This approach is more similar to the tmux solution and supports understanding that vim/nvim is the fg process even if it's started through another command (that uses $EDITOR for example), such as git commit, git jump, git rebase, chezmoi edit, ...

This uses the tty information provided by wezterm since 20230408 (see pane:get_tty_name).

local w = require 'wezterm'
local a = w.action

local function is_inside_vim(pane)
  local tty = pane:get_tty_name()
  if tty == nil then return false end

  local success, stdout, stderr = w.run_child_process
    { 'sh', '-c',
      'ps -o state= -o comm= -t' .. w.shell_quote_arg(tty) .. ' | ' ..
      'grep -iqE \'^[^TXZ ]+ +(\\S+\\/)?g?(view|l?n?vim?x?)(diff)?$\'' }

  return success
end

local function is_outside_vim(pane) return not is_inside_vim(pane) end

local function bind_if(cond, key, mods, action)
  local function callback (win, pane)
    if cond(pane) then
      win:perform_action(action, pane)
    else
      win:perform_action(a.SendKey({key=key, mods=mods}), pane)
    end
  end

  return {key=key, mods=mods, action=w.action_callback(callback)}
end

return {
  keys = {
    bind_if(is_outside_vim, 'h', 'ALT', a.ActivatePaneDirection('Left')),
    bind_if(is_outside_vim, 'l', 'ALT', a.ActivatePaneDirection('Right')),
  },
}