From 6b939f04868680e30fb430fc030f2493494209c0 Mon Sep 17 00:00:00 2001 From: Ade Attwood Date: Wed, 4 Sep 2024 18:20:25 +0100 Subject: [PATCH] feat(term): move to wezterm mux from tmux So this is the first commit where we are starting to migrate from tmux. Right now I'm not sure how this will go, every other attempt has not lasted very long. This does support all the features I am using in tmux though. TBH most of the stuff in the tmux.conf wezterm does by default. For example, the pain numbers start at 1 not 0. This implements a fork of tmux navigation, the plugin I have been using in vim since like.... day one. --- .../files/vim/plugin/wezterm-navigation.vim | 112 ++++++++++++++++++ site-modules/core/files/wezterm.lua | 91 +++++++++++++- 2 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 site-modules/core/files/vim/plugin/wezterm-navigation.vim diff --git a/site-modules/core/files/vim/plugin/wezterm-navigation.vim b/site-modules/core/files/vim/plugin/wezterm-navigation.vim new file mode 100644 index 0000000..9c92758 --- /dev/null +++ b/site-modules/core/files/vim/plugin/wezterm-navigation.vim @@ -0,0 +1,112 @@ +" Maps to switch vim splits in the given direction. If there are +" no more windows in that direction, forwards the operation to wezterm. +" Additionally, toggles between last active vim splits/wezterm panes. + +if exists("g:loaded_wezterm_navigator") || &cp || v:version < 700 + finish +endif +let g:loaded_wezterm_navigator = 1 + +function! s:DirectionToKey(direction) + if a:direction ==# 'Up' + return 'k' + elseif a:direction ==# 'Down' + return 'j' + elseif a:direction ==# 'Left' + return 'h' + elseif a:direction ==# 'Right' + return 'l' + else + return 'p' + endif +endfunction + +function! s:VimNavigate(direction) + try + execute 'wincmd ' . s:DirectionToKey(a:direction) + catch + echohl ErrorMsg | echo 'E11: Invalid in command-line window; executes, CTRL-C quits: wincmd k' | echohl None + endtry +endfunction + +if !get(g:, 'wezterm_navigator_no_mappings', 0) + nnoremap :WestermNavigateLeft + nnoremap :WestermNavigateDown + nnoremap :WestermNavigateUp + nnoremap :WestermNavigateRight + nnoremap :WestermNavigatePrevious +endif + +if empty($WEZTERM_PANE) + command! WestermNavigateLeft call s:VimNavigate('h') + command! WestermNavigateDown call s:VimNavigate('j') + command! WestermNavigateUp call s:VimNavigate('k') + command! WestermNavigateRight call s:VimNavigate('l') + command! WestermNavigatePrevious call s:VimNavigate('p') + finish +endif + +command! WestermNavigateLeft call s:WeztermAwareNavigate('Left') +command! WestermNavigateDown call s:WeztermAwareNavigate('Down') +command! WestermNavigateUp call s:WeztermAwareNavigate('Up') +command! WestermNavigateRight call s:WeztermAwareNavigate('Right') +command! WestermNavigatePrevious call s:WeztermAwareNavigate('Prev') + +let s:pane_position_from_direction = {'h': 'left', 'j': 'bottom', 'k': 'top', 'l': 'right'} + +function! s:weztermOrTmateExecutable() + return "wezterm" +endfunction + +function! s:weztermSocket() + " The socket path is the first value in the comma-separated list of $wezterm. + return split($wezterm, ',')[0] +endfunction + +let s:wezterm_is_last_pane = 0 +augroup wezterm_navigator + au! + autocmd WinEnter * let s:wezterm_is_last_pane = 0 +augroup END + +function! s:NeedsVitalityRedraw() + return exists('g:loaded_vitality') && v:version < 704 && !has("patch481") +endfunction + +function! s:ShouldForwardNavigationBackToWezterm(wezterm_last_pane, at_tab_page_edge) +endfunction + +function! s:ShouldForwardNavigationBackToWezterm(wezterm_last_pane, at_tab_page_edge) + return a:wezterm_last_pane || a:at_tab_page_edge +endfunction + +function! s:WeztermCommand(args) + let cmd = 'wezterm cli ' . a:args + let l:x=&shellcmdflag + let retval=system(cmd) + let &shellcmdflag=l:x + return retval +endfunction + +function! s:WeztermAwareNavigate(direction) + let nr = winnr() + let wezterm_last_pane = (a:direction == 'p' && s:wezterm_is_last_pane) + if !wezterm_last_pane + call s:VimNavigate(a:direction) + endif + let at_tab_page_edge = (nr == winnr()) + " Forward the switch panes command to wezterm if: + " a) we're toggling between the last wezterm pane; + " b) we tried switching windows in vim but it didn't have effect. + if s:ShouldForwardNavigationBackToWezterm(wezterm_last_pane, at_tab_page_edge) + let args = 'activate-pane-direction ' . shellescape(a:direction) + + silent call s:WeztermCommand(args) + if s:NeedsVitalityRedraw() + redraw! + endif + let s:wezterm_is_last_pane = 1 + else + let s:wezterm_is_last_pane = 0 + endif +endfunction diff --git a/site-modules/core/files/wezterm.lua b/site-modules/core/files/wezterm.lua index db1639b..11bdac0 100644 --- a/site-modules/core/files/wezterm.lua +++ b/site-modules/core/files/wezterm.lua @@ -1,5 +1,26 @@ local wezterm = require "wezterm" +local scheme = wezterm.get_builtin_color_schemes() +local nord = scheme["nord"] + +local function vim_pass_though_action(config) + return { + key = config.key, + mods = config.mods, + action = wezterm.action_callback(function(win, pane) + local process_name = pane:get_foreground_process_name() + + -- If we are in vim then we want to send the key to go to the net pain + if string.match(process_name, "vim") or string.match(process_name, "emacs") then + win:perform_action({ SendKey = { key = config.key, mods = config.mods } }, pane) + return + end + + win:perform_action({ ActivatePaneDirection = config.direction }, pane) + end), + } +end + return { -- Use a sexy terminal font with ligatures. -- You will need to install the beta version of the font to get the ligatures @@ -9,7 +30,36 @@ return { }, -- The nord theme to fit with everyting else - color_scheme = 'nord', + color_scheme = "nord", + colors = { + tab_bar = { + background = nord.background, + active_tab = { + bg_color = "#88c0d0", -- nord.background, + fg_color = nord.background, + }, + inactive_tab = { + bg_color = nord.background, + fg_color = nord.foreground, + }, + inactive_tab_hover = { + bg_color = "#4c566a", + fg_color = nord.foreground, + italic = false, + }, + new_tab = { + bg_color = nord.background, + fg_color = nord.foreground, + }, + new_tab_hover = { + bg_color = "#4c566a", + fg_color = nord.foreground, + italic = false, + }, + }, + }, + + use_fancy_tab_bar = false, -- Give the font some more line height, just makes thinks look a bit nicer line_height = 1.4, @@ -23,7 +73,7 @@ return { audible_bell = "Disabled", -- Have a really clean UI when there is only one tab open - hide_tab_bar_if_only_one_tab = true, + hide_tab_bar_if_only_one_tab = false, -- Disabled all the padding, this makes vim look a lot nicer when all the -- window bars go to the edges of the terminal @@ -31,7 +81,11 @@ return { warn_about_missing_glyphs = false, - enable_wayland = false, + tab_bar_at_bottom = true, + + enable_wayland = true, + + leader = { key = "b", mods = "CTRL" }, keys = { -- Bind to to `werase` in bash. This is to keep @@ -43,5 +97,36 @@ return { key = "Backspace", action = wezterm.action.SendKey { mods = "CTRL", key = "w" }, }, + + -- tmux features to complete + -- - Fuzzy finding / switching between pains + -- - Prompt search back + -- - Find out the copy and pasteing story + -- - Is there a "copy mode" like in tmux? + -- - Nvim split navigation intergation + + -- Pane navigation like vim, this is what I have been using in tmux and how + -- the finger move + vim_pass_though_action { key = "h", mods = "CTRL", direction = "Left" }, + vim_pass_though_action { key = "j", mods = "CTRL", direction = "Down" }, + vim_pass_though_action { key = "k", mods = "CTRL", direction = "Up" }, + vim_pass_though_action { key = "l", mods = "CTRL", direction = "Right" }, + + -- Split panes with the tmux keys. Again this alrady uses the same + -- directory as the current pane. Again no shinanigans needed + { key = "s", mods = "LEADER", action = wezterm.action { SplitVertical = { domain = "CurrentPaneDomain" } } }, + { key = "v", mods = "LEADER", action = wezterm.action { SplitHorizontal = { domain = "CurrentPaneDomain" } } }, + + -- Tab navigation via numbers. This already starts a 1 so we don't need + -- todo any shinangans to make that work better + { key = "1", mods = "LEADER", action = wezterm.action { ActivateTab = 0 } }, + { key = "2", mods = "LEADER", action = wezterm.action { ActivateTab = 1 } }, + { key = "3", mods = "LEADER", action = wezterm.action { ActivateTab = 2 } }, + { key = "4", mods = "LEADER", action = wezterm.action { ActivateTab = 3 } }, + { key = "5", mods = "LEADER", action = wezterm.action { ActivateTab = 4 } }, + { key = "6", mods = "LEADER", action = wezterm.action { ActivateTab = 5 } }, + { key = "7", mods = "LEADER", action = wezterm.action { ActivateTab = 6 } }, + { key = "8", mods = "LEADER", action = wezterm.action { ActivateTab = 7 } }, + { key = "9", mods = "LEADER", action = wezterm.action { ActivateTab = 8 } }, }, }