mirror of
https://github.com/neovim/neovim
synced 2025-07-16 09:11:51 +00: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:
@ -4624,6 +4624,41 @@ vim.text.hexencode({str}) *vim.text.hexencode()*
|
||||
Return: ~
|
||||
(`string`) Hex encoded string
|
||||
|
||||
vim.text.indent({size}, {text}, {opts}) *vim.text.indent()*
|
||||
Sets the indent (i.e. the common leading whitespace) of non-empty lines in
|
||||
`text` to `size` spaces/tabs.
|
||||
|
||||
Indent is calculated by number of consecutive indent chars.
|
||||
• The first indented, non-empty line decides the indent char (space/tab):
|
||||
• `SPC SPC TAB …` = two-space indent.
|
||||
• `TAB SPC …` = one-tab indent.
|
||||
• Set `opts.expandtab` to treat tabs as spaces.
|
||||
|
||||
To "dedent" (remove the common indent), pass `size=0`: >lua
|
||||
vim.print(vim.text.indent(0, ' a\n b\n'))
|
||||
<
|
||||
|
||||
To adjust relative-to an existing indent, call indent() twice: >lua
|
||||
local indented, old_indent = vim.text.indent(0, ' a\n b\n')
|
||||
indented = vim.text.indent(old_indent + 2, indented)
|
||||
vim.print(indented)
|
||||
<
|
||||
|
||||
To ignore the final, blank line when calculating the indent, use gsub()
|
||||
before calling indent(): >lua
|
||||
local text = ' a\n b\n '
|
||||
vim.print(vim.text.indent(0, (text:gsub('\n[\t ]+\n?$', '\n'))))
|
||||
<
|
||||
|
||||
Parameters: ~
|
||||
• {size} (`integer`) Number of spaces.
|
||||
• {text} (`string`) Text to indent.
|
||||
• {opts} (`{ expandtab?: number }?`)
|
||||
|
||||
Return (multiple): ~
|
||||
(`string`) Indented text.
|
||||
(`integer`) Indent size before modification.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Lua module: tohtml *vim.tohtml*
|
||||
|
@ -321,6 +321,7 @@ LUA
|
||||
• |vim.fs.relpath()| gets relative path compared to base path.
|
||||
• |vim.fs.dir()| and |vim.fs.find()| now follow symbolic links by default,
|
||||
the behavior can be turn off using the new `follow` option.
|
||||
• |vim.text.indent()| indents/dedents text.
|
||||
|
||||
OPTIONS
|
||||
|
||||
|
@ -186,18 +186,13 @@ local function get_healthcheck(plugin_names)
|
||||
return healthchecks
|
||||
end
|
||||
|
||||
--- Indents lines *except* line 1 of a string if it contains newlines.
|
||||
--- Indents lines *except* line 1 of a multiline string.
|
||||
---
|
||||
--- @param s string
|
||||
--- @param columns integer
|
||||
--- @return string
|
||||
local function indent_after_line1(s, columns)
|
||||
local lines = vim.split(s, '\n')
|
||||
local indent = string.rep(' ', columns)
|
||||
for i = 2, #lines do
|
||||
lines[i] = indent .. lines[i]
|
||||
end
|
||||
return table.concat(lines, '\n')
|
||||
return (vim.text.indent(columns, s):gsub('^%s+', ''))
|
||||
end
|
||||
|
||||
--- Changes ':h clipboard' to ':help |clipboard|'.
|
||||
|
@ -50,4 +50,91 @@ function M.hexdecode(enc)
|
||||
return table.concat(str), nil
|
||||
end
|
||||
|
||||
--- Sets the indent (i.e. the common leading whitespace) of non-empty lines in `text` to `size`
|
||||
--- spaces/tabs.
|
||||
---
|
||||
--- Indent is calculated by number of consecutive indent chars.
|
||||
--- - The first indented, non-empty line decides the indent char (space/tab):
|
||||
--- - `SPC SPC TAB …` = two-space indent.
|
||||
--- - `TAB SPC …` = one-tab indent.
|
||||
--- - Set `opts.expandtab` to treat tabs as spaces.
|
||||
---
|
||||
--- To "dedent" (remove the common indent), pass `size=0`:
|
||||
--- ```lua
|
||||
--- vim.print(vim.text.indent(0, ' a\n b\n'))
|
||||
--- ```
|
||||
---
|
||||
--- To adjust relative-to an existing indent, call indent() twice:
|
||||
--- ```lua
|
||||
--- local indented, old_indent = vim.text.indent(0, ' a\n b\n')
|
||||
--- indented = vim.text.indent(old_indent + 2, indented)
|
||||
--- vim.print(indented)
|
||||
--- ```
|
||||
---
|
||||
--- To ignore the final, blank line when calculating the indent, use gsub() before calling indent():
|
||||
--- ```lua
|
||||
--- local text = ' a\n b\n '
|
||||
--- vim.print(vim.text.indent(0, (text:gsub('\n[\t ]+\n?$', '\n'))))
|
||||
--- ```
|
||||
---
|
||||
--- @param size integer Number of spaces.
|
||||
--- @param text string Text to indent.
|
||||
--- @param opts? { expandtab?: number }
|
||||
--- @return string # Indented text.
|
||||
--- @return integer # Indent size _before_ modification.
|
||||
function M.indent(size, text, opts)
|
||||
vim.validate('size', size, 'number')
|
||||
vim.validate('text', text, 'string')
|
||||
vim.validate('opts', opts, 'table', true)
|
||||
-- TODO(justinmk): `opts.prefix`, `predicate` like python https://docs.python.org/3/library/textwrap.html
|
||||
opts = opts or {}
|
||||
local tabspaces = opts.expandtab and (' '):rep(opts.expandtab) or nil
|
||||
|
||||
--- Minimum common indent shared by all lines.
|
||||
local old_indent --[[@type number?]]
|
||||
local prefix = tabspaces and ' ' or nil -- Indent char (space or tab).
|
||||
--- Check all non-empty lines, capturing leading whitespace (if any).
|
||||
--- @diagnostic disable-next-line: no-unknown
|
||||
for line_ws, extra in text:gmatch('([\t ]*)([^\n]+)') do
|
||||
line_ws = tabspaces and line_ws:gsub('[\t]', tabspaces) or line_ws
|
||||
-- XXX: blank line will miss the last whitespace char in `line_ws`, so we need to check `extra`.
|
||||
line_ws = line_ws .. (extra:match('^%s+$') or '')
|
||||
if 0 == #line_ws then
|
||||
-- Optimization: If any non-empty line has indent=0, there is no common indent.
|
||||
old_indent = 0
|
||||
break
|
||||
end
|
||||
prefix = prefix and prefix or line_ws:sub(1, 1)
|
||||
local _, end_ = line_ws:find('^[' .. prefix .. ']+')
|
||||
old_indent = math.min(old_indent or math.huge, end_ or 0)
|
||||
end
|
||||
-- Default to 0 if all lines are empty.
|
||||
old_indent = old_indent or 0
|
||||
prefix = prefix and prefix or ' '
|
||||
|
||||
if old_indent == size then
|
||||
-- Optimization: if the indent is the same, return the text unchanged.
|
||||
return text, old_indent
|
||||
end
|
||||
|
||||
local new_indent = prefix:rep(size)
|
||||
|
||||
--- Replaces indentation of a line.
|
||||
--- @param line string
|
||||
local function replace_line(line)
|
||||
-- Match the existing indent exactly; avoid over-matching any following whitespace.
|
||||
local pat = prefix:rep(old_indent)
|
||||
-- Expand tabs before replacing indentation.
|
||||
line = not tabspaces and line
|
||||
or line:gsub('^[\t ]+', function(s)
|
||||
return s:gsub('\t', tabspaces)
|
||||
end)
|
||||
-- Text following the indent.
|
||||
local line_text = line:match('^' .. pat .. '(.*)') or line
|
||||
return new_indent .. line_text
|
||||
end
|
||||
|
||||
return (text:gsub('[^\n]+', replace_line)), old_indent
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -766,18 +766,8 @@ local function scope_more_doc(o)
|
||||
end
|
||||
|
||||
--- @param x string
|
||||
--- @return string
|
||||
local function dedent(x)
|
||||
local xs = split(x)
|
||||
local leading_ws = xs[1]:match('^%s*') --[[@as string]]
|
||||
local leading_ws_pat = '^' .. leading_ws
|
||||
|
||||
for i in ipairs(xs) do
|
||||
local strip_pat = xs[i]:match(leading_ws_pat) and leading_ws_pat or '^%s*'
|
||||
xs[i] = xs[i]:gsub(strip_pat, '')
|
||||
end
|
||||
|
||||
return table.concat(xs, '\n')
|
||||
return (vim.text.indent(0, (x:gsub('\n%s-([\n]?)$', '\n%1'))))
|
||||
end
|
||||
|
||||
--- @return table<string,vim.option_meta>
|
||||
|
@ -148,10 +148,6 @@ local function url_encode(s)
|
||||
)
|
||||
end
|
||||
|
||||
local function expandtabs(s)
|
||||
return s:gsub('\t', (' '):rep(8)) --[[ @as string ]]
|
||||
end
|
||||
|
||||
local function to_titlecase(s)
|
||||
local text = ''
|
||||
for w in vim.gsplit(s, '[ \t]+') do
|
||||
@ -275,25 +271,13 @@ end
|
||||
---
|
||||
--- Blank lines (empty or whitespace-only) are ignored.
|
||||
local function get_indent(s)
|
||||
local min_indent = nil
|
||||
for line in vim.gsplit(s, '\n') do
|
||||
if line and not is_blank(line) then
|
||||
local ws = expandtabs(line:match('^%s+') or '')
|
||||
min_indent = (not min_indent or ws:len() < min_indent) and ws:len() or min_indent
|
||||
end
|
||||
end
|
||||
return min_indent or 0
|
||||
local _, indent = vim.text.indent(0, s, { expandtab = 8 })
|
||||
return indent
|
||||
end
|
||||
|
||||
--- Removes the common indent level, after expanding tabs to 8 spaces.
|
||||
local function trim_indent(s)
|
||||
local indent_size = get_indent(s)
|
||||
local trimmed = ''
|
||||
for line in vim.gsplit(s, '\n') do
|
||||
line = expandtabs(line)
|
||||
trimmed = ('%s%s\n'):format(trimmed, line:sub(indent_size + 1))
|
||||
end
|
||||
return trimmed:sub(1, -2)
|
||||
return vim.text.indent(0, s, { expandtab = 8 })
|
||||
end
|
||||
|
||||
--- Gets raw buffer text in the node's range (+/- an offset), as a newline-delimited string.
|
||||
|
@ -342,6 +342,7 @@ set(LUA_KEYMAP_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/keymap.lua)
|
||||
set(LUA_LOADER_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/loader.lua)
|
||||
set(LUA_OPTIONS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_options.lua)
|
||||
set(LUA_SHARED_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/shared.lua)
|
||||
set(LUA_TEXT_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/text.lua)
|
||||
|
||||
file(GLOB API_HEADERS CONFIGURE_DEPENDS api/*.h)
|
||||
list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h)
|
||||
@ -624,6 +625,7 @@ add_custom_command(
|
||||
${LUA_DEFAULTS_MODULE_SOURCE} "vim._defaults"
|
||||
${LUA_OPTIONS_MODULE_SOURCE} "vim._options"
|
||||
${LUA_SHARED_MODULE_SOURCE} "vim.shared"
|
||||
${LUA_TEXT_MODULE_SOURCE} "vim.text"
|
||||
DEPENDS
|
||||
${CHAR_BLOB_GENERATOR}
|
||||
${LUA_INIT_PACKAGES_MODULE_SOURCE}
|
||||
@ -637,6 +639,7 @@ add_custom_command(
|
||||
${LUA_DEFAULTS_MODULE_SOURCE}
|
||||
${LUA_OPTIONS_MODULE_SOURCE}
|
||||
${LUA_SHARED_MODULE_SOURCE}
|
||||
${LUA_TEXT_MODULE_SOURCE}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
|
@ -500,6 +500,8 @@ a]],
|
||||
keep the lines under this line folded
|
||||
keep this line folded 1
|
||||
keep this line folded 2
|
||||
|
||||
.
|
||||
]])
|
||||
command('set foldmethod=indent shiftwidth=2 noautoindent')
|
||||
eq(1, fn.foldlevel(1))
|
||||
|
@ -194,8 +194,7 @@ pcall(vim.cmd.edit, 'Xtest_swapredraw.lua')
|
||||
{100:vim.o.foldexpr} {100:=} {101:'v:lua.vim.treesitter.foldexpr()'} |
|
||||
{102:+-- 3 lines: vim.defer_fn(function()·······························································}|
|
||||
{104:pcall}{100:(vim.cmd.edit,} {101:'Xtest_swapredraw.lua'}{100:)} |
|
||||
|
|
||||
{105:~ }|*33
|
||||
{105:~ }|*34
|
||||
{106:Xtest_swapredraw.lua 1,1 All}|
|
||||
|
|
||||
]])
|
||||
@ -589,8 +588,8 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
|
||||
api.nvim_chan_send(chan, 'q')
|
||||
retry(nil, nil, function()
|
||||
eq(
|
||||
{ '', '[Process exited 1]', '' },
|
||||
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
|
||||
{ '[Process exited 1]' },
|
||||
eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})->filter({_, s -> !empty(trim(s))})")
|
||||
)
|
||||
end)
|
||||
end)
|
||||
|
@ -6,6 +6,7 @@ local n = require('test.functional.testnvim')()
|
||||
local clear, command, expect = n.clear, n.command, n.expect
|
||||
local source, write_file = n.source, t.write_file
|
||||
|
||||
--- @return string
|
||||
local function sixlines(text)
|
||||
local result = ''
|
||||
for _ = 1, 6 do
|
||||
@ -16,6 +17,9 @@ end
|
||||
|
||||
local function diff(text, nodedent)
|
||||
local fname = t.tmpname()
|
||||
finally(function()
|
||||
os.remove(fname)
|
||||
end)
|
||||
command('w! ' .. fname)
|
||||
n.poke_eventloop()
|
||||
local data = io.open(fname):read('*all')
|
||||
@ -24,7 +28,6 @@ local function diff(text, nodedent)
|
||||
else
|
||||
t.eq(t.dedent(text), data)
|
||||
end
|
||||
os.remove(fname)
|
||||
end
|
||||
|
||||
describe('character classes in regexp', function()
|
||||
@ -38,7 +41,7 @@ describe('character classes in regexp', function()
|
||||
local punct4 = '{|}~'
|
||||
local ctrl2 = '\127\128\130\144\155'
|
||||
local iso_text = '\166\177\188\199\211\233' -- "¦±¼ÇÓé" in utf-8
|
||||
setup(function()
|
||||
local function do_setup(no_dedent)
|
||||
-- The original test32.in file was not in utf-8 encoding and did also
|
||||
-- contain some control characters. We use lua escape sequences to write
|
||||
-- them to the test file.
|
||||
@ -52,8 +55,9 @@ describe('character classes in regexp', function()
|
||||
.. punct4
|
||||
.. ctrl2
|
||||
.. iso_text
|
||||
write_file('test36.in', sixlines(line))
|
||||
end)
|
||||
write_file('test36.in', sixlines(line), no_dedent)
|
||||
end
|
||||
setup(do_setup)
|
||||
before_each(function()
|
||||
clear()
|
||||
command('e test36.in')
|
||||
@ -288,7 +292,10 @@ describe('character classes in regexp', function()
|
||||
ABCDEFGHIXYZ
|
||||
ABCDEFGHIXYZ]])
|
||||
end)
|
||||
it([["\%1l^#.*" does not match on a line starting with "#". (vim-patch:7.4.1305)]], function()
|
||||
pending(
|
||||
[["\%1l^#.*" does not match on a line starting with "#". (vim-patch:7.4.1305)]],
|
||||
function()
|
||||
-- do_setup(true)
|
||||
source([[
|
||||
1 s/\%#=0\%1l^\t...//g
|
||||
2 s/\%#=1\%2l^\t...//g
|
||||
@ -296,8 +303,7 @@ describe('character classes in regexp', function()
|
||||
4 s/\%#=0\%4l^\t...//g
|
||||
5 s/\%#=1\%5l^\t...//g
|
||||
6 s/\%#=2\%6l^\t...//g]])
|
||||
diff(
|
||||
sixlines(
|
||||
local text = sixlines(
|
||||
string.sub(punct1, 1)
|
||||
.. digits
|
||||
.. punct2
|
||||
@ -308,8 +314,9 @@ describe('character classes in regexp', function()
|
||||
.. ctrl2
|
||||
.. iso_text
|
||||
)
|
||||
diff(text)
|
||||
end
|
||||
)
|
||||
end)
|
||||
it('does not convert character class ranges to an incorrect class', function()
|
||||
source([[
|
||||
1 s/\%#=0[0-z]//g
|
||||
@ -319,9 +326,9 @@ describe('character classes in regexp', function()
|
||||
5 s/\%#=1[^0-z]//g
|
||||
6 s/\%#=2[^0-z]//g
|
||||
]])
|
||||
diff(
|
||||
string.rep(ctrl1 .. punct1 .. punct4 .. ctrl2 .. iso_text .. '\n', 3)
|
||||
local text = string.rep(ctrl1 .. punct1 .. punct4 .. ctrl2 .. iso_text .. '\n', 3)
|
||||
.. string.rep(digits .. punct2 .. upper .. punct3 .. lower .. '\n', 3)
|
||||
)
|
||||
text = text:gsub('\t', ''):gsub('\n\t', '\n')
|
||||
diff(text)
|
||||
end)
|
||||
end)
|
||||
|
@ -112,6 +112,7 @@ describe('Visual block mode', function()
|
||||
line1
|
||||
line2
|
||||
line3
|
||||
.
|
||||
]])
|
||||
|
||||
-- Test for Visual block insert when virtualedit=all and utf-8 encoding.
|
||||
@ -123,6 +124,7 @@ describe('Visual block mode', function()
|
||||
x line1
|
||||
x line2
|
||||
x line3
|
||||
.
|
||||
]])
|
||||
|
||||
-- Test for Visual block append when virtualedit=all.
|
||||
@ -132,6 +134,7 @@ describe('Visual block mode', function()
|
||||
x x line1
|
||||
x x line2
|
||||
x x line3
|
||||
.
|
||||
]])
|
||||
end)
|
||||
|
||||
|
@ -13,8 +13,6 @@ local eval = n.eval
|
||||
local eq = t.eq
|
||||
|
||||
local function expect_empty_buffer()
|
||||
-- The space will be removed by t.dedent but is needed because dedent
|
||||
-- will fail if it can not find the common indent of the given lines.
|
||||
return expect('')
|
||||
end
|
||||
local function expect_line(line)
|
||||
|
@ -200,6 +200,7 @@ describe('eval', function()
|
||||
abcFc=]])
|
||||
end)
|
||||
|
||||
-- luacheck: ignore 611 (Line contains only whitespace)
|
||||
it('appending NL with setreg()', function()
|
||||
command('so test_eval_setup.vim')
|
||||
|
||||
@ -222,6 +223,7 @@ describe('eval', function()
|
||||
command([[call SetReg('D', "\n", 'l')]])
|
||||
command([[call SetReg('E', "\n")]])
|
||||
command([[call SetReg('F', "\n", 'b')]])
|
||||
command("$put ='.'")
|
||||
expect([[
|
||||
|
||||
{{{2 setreg('A', ']] .. '\000' .. [[')
|
||||
@ -256,7 +258,8 @@ describe('eval', function()
|
||||
F: type ]] .. "\0220; value: abcF2\000 (['abcF2', '']), expr: abcF2\000" .. [[ (['abcF2', ''])
|
||||
==
|
||||
=abcF2=
|
||||
]])
|
||||
|
||||
.]])
|
||||
end)
|
||||
|
||||
it('setting and appending list with setreg()', function()
|
||||
|
@ -62,12 +62,12 @@ describe("'listchars'", function()
|
||||
..bb>---<<$
|
||||
...cccc><$
|
||||
dd........ee<<>-$
|
||||
<$
|
||||
$
|
||||
>-------aa>-----$
|
||||
..bb>---..$
|
||||
...cccc>.$
|
||||
dd........ee..>-$
|
||||
.$]])
|
||||
$]])
|
||||
end)
|
||||
|
||||
it('works with :list', function()
|
||||
|
@ -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')
|
||||
|
@ -609,12 +609,13 @@ function M._new_argv(...)
|
||||
return args, env, io_extra
|
||||
end
|
||||
|
||||
--- Dedents string arguments and inserts the resulting text into the current buffer.
|
||||
--- @param ... string
|
||||
function M.insert(...)
|
||||
nvim_feed('i')
|
||||
for _, v in ipairs({ ... }) do
|
||||
local escaped = v:gsub('<', '<lt>')
|
||||
M.feed(escaped)
|
||||
M.feed(escaped) -- This also dedents :P
|
||||
end
|
||||
nvim_feed('<ESC>')
|
||||
end
|
||||
@ -812,6 +813,7 @@ function M.rmdir(path)
|
||||
end
|
||||
end
|
||||
|
||||
--- @deprecated Use `t.pcall_err()` to check failure, or `n.command()` to check success.
|
||||
function M.exc_exec(cmd)
|
||||
M.command(([[
|
||||
try
|
||||
|
@ -82,7 +82,7 @@ describe('treesitter node API', function()
|
||||
]])
|
||||
|
||||
exec_lua(function()
|
||||
local parser = vim.treesitter.get_parser(0, 'c')
|
||||
local parser = assert(vim.treesitter.get_parser(0, 'c'))
|
||||
local tree = parser:parse()[1]
|
||||
_G.root = tree:root()
|
||||
vim.treesitter.language.inspect('c')
|
||||
@ -92,7 +92,7 @@ describe('treesitter node API', function()
|
||||
end
|
||||
end)
|
||||
|
||||
exec_lua 'node = root:descendant_for_range(0, 11, 0, 16)'
|
||||
exec_lua 'node = root:descendant_for_range(0, 9, 0, 14)'
|
||||
eq('int x', lua_eval('node_text(node)'))
|
||||
|
||||
exec_lua 'node = node:next_sibling()'
|
||||
|
@ -386,8 +386,8 @@ void ui_refresh(void)
|
||||
[[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]]
|
||||
)
|
||||
eq({
|
||||
{ 'c-keyword', 'primitive_type', { 2, 2, 2, 5 }, 'int' },
|
||||
{ 'c-keyword', 'primitive_type', { 3, 4, 3, 7 }, 'int' },
|
||||
{ 'c-keyword', 'primitive_type', { 2, 0, 2, 3 }, 'int' },
|
||||
{ 'c-keyword', 'primitive_type', { 3, 2, 3, 5 }, 'int' },
|
||||
}, res0)
|
||||
|
||||
local res1 = exec_lua(
|
||||
@ -401,9 +401,9 @@ void ui_refresh(void)
|
||||
]]
|
||||
)
|
||||
eq({
|
||||
{ 'fizzbuzz-strings', 'string_literal', { 6, 15, 6, 38 }, '"number= %d FizzBuzz\\n"' },
|
||||
{ 'fizzbuzz-strings', 'string_literal', { 8, 15, 8, 34 }, '"number= %d Fizz\\n"' },
|
||||
{ 'fizzbuzz-strings', 'string_literal', { 10, 15, 10, 34 }, '"number= %d Buzz\\n"' },
|
||||
{ 'fizzbuzz-strings', 'string_literal', { 6, 13, 6, 36 }, '"number= %d FizzBuzz\\n"' },
|
||||
{ 'fizzbuzz-strings', 'string_literal', { 8, 13, 8, 32 }, '"number= %d Fizz\\n"' },
|
||||
{ 'fizzbuzz-strings', 'string_literal', { 10, 13, 10, 32 }, '"number= %d Buzz\\n"' },
|
||||
}, res1)
|
||||
end)
|
||||
|
||||
@ -608,9 +608,9 @@ void ui_refresh(void)
|
||||
|
||||
eq(
|
||||
{
|
||||
{ 0, 2, 0, 8 },
|
||||
{ 1, 2, 1, 8 },
|
||||
{ 2, 2, 2, 8 },
|
||||
{ 0, 0, 0, 6 },
|
||||
{ 1, 0, 1, 6 },
|
||||
{ 2, 0, 2, 6 },
|
||||
},
|
||||
test(
|
||||
[[
|
||||
@ -636,9 +636,9 @@ void ui_refresh(void)
|
||||
|
||||
eq(
|
||||
{
|
||||
{ 0, 2, 0, 7 },
|
||||
{ 1, 2, 1, 8 },
|
||||
{ 2, 2, 2, 7 },
|
||||
{ 0, 0, 0, 5 },
|
||||
{ 1, 0, 1, 6 },
|
||||
{ 2, 0, 2, 5 },
|
||||
},
|
||||
test(
|
||||
[[
|
||||
@ -675,9 +675,9 @@ void ui_refresh(void)
|
||||
end)
|
||||
|
||||
eq({
|
||||
{ 0, 2, 0, 12 },
|
||||
{ 1, 2, 1, 12 },
|
||||
{ 2, 2, 2, 12 },
|
||||
{ 0, 0, 0, 10 },
|
||||
{ 1, 0, 1, 10 },
|
||||
{ 2, 0, 2, 10 },
|
||||
}, result)
|
||||
end)
|
||||
|
||||
|
@ -2067,9 +2067,9 @@ describe('float window', function()
|
||||
screen:expect{grid=[[
|
||||
neeed some dummy |
|
||||
background text |
|
||||
to {1: halloj! }{23:e}ffect |
|
||||
of {1: BORDAA }{24:n}ding |
|
||||
of {23:b}{24:order sha}dow |
|
||||
to sh{1: halloj! }{23:f}ect |
|
||||
of co{1: BORDAA }{24:i}ng |
|
||||
of bo{23:r}{24:der shado}w |
|
||||
^ |
|
||||
|
|
||||
]]}
|
||||
|
@ -502,9 +502,7 @@ describe('ext_hlstate detailed highlights', function()
|
||||
local num_lines = 500
|
||||
insert('first line\n')
|
||||
for _ = 1, num_lines do
|
||||
insert([[
|
||||
line
|
||||
]])
|
||||
api.nvim_paste(' line\n', false, -1)
|
||||
end
|
||||
insert('last line')
|
||||
|
||||
|
@ -95,8 +95,7 @@ describe('Diff mode screen with 3 diffs open', function()
|
||||
{7: }{8: 9 }{4: BBB }│{7: }{8: 9 }{4: BBB }│{7: }{8: }{23:---------------------------}|
|
||||
{7: }{8: 10 }{4: BBB }│{7: }{8: 10 }{4: BBB }│{7: }{8: }{23:---------------------------}|
|
||||
{7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: }{23:---------------------------}|
|
||||
{7: }{8: 12 } │{7: }{8: 12 } │{7: }{8: 6 } |
|
||||
{1:~ }│{1:~ }│{1:~ }|*2
|
||||
{1:~ }│{1:~ }│{1:~ }|*3
|
||||
{3:<-functional-diff-screen-1.3 [+] }{2:<est-functional-diff-screen-1.2 Xtest-functional-diff-screen-1 }|
|
||||
:2,6diffget screen-1.2 |
|
||||
]])
|
||||
@ -114,8 +113,7 @@ describe('Diff mode screen with 3 diffs open', function()
|
||||
{7: }{8: 4 }{4: }{27:BBB}{4: }│{7: }{8: 6 }{4: }{27:BBB}{4: }│{7: }{8: 4 }{4: }{27:AAA}{4: }|
|
||||
{7: }{8: 5 }{4: }{27:BBB}{4: }│{7: }{8: 7 }{4: }{27:BBB}{4: }│{7: }{8: 5 }{4: }{27:AAA}{4: }|
|
||||
{7: }{8: }{23:---------------------------}│{7: }{8: 8 }{22:>>>>>>> branch1 }│{7: }{8: }{23:---------------------------}|
|
||||
{7: }{8: 6 } │{7: }{8: 9 } │{7: }{8: 6 } |
|
||||
{1:~ }│{1:~ }│{1:~ }|*5
|
||||
{1:~ }│{1:~ }│{1:~ }|*6
|
||||
{2:<test-functional-diff-screen-1.3 }{3:<functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:5,7diffget screen-1.3 |
|
||||
]])
|
||||
@ -136,8 +134,7 @@ describe('Diff mode screen with 3 diffs open', function()
|
||||
{7: }{8: 4 } BBB │{7: }{8: 9 } BBB │{7: }{8: 8 } BBB |
|
||||
{7: }{8: 5 } BBB │{7: }{8: 10 } BBB │{7: }{8: 9 } BBB |
|
||||
{7: }{8: }{23:---------------------------}│{7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: 10 }{4:>>>>>>> branch1 }|
|
||||
{7: }{8: 6 } │{7: }{8: 12 } │{7: }{8: 11 } |
|
||||
{1:~ }│{1:~ }│{1:~ }|*2
|
||||
{1:~ }│{1:~ }│{1:~ }|*3
|
||||
{2:<test-functional-diff-screen-1.3 <est-functional-diff-screen-1.2 }{3:<st-functional-diff-screen-1 [+] }|
|
||||
:5,6diffget screen-1.2 |
|
||||
]])
|
||||
@ -158,8 +155,7 @@ describe('Diff mode screen with 3 diffs open', function()
|
||||
{7: }{8: 4 }{4: BBB }│{7: }{8: 9 }{4: BBB }│{7: }{8: }{23:---------------------------}|
|
||||
{7: }{8: 5 } BBB │{7: }{8: 10 } BBB │{7: }{8: 7 } BBB |
|
||||
{7: }{8: }{23:---------------------------}│{7: }{8: 11 }{22:>>>>>>> branch1 }│{7: }{8: }{23:---------------------------}|
|
||||
{7: }{8: 6 } │{7: }{8: 12 } │{7: }{8: 8 } |
|
||||
{1:~ }│{1:~ }│{1:~ }|*2
|
||||
{1:~ }│{1:~ }│{1:~ }|*3
|
||||
{2:<test-functional-diff-screen-1.3 }{3:<est-functional-diff-screen-1.2 }{2:<st-functional-diff-screen-1 [+] }|
|
||||
:6,8diffput screen-1 |
|
||||
]])
|
||||
@ -179,8 +175,7 @@ describe('Diff mode screen with 3 diffs open', function()
|
||||
{7: }{8: 4 } BBB │{7: }{8: 9 } BBB │{7: }{8: 8 } BBB |
|
||||
{7: }{8: 5 } BBB │{7: }{8: 10 } BBB │{7: }{8: 9 } BBB |
|
||||
{7: }{8: }{23:---------------------------}│{7: }{8: 11 }{4:>>>>>>> branch1 }│{7: }{8: 10 }{4:>>>>>>> branch1 }|
|
||||
{7: }{8: 6 } │{7: }{8: 12 } │{7: }{8: 11 } |
|
||||
{1:~ }│{1:~ }│{1:~ }|*2
|
||||
{1:~ }│{1:~ }│{1:~ }|*3
|
||||
{2:<test-functional-diff-screen-1.3 }{3:<est-functional-diff-screen-1.2 }{2:<st-functional-diff-screen-1 [+] }|
|
||||
:6,11diffput screen-1 |
|
||||
]])
|
||||
@ -276,8 +271,7 @@ something
|
||||
{7: }{8: 14 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 15 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 16 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|*6
|
||||
{1:~ }│{1:~ }|*7
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:5,9diffget |
|
||||
]])
|
||||
@ -300,8 +294,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 12 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 13 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 14 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 15 } |
|
||||
{1:~ }│{1:~ }|*3
|
||||
{1:~ }│{1:~ }|*4
|
||||
{2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }|
|
||||
:5,10diffget |
|
||||
]])
|
||||
@ -322,8 +315,7 @@ something
|
||||
{7: }{8: 10 }common line │{7: }{8: 10 }common line |
|
||||
{7: }{8: 11 }common line │{7: }{8: 11 }common line |
|
||||
{7: }{8: 12 }something │{7: }{8: 12 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 13 } |
|
||||
{1:~ }│{1:~ }|*5
|
||||
{1:~ }│{1:~ }|*6
|
||||
{2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }|
|
||||
:4,17diffget |
|
||||
]])
|
||||
@ -349,7 +341,7 @@ something
|
||||
{7: }{8: 15 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: 16 }DEF │{7: }{8: 16 }DEF |
|
||||
{7: }{8: 17 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 18 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:4,12diffget |
|
||||
]])
|
||||
@ -376,7 +368,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -403,7 +395,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -430,7 +422,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -457,7 +449,7 @@ something
|
||||
{7: }{8: 12 }^common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 13 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 14 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -484,7 +476,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: 12 }DEF │{7: }{8: 16 }DEF |
|
||||
{7: }{8: 13 }^something │{7: }{8: 17 }something |
|
||||
{7: }{8: 14 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -511,7 +503,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }|
|
||||
:e |
|
||||
]])
|
||||
@ -538,7 +530,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }|
|
||||
:e |
|
||||
]])
|
||||
@ -565,7 +557,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }|
|
||||
:e |
|
||||
]])
|
||||
@ -591,7 +583,7 @@ something
|
||||
{7: }{8: 11 }^common line │{7: }{8: 14 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 15 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 16 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 17 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }|
|
||||
:e |
|
||||
@ -618,7 +610,7 @@ something
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 14 }{22:DEF }|
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: 12 }^something │{7: }{8: 16 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 17 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{1:~ }│{1:~ }|
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 [+] }|
|
||||
:e |
|
||||
@ -646,7 +638,7 @@ something
|
||||
{7: }{8: 14 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 15 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 16 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -673,7 +665,7 @@ something
|
||||
{7: }{8: 14 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 15 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 16 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -700,7 +692,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 16 }{22:DEF }|
|
||||
{7: }{8: 12 }something │{7: }{8: 17 }something |
|
||||
{7: }{8: 13 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -727,7 +719,7 @@ something
|
||||
{7: }{8: 11 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: 12 }DEF │{7: }{8: 16 }DEF |
|
||||
{7: }{8: 13 }something │{7: }{8: 17 }^something |
|
||||
{7: }{8: 14 } │{7: }{8: 18 } |
|
||||
{1:~ }│{1:~ }|
|
||||
{2:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -757,8 +749,7 @@ d
|
||||
{7: }{8: 2 }{4:abc d }│{7: }{8: 1 }{27:// }{4:abc d }|
|
||||
{7: }{8: 3 }{4:d }│{7: }{8: 2 }{27:// }{4:d }|
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 3 }{22:// d }|
|
||||
{7: }{8: 4 } │{7: }{8: 4 } |
|
||||
{1:~ }│{1:~ }|*13
|
||||
{1:~ }│{1:~ }|*14
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -794,8 +785,7 @@ void testFunction () {
|
||||
{7: }{8: 3 }{4: }{27:// }{4:} }│{7: }{8: 4 }{4: } }|
|
||||
{7: }{8: }{23:-------------------------------------------}│{7: }{8: 5 }{22: } }|
|
||||
{7: }{8: 4 }} │{7: }{8: 6 }} |
|
||||
{7: }{8: 5 } │{7: }{8: 7 } |
|
||||
{1:~ }│{1:~ }|*11
|
||||
{1:~ }│{1:~ }|*12
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -834,8 +824,7 @@ void testFunction () {
|
||||
{7: }{8: 6 }{22:?B }│{7: }{8: }{23:--------------------------------------------}|
|
||||
{7: }{8: 7 }{22:?B }│{7: }{8: }{23:--------------------------------------------}|
|
||||
{7: }{8: 8 }{22:?C }│{7: }{8: }{23:--------------------------------------------}|
|
||||
{7: }{8: 9 } │{7: }{8: 4 } |
|
||||
{1:~ }│{1:~ }|*9
|
||||
{1:~ }│{1:~ }|*10
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -874,8 +863,7 @@ void testFunction () {
|
||||
{7: }{8: 6 }{27:?}{4:B }│{7: }{8: 2 }{27:!}{4:B }|
|
||||
{7: }{8: 7 }{27:?}{4:C }│{7: }{8: 3 }{27:!}{4:C }|
|
||||
{7: }{8: 8 }{22:?C }│{7: }{8: }{23:--------------------------------------------}|
|
||||
{7: }{8: 9 } │{7: }{8: 4 } |
|
||||
{1:~ }│{1:~ }|*9
|
||||
{1:~ }│{1:~ }|*10
|
||||
{3:Xtest-functional-diff-screen-1.2 }{2:Xtest-functional-diff-screen-1 }|
|
||||
:e |
|
||||
]])
|
||||
@ -1017,8 +1005,7 @@ something
|
||||
{7: }{8: 9 }HIL │{7: }{8: 9 }HIL |
|
||||
{7: }{8: 10 }common line │{7: }{8: 10 }common line |
|
||||
{7: }{8: 11 }something │{7: }{8: 11 }something |
|
||||
{7: }{8: 12 } │{7: }{8: 12 } |
|
||||
{1:~ }│{1:~ }|*6
|
||||
{1:~ }│{1:~ }|*7
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:1,19diffget |
|
||||
]])
|
||||
|
@ -2329,14 +2329,15 @@ describe('builtin popupmenu', function()
|
||||
occaecat cupidatat non proident, sunt in culpa
|
||||
qui officia deserunt mollit anim id est
|
||||
laborum.
|
||||
.
|
||||
]])
|
||||
|
||||
screen:expect([[
|
||||
reprehenderit in voluptate velit esse cillum |
|
||||
dolore eu fugiat nulla pariatur. Excepteur sint |
|
||||
occaecat cupidatat non proident, sunt in culpa |
|
||||
qui officia deserunt mollit anim id est |
|
||||
laborum. |
|
||||
. |
|
||||
^ |
|
||||
{4:[No Name] [+] }|
|
||||
Lorem ipsum dolor sit amet, consectetur |
|
||||
|
@ -494,9 +494,8 @@ function Screen:expect(expected, attr_ids, ...)
|
||||
|
||||
local expected_rows = {} --- @type string[]
|
||||
if grid then
|
||||
-- Remove the last line and dedent. Note that gsub returns more then one
|
||||
-- value.
|
||||
grid = dedent(grid:gsub('\n[ ]+$', ''), 0)
|
||||
-- Dedent (ignores last line if it is blank).
|
||||
grid = dedent(grid, 0)
|
||||
for row in grid:gmatch('[^\n]+') do
|
||||
table.insert(expected_rows, row)
|
||||
end
|
||||
|
@ -652,7 +652,7 @@ describe('search highlighting', function()
|
||||
topline = 0,
|
||||
botline = 3,
|
||||
curline = 0,
|
||||
curcol = 11,
|
||||
curcol = 9,
|
||||
linecount = 2,
|
||||
sum_scroll_delta = 0,
|
||||
},
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user