Line data Source code
1 : -- lua/yoda/commands/formatting.lua
2 : -- Feature file (Gherkin) formatting commands
3 :
4 1 : local M = {}
5 :
6 1 : local notify = require("yoda-adapters.notification")
7 :
8 : --- Trim trailing whitespace from all lines in current buffer
9 : local function trim_trailing_whitespace()
10 1 : local bufnr = vim.api.nvim_get_current_buf()
11 1 : local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
12 1 : local updated = {}
13 :
14 5 : for _, line in ipairs(lines) do
15 4 : local trimmed = line:gsub("%s+$", "")
16 4 : table.insert(updated, trimmed)
17 : end
18 :
19 1 : vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, updated)
20 1 : notify.notify("✅ Trailing whitespace removed", "info")
21 2 : end
22 :
23 : --- Format an Examples table block
24 : local function format_example_block(lines)
25 1 : local result = {}
26 1 : local widths = {}
27 :
28 3 : for _, line in ipairs(lines) do
29 2 : local cells = {}
30 8 : for cell in line:gmatch("%s*|%s*([^|]*)") do
31 6 : table.insert(cells, cell:match("^%s*(.-)%s*$"))
32 : end
33 2 : table.insert(result, cells)
34 :
35 8 : for i, cell in ipairs(cells) do
36 6 : widths[i] = math.max(widths[i] or 0, #cell)
37 : end
38 : end
39 :
40 1 : local formatted = {}
41 3 : for _, cells in ipairs(result) do
42 2 : local parts = {}
43 8 : for i, cell in ipairs(cells) do
44 6 : local padded = cell .. string.rep(" ", widths[i] - #cell)
45 6 : table.insert(parts, padded)
46 : end
47 2 : table.insert(formatted, " | " .. table.concat(parts, " | ") .. " |")
48 : end
49 :
50 1 : return formatted
51 1 : end
52 :
53 : --- Fix alignment of Examples blocks in feature files
54 : local function fix_feature_examples()
55 1 : local bufnr = vim.api.nvim_get_current_buf()
56 1 : local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
57 1 : local updated = {}
58 1 : local in_examples = false
59 1 : local example_lines = {}
60 :
61 5 : for _, line in ipairs(lines) do
62 4 : if line:match("^%s*Examples:") then
63 1 : in_examples = true
64 1 : table.insert(updated, line)
65 3 : elseif in_examples and line:match("|") then
66 2 : table.insert(example_lines, line)
67 : else
68 1 : if in_examples and #example_lines > 0 then
69 : vim.list_extend(updated, format_example_block(example_lines))
70 : example_lines = {}
71 : in_examples = false
72 : end
73 1 : table.insert(updated, line)
74 : end
75 : end
76 :
77 1 : if #example_lines > 0 then
78 2 : vim.list_extend(updated, format_example_block(example_lines))
79 : end
80 :
81 1 : vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, updated)
82 1 : notify.notify("✅ Examples blocks aligned", "info")
83 2 : end
84 :
85 : --- Format the current feature file
86 : local function format_feature()
87 1 : fix_feature_examples()
88 1 : trim_trailing_whitespace()
89 2 : end
90 :
91 1 : function M.setup()
92 22 : vim.api.nvim_create_user_command("FormatFeature", function()
93 1 : format_feature()
94 12 : end, { desc = "Format Gherkin feature file" })
95 :
96 : -- Toggle conform.nvim auto-format on save.
97 : -- vim.g.autoformat is initialised to true in formatters.lua so the first
98 : -- call always disables, matching the common "I need to save without formatting"
99 : -- use-case without requiring the user to remember the current state.
100 22 : vim.api.nvim_create_user_command("ToggleFormat", function()
101 : vim.g.autoformat = not vim.g.autoformat
102 : vim.notify(string.format("%s formatting on save", vim.g.autoformat and "Enabled" or "Disabled"), vim.log.levels.INFO)
103 11 : end, { desc = "Toggle conform.nvim auto-formatting on save" })
104 12 : end
105 :
106 1 : return M
|