Skip to content

Commit be28d38

Browse files
authored
feat: make the sizes of the list and preview window configurable
1 parent 4957540 commit be28d38

File tree

6 files changed

+111
-5
lines changed

6 files changed

+111
-5
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ require('taskfile').setup({
4747
width = 0.6,
4848
height = 0.4,
4949
border = "rounded"
50+
width_ratio = 0.4 -- Ratio (0-1) of list vs preview width
5051
},
5152
},
5253
scroll = {

lua/taskfile/core.lua

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ local config = {
1515
width = 0.6,
1616
height = 0.4,
1717
border = "rounded",
18+
width_ratio = 0.4,
1819
},
1920
},
2021
scroll = {
@@ -77,8 +78,11 @@ end
7778
---@field height? number # Height of the window (0–1 for percentage)
7879
---@field border? string # Border style (e.g., "single", "rounded")
7980

81+
---@class ListWindowConfig : WindowConfig
82+
---@field width_ratio? number # Ratio (0–1) of list vs preview width. Default is 0.4
83+
8084
---@class TaskfileConfig
81-
---@field windows? { output?: WindowConfig, list?: WindowConfig } # Floating window layouts
85+
---@field windows? { output?: WindowConfig, list?: ListWindowConfig } # Floating window layouts
8286
---@field scroll? { auto?: boolean } # Auto-scroll output to the bottom
8387
---@field keymaps? { rerun?: string } # Keymap configuration for commands like rerun
8488
--- Setup the Taskfile plugin
@@ -92,6 +96,14 @@ M.setup = function(opts)
9296
})
9397
M._options = vim.tbl_deep_extend("force", {}, config, opts or {})
9498

99+
utils.validate_range({
100+
["windows.output.width"] = M._options.windows.output.width,
101+
["windows.output.height"] = M._options.windows.output.height,
102+
["windows.list.width"] = M._options.windows.list.width,
103+
["windows.list.height"] = M._options.windows.list.height,
104+
["windows.list.width_ratio"] = M._options.windows.list.width_ratio,
105+
}, 0, 1)
106+
95107
if M._options.keymaps ~= false then
96108
setup_global_keymaps()
97109
end
@@ -169,7 +181,7 @@ M.close_task_output_window = function()
169181
end
170182

171183
--- Return the window configuration for the list
172-
---@return WindowConfig
184+
---@return ListWindowConfig
173185
M.get_list_config = function()
174186
return M._options.windows.list
175187
end

lua/taskfile/ui.lua

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
local M = {}
33
local utils = require("taskfile.utils")
44

5+
local WINDOW_GAP = 2
6+
57
M._list_win = nil
68
M._preview_win = nil
79
M._list_buf = nil
@@ -73,7 +75,7 @@ end
7375

7476
--- Opens a floating window with a list of tasks and a preview of the selected task.
7577
---@param tasks table List of tasks
76-
---@param config WindowConfig The window config for the preview
78+
---@param config ListWindowConfig Window Configuration for the list
7779
M.select_task_with_preview = function(tasks, config)
7880
if #tasks == 0 then
7981
vim.notify("No tasks available", vim.log.levels.WARN)
@@ -84,8 +86,9 @@ M.select_task_with_preview = function(tasks, config)
8486
close_task_list_and_preview()
8587

8688
local total_width, total_height, row, col = utils.calculate_dimensions(config.width, config.height)
87-
local list_width = math.floor(total_width * 0.3)
88-
local preview_width = total_width - list_width - 2
89+
local ratio = config.width_ratio or 0.4
90+
local list_width = math.floor(total_width * ratio)
91+
local preview_width = total_width - list_width - WINDOW_GAP
8992

9093
M._list_buf = vim.api.nvim_create_buf(false, true)
9194
M._preview_buf = vim.api.nvim_create_buf(false, true)

lua/taskfile/utils.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,22 @@ M.open_floating_win = function(buf, opts, enter)
5858
)
5959
end
6060

61+
--- Validate numeric fields fall within a given range
62+
---@param t table<string, number|nil>
63+
---@param min number
64+
---@param max number
65+
M.validate_range = function(t, min, max)
66+
for name, value in pairs(t) do
67+
vim.validate({
68+
[name] = {
69+
value,
70+
function(v)
71+
return (v == nil) or ((type(v) == "number") and ((v >= min) and (v <= max)))
72+
end,
73+
string.format("number between %s and %s", min, max),
74+
},
75+
})
76+
end
77+
end
78+
6179
return M

tests/taskfile/setup_spec.lua

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,59 @@ describe("setup", function()
6464
local keymap_cfg = core._options.keymap
6565
assert.are.same(keymap_cfg.rerun, "<leader>tt")
6666
end)
67+
68+
it("should apply valid width_ratio", function()
69+
plugin.setup({
70+
windows = {
71+
list = {
72+
width_ratio = 0.9,
73+
},
74+
},
75+
})
76+
77+
local ratio = core._options.windows.list.width_ratio
78+
assert.are.same(0.9, ratio)
79+
end)
80+
81+
it("should raise error for invalid output width < 0", function()
82+
local ok, err = pcall(function()
83+
plugin.setup({
84+
windows = {
85+
output = {
86+
width = -0.1,
87+
},
88+
},
89+
})
90+
end)
91+
assert.is_false(ok)
92+
assert.matches("output.width", err)
93+
end)
94+
95+
it("should raise error for invalid list height > 1", function()
96+
local ok, err = pcall(function()
97+
plugin.setup({
98+
windows = {
99+
list = {
100+
height = 1.5,
101+
},
102+
},
103+
})
104+
end)
105+
assert.is_false(ok)
106+
assert.matches("list.height", err)
107+
end)
108+
109+
it("should raise error for invalid width_ratio type", function()
110+
local ok, err = pcall(function()
111+
plugin.setup({
112+
windows = {
113+
list = {
114+
width_ratio = "wide",
115+
},
116+
},
117+
})
118+
end)
119+
assert.is_false(ok)
120+
assert.matches("width_ratio", err)
121+
end)
67122
end)

tests/taskfile/ui_spec.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,21 @@ tasks:
134134
ui.select_task_with_preview({})
135135
end)
136136
end)
137+
138+
it("respects width_ratio when calculating window sizes", function()
139+
local ratio = 0.5
140+
local available_width = 1.0
141+
local total_width = math.floor(vim.o.columns * available_width)
142+
local expected_list_width = math.floor(total_width * ratio)
143+
144+
ui.select_task_with_preview(tasks, {
145+
width = available_width,
146+
height = 0.4,
147+
border = "rounded",
148+
width_ratio = ratio,
149+
})
150+
151+
local list_win_config = vim.api.nvim_win_get_config(ui._list_win)
152+
assert.are.same(expected_list_width, list_win_config.width)
153+
end)
137154
end)

0 commit comments

Comments
 (0)