diff --git a/README.md b/README.md index d4e801f..991ceb8 100644 --- a/README.md +++ b/README.md @@ -306,24 +306,22 @@ Add the following snippet to your `~/.tmux.conf`/`~/.config/tmux/tmux.conf` file ```tmux # Smart pane switching with awareness of Vim splits. -# See: https://github.com/christoomey/vim-tmux-navigator -is_vim="ps -o state= -o comm= -t '#{pane_tty}' \ - | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" -bind-key -n C-h if-shell "$is_vim" 'send-keys C-h' 'select-pane -L' -bind-key -n C-j if-shell "$is_vim" 'send-keys C-j' 'select-pane -D' -bind-key -n C-k if-shell "$is_vim" 'send-keys C-k' 'select-pane -U' -bind-key -n C-l if-shell "$is_vim" 'send-keys C-l' 'select-pane -R' - -bind-key -n M-h if-shell "$is_vim" 'send-keys M-h' 'resize-pane -L 3' -bind-key -n M-j if-shell "$is_vim" 'send-keys M-j' 'resize-pane -D 3' -bind-key -n M-k if-shell "$is_vim" 'send-keys M-k' 'resize-pane -U 3' -bind-key -n M-l if-shell "$is_vim" 'send-keys M-l' 'resize-pane -R 3' +" +bind-key -n C-h if -F "#{@pane-is-vim}" 'send-keys C-h' 'select-pane -L' +bind-key -n C-j if -F "#{@pane-is-vim}" 'send-keys C-j' 'select-pane -D' +bind-key -n C-k if -F "#{@pane-is-vim}" 'send-keys C-k' 'select-pane -U' +bind-key -n C-l if -F "#{@pane-is-vim}" 'send-keys C-l' 'select-pane -R' + +bind-key -n M-h if -F "#{@pane-is-vim}" 'send-keys M-h' 'resize-pane -L 3' +bind-key -n M-j if -F "#{@pane-is-vim}" 'send-keys M-j' 'resize-pane -D 3' +bind-key -n M-k if -F "#{@pane-is-vim}" 'send-keys M-k' 'resize-pane -U 3' +bind-key -n M-l if -F "#{@pane-is-vim}" 'send-keys M-l' 'resize-pane -R 3' tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")' if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \ - "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\' 'select-pane -l'" + "bind-key -n 'C-\\' if -F \"#{@pane-is-vim}\" 'send-keys C-\\' 'select-pane -l'" if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \ - "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\' 'select-pane -l'" + "bind-key -n 'C-\\' if -F \"#{@pane-is-vim}\" 'send-keys C-\\\\' 'select-pane -l'" bind-key -T copy-mode-vi 'C-h' select-pane -L bind-key -T copy-mode-vi 'C-j' select-pane -D @@ -365,7 +363,7 @@ smart_splits.apply_to_config(config, { modifiers = { move = 'CTRL', -- modifier to use for pane movement, e.g. CTRL+h to move left resize = 'META', -- modifier to use for pane resize, e.g. META+h to resize to the left - } + }, }) ``` diff --git a/plugin/smart-splits.vim b/autoload/smart_splits.vim similarity index 76% rename from plugin/smart-splits.vim rename to autoload/smart_splits.vim index 80e4ccf..af1072b 100644 --- a/plugin/smart-splits.vim +++ b/autoload/smart_splits.vim @@ -48,7 +48,7 @@ function s:encode_b64(str, size) return chunked endfunction -function s:write(var) +function smart_splits#write_wezterm_var(var) if filewritable('/dev/fd/2') == 1 let l:success = writefile([a:var], '/dev/fd/2', 'b') == 0 else @@ -57,18 +57,6 @@ function s:write(var) return l:success endfunction -function s:format_var(val) +function smart_splits#format_wezterm_var(val) return printf("\033]1337;SetUserVar=IS_NVIM=%s\007", s:encode_b64(a:val, 0)) endfunction - -let s:are_we_wezterm = luaeval("require('smart-splits.mux.utils').are_we_wezterm()") - -if s:are_we_wezterm - call s:write(s:format_var("true")) - " Set to false if nvim is suspended with ctrl+z - autocmd VimSuspend * :call s:write(s:format_var("false")) - " Set to true if nvim is resumed after being suspended with ctrl+z - autocmd VimResume * :call s:write(s:format_var("true")) - " Set to false when nvim exits - autocmd VimLeave * :call s:write(s:format_var("false")) -endif diff --git a/lua/smart-splits/config.lua b/lua/smart-splits/config.lua index b8406c7..322a4a7 100644 --- a/lua/smart-splits/config.lua +++ b/lua/smart-splits/config.lua @@ -3,7 +3,6 @@ local log = lazy.require_on_exported_call('smart-splits.log') --[[@as SmartSplit local types = require('smart-splits.types') local AtEdgeBehavior = types.AtEdgeBehavior local Multiplexer = types.Multiplexer -local utils = require('smart-splits.utils') local mux_utils = require('smart-splits.mux.utils') ---@class SmartResizeModeHooks @@ -108,7 +107,18 @@ function M.set_default_multiplexer() end function M.setup(new_config) + local original_mux = config.multiplexer_integration + config = vim.tbl_deep_extend('force', config, new_config or {}) + -- if the mux setting changed, run startup again + if + original_mux ~= nil + and original_mux ~= false + and #tostring(original_mux or '') == 0 + and original_mux ~= config.multiplexer_integration + then + mux_utils.startup() + end -- check deprecated settings ---@diagnostic disable:undefined-field diff --git a/lua/smart-splits/mux/tmux.lua b/lua/smart-splits/mux/tmux.lua index 505474d..e4b9cdb 100644 --- a/lua/smart-splits/mux/tmux.lua +++ b/lua/smart-splits/mux/tmux.lua @@ -1,5 +1,6 @@ local types = require('smart-splits.types') local Direction = types.Direction +local Log = require('smart-splts.log') local dir_keys_tmux = { [Direction.left] = 'L', @@ -34,7 +35,7 @@ local function tmux_exec(args, as_list) end ---@type SmartSplitsMultiplexer -local M = {} +local M = {} ---@diagnostic disable-line: missing-fields M.type = 'tmux' @@ -146,4 +147,28 @@ function M.split_pane(direction, size) return ok end +function M.on_init() + local pane_id = M.current_pane_id() + if not pane_id then + Log.warn('tmux init: could not detect pane ID!') + return + end + tmux_exec({ 'set-option', '-pt', pane_id, '@pane-is-vim', 1 }) + if vim.v.shell_error ~= 0 then + Log.warn('tmux init: failed to detect pane_id') + end +end + +function M.on_exit() + local pane_id = M.current_pane_id() + if not pane_id then + Log.warn('tmux init: could not detect pane ID!') + return + end + tmux_exec({ 'set-option', '-pt', pane_id, '@pane-is-vim', 0 }) + if vim.v.shell_error ~= 0 then + Log.warn('tmux init: failed to detect pane_id') + end +end + return M diff --git a/lua/smart-splits/mux/utils.lua b/lua/smart-splits/mux/utils.lua index 4a7c970..0712c1c 100644 --- a/lua/smart-splits/mux/utils.lua +++ b/lua/smart-splits/mux/utils.lua @@ -1,16 +1,5 @@ local M = {} ----Check if Neovim is running in Wezterm TUI ----@return boolean -function M.are_we_wezterm() - if M.are_we_gui() then - return false - end - local term = vim.trim((vim.env.TERM_PROGRAM or ''):lower()) - local wezterm_pane = vim.trim(vim.env.WEZTERM_PANE or '') - return term == 'wezterm' or wezterm_pane ~= '' -end - function M.are_we_tmux() if M.are_we_gui() then return false @@ -31,4 +20,30 @@ function M.are_we_gui() return current_ui ~= nil and not current_ui.stdin_tty and not current_ui.stdout_tty end +---Initialization for mux capabilities. +---If selected mux has an `on_init` or `on_exit`, +---call `on_init` and set up autocmds to call `on_init` on `VimResume` +---and `on_exit` on `VimSuspend` and `VimLeave`. +function M.startup() + local mux = require('smart-splits.mux').get() + if not mux then + return + end + if mux.on_init then + mux.on_init() + vim.api.nvim_create_autocmd('VimResume', { + callback = function() + mux.on_init() + end, + }) + end + if mux.on_exit then + vim.api.nvim_create_autocmd({ 'VimSuspend', 'VimLeave' }, { + callback = function() + mux.on_exit() + end, + }) + end +end + return M diff --git a/lua/smart-splits/mux/wezterm.lua b/lua/smart-splits/mux/wezterm.lua index a8d30a9..c10f198 100644 --- a/lua/smart-splits/mux/wezterm.lua +++ b/lua/smart-splits/mux/wezterm.lua @@ -150,4 +150,16 @@ function M.split_pane(direction, size) return ok end +function M.on_init() + local format_var = vim.fn['smart_splits#format_wezterm_var'] + local write_var = vim.fn['smart_splits#write_wezterm_var'] + write_var(format_var('true')) +end + +function M.on_exit() + local format_var = vim.fn['smart_splits#format_wezterm_var'] + local write_var = vim.fn['smart_splits#write_wezterm_var'] + write_var(format_var('false')) +end + return M diff --git a/lua/smart-splits/types.lua b/lua/smart-splits/types.lua index c4823f7..7649489 100644 --- a/lua/smart-splits/types.lua +++ b/lua/smart-splits/types.lua @@ -7,6 +7,8 @@ ---@field resize_pane fun(direction:SmartSplitsDirection, amount:number):boolean ---@field split_pane fun(direction:SmartSplitsDirection,size:number|nil):boolean ---@field type SmartSplitsMultiplexerType +---@field on_init fun()|nil +---@field on_exit fun()|nil ---@alias SmartSplitsDirection 'left'|'right'|'up'|'down' diff --git a/plugin/smart-splits.lua b/plugin/smart-splits.lua index bb46ffb..17766a2 100644 --- a/plugin/smart-splits.lua +++ b/plugin/smart-splits.lua @@ -5,3 +5,4 @@ vim.tbl_map(function(cmd) end, cmds) require('smart-splits.config').set_default_multiplexer() +require('smart-splits.mux.utils').startup()