From 003aaadd2ac60516776bf6743876d7a1da912cda Mon Sep 17 00:00:00 2001 From: MrZeLee <mrzelee404@gmail.com> Date: Tue, 4 Mar 2025 15:53:48 +0000 Subject: [PATCH 1/2] feat: add focused window minwidth and minheight options Adds options to set minimum width and height for the focused window. This allows users to customize the size of the focused window. --- README.md | 16 ++++++++++++++++ doc/focus.txt | 30 ++++++++++++++++++++++++------ extras/repro.lua | 2 ++ lua/focus/init.lua | 10 ++++++++++ lua/focus/modules/resizer.lua | 22 ++++++++++++++++++---- 5 files changed, 70 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a3c418f..5d4b381 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,8 @@ require("focus").setup({ height = 0, -- Force height for the focused window minwidth = 0, -- Force minimum width for the unfocused window minheight = 0, -- Force minimum height for the unfocused window + focusedwindow_minwidth = 0, --Force minimum width for the focused window + focusedwindow_minheight = 0, --Force minimum height for the focused window height_quickfix = 10, -- Set the height of quickfix panel }, split = { @@ -187,6 +189,13 @@ require("focus").setup({ autoresize = { width = 120 } }) require("focus").setup({ autoresize = { minwidth = 80} }) ``` +**Set Focus Minimum Width for Focused Window** +```lua +-- Force minimum width for the focused window +-- Default: Calculated based on golden ratio +require("focus").setup({ autoresize = { focusedwindow_minwidth = 80} }) +``` + **Set Focus Height** ```lua -- Force height for the focused window @@ -201,6 +210,13 @@ require("focus").setup({ autoresize = { height = 40 } }) require("focus").setup({ autoresize = { minheight = 10} }) ``` +**Set Focus Minimum Height for Focused Window** +```lua +-- Force minimum height for the focused window +-- Default: Calculated based on golden ratio +require("focus").setup({ autoresize = { focusedwindow_minheight = 80} }) +``` + **Set Focus Quickfix Height** ```lua -- Sets the height of quickfix panel, in case you pass the height to diff --git a/doc/focus.txt b/doc/focus.txt index 2e1e1b4..22b85de 100644 --- a/doc/focus.txt +++ b/doc/focus.txt @@ -80,6 +80,8 @@ default settings: height = 0, -- Force height for the focused window minwidth = 0, -- Force minimum width for the unfocused window minheight = 0, -- Force minimum height for the unfocused window + focusedwindow_minwidth = 0, -- Force minimum width for the focused window + focusedwindow_minheight = 0, -- Force minimum height for the focused window height_quickfix = 10, -- Set the height of quickfix panel }, split = { @@ -91,7 +93,7 @@ default settings: relativenumber = false, -- Display relative line numbers in the focussed window only hybridnumber = false, -- Display hybrid line numbers in the focussed window only absolutenumber_unfocussed = false, -- Preserve absolute numbers in the unfocussed windows - + cursorline = true, -- Display a cursorline in the focussed window only cursorcolumn = false, -- Display cursorcolumn in the focussed window only colorcolumn = { @@ -154,6 +156,14 @@ SETUP OPTIONS ~ require("focus").setup({ autoresize = { minwidth = 80} }) < +**Set Focus Minimum Width for Focused Window** + +>lua + -- Force minimum width for the focused window + -- Default: Calculated based on golden ratio + require("focus").setup({ autoresize = { focusedwindow_minwidth = 80} }) +< + **Set Focus Height** >lua @@ -170,6 +180,14 @@ SETUP OPTIONS ~ require("focus").setup({ autoresize = { minheight = 10} }) < +**Set Focus Minimum Height for Focused Window** + +>lua + -- Force minimum height for the focused window + -- Default: Calculated based on golden ratio + require("focus").setup({ autoresize = { focusedwindow_minheight = 80} }) +< + **Set Focus Quickfix Height** >lua @@ -287,7 +305,7 @@ buffer** -- Enable auto highlighting for focussed/unfocussed windows -- Default: false require("focus").setup({ ui = { winhighlight = true } }) - + -- By default, the highlight groups are setup as such: -- hi default link FocusedWindow VertSplit -- hi default link UnfocusedWindow Normal @@ -312,10 +330,10 @@ Here is an example: >lua local ignore_filetypes = { 'neo-tree' } local ignore_buftypes = { 'nofile', 'prompt', 'popup' } - + local augroup = vim.api.nvim_create_augroup('FocusDisable', { clear = true }) - + vim.api.nvim_create_autocmd('WinEnter', { group = augroup, callback = function(_) @@ -328,7 +346,7 @@ Here is an example: end, desc = 'Disable focus autoresize for BufType', }) - + vim.api.nvim_create_autocmd('FileType', { group = augroup, callback = function(_) @@ -473,7 +491,7 @@ LEVERAGE HJKL TO MOVE OR CREATE YOUR SPLITS DIRECTIONALLY ~ require('focus').split_command(direction) end, { desc = string.format('Create or move to split (%s)', direction) }) end - + -- Use `<Leader>h` to split the screen to the left, same as command FocusSplitLeft etc focusmap('h') focusmap('j') diff --git a/extras/repro.lua b/extras/repro.lua index 01f5f5b..9dcf798 100644 --- a/extras/repro.lua +++ b/extras/repro.lua @@ -37,6 +37,8 @@ require('focus').setup({ height = 0, -- Force height for the focused window minwidth = 0, -- Force minimum width for the unfocused window minheight = 0, -- Force minimum height for the unfocused window + focusedwindow_minwidth = 0, -- Force minimum width for the focused window + focusedwindow_minheight = 0, -- Force minimum height for the focused window height_quickfix = 10, -- Set the height of quickfix panel }, split = { diff --git a/lua/focus/init.lua b/lua/focus/init.lua index 2379018..39d5da4 100644 --- a/lua/focus/init.lua +++ b/lua/focus/init.lua @@ -27,6 +27,8 @@ Focus.config = { height = 0, -- Force height for the focused window minwidth = 0, -- Force minimum width for the unfocused window minheight = 0, -- Force minimum height for the unfocused window + focusedwindow_minwidth = 0, -- Force minimum width for the focused window + focusedwindow_minheight = 0, -- Force minimum height for the focused window height_quickfix = 10, -- Set the height of quickfix panel }, split = { @@ -196,6 +198,14 @@ H.setup_config = function(config) ['autoresize.height'] = { config.autoresize.height, 'number' }, ['autoresize.minwidth'] = { config.autoresize.minwidth, 'number' }, ['autoresize.minheight'] = { config.autoresize.minheight, 'number' }, + ['autoresize.focusedwindow_minwidth'] = { + config.autoresize.focusedwindow_minwidth, + 'number', + }, + ['autoresize.focusedwindow_minheight'] = { + config.autoresize.focusedwindow_minheight, + 'number', + }, ['autoresize.height_quickfix'] = { config.autoresize.height_quickfix, 'number', diff --git a/lua/focus/modules/resizer.lua b/lua/focus/modules/resizer.lua index 2dbc357..1d83cdc 100644 --- a/lua/focus/modules/resizer.lua +++ b/lua/focus/modules/resizer.lua @@ -54,7 +54,11 @@ function M.autoresize(config) width = config.autoresize.width else width = golden_ratio_width() - if config.autoresize.minwidth > 0 then + if config.autoresize.focusedwindow_minwidth > 0 then + if width < config.autoresize.focusedwindow_minwidth then + width = config.autoresize.focusedwindow_minwidth + end + elseif config.autoresize.minwidth > 0 then width = math.max(width, config.autoresize.minwidth) elseif width < golden_ratio_minwidth() then width = golden_ratio_minwidth() @@ -66,7 +70,11 @@ function M.autoresize(config) height = config.autoresize.height else height = golden_ratio_height() - if config.autoresize.minheight > 0 then + if config.autoresize.focusedwindow_minheight > 0 then + if height < config.autoresize.focusedwindow_minheight then + height = config.autoresize.focusedwindow_minheight + end + elseif config.autoresize.minheight > 0 then height = math.max(height, config.autoresize.minheight) elseif height < golden_ratio_minheight() then height = golden_ratio_minheight() @@ -121,13 +129,19 @@ function M.split_resizer(config, goal) --> Only resize normal buffers, set qf to vim.o.winheight = 1 return else - if config.autoresize.minwidth > 0 then + if + config.autoresize.minwidth > 0 + and config.autoresize.focusedwindow_minwidth <= 0 + then if vim.o.winwidth < config.autoresize.minwidth then vim.o.winwidth = config.autoresize.minwidth end vim.o.winminwidth = config.autoresize.minwidth end - if config.autoresize.minheight > 0 then + if + config.autoresize.minheight > 0 + and config.autoresize.focusedwindow_minheight <= 0 + then if vim.o.winheight < config.autoresize.minheight then vim.o.winheight = config.autoresize.minheight end From 99db1e1edf94c2c9a38132010bfbc72360697f28 Mon Sep 17 00:00:00 2001 From: MrZeLee <mrzelee404@gmail.com> Date: Sun, 9 Mar 2025 22:25:30 +0000 Subject: [PATCH 2/2] test: add tests for the focused window minwidth and minheight options Testing focusedwindow_minwidth and focusedwindow_minheight when value is bigger and smaller then the expected width and height value from golden ratio function. Testing integration of focusedwindow_minwidth and focusedwindow_minheight with minwidth and minheight values. --- tests/test_autoresize.lua | 123 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/tests/test_autoresize.lua b/tests/test_autoresize.lua index 5c5d403..a70d6f3 100644 --- a/tests/test_autoresize.lua +++ b/tests/test_autoresize.lua @@ -211,6 +211,129 @@ T['autoresize']['vsplit minwidth'] = function() validate_win_dims(win_id_right, { 30, 23 }) end +-- focused minwidth for vertical splits +T['autoresize']['vsplit focusedwindow_minwidth'] = function() + reload_module({ autoresize = { focusedwindow_minwidth = 55 } }) + edit(lorem_ipsum_file) + child.set_cursor(15, 1) + child.cmd('vsplit') + local resize_state = child.get_resize_state() + local win_id_left = resize_state.windows[1] + local win_id_right = resize_state.windows[2] + + eq(win_id_left, child.api.nvim_get_current_win()) + + -- Expect the left window's width to be at least 55. + -- In the default test, the left width is 49. + -- With forced focusedwindow_minwidth, we now expect 55. + validate_win_dims(win_id_left, { 55, 23 }) + -- The right window should take the remaining width + validate_win_dims(win_id_right, { 24, 23 }) +end + +-- focused minwidth for vertical splits inferior to the default one obtained by +-- the golden ratio +T['autoresize']['vsplit focusedwindow_minwidth < golden_ratio expected value'] = function() + reload_module({ autoresize = { focusedwindow_minwidth = 40 } }) + edit(lorem_ipsum_file) + child.set_cursor(15, 1) + child.cmd('vsplit') + local resize_state = child.get_resize_state() + local win_id_left = resize_state.windows[1] + local win_id_right = resize_state.windows[2] + + eq(win_id_left, child.api.nvim_get_current_win()) + + -- The expected value is the golden ratio one + validate_win_dims(win_id_left, { 49, 23 }) + -- The right window should take the remaining width + validate_win_dims(win_id_right, { 30, 23 }) +end + +-- focused minheight for horizontal splits +T['autoresize']['split focusedwindow_minheight'] = function() + reload_module({ autoresize = { focusedwindow_minheight = 17 } }) + edit(lorem_ipsum_file) + child.set_cursor(15, 1) + child.cmd('split') + local resize_state = child.get_resize_state() + local win_id_upper = resize_state.windows[1] + local win_id_lower = resize_state.windows[2] + + -- In the default test, the upper window height is 15. + -- With forced focusedwindow_minheight, we now expect 17. + validate_win_dims(win_id_upper, { 80, 17 }) + -- The lower window gets the rest (assuming total height used equals 22) + validate_win_dims(win_id_lower, { 80, 5 }) +end + +-- focused minheight for horizontal splits inferior to the default one obtained by +-- the golden ratio +T['autoresize']['split focusedwindow_minheight < golden_ratio expected value'] = function() + reload_module({ autoresize = { focusedwindow_minheight = 10 } }) + edit(lorem_ipsum_file) + child.set_cursor(15, 1) + child.cmd('split') + local resize_state = child.get_resize_state() + local win_id_upper = resize_state.windows[1] + local win_id_lower = resize_state.windows[2] + + -- The expected value is the golden ratio one + validate_win_dims(win_id_upper, { 80, 15 }) + -- The lower window gets the rest + validate_win_dims(win_id_lower, { 80, 7 }) +end + +-- focused minwidth for vertical splits with minwidth + focusedwindow_minwidth > +-- maxwidth. +T['autoresize']['vsplit minwidth focusedwindow_minwidth'] = function() + reload_module({ + autoresize = { minwidth = 20, focusedwindow_minwidth = 80 }, + }) + edit(lorem_ipsum_file) + child.set_cursor(15, 1) + child.cmd('vsplit') + local resize_state = child.get_resize_state() + local win_id_left = resize_state.windows[1] + local win_id_right = resize_state.windows[2] + + eq(win_id_left, child.api.nvim_get_current_win()) + + -- Expect the left window's width to be at least the maxwidth (80) minus 21, + -- 20 from the right window as the minimum width possible and 1 from the + -- separator. + -- With forced focusedwindow_minwidth, we now expect 59. + validate_win_dims(win_id_left, { 78, 23 }) + -- The right window should have the minwidth. + validate_win_dims(win_id_right, { 1, 23 }) + + child.api.nvim_set_current_win(win_id_right) + + validate_win_dims(win_id_left, { 1, 23 }) + -- The right window should have the minwidth. + validate_win_dims(win_id_right, { 78, 23 }) +end + +-- focused minheight for horizontal splits with minheight as 0 +T['autoresize']['split minheight focusedwindow_minheight'] = function() + reload_module({ + autoresize = { minheight = 10, focusedwindow_minheight = 25 }, + }) + edit(lorem_ipsum_file) + child.set_cursor(15, 1) + child.cmd('split') + local resize_state = child.get_resize_state() + local win_id_upper = resize_state.windows[1] + local win_id_lower = resize_state.windows[2] + + -- Expect the upper window's height to be at least the maxheight (23) minus 2, + -- 1 from the lower window as the minimum height and 1 from the separator. + -- With forced focusedwindow_minheight, we now expect 21. + validate_win_dims(win_id_upper, { 80, 21 }) + -- The lower window should have the minimum height. + validate_win_dims(win_id_lower, { 80, 1 }) +end + T['autoresize']['quickfix'] = function() reload_module({ autoresize = { height_quickfix = 10 } }) child.cmd('vimgrep /ipsum/' .. lorem_ipsum_file)