From da7e9104de4ff9303e1c722f7c9216f994622067 Mon Sep 17 00:00:00 2001 From: Steven Arcangeli Date: Wed, 13 Nov 2024 22:50:34 -0800 Subject: [PATCH] feat: add option to remove all leading whitespace from items (#26) --- README.md | 4 +- doc/quicker.txt | 4 +- lua/quicker/config.lua | 15 ++++-- lua/quicker/display.lua | 16 ++++-- lua/quicker/editor.lua | 9 +++- tests/editor_spec.lua | 72 ++++++++++++++++++++++++- tests/snapshots/edit_all_whitespace | 4 ++ tests/snapshots/edit_all_whitespace_qf | 2 + tests/snapshots/edit_none_whitespace | 4 ++ tests/snapshots/edit_none_whitespace_qf | 2 + tests/snapshots/trim_all_whitespace | 2 + tests/whitespace_spec.lua | 29 +++++++++- 12 files changed, 145 insertions(+), 18 deletions(-) create mode 100644 tests/snapshots/edit_all_whitespace create mode 100644 tests/snapshots/edit_all_whitespace_qf create mode 100644 tests/snapshots/edit_none_whitespace create mode 100644 tests/snapshots/edit_none_whitespace_qf create mode 100644 tests/snapshots/trim_all_whitespace diff --git a/README.md b/README.md index 9cabf70..1af5b8d 100644 --- a/README.md +++ b/README.md @@ -225,8 +225,8 @@ require("quicker").setup({ soft_cross = "╂", soft_end = "┨", }, - -- Trim the leading whitespace from results - trim_leading_whitespace = true, + -- How to trim the leading whitespace from results. Can be 'all', 'common', or false + trim_leading_whitespace = "common", -- Maximum width of the filename column max_filename_width = function() return math.floor(math.min(95, vim.o.columns / 2)) diff --git a/doc/quicker.txt b/doc/quicker.txt index db7eeec..846a811 100644 --- a/doc/quicker.txt +++ b/doc/quicker.txt @@ -65,8 +65,8 @@ OPTIONS *quicker-option soft_cross = "╂", soft_end = "┨", }, - -- Trim the leading whitespace from results - trim_leading_whitespace = true, + -- How to trim the leading whitespace from results. Can be 'all', 'common', or false + trim_leading_whitespace = "common", -- Maximum width of the filename column max_filename_width = function() return math.floor(math.min(95, vim.o.columns / 2)) diff --git a/lua/quicker/config.lua b/lua/quicker/config.lua index bd24f8f..517cc83 100644 --- a/lua/quicker/config.lua +++ b/lua/quicker/config.lua @@ -53,8 +53,8 @@ local default_config = { soft_cross = "╂", soft_end = "┨", }, - -- Trim the leading whitespace from results - trim_leading_whitespace = true, + -- How to trim the leading whitespace from results. Can be 'all', 'common', or false + trim_leading_whitespace = "common", -- Maximum width of the filename column max_filename_width = function() return math.floor(math.min(95, vim.o.columns / 2)) @@ -65,6 +65,8 @@ local default_config = { end, } +---@alias quicker.TrimEnum "all"|"common"|false + ---@class quicker.Config ---@field on_qf fun(bufnr: number) ---@field opts table @@ -75,7 +77,7 @@ local default_config = { ---@field edit quicker.EditConfig ---@field type_icons table ---@field borders quicker.Borders ----@field trim_leading_whitespace boolean +---@field trim_leading_whitespace quicker.TrimEnum ---@field max_filename_width fun(): integer ---@field header_length fun(type: "hard"|"soft", start_col: integer): integer local M = {} @@ -90,7 +92,7 @@ local M = {} ---@field edit? quicker.SetupEditConfig ---@field type_icons? table Map of quickfix item type to icon ---@field borders? quicker.SetupBorders Characters used for drawing the borders ----@field trim_leading_whitespace? boolean Trim the leading whitespace from results +---@field trim_leading_whitespace? quicker.TrimEnum How to trim the leading whitespace from results ---@field max_filename_width? fun(): integer Maximum width of the filename column ---@field header_length? fun(type: "hard"|"soft", start_col: integer): integer How far the header should extend to the right @@ -104,6 +106,11 @@ M.setup = function(opts) M[k] = v end + -- Shim for when this was only a boolean. 'true' meant 'common' + if M.trim_leading_whitespace == true then + M.trim_leading_whitespace = "common" + end + -- Remove the default opts values if use_default_opts is false if not new_conf.use_default_opts then M.opts = opts.opts or {} diff --git a/lua/quicker/display.lua b/lua/quicker/display.lua index 894e842..b53092d 100644 --- a/lua/quicker/display.lua +++ b/lua/quicker/display.lua @@ -90,7 +90,7 @@ end ---@return table local function calc_whitespace_prefix(items) local prefixes = {} - if not config.trim_leading_whitespace then + if config.trim_leading_whitespace ~= "common" then return prefixes end @@ -495,24 +495,32 @@ function M.quickfixtextfunc(info) end -- Construct the lines and save the filename + lnum to render as virtual text later + local trimmed_text + if config.trim_leading_whitespace == "all" then + trimmed_text = item.text:gsub("^%s*", "") + elseif config.trim_leading_whitespace == "common" then + trimmed_text = remove_prefix(item.text, prefixes[item.bufnr]) + else + trimmed_text = item.text + end if item.valid == 1 then -- Matching line local lnum = item.lnum == 0 and " " or item.lnum local filename = rpad(M.get_filename_from_item(item), col_width) table.insert(locations, get_virt_text(lnum)) - table.insert(ret, filename .. EM_QUAD .. remove_prefix(item.text, prefixes[item.bufnr])) + table.insert(ret, filename .. EM_QUAD .. trimmed_text) elseif user_data.lnum then -- Non-matching line from quicker.nvim context lines local filename = string.rep(" ", col_width) table.insert(locations, get_virt_text(user_data.lnum)) - table.insert(ret, filename .. EM_QUAD .. remove_prefix(item.text, prefixes[item.bufnr])) + table.insert(ret, filename .. EM_QUAD .. trimmed_text) else -- Other non-matching line local lnum = item.lnum == 0 and " " or item.lnum local filename = rpad(M.get_filename_from_item(item), col_width) table.insert(locations, get_virt_text(lnum)) invalid_filenames[#locations] = true - table.insert(ret, filename .. EM_QUAD .. remove_prefix(item.text, prefixes[item.bufnr])) + table.insert(ret, filename .. EM_QUAD .. trimmed_text) end end diff --git a/lua/quicker/editor.lua b/lua/quicker/editor.lua index 9486f60..3f5db65 100644 --- a/lua/quicker/editor.lua +++ b/lua/quicker/editor.lua @@ -217,10 +217,15 @@ local function save_changes(bufnr, loclist_win) if not vim.api.nvim_buf_is_loaded(item.bufnr) then vim.fn.bufload(item.bufnr) end + local src_line = vim.api.nvim_buf_get_lines(item.bufnr, item.lnum - 1, item.lnum, false)[1] + -- add the whitespace prefix back to the parsed line text - text = (prefixes[item.bufnr] or "") .. text + if config.trim_leading_whitespace == "common" then + text = (prefixes[item.bufnr] or "") .. text + elseif config.trim_leading_whitespace == "all" and src_line then + text = src_line:match("^%s*") .. text + end - local src_line = vim.api.nvim_buf_get_lines(item.bufnr, item.lnum - 1, item.lnum, false)[1] if src_line and text ~= src_line then if text:gsub("^%s*", "") == src_line:gsub("^%s*", "") then -- If they only disagree in their leading whitespace, just take the changes after the diff --git a/tests/editor_spec.lua b/tests/editor_spec.lua index c8fab7e..0999508 100644 --- a/tests/editor_spec.lua +++ b/tests/editor_spec.lua @@ -243,8 +243,8 @@ describe("editor", function() test_util.assert_snapshot(bufnr, "edit_delim") end) - it("can edit lines with trimmed whitespace", function() - require("quicker.config").trim_leading_whitespace = true + it("can edit lines with trimmed common whitespace", function() + require("quicker.config").trim_leading_whitespace = "common" vim.cmd.edit({ args = { test_util.make_tmp_file("edit_whitespace.txt", { @@ -276,4 +276,72 @@ describe("editor", function() vim.cmd.write() test_util.assert_snapshot(bufnr, "edit_whitespace") end) + + it("can edit lines with trimmed all whitespace", function() + require("quicker.config").trim_leading_whitespace = "all" + vim.cmd.edit({ + args = { + test_util.make_tmp_file("edit_whitespace.txt", { + " line 1", + " line 2", + " line 3", + " line 4", + }), + }, + }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + wait_virt_text() + test_util.assert_snapshot(0, "edit_all_whitespace_qf") + replace_text(1, "foo") + replace_text(2, "bar") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_all_whitespace") + end) + + it("can edit lines with untrimmed whitespace", function() + require("quicker.config").trim_leading_whitespace = false + vim.cmd.edit({ + args = { + test_util.make_tmp_file("edit_whitespace.txt", { + " line 1", + " line 2", + " line 3", + " line 4", + }), + }, + }) + local bufnr = vim.api.nvim_get_current_buf() + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + wait_virt_text() + test_util.assert_snapshot(0, "edit_none_whitespace_qf") + replace_text(1, "foo") + replace_text(2, "bar") + vim.cmd.write() + test_util.assert_snapshot(bufnr, "edit_none_whitespace") + end) end) diff --git a/tests/snapshots/edit_all_whitespace b/tests/snapshots/edit_all_whitespace new file mode 100644 index 0000000..998c877 --- /dev/null +++ b/tests/snapshots/edit_all_whitespace @@ -0,0 +1,4 @@ + line 1 + foo + bar + line 4 \ No newline at end of file diff --git a/tests/snapshots/edit_all_whitespace_qf b/tests/snapshots/edit_all_whitespace_qf new file mode 100644 index 0000000..baf8533 --- /dev/null +++ b/tests/snapshots/edit_all_whitespace_qf @@ -0,0 +1,2 @@ +tests/tmp/edit_whitespace.txt ┃ 2┃line 2 +tests/tmp/edit_whitespace.txt ┃ 3┃line 3 \ No newline at end of file diff --git a/tests/snapshots/edit_none_whitespace b/tests/snapshots/edit_none_whitespace new file mode 100644 index 0000000..4b592c2 --- /dev/null +++ b/tests/snapshots/edit_none_whitespace @@ -0,0 +1,4 @@ + line 1 +foo +bar + line 4 \ No newline at end of file diff --git a/tests/snapshots/edit_none_whitespace_qf b/tests/snapshots/edit_none_whitespace_qf new file mode 100644 index 0000000..5be47f1 --- /dev/null +++ b/tests/snapshots/edit_none_whitespace_qf @@ -0,0 +1,2 @@ +tests/tmp/edit_whitespace.txt ┃ 2┃ line 2 +tests/tmp/edit_whitespace.txt ┃ 3┃ line 3 \ No newline at end of file diff --git a/tests/snapshots/trim_all_whitespace b/tests/snapshots/trim_all_whitespace new file mode 100644 index 0000000..e664f80 --- /dev/null +++ b/tests/snapshots/trim_all_whitespace @@ -0,0 +1,2 @@ +tests/tmp/whitespace_1.txt ┃ 2┃line 2 +tests/tmp/whitespace_1.txt ┃ 3┃line 3 \ No newline at end of file diff --git a/tests/whitespace_spec.lua b/tests/whitespace_spec.lua index d1b1cd2..0933276 100644 --- a/tests/whitespace_spec.lua +++ b/tests/whitespace_spec.lua @@ -3,13 +3,13 @@ local test_util = require("tests.test_util") describe("whitespace", function() before_each(function() - require("quicker.config").trim_leading_whitespace = true + require("quicker.config").trim_leading_whitespace = "common" end) after_each(function() test_util.reset_editor() end) - it("removes leading whitespace from valid results", function() + it("removes common leading whitespace from valid results", function() local bufnr = vim.fn.bufadd(test_util.make_tmp_file("whitespace.txt", { " line 1", " line 2", @@ -55,4 +55,29 @@ describe("whitespace", function() vim.cmd.copen() test_util.assert_snapshot(0, "trim_mixed_whitespace") end) + + it("removes all leading whitespace", function() + require("quicker.config").trim_leading_whitespace = "all" + local bufnr = vim.fn.bufadd(test_util.make_tmp_file("whitespace_1.txt", { + " line 1", + " line 2", + " line 3", + "", + " line 4", + })) + vim.fn.setqflist({ + { + bufnr = bufnr, + text = " line 2", + lnum = 2, + }, + { + bufnr = bufnr, + text = " line 3", + lnum = 3, + }, + }) + vim.cmd.copen() + test_util.assert_snapshot(0, "trim_all_whitespace") + end) end)