From ec6ca805bb61ad9a6b67a81b2fe5bbd935ef3cf1 Mon Sep 17 00:00:00 2001 From: Markus Koller Date: Sun, 26 May 2024 22:30:35 +0200 Subject: [PATCH] feat: make floating window behavior configurable --- README.md | 4 +++ lua/smart-splits/api.lua | 62 +++++++++++++++++++++---------------- lua/smart-splits/config.lua | 3 ++ lua/smart-splits/types.lua | 8 +++++ 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 66c4739..9dc446f 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,10 @@ require('smart-splits').setup({ -- NOTE: `at_edge = 'wrap'` is not supported on Kitty terminal -- multiplexer, as there is no way to determine layout via the CLI at_edge = 'wrap', + -- Desired behavior when the current window is floating: + -- 'previous' => Focus previous Vim window and perform action + -- 'mux' => Always forward action to multiplexer + float_win_behavior = 'previous', -- when moving cursor between splits left or right, -- place the cursor on the same row of the *screen* -- regardless of line numbers. False by default. diff --git a/lua/smart-splits/api.lua b/lua/smart-splits/api.lua index e77ebeb..fccb12a 100644 --- a/lua/smart-splits/api.lua +++ b/lua/smart-splits/api.lua @@ -6,6 +6,7 @@ local mux_utils = require('smart-splits.mux.utils') local types = require('smart-splits.types') local Direction = types.Direction local AtEdgeBehavior = types.AtEdgeBehavior +local FloatWinBehavior = types.FloatWinBehavior local M = {} @@ -194,20 +195,39 @@ local function compute_direction_horizontal(direction) return result end +---@param mux_callback fun()|nil +---@return boolean +local function handle_floating_window(mux_callback) + if utils.is_floating_window() then + if config.float_win_behavior == FloatWinBehavior.previous then + -- focus the last accessed window. + -- if it's also floating, do not attempt to perform the action. + local prev_win = vim.fn.win_getid(vim.fn.winnr('#')) + if utils.is_floating_window(prev_win) then + return true + end + + vim.api.nvim_set_current_win(prev_win) + return false + elseif config.float_win_behavior == FloatWinBehavior.mux then + -- always forward the action to the multiplexer + if mux_callback then + mux_callback() + end + return true + end + end +end + ---@param direction SmartSplitsDirection ---@param amount number local function resize(direction, amount) amount = amount or config.default_amount - -- ignore currently focused floating windows by focusing the last accessed window - -- if the last accessed window is also floating, do not attempt to resize it - if utils.is_floating_window() then - local prev_win = vim.fn.win_getid(vim.fn.winnr('#')) - if utils.is_floating_window(prev_win) then - return - end - - vim.api.nvim_set_current_win(prev_win) + if handle_floating_window(function() + mux.resize_pane(direction, amount) + end) then + return end -- if a full width window and horizontall resize check if we can resize with multiplexer @@ -336,15 +356,10 @@ local function move_cursor(direction, opts) end end - -- ignore currently focused floating windows by focusing the last accessed window - -- if the last accessed window is also floating, do not attempt to move the cursor - if utils.is_floating_window() then - local prev_win = vim.fn.win_getid(vim.fn.winnr('#')) - if utils.is_floating_window(prev_win) then - return - end - - vim.api.nvim_set_current_win(prev_win) + if handle_floating_window(function() + mux.move_pane(direction, true, at_edge) + end) then + return end local offset = vim.fn.winline() + vim.api.nvim_win_get_position(0)[1] @@ -421,15 +436,8 @@ end local function swap_bufs(direction, opts) opts = opts or {} - -- ignore currently focused floating windows by focusing the last accessed window - -- if the last accessed window is also floating, do not attempt to swap buffers - if utils.is_floating_window() then - local prev_win = vim.fn.win_getid(vim.fn.winnr('#')) - if utils.is_floating_window(prev_win) then - return - end - - vim.api.nvim_set_current_win(prev_win) + if handle_floating_window() then + return end local buf_1 = vim.api.nvim_get_current_buf() diff --git a/lua/smart-splits/config.lua b/lua/smart-splits/config.lua index e6c0d43..206ebcf 100644 --- a/lua/smart-splits/config.lua +++ b/lua/smart-splits/config.lua @@ -2,6 +2,7 @@ local lazy = require('smart-splits.lazy') local log = lazy.require_on_exported_call('smart-splits.log') --[[@as SmartSplitsLogger]] local types = require('smart-splits.types') local AtEdgeBehavior = types.AtEdgeBehavior +local FloatWinBehavior = types.FloatWinBehavior local Multiplexer = types.Multiplexer local mux_utils = require('smart-splits.mux.utils') @@ -20,6 +21,7 @@ local mux_utils = require('smart-splits.mux.utils') ---@field ignored_filetypes string[] ---@field default_amount number ---@field at_edge SmartSplitsAtEdgeBehavior +---@field float_win_behavior SmartSplitsFloatWinBehavior ---@field move_cursor_same_row boolean ---@field cursor_follows_swapped_bufs boolean ---@field resize_mode SmartResizeModeConfig @@ -45,6 +47,7 @@ local config = { ---@diagnostic disable-line:missing-fields }, default_amount = 3, at_edge = AtEdgeBehavior.wrap, + float_win_behavior = FloatWinBehavior.previous, move_cursor_same_row = false, cursor_follows_swapped_bufs = false, resize_mode = { diff --git a/lua/smart-splits/types.lua b/lua/smart-splits/types.lua index 7649489..abc1fb2 100644 --- a/lua/smart-splits/types.lua +++ b/lua/smart-splits/types.lua @@ -13,6 +13,8 @@ ---@alias SmartSplitsDirection 'left'|'right'|'up'|'down' ---@alias SmartSplitsAtEdgeBehavior 'split'|'wrap'|'stop'|function +--- +---@alias SmartSplitsFloatWinBehavior 'previous'|'mux' ---@alias SmartSplitsMultiplexerType 'tmux'|'wezterm'|'kitty' @@ -40,6 +42,12 @@ local M = { ---@type SmartSplitsAtEdgeBehavior stop = 'stop', }, + FloatWinBehavior = { + ---@type SmartSplitsFloatWinBehavior + previous = 'previous', + ---@type SmartSplitsFloatWinBehavior + mux = 'mux', + }, Multiplexer = { ---@type SmartSplitsMultiplexerType tmux = 'tmux',