mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	Merge #32601 vim.text.indent()
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
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -496,10 +496,12 @@ a]],
 | 
			
		||||
 | 
			
		||||
  it("fdm=indent doesn't open folds when inserting lower foldlevel line", function()
 | 
			
		||||
    insert([[
 | 
			
		||||
      insert an unindented line under this line
 | 
			
		||||
      keep the lines under this line folded
 | 
			
		||||
        keep this line folded 1
 | 
			
		||||
        keep this line folded 2
 | 
			
		||||
        insert an unindented line under this line
 | 
			
		||||
        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))
 | 
			
		||||
 
 | 
			
		||||
@@ -227,7 +227,7 @@ describe(':source', function()
 | 
			
		||||
 | 
			
		||||
        feed('GVkk')
 | 
			
		||||
        feed_command(':source')
 | 
			
		||||
        eq('   "\\ a\n    \\ b', exec_lua('return _G.a'))
 | 
			
		||||
        eq(' "\\ a\n  \\ b', exec_lua('return _G.a'))
 | 
			
		||||
      end)
 | 
			
		||||
 | 
			
		||||
      it('whole buffer', function()
 | 
			
		||||
@@ -247,7 +247,7 @@ describe(':source', function()
 | 
			
		||||
        feed_command(':source')
 | 
			
		||||
 | 
			
		||||
        eq(12, eval('g:c'))
 | 
			
		||||
        eq('    \\ 1\n   "\\ 2', exec_lua('return _G.a'))
 | 
			
		||||
        eq('  \\ 1\n "\\ 2', exec_lua('return _G.a'))
 | 
			
		||||
        eq(':source (no file)', api.nvim_get_var('sfile_value'))
 | 
			
		||||
        eq(':source (no file)', api.nvim_get_var('stack_value'))
 | 
			
		||||
        eq(':source (no file)', api.nvim_get_var('script_value'))
 | 
			
		||||
 
 | 
			
		||||
@@ -152,6 +152,9 @@ describe('swapfile detection', function()
 | 
			
		||||
 | 
			
		||||
  it('redrawing during prompt does not break treesitter', function()
 | 
			
		||||
    local testfile = 'Xtest_swapredraw.lua'
 | 
			
		||||
    finally(function()
 | 
			
		||||
      os.remove(testfile)
 | 
			
		||||
    end)
 | 
			
		||||
    write_file(
 | 
			
		||||
      testfile,
 | 
			
		||||
      [[
 | 
			
		||||
@@ -194,8 +197,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 +591,10 @@ 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,16 +292,18 @@ 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()
 | 
			
		||||
    source([[
 | 
			
		||||
  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
 | 
			
		||||
      3 s/\%#=2\%3l^\t...//g
 | 
			
		||||
      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
 | 
			
		||||
      )
 | 
			
		||||
    )
 | 
			
		||||
  end)
 | 
			
		||||
      diff(text)
 | 
			
		||||
    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)
 | 
			
		||||
        .. string.rep(digits .. punct2 .. upper .. punct3 .. lower .. '\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,7 +112,8 @@ describe('Visual block mode', function()
 | 
			
		||||
      		line1
 | 
			
		||||
      		line2
 | 
			
		||||
      		line3
 | 
			
		||||
      ]])
 | 
			
		||||
      .
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    -- Test for Visual block insert when virtualedit=all and utf-8 encoding.
 | 
			
		||||
    feed_command('set ve=all')
 | 
			
		||||
@@ -123,7 +124,8 @@ describe('Visual block mode', function()
 | 
			
		||||
             x 	line1
 | 
			
		||||
             x 	line2
 | 
			
		||||
             x 	line3
 | 
			
		||||
      ]])
 | 
			
		||||
      .
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    -- Test for Visual block append when virtualedit=all.
 | 
			
		||||
    feed('012l<C-v>jjAx<ESC>')
 | 
			
		||||
@@ -132,7 +134,8 @@ describe('Visual block mode', function()
 | 
			
		||||
             x     x   line1
 | 
			
		||||
             x     x   line2
 | 
			
		||||
             x     x   line3
 | 
			
		||||
      ]])
 | 
			
		||||
      .
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('should make a selected part uppercase', function()
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,7 @@ 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(' ')
 | 
			
		||||
  return expect('')
 | 
			
		||||
end
 | 
			
		||||
local function expect_line(line)
 | 
			
		||||
  return eq(line, eval('getline(".")'))
 | 
			
		||||
 
 | 
			
		||||
@@ -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,10 +62,10 @@ describe('folding', function()
 | 
			
		||||
 | 
			
		||||
    n.poke_eventloop()
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        dd {{{            |
 | 
			
		||||
        ee {{{ }}}        |
 | 
			
		||||
      dd {{{              |
 | 
			
		||||
      ee {{{ }}}          |
 | 
			
		||||
      {{{                 |
 | 
			
		||||
        ff }}}            |*2
 | 
			
		||||
      ff }}}              |*2
 | 
			
		||||
      ^                    |
 | 
			
		||||
      line 2 foldlevel=2  |
 | 
			
		||||
      1                   |*2
 | 
			
		||||
 
 | 
			
		||||
@@ -62,12 +62,12 @@ describe("'listchars'", function()
 | 
			
		||||
      ..bb>---<<$
 | 
			
		||||
      ...cccc><$
 | 
			
		||||
      dd........ee<<>-$
 | 
			
		||||
      <$
 | 
			
		||||
      $
 | 
			
		||||
      >-------aa>-----$
 | 
			
		||||
      ..bb>---..$
 | 
			
		||||
      ...cccc>.$
 | 
			
		||||
      dd........ee..>-$
 | 
			
		||||
      .$]])
 | 
			
		||||
      $]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('works with :list', function()
 | 
			
		||||
 
 | 
			
		||||
@@ -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')
 | 
			
		||||
 
 | 
			
		||||
@@ -316,13 +316,13 @@ test text
 | 
			
		||||
 | 
			
		||||
  local grid_without_inlay_hints = [[
 | 
			
		||||
  test text                                         |
 | 
			
		||||
   ^                                                 |
 | 
			
		||||
  ^                                                  |
 | 
			
		||||
                                                    |
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
  local grid_with_inlay_hints = [[
 | 
			
		||||
  {1:01234}test text                                    |
 | 
			
		||||
   ^                                                 |
 | 
			
		||||
  ^                                                  |
 | 
			
		||||
                                                    |
 | 
			
		||||
]]
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -786,9 +786,9 @@ describe('treesitter highlighting (C)', function()
 | 
			
		||||
 | 
			
		||||
    screen:expect({
 | 
			
		||||
      grid = [[
 | 
			
		||||
          {26:int x = 4;}                                                     |
 | 
			
		||||
          {26:int y = 5;}                                                     |
 | 
			
		||||
          {26:int z = 6;}                                                     |
 | 
			
		||||
        {26:int x = 4;}                                                       |
 | 
			
		||||
        {26:int y = 5;}                                                       |
 | 
			
		||||
        {26:int z = 6;}                                                       |
 | 
			
		||||
        ^                                                                 |
 | 
			
		||||
        {1:~                                                                }|*13
 | 
			
		||||
                                                                         |
 | 
			
		||||
@@ -815,7 +815,7 @@ describe('treesitter highlighting (C)', function()
 | 
			
		||||
 | 
			
		||||
    screen:expect({
 | 
			
		||||
      grid = [[
 | 
			
		||||
          void foo(int {15:*}{25:bar});                                            |
 | 
			
		||||
        void foo(int {15:*}{25:bar});                                              |
 | 
			
		||||
        ^                                                                 |
 | 
			
		||||
        {1:~                                                                }|*15
 | 
			
		||||
                                                                         |
 | 
			
		||||
@@ -883,8 +883,8 @@ describe('treesitter highlighting (lua)', function()
 | 
			
		||||
 | 
			
		||||
    screen:expect({
 | 
			
		||||
      grid = [[
 | 
			
		||||
          {15:local} {25:ffi} {15:=} {16:require(}{26:'ffi'}{16:)}                                     |
 | 
			
		||||
          {25:ffi}{16:.}{25:cdef}{16:(}{26:"}{16:int}{26: }{16:(}{15:*}{26:fun}{16:)(int,}{26: }{16:char}{26: }{15:*}{16:);}{26:"}{16:)}                           |
 | 
			
		||||
        {15:local} {25:ffi} {15:=} {16:require(}{26:'ffi'}{16:)}                                       |
 | 
			
		||||
        {25:ffi}{16:.}{25:cdef}{16:(}{26:"}{16:int}{26: }{16:(}{15:*}{26:fun}{16:)(int,}{26: }{16:char}{26: }{15:*}{16:);}{26:"}{16:)}                             |
 | 
			
		||||
        ^                                                                 |
 | 
			
		||||
        {1:~                                                                }|*14
 | 
			
		||||
                                                                         |
 | 
			
		||||
@@ -1185,7 +1185,7 @@ printf('Hello World!');
 | 
			
		||||
        {18:```}{15:c}                                    |
 | 
			
		||||
        {25:printf}{16:(}{26:'Hello World!'}{16:);}                 |
 | 
			
		||||
        {18:```}                                     |
 | 
			
		||||
           ^                                     |
 | 
			
		||||
        ^                                        |
 | 
			
		||||
                                                |
 | 
			
		||||
      ]],
 | 
			
		||||
    })
 | 
			
		||||
@@ -1271,7 +1271,7 @@ printf('Hello World!');
 | 
			
		||||
      {8:120 }{25:printf}{16:(}{26:'Hello World!'}{16:);}             |
 | 
			
		||||
      {8:122 }                                    |
 | 
			
		||||
      {8:124 }{25:printf}{16:(}{26:'Hello World!'}{16:);}             |
 | 
			
		||||
      {8:126 }   ^                                 |
 | 
			
		||||
      {8:126 }^                                    |
 | 
			
		||||
                                              |
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2041,11 +2041,11 @@ describe('float window', function()
 | 
			
		||||
          [2:----------------------------------------]|*6
 | 
			
		||||
          [3:----------------------------------------]|
 | 
			
		||||
        ## grid 2
 | 
			
		||||
            neeed some dummy                      |
 | 
			
		||||
            background text                       |
 | 
			
		||||
            to show the effect                    |
 | 
			
		||||
            of color blending                     |
 | 
			
		||||
            of border shadow                      |
 | 
			
		||||
          neeed some dummy                        |
 | 
			
		||||
          background text                         |
 | 
			
		||||
          to show the effect                      |
 | 
			
		||||
          of color blending                       |
 | 
			
		||||
          of border shadow                        |
 | 
			
		||||
          ^                                        |
 | 
			
		||||
        ## grid 3
 | 
			
		||||
                                                  |
 | 
			
		||||
@@ -2065,11 +2065,11 @@ describe('float window', function()
 | 
			
		||||
        }}
 | 
			
		||||
      else
 | 
			
		||||
        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                      |
 | 
			
		||||
          neeed some dummy                        |
 | 
			
		||||
          background text                         |
 | 
			
		||||
          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')
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -281,14 +281,14 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    ]])
 | 
			
		||||
    feed('<Esc>')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        text on line 1                        |
 | 
			
		||||
        more text on line 2                   |
 | 
			
		||||
        oh no, even more text                 |
 | 
			
		||||
        will the text ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the text stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the text stop                    |
 | 
			
		||||
      text on line 1                          |
 | 
			
		||||
      more text on line 2                     |
 | 
			
		||||
      oh no, even more text                   |
 | 
			
		||||
      will the text ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the text stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the text stop                      |
 | 
			
		||||
      ^                                        |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
                                              |
 | 
			
		||||
@@ -301,14 +301,14 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    command('set inccommand=nosplit')
 | 
			
		||||
    feed(':Replace text cats')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        {10:cats} on line 1                        |
 | 
			
		||||
        more {10:cats} on line 2                   |
 | 
			
		||||
        oh no, even more {10:cats}                 |
 | 
			
		||||
        will the {10:cats} ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the {10:cats} stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the {10:cats} stop                    |
 | 
			
		||||
      {10:cats} on line 1                          |
 | 
			
		||||
      more {10:cats} on line 2                     |
 | 
			
		||||
      oh no, even more {10:cats}                   |
 | 
			
		||||
      will the {10:cats} ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the {10:cats} stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the {10:cats} stop                      |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
      :Replace text cats^                      |
 | 
			
		||||
@@ -319,21 +319,21 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    command('set inccommand=split')
 | 
			
		||||
    feed(':Replace text cats')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        {10:cats} on line 1                        |
 | 
			
		||||
        more {10:cats} on line 2                   |
 | 
			
		||||
        oh no, even more {10:cats}                 |
 | 
			
		||||
        will the {10:cats} ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the {10:cats} stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the {10:cats} stop                    |
 | 
			
		||||
      {10:cats} on line 1                          |
 | 
			
		||||
      more {10:cats} on line 2                     |
 | 
			
		||||
      oh no, even more {10:cats}                   |
 | 
			
		||||
      will the {10:cats} ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the {10:cats} stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the {10:cats} stop                      |
 | 
			
		||||
                                              |
 | 
			
		||||
      {3:[No Name] [+]                           }|
 | 
			
		||||
      |1|   {10:cats} on line 1                    |
 | 
			
		||||
      |2|   more {10:cats} on line 2               |
 | 
			
		||||
      |3|   oh no, even more {10:cats}             |
 | 
			
		||||
      |4|   will the {10:cats} ever stop           |
 | 
			
		||||
      |6|   did the {10:cats} stop                 |
 | 
			
		||||
      |1| {10:cats} on line 1                      |
 | 
			
		||||
      |2| more {10:cats} on line 2                 |
 | 
			
		||||
      |3| oh no, even more {10:cats}               |
 | 
			
		||||
      |4| will the {10:cats} ever stop             |
 | 
			
		||||
      |6| did the {10:cats} stop                   |
 | 
			
		||||
      {2:[Preview]                               }|
 | 
			
		||||
      :Replace text cats^                      |
 | 
			
		||||
    ]])
 | 
			
		||||
@@ -343,14 +343,14 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    command('set inccommand=split')
 | 
			
		||||
    feed(':Replace text cats<Esc>')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        text on line 1                        |
 | 
			
		||||
        more text on line 2                   |
 | 
			
		||||
        oh no, even more text                 |
 | 
			
		||||
        will the text ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the text stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the text stop                    |
 | 
			
		||||
      text on line 1                          |
 | 
			
		||||
      more text on line 2                     |
 | 
			
		||||
      oh no, even more text                   |
 | 
			
		||||
      will the text ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the text stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the text stop                      |
 | 
			
		||||
      ^                                        |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
                                              |
 | 
			
		||||
@@ -361,14 +361,14 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    command('set inccommand=split')
 | 
			
		||||
    feed(':Replace text cats<CR>')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        cats on line 1                        |
 | 
			
		||||
        more cats on line 2                   |
 | 
			
		||||
        oh no, even more cats                 |
 | 
			
		||||
        will the cats ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the cats stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the cats stop                    |
 | 
			
		||||
      cats on line 1                          |
 | 
			
		||||
      more cats on line 2                     |
 | 
			
		||||
      oh no, even more cats                   |
 | 
			
		||||
      will the cats ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the cats stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the cats stop                      |
 | 
			
		||||
      ^                                        |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
      :Replace text cats                      |
 | 
			
		||||
@@ -379,14 +379,14 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    command('set inccommand=split')
 | 
			
		||||
    feed('gg:.Replace text cats')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        {10:cats} on line 1                        |
 | 
			
		||||
        more text on line 2                   |
 | 
			
		||||
        oh no, even more text                 |
 | 
			
		||||
        will the text ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the text stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the text stop                    |
 | 
			
		||||
      {10:cats} on line 1                          |
 | 
			
		||||
      more text on line 2                     |
 | 
			
		||||
      oh no, even more text                   |
 | 
			
		||||
      will the text ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the text stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the text stop                      |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
      :.Replace text cats^                     |
 | 
			
		||||
@@ -432,14 +432,14 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    ]])
 | 
			
		||||
    feed(':C')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      {10:  cats on line 1}                        |
 | 
			
		||||
        more cats on line 2                   |
 | 
			
		||||
        oh no, even more cats                 |
 | 
			
		||||
        will the cats ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the cats stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the cats stop                    |
 | 
			
		||||
      {10:cats on line 1}                          |
 | 
			
		||||
      more cats on line 2                     |
 | 
			
		||||
      oh no, even more cats                   |
 | 
			
		||||
      will the cats ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the cats stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the cats stop                      |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
      :C^                                      |
 | 
			
		||||
@@ -482,42 +482,42 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    ]])
 | 
			
		||||
    feed(':Test a.a.a.a.')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        text on line 1                        |
 | 
			
		||||
        more text on line 2                   |
 | 
			
		||||
        oh no, even more text                 |
 | 
			
		||||
        will the text ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the text stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the text stop                    |
 | 
			
		||||
      text on line 1                          |
 | 
			
		||||
      more text on line 2                     |
 | 
			
		||||
      oh no, even more text                   |
 | 
			
		||||
      will the text ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the text stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the text stop                      |
 | 
			
		||||
      a.a.a.a.                                |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
      :Test a.a.a.a.^                          |
 | 
			
		||||
    ]])
 | 
			
		||||
    feed('<C-V><Esc>u')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        text on line 1                        |
 | 
			
		||||
        more text on line 2                   |
 | 
			
		||||
        oh no, even more text                 |
 | 
			
		||||
        will the text ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the text stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the text stop                    |
 | 
			
		||||
      text on line 1                          |
 | 
			
		||||
      more text on line 2                     |
 | 
			
		||||
      oh no, even more text                   |
 | 
			
		||||
      will the text ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the text stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the text stop                      |
 | 
			
		||||
      a.a.a.                                  |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
      :Test a.a.a.a.{18:^[}u^                       |
 | 
			
		||||
    ]])
 | 
			
		||||
    feed('<Esc>')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        text on line 1                        |
 | 
			
		||||
        more text on line 2                   |
 | 
			
		||||
        oh no, even more text                 |
 | 
			
		||||
        will the text ever stop               |
 | 
			
		||||
        oh well                               |
 | 
			
		||||
        did the text stop                     |
 | 
			
		||||
        why won't it stop                     |
 | 
			
		||||
        make the text stop                    |
 | 
			
		||||
      text on line 1                          |
 | 
			
		||||
      more text on line 2                     |
 | 
			
		||||
      oh no, even more text                   |
 | 
			
		||||
      will the text ever stop                 |
 | 
			
		||||
      oh well                                 |
 | 
			
		||||
      did the text stop                       |
 | 
			
		||||
      why won't it stop                       |
 | 
			
		||||
      make the text stop                      |
 | 
			
		||||
      ^                                        |
 | 
			
		||||
      {1:~                                       }|*7
 | 
			
		||||
                                              |
 | 
			
		||||
@@ -572,12 +572,12 @@ describe("'inccommand' for user commands", function()
 | 
			
		||||
    screen:expect({
 | 
			
		||||
      grid = [[
 | 
			
		||||
        Preview                                 |
 | 
			
		||||
          oh no, even more text                 |
 | 
			
		||||
          will the text ever stop               |
 | 
			
		||||
          oh well                               |
 | 
			
		||||
          did the text stop                     |
 | 
			
		||||
          why won't it stop                     |
 | 
			
		||||
          make the text stop                    |
 | 
			
		||||
        oh no, even more text                   |
 | 
			
		||||
        will the text ever stop                 |
 | 
			
		||||
        oh well                                 |
 | 
			
		||||
        did the text stop                       |
 | 
			
		||||
        why won't it stop                       |
 | 
			
		||||
        make the text stop                      |
 | 
			
		||||
                                                |
 | 
			
		||||
        {1:~                                       }|*8
 | 
			
		||||
        :Test barb^az                            |
 | 
			
		||||
@@ -611,9 +611,9 @@ describe("'inccommand' with multiple buffers", function()
 | 
			
		||||
    command('set inccommand=nosplit')
 | 
			
		||||
    feed(':Replace foo bar')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        bar baz {10:bar}       │  {10:bar} bar baz      |
 | 
			
		||||
        baz {10:bar} bar       │  bar baz {10:bar}      |
 | 
			
		||||
        {10:bar} bar baz       │  baz {10:bar} bar      |
 | 
			
		||||
      bar baz {10:bar}         │{10:bar} bar baz        |
 | 
			
		||||
      baz {10:bar} bar         │bar baz {10:bar}        |
 | 
			
		||||
      {10:bar} bar baz         │baz {10:bar} bar        |
 | 
			
		||||
                          │                   |
 | 
			
		||||
      {1:~                   }│{1:~                  }|*11
 | 
			
		||||
      {3:[No Name] [+]        }{2:[No Name] [+]      }|
 | 
			
		||||
@@ -621,9 +621,9 @@ describe("'inccommand' with multiple buffers", function()
 | 
			
		||||
    ]])
 | 
			
		||||
    feed('<CR>')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        bar baz bar       │  bar bar baz      |
 | 
			
		||||
        baz bar bar       │  bar baz bar      |
 | 
			
		||||
        bar bar baz       │  baz bar bar      |
 | 
			
		||||
      bar baz bar         │bar bar baz        |
 | 
			
		||||
      baz bar bar         │bar baz bar        |
 | 
			
		||||
      bar bar baz         │baz bar bar        |
 | 
			
		||||
      ^                    │                   |
 | 
			
		||||
      {1:~                   }│{1:~                  }|*11
 | 
			
		||||
      {3:[No Name] [+]        }{2:[No Name] [+]      }|
 | 
			
		||||
@@ -635,19 +635,19 @@ describe("'inccommand' with multiple buffers", function()
 | 
			
		||||
    command('set inccommand=split')
 | 
			
		||||
    feed(':Replace foo bar')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        bar baz {10:bar}       │  {10:bar} bar baz      |
 | 
			
		||||
        baz {10:bar} bar       │  bar baz {10:bar}      |
 | 
			
		||||
        {10:bar} bar baz       │  baz {10:bar} bar      |
 | 
			
		||||
      bar baz {10:bar}         │{10:bar} bar baz        |
 | 
			
		||||
      baz {10:bar} bar         │bar baz {10:bar}        |
 | 
			
		||||
      {10:bar} bar baz         │baz {10:bar} bar        |
 | 
			
		||||
                          │                   |
 | 
			
		||||
      {3:[No Name] [+]        }{2:[No Name] [+]      }|
 | 
			
		||||
      Buffer #1:                              |
 | 
			
		||||
      |1|   {10:bar} bar baz                       |
 | 
			
		||||
      |2|   bar baz {10:bar}                       |
 | 
			
		||||
      |3|   baz {10:bar} bar                       |
 | 
			
		||||
      |1| {10:bar} bar baz                         |
 | 
			
		||||
      |2| bar baz {10:bar}                         |
 | 
			
		||||
      |3| baz {10:bar} bar                         |
 | 
			
		||||
      Buffer #2:                              |
 | 
			
		||||
      |1|   bar baz {10:bar}                       |
 | 
			
		||||
      |2|   baz {10:bar} bar                       |
 | 
			
		||||
      |3|   {10:bar} bar baz                       |
 | 
			
		||||
      |1| bar baz {10:bar}                         |
 | 
			
		||||
      |2| baz {10:bar} bar                         |
 | 
			
		||||
      |3| {10:bar} bar baz                         |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|
 | 
			
		||||
      {2:[Preview]                               }|
 | 
			
		||||
@@ -655,9 +655,9 @@ describe("'inccommand' with multiple buffers", function()
 | 
			
		||||
    ]])
 | 
			
		||||
    feed('<CR>')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        bar baz bar       │  bar bar baz      |
 | 
			
		||||
        baz bar bar       │  bar baz bar      |
 | 
			
		||||
        bar bar baz       │  baz bar bar      |
 | 
			
		||||
      bar baz bar         │bar bar baz        |
 | 
			
		||||
      baz bar bar         │bar baz bar        |
 | 
			
		||||
      bar bar baz         │baz bar bar        |
 | 
			
		||||
      ^                    │                   |
 | 
			
		||||
      {1:~                   }│{1:~                  }|*11
 | 
			
		||||
      {3:[No Name] [+]        }{2:[No Name] [+]      }|
 | 
			
		||||
 
 | 
			
		||||
@@ -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                                                                                        |
 | 
			
		||||
      ]])
 | 
			
		||||
 
 | 
			
		||||
@@ -2318,25 +2318,26 @@ describe('builtin popupmenu', function()
 | 
			
		||||
        command('set completeopt+=noinsert')
 | 
			
		||||
        command('set mouse=a')
 | 
			
		||||
        insert([[
 | 
			
		||||
          Lorem ipsum dolor sit amet, consectetur
 | 
			
		||||
          adipisicing elit, sed do eiusmod tempor
 | 
			
		||||
          incididunt ut labore et dolore magna aliqua.
 | 
			
		||||
          Ut enim ad minim veniam, quis nostrud
 | 
			
		||||
          exercitation ullamco laboris nisi ut aliquip ex
 | 
			
		||||
          ea commodo consequat. Duis aute irure dolor in
 | 
			
		||||
          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.
 | 
			
		||||
            Lorem ipsum dolor sit amet, consectetur
 | 
			
		||||
            adipisicing elit, sed do eiusmod tempor
 | 
			
		||||
            incididunt ut labore et dolore magna aliqua.
 | 
			
		||||
            Ut enim ad minim veniam, quis nostrud
 | 
			
		||||
            exercitation ullamco laboris nisi ut aliquip ex
 | 
			
		||||
            ea commodo consequat. Duis aute irure dolor in
 | 
			
		||||
            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.
 | 
			
		||||
          .
 | 
			
		||||
        ]])
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
 
 | 
			
		||||
@@ -73,10 +73,10 @@ describe('search highlighting', function()
 | 
			
		||||
    -- 'hlsearch' is enabled by default. #2859
 | 
			
		||||
    feed('gg/text<cr>')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        some {2:^text}                             |
 | 
			
		||||
        more {2:text}stuff                        |
 | 
			
		||||
        stupid{2:texttext}stuff                   |
 | 
			
		||||
        a {2:text} word                           |
 | 
			
		||||
      some {2:^text}                               |
 | 
			
		||||
      more {2:text}stuff                          |
 | 
			
		||||
      stupid{2:texttext}stuff                     |
 | 
			
		||||
      a {2:text} word                             |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|
 | 
			
		||||
      /text                                   |
 | 
			
		||||
@@ -85,10 +85,10 @@ describe('search highlighting', function()
 | 
			
		||||
    -- overlapping matches not allowed
 | 
			
		||||
    feed('3nx')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        some {2:text}                             |
 | 
			
		||||
        more {2:text}stuff                        |
 | 
			
		||||
        stupid{2:text}^extstuff                    |
 | 
			
		||||
        a {2:text} word                           |
 | 
			
		||||
      some {2:text}                               |
 | 
			
		||||
      more {2:text}stuff                          |
 | 
			
		||||
      stupid{2:text}^extstuff                      |
 | 
			
		||||
      a {2:text} word                             |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|
 | 
			
		||||
      /text                                   |
 | 
			
		||||
@@ -96,10 +96,10 @@ describe('search highlighting', function()
 | 
			
		||||
 | 
			
		||||
    feed('ggn*') -- search for entire word
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        some {2:text}                             |
 | 
			
		||||
        more textstuff                        |
 | 
			
		||||
        stupidtextextstuff                    |
 | 
			
		||||
        a {2:^text} word                           |
 | 
			
		||||
      some {2:text}                               |
 | 
			
		||||
      more textstuff                          |
 | 
			
		||||
      stupidtextextstuff                      |
 | 
			
		||||
      a {2:^text} word                             |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|
 | 
			
		||||
      /\<text\>                               |
 | 
			
		||||
@@ -107,10 +107,10 @@ describe('search highlighting', function()
 | 
			
		||||
 | 
			
		||||
    feed_command('nohlsearch')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        some text                             |
 | 
			
		||||
        more textstuff                        |
 | 
			
		||||
        stupidtextextstuff                    |
 | 
			
		||||
        a ^text word                           |
 | 
			
		||||
      some text                               |
 | 
			
		||||
      more textstuff                          |
 | 
			
		||||
      stupidtextextstuff                      |
 | 
			
		||||
      a ^text word                             |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|
 | 
			
		||||
      :nohlsearch                             |
 | 
			
		||||
@@ -641,7 +641,7 @@ describe('search highlighting', function()
 | 
			
		||||
    feed_command('/ial te')
 | 
			
		||||
    screen:expect {
 | 
			
		||||
      grid = [[
 | 
			
		||||
        very {5:spec^ial}{2: te}{6:xt}                     |
 | 
			
		||||
      very {5:spec^ial}{2: te}{6:xt}                       |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|*4
 | 
			
		||||
      {4:search hit BOTTOM, continuing at TOP}    |
 | 
			
		||||
@@ -652,7 +652,7 @@ describe('search highlighting', function()
 | 
			
		||||
          topline = 0,
 | 
			
		||||
          botline = 3,
 | 
			
		||||
          curline = 0,
 | 
			
		||||
          curcol = 11,
 | 
			
		||||
          curcol = 9,
 | 
			
		||||
          linecount = 2,
 | 
			
		||||
          sum_scroll_delta = 0,
 | 
			
		||||
        },
 | 
			
		||||
@@ -670,7 +670,7 @@ describe('search highlighting', function()
 | 
			
		||||
    }
 | 
			
		||||
    command('%foldopen')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        very {5:spec^ial}{2: te}{6:xt}                     |
 | 
			
		||||
      very {5:spec^ial}{2: te}{6:xt}                       |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|*4
 | 
			
		||||
      {4:search hit BOTTOM, continuing at TOP}    |
 | 
			
		||||
@@ -678,7 +678,7 @@ describe('search highlighting', function()
 | 
			
		||||
 | 
			
		||||
    feed_command('call clearmatches()')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        very spec{2:^ial te}xt                     |
 | 
			
		||||
      very spec{2:^ial te}xt                       |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|*4
 | 
			
		||||
      :call clearmatches()                    |
 | 
			
		||||
@@ -688,7 +688,7 @@ describe('search highlighting', function()
 | 
			
		||||
    -- nonconflicting attributes are combined
 | 
			
		||||
    feed_command('syntax keyword MyGroup special')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
        very {5:spec}{7:^ial}{2: te}xt                     |
 | 
			
		||||
      very {5:spec}{7:^ial}{2: te}xt                       |
 | 
			
		||||
                                              |
 | 
			
		||||
      {1:~                                       }|*4
 | 
			
		||||
      :syntax keyword MyGroup special         |
 | 
			
		||||
 
 | 
			
		||||
@@ -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