feat(lua): vim.text.indent()

Problem:
Indenting text is a common task in plugins/scripts for
presentation/formatting, yet vim has no way of doing it (especially
"dedent", and especially non-buffer text).

Solution:
Introduce `vim.text.indent()`. It sets the *exact* indentation because
that's a more difficult (and thus more useful) task than merely
"increasing the current indent" (which is somewhat easy with a `gsub()`
one-liner).
This commit is contained in:
Justin M. Keyes
2025-02-21 02:02:32 +01:00
parent f4921e2b7d
commit be1fbe38b3
31 changed files with 533 additions and 331 deletions

View File

@@ -148,6 +148,7 @@ end
--- @param actual string
--- @return boolean
function M.matches(pat, actual)
assert(pat and pat ~= '', 'pat must be a non-empty string')
if nil ~= string.match(actual, pat) then
return true
end
@@ -641,28 +642,9 @@ end
--- @param leave_indent? integer
--- @return string
function M.dedent(str, leave_indent)
-- find minimum common indent across lines
local indent --- @type string?
for line in str:gmatch('[^\n]+') do
local line_indent = line:match('^%s+') or ''
if indent == nil or #line_indent < #indent then
indent = line_indent
end
end
if not indent or #indent == 0 then
-- no minimum common indent
return str
end
local left_indent = (' '):rep(leave_indent or 0)
-- create a pattern for the indent
indent = indent:gsub('%s', '[ \t]')
-- strip it from the first line
str = str:gsub('^' .. indent, left_indent)
-- strip it from the remaining lines
str = str:gsub('[\n]' .. indent, '\n' .. left_indent)
return str
-- Last blank line often has non-matching indent, so remove it.
str = str:gsub('\n[ ]+$', '\n')
return (vim.text.indent(leave_indent or 0, str))
end
function M.intchar2lua(ch)