mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 11:28:22 +00:00

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).
173 lines
4.3 KiB
Lua
173 lines
4.3 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
|
|
local clear = n.clear
|
|
local eq = t.eq
|
|
|
|
describe('vim.text', function()
|
|
before_each(clear)
|
|
|
|
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' },
|
|
{ '😂', 'F09F9882' },
|
|
}
|
|
|
|
for _, v in ipairs(cases) do
|
|
local input, output = unpack(v)
|
|
eq(output, vim.text.hexencode(input))
|
|
eq(input, vim.text.hexdecode(output))
|
|
end
|
|
end)
|
|
|
|
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('invalid input', function()
|
|
-- Odd number of hex characters
|
|
do
|
|
local res, err = vim.text.hexdecode('ABC')
|
|
eq(nil, res)
|
|
eq('string must have an even number of hex characters', err)
|
|
end
|
|
|
|
-- Non-hexadecimal input
|
|
do
|
|
local res, err = vim.text.hexdecode('nothex')
|
|
eq(nil, res)
|
|
eq('string must contain only hex characters', err)
|
|
end
|
|
end)
|
|
end)
|
|
end)
|