Skip to content

Commit

Permalink
test(nvim): trim one trailing newline in dedent helper
Browse files Browse the repository at this point in the history
The `helpers.dedent()` now trims one trailing newline by default.
Additionally, it now ignores lines that contain only whitespaces.
This change allows to ignore the last line of a Lua literal string.
For example:
    helpers.dedent([[
      line1
      line2
    ]])
will now return `line1\nline2` by default. This behavior can be
disabled by setting `opts.trim = false`.
  • Loading branch information
stasjok committed Oct 14, 2024
1 parent 83330ce commit 8b7f5ab
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 23 deletions.
14 changes: 8 additions & 6 deletions tests/nvim/filetypes/mediawiki_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -166,18 +166,20 @@ T["fenced languages"]["refreshed after buffer reloading"] = function()

-- Set initial buffer contents
set_lines(dedent([[
<!-- vim: set ft=mediawiki: -->
== Heading ==
]]))
<!-- vim: set ft=mediawiki: -->
== Heading ==
]]))
cmd.write(f)
cmd.edit()

-- Add new syntaxhighlight region
set_lines(
dedent([[
<syntaxhighlight lang="yaml">
key: 123
</syntaxhighlight>]]),
<syntaxhighlight lang="yaml">
key: 123
</syntaxhighlight>
]]),
{ start = -1 }
)
cmd.write()
Expand Down
23 changes: 17 additions & 6 deletions tests/nvim/runtime/lua/test/helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,41 @@ local M = {}
M.expect = require("test.expect")
M.new_child = require("test.Child").new

--- Remove common indent from a given string
---@param str string
---@class test.helpers.dedent.opts
---@field trim? boolean Trim last trailing newline. Default: `true`.

--- Remove common indent from a given string.
--- One trailing newline is trimmed by default.
--- Can be disabled with `opts.trim = false`.
--- Empty lines (lines containing only whitespaces) are ignored.
---@param str string Input string
---@param opts? test.helpers.dedent.opts Options
---@return string
function M.dedent(str)
function M.dedent(str, opts)
opts = opts or {}
local trim = vim.F.if_nil(opts.trim, true)

-- Find minimal indent
local minimal_indent = math.huge
for s in vim.gsplit(str, "\n", { plain = true, trimempty = true }) do
if s ~= "" then
local _, indent = s:find("^%s*")
if indent == 0 then
-- No indent, return early
return str
elseif indent and indent < minimal_indent then
return str:sub(-1) == "\n" and trim and str:sub(1, -2) or str
elseif indent and indent < minimal_indent and indent ~= #s then
minimal_indent = indent
end
end
end

return vim
local out = vim
.iter(vim.gsplit(str, "\n", { plain = true }))
:map(function(s)
return s:sub(minimal_indent + 1)
end)
:join("\n")
return out:sub(-1) == "\n" and trim and out:sub(1, -2) or out
end

--- Wrap every value in the table into another table,
Expand Down
3 changes: 2 additions & 1 deletion tests/nvim/skeletons_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ local skeletons = {
return T]]),
return T
]]),
cursor_line = 17,
},
}
Expand Down
32 changes: 22 additions & 10 deletions tests/nvim/test/helpers_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,37 @@ local T = new_set()
T["dedent"] = new_set({
parametrize = {
-- Empty input
{ "", "" },
{ { "" }, "" },
-- No indent
{ "a\nb", "a\nb" },
{ { "a\nb" }, "a\nb" },
-- Common indent
{ " a\n b", "a\nb" },
{ { " a\n b" }, "a\nb" },
-- Not all lines are indented
{ " a\nb", " a\nb" },
{ "a\n b", "a\n b" },
{ { " a\nb" }, " a\nb" },
{ { "a\n b" }, "a\n b" },
-- Different indent
{ " a\n b\n c", "a\n b\n c" },
{ { " a\n b\n c" }, "a\n b\n c" },
-- Empty lines
{ " a\n\n b\n", "a\n\nb\n" },
{ { " a\n\n b\n c" }, "a\n\nb\nc" },
-- Tabs
{ "\ta\n\tb", "a\nb" },
{ "\t\ta\n\tb", "\ta\nb" },
{ { "\ta\n\tb" }, "a\nb" },
{ { "\t\ta\n\tb" }, "\ta\nb" },
-- Ignore less-indented spaces
{ { " a\n \n b" }, "a\n\nb" },
-- Trims last newline
{ { "a\nb\n" }, "a\nb" },
-- Trims only one newline
{ { " a\n\n b\n\n\n" }, "a\n\nb\n\n" },
-- Last empty and less-indented line is trimmed
{ { " a\n b\n c\n " }, "a\n b\nc" },
{ { " a\n b\n c\n\n " }, "a\n b\nc\n" },
-- '{opts.trim = false}'
{ { "a\nb\n", { trim = false } }, "a\nb\n" },
{ { " a\n \n b\n", { trim = false } }, "a\n\nb\n" },
},
}, {
test = function(input, expectation)
eq(helpers.dedent(input), expectation)
eq(helpers.dedent(unpack(input)), expectation)
end,
})

Expand Down

0 comments on commit 8b7f5ab

Please sign in to comment.