mirror of
https://github.com/neovim/neovim.git
synced 2026-01-03 18:06:29 +10:00
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:
@@ -153,16 +153,16 @@ describe('vim.secure', function()
|
||||
feed('v')
|
||||
screen:expect {
|
||||
grid = [[
|
||||
^let g:foobar = 42 |
|
||||
{1:~ }|*2
|
||||
{2:]]
|
||||
^let g:foobar = 42 |
|
||||
{1:~ }|*2
|
||||
{2:]]
|
||||
.. fn.fnamemodify(cwd, ':~')
|
||||
.. pathsep
|
||||
.. [[Xfile [RO]{MATCH:%s+}}|
|
||||
|
|
||||
{1:~ }|
|
||||
{4:[No Name] }|
|
||||
|
|
||||
|
|
||||
{1:~ }|
|
||||
{4:[No Name] }|
|
||||
|
|
||||
]],
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,133 @@ local eq = t.eq
|
||||
describe('vim.text', function()
|
||||
before_each(clear)
|
||||
|
||||
describe('hexencode() and hexdecode()', function()
|
||||
describe('indent()', function()
|
||||
it('validation', function()
|
||||
t.matches('size%: expected number, got string', t.pcall_err(vim.text.indent, 'x', 'x'))
|
||||
t.matches('size%: expected number, got nil', t.pcall_err(vim.text.indent, nil, 'x'))
|
||||
t.matches('opts%: expected table, got string', t.pcall_err(vim.text.indent, 0, 'x', 'z'))
|
||||
end)
|
||||
|
||||
it('basic cases', function()
|
||||
-- Basic cases.
|
||||
eq({ '', 0 }, { vim.text.indent(0, '') })
|
||||
eq({ '', 0 }, { vim.text.indent(2, '') })
|
||||
eq({ ' a', 4 }, { vim.text.indent(2, ' a') })
|
||||
eq({ ' a\n b', 4 }, { vim.text.indent(2, ' a\n b') })
|
||||
eq({ '\t\ta', 1 }, { vim.text.indent(2, '\ta') })
|
||||
eq({ ' a\n\n', 5 }, { vim.text.indent(1, ' a\n\n') })
|
||||
-- Indent 1 (tab) => 0. Starting with empty + blank lines.
|
||||
eq({ '\n\naa a aa', 1 }, { vim.text.indent(0, '\n \n aa a aa') })
|
||||
-- Indent 1 (tab) => 2 (tabs). Starting with empty + blank lines, 1-tab indent.
|
||||
eq({ '\n\t\t\n\t\taa a aa', 1 }, { vim.text.indent(2, '\n\t\n\taa a aa') })
|
||||
|
||||
-- Indent 4 => 2, expandtab=false preserves tabs after the common indent.
|
||||
eq(
|
||||
{ ' foo\n bar\n \tbaz\n', 4 },
|
||||
{ vim.text.indent(2, ' foo\n bar\n \tbaz\n') }
|
||||
)
|
||||
-- Indent 9 => 3, expandtab=true.
|
||||
eq(
|
||||
{ ' foo\n\n bar \t baz\n', 9 },
|
||||
{ vim.text.indent(3, '\t foo\n\n bar \t baz\n', { expandtab = 8 }) }
|
||||
)
|
||||
-- Indent 9 => 8, expandtab=true.
|
||||
eq(
|
||||
{ ' foo\n\n bar\n', 9 },
|
||||
{ vim.text.indent(8, '\t foo\n\n bar\n', { expandtab = 8 }) }
|
||||
)
|
||||
-- Dedent: 5 => 0.
|
||||
eq({ ' foo\n\nbar\n', 5 }, { vim.text.indent(0, ' foo\n\n bar\n') })
|
||||
-- Dedent: 1 => 0. Empty lines are ignored when deciding "common indent".
|
||||
eq(
|
||||
{ ' \n \nfoo\n\nbar\nbaz\n \n', 1 },
|
||||
{ vim.text.indent(0, ' \n \n foo\n\n bar\n baz\n \n') }
|
||||
)
|
||||
end)
|
||||
|
||||
it('real-world cases', function()
|
||||
-- Dedent.
|
||||
eq({
|
||||
[[
|
||||
bufs:
|
||||
nvim args: 3
|
||||
lua args: {
|
||||
[0] = "foo.lua"
|
||||
}
|
||||
]],
|
||||
10,
|
||||
}, {
|
||||
vim.text.indent(
|
||||
0,
|
||||
[[
|
||||
bufs:
|
||||
nvim args: 3
|
||||
lua args: {
|
||||
[0] = "foo.lua"
|
||||
}
|
||||
]]
|
||||
),
|
||||
})
|
||||
|
||||
-- Indent 0 => 2.
|
||||
eq({
|
||||
[[
|
||||
# yay
|
||||
|
||||
local function foo()
|
||||
if true then
|
||||
# yay
|
||||
end
|
||||
end
|
||||
|
||||
return
|
||||
]],
|
||||
0,
|
||||
}, {
|
||||
vim.text.indent(
|
||||
2,
|
||||
[[
|
||||
# yay
|
||||
|
||||
local function foo()
|
||||
if true then
|
||||
# yay
|
||||
end
|
||||
end
|
||||
|
||||
return
|
||||
]]
|
||||
),
|
||||
})
|
||||
|
||||
-- 1-tab indent, last line spaces < tabsize.
|
||||
-- Preserves tab char immediately following the indent.
|
||||
eq({ 'text\n\tmatch\nmatch\ntext\n', 1 }, {
|
||||
vim.text.indent(0, (([[
|
||||
text
|
||||
match
|
||||
match
|
||||
text
|
||||
]]):gsub('\n%s-([\n]?)$', '\n%1'))),
|
||||
})
|
||||
|
||||
-- 1-tab indent, last line spaces=tabsize.
|
||||
eq({ 'text\n match\nmatch\ntext\n', 6 }, {
|
||||
vim.text.indent(
|
||||
0,
|
||||
[[
|
||||
text
|
||||
match
|
||||
match
|
||||
text
|
||||
]],
|
||||
{ expandtab = 6 }
|
||||
),
|
||||
})
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('hexencode(), hexdecode()', function()
|
||||
it('works', function()
|
||||
local cases = {
|
||||
{ 'Hello world!', '48656C6C6F20776F726C6421' },
|
||||
@@ -21,13 +147,13 @@ describe('vim.text', function()
|
||||
end
|
||||
end)
|
||||
|
||||
it('works with very large strings', function()
|
||||
it('with very large strings', function()
|
||||
local input, output = string.rep('😂', 2 ^ 16), string.rep('F09F9882', 2 ^ 16)
|
||||
eq(output, vim.text.hexencode(input))
|
||||
eq(input, vim.text.hexdecode(output))
|
||||
end)
|
||||
|
||||
it('errors on invalid input', function()
|
||||
it('invalid input', function()
|
||||
-- Odd number of hex characters
|
||||
do
|
||||
local res, err = vim.text.hexdecode('ABC')
|
||||
|
||||
Reference in New Issue
Block a user