aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAIN.md1
-rw-r--r--runtime/doc/filetype.txt5
-rw-r--r--runtime/doc/lua.txt61
-rw-r--r--runtime/filetype.lua12
-rw-r--r--runtime/filetype.vim14
-rw-r--r--runtime/lua/vim/filetype.lua9
-rw-r--r--runtime/lua/vim/inspect.lua383
-rw-r--r--runtime/lua/vim/keymap.lua3
-rw-r--r--runtime/lua/vim/treesitter.lua2
-rw-r--r--src/nvim/buffer.c35
-rw-r--r--src/nvim/buffer_defs.h3
-rw-r--r--src/nvim/eval.c3
-rw-r--r--src/nvim/ex_cmds.c8
-rw-r--r--src/nvim/ex_getln.c1
-rw-r--r--src/nvim/match.c38
-rw-r--r--src/nvim/move.c4
-rw-r--r--src/nvim/normal.c1304
-rw-r--r--src/nvim/ops.c59
-rw-r--r--src/nvim/option.c4
-rw-r--r--src/nvim/quickfix.c5
-rw-r--r--src/nvim/testdir/test_autocmd.vim61
-rw-r--r--src/nvim/testdir/test_bufwintabinfo.vim34
-rw-r--r--src/nvim/testdir/test_cursorline.vim36
-rw-r--r--src/nvim/testdir/test_ex_mode.vim7
-rw-r--r--src/nvim/testdir/test_expand_func.vim31
-rw-r--r--src/nvim/testdir/test_filetype.vim2
-rw-r--r--src/nvim/testdir/test_indent.vim124
-rw-r--r--src/nvim/testdir/test_lispwords.vim3
-rw-r--r--src/nvim/testdir/test_search.vim45
-rw-r--r--src/nvim/testdir/test_smartindent.vim23
-rw-r--r--src/nvim/testdir/test_vartabs.vim42
-rw-r--r--src/nvim/testdir/test_window_cmd.vim5
-rw-r--r--src/nvim/window.c65
-rw-r--r--test/functional/autocmd/autocmd_spec.lua29
-rw-r--r--test/functional/legacy/ex_mode_spec.lua6
-rw-r--r--test/functional/lua/vim_spec.lua33
-rw-r--r--test/functional/options/cursorbind_spec.lua91
-rw-r--r--test/functional/treesitter/language_spec.lua11
-rw-r--r--test/functional/ui/searchhl_spec.lua186
39 files changed, 1580 insertions, 1208 deletions
diff --git a/MAINTAIN.md b/MAINTAIN.md
index 927ddea5a1..2f936c8a00 100644
--- a/MAINTAIN.md
+++ b/MAINTAIN.md
@@ -87,6 +87,7 @@ These dependencies are "vendored" (inlined), we need to update the sources manua
- [xdiff](https://github.com/git/git/tree/master/xdiff)
- [lua-cjson](https://github.com/openresty/lua-cjson)
- [Klib](https://github.com/attractivechaos/klib)
+ - [inspect.lua](https://github.com/kikito/inspect.lua)
We also maintain some forks, particularly for Windows, if we are waiting on upstream changes:
https://github.com/neovim/neovim/wiki/Deps
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index e1b0e88c95..c50ccc7a91 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -257,7 +257,10 @@ C. If your file type can be detected by the file name or extension.
disabled by setting the did_load_filetypes global variable. If this
variable exists, $VIMRUNTIME/filetype.vim will not run.
Example: >
- " Disable filetype.vim
+ " Disable filetype.vim (but still load filetype.lua if enabled)
+ let g:did_load_filetypes = 0
+
+ " Disable filetype.vim and filetype.lua
let g:did_load_filetypes = 1
< 3. To use the new filetype detection you must restart Vim.
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 16f27486c8..ed4cc77369 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -138,16 +138,16 @@ Lua functions can be called in multiple ways. Consider the function: >
end
-The first way to call a function is: >
-
+The first way to call this function is: >
+
example_func(1, 2)
-- ==== Result ====
-- A is: 1
-- B is: 2
<
- This way of calling a function is familiar to most scripting languages.
- In Lua, it's important to understand that any function arguments that are
- not supplied are automatically set to `nil`. For example: >
+This way of calling a function is familiar from most scripting languages.
+In Lua, it's important to understand that any function arguments that are
+not supplied are automatically set to `nil`. For example: >
example_func(1)
-- ==== Result ====
@@ -155,12 +155,13 @@ The first way to call a function is: >
-- B is: nil
<
- Additionally, if any extra parameters are passed, they are discarded
- completely.
+Additionally, if any extra parameters are passed, they are discarded
+completely.
-In Lua, it is also possible (when only one argument is passed) to call the
-function without any parentheses. This is most often used to approximate
-"keyword"-style arguments with a single dictionary. For example: >
+In Lua, it is also possible to omit the parentheses (only) if the function
+takes a single string or table literal (`"foo"` or "`{1,2,3}`", respectively).
+The latter is most often used to approximate "keyword-style" arguments with a
+single dictionary, for example: >
local func_with_opts = function(opts)
local will_do_foo = opts.foo
@@ -172,15 +173,38 @@ function without any parentheses. This is most often used to approximate
func_with_opts { foo = true, filename = "hello.world" }
<
- In this style, each "parameter" is passed via keyword. It is still valid
- to call the function in this style: >
+In this style, each "parameter" is passed via keyword. It is still valid
+to call the function in the standard style: >
func_with_opts({ foo = true, filename = "hello.world" })
<
- But often in the documentation, you will see the former rather than the
- latter style, due to its brevity (this is vim after all!).
+But often in the documentation, you will see the former rather than the
+latter style due to its brevity.
+
+==============================================================================
+Lua Patterns *lua-patterns*
+
+For performance reasons, Lua does not support regular expressions natively.
+Instead, the Lua `string` standard library allows manipulations using a
+restricted set of "patterns", see https://www.lua.org/manual/5.1/manual.html#5.4.1
+
+Examples (`string.match` extracts the first match): >
+
+ print(string.match("foo123bar123", "%d+"))
+ -- -> 123
+
+ print(string.match("foo123bar123", "[^%d]+"))
+ -- -> foo
+
+ print(string.match("foo123bar123", "[abc]+"))
+ -- -> ba
+
+ print(string.match("foo.bar", "%.bar"))
+ -- -> .bar
+For more complex matching, Vim regular expressions can be used from Lua
+through |vim.regex()|.
------------------------------------------------------------------------------
LUA PLUGIN EXAMPLE *lua-require-example*
@@ -1924,9 +1948,9 @@ add({filetypes}) *vim.filetype.add()*
filename (either the "tail" or the full file path). The full
file path is checked first, followed by the file name. If a
match is not found using the filename, then the filename is
- matched against the list of patterns (sorted by priority)
- until a match is found. Lastly, if pattern matching does not
- find a filetype, then the file extension is used.
+ matched against the list of |lua-patterns| (sorted by
+ priority) until a match is found. Lastly, if pattern matching
+ does not find a filetype, then the file extension is used.
The filetype can be either a string (in which case it is used
as the filetype directly) or a function. If a function, it
@@ -2055,6 +2079,9 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
"silent". In addition to the options listed in
|nvim_set_keymap()|, this table also accepts the
following keys:
+ • buffer: (number or boolean) Add a mapping to the
+ given buffer. When "true" or 0, use the current
+ buffer.
• replace_keycodes: (boolean, default true) When
both this and expr is "true",
|nvim_replace_termcodes()| is applied to the
diff --git a/runtime/filetype.lua b/runtime/filetype.lua
index 8224b79534..47d55d8465 100644
--- a/runtime/filetype.lua
+++ b/runtime/filetype.lua
@@ -17,10 +17,14 @@ vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
})
-- These *must* be sourced after the autocommand above is created
-vim.cmd [[
-runtime! ftdetect/*.vim
-runtime! ftdetect/*.lua
-]]
+if not vim.g.did_load_ftdetect then
+ vim.cmd [[
+ augroup filetypedetect
+ runtime! ftdetect/*.vim
+ runtime! ftdetect/*.lua
+ augroup END
+ ]]
+end
-- Set a marker so that the ftdetect scripts are not sourced a second time by filetype.vim
vim.g.did_load_ftdetect = 1
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 08dfe6223f..e72d6fc0c0 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -151,14 +151,21 @@ au BufNewFile,BufRead *.asp
\ setf aspvbs |
\ endif
-" Grub (must be before catch *.lst)
+" Grub (must be before pattern *.lst)
au BufNewFile,BufRead */boot/grub/menu.lst,*/boot/grub/grub.conf,*/etc/grub.conf setf grub
+" Maxima, see:
+" https://maxima.sourceforge.io/docs/manual/maxima_71.html#file_005ftype_005fmaxima
+" Must be before the pattern *.mac.
+" *.dem omitted - also used by gnuplot demos
+" *.mc omitted - used by dist#ft#McSetf()
+au BufNewFile,BufRead *.demo,*.dm{1,2,3,t},*.wxm,maxima-init.mac setf maxima
+
" Assembly (all kinds)
" *.lst is not pure assembly, it has two extra columns (address, byte codes)
au BufNewFile,BufRead *.asm,*.[sS],*.[aA],*.mac,*.lst call dist#ft#FTasm()
-" Macro (VAX)
+" Assembly - Macro (VAX)
au BufNewFile,BufRead *.mar setf vmasm
" Atlas
@@ -1674,7 +1681,8 @@ au BufNewFile,BufRead *.siv,*.sieve setf sieve
" Sendmail
au BufNewFile,BufRead sendmail.cf setf sm
-" Sendmail .mc files are actually m4. Could also be MS Message text file.
+" Sendmail .mc files are actually m4. Could also be MS Message text file or
+" Maxima.
au BufNewFile,BufRead *.mc call dist#ft#McSetf()
" Services
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index ac36210b23..420d343a8a 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -389,6 +389,12 @@ local extension = {
mason = "mason",
master = "master",
mas = "master",
+ demo = "maxima",
+ dm1 = "maxima",
+ dm2 = "maxima",
+ dm3 = "maxima",
+ dmt = "maxima",
+ wxm = "maxima",
mel = "mel",
mf = "mf",
mgl = "mgl",
@@ -1013,6 +1019,7 @@ local filename = {
[".mailcap"] = "mailcap",
["/etc/man.conf"] = "manconf",
["man.config"] = "manconf",
+ ["maxima-init.mac"] = "maxima",
["meson.build"] = "meson",
["meson_options.txt"] = "meson",
["/etc/conf.modules"] = "modconf",
@@ -1480,7 +1487,7 @@ end
--- Filetype mappings can be added either by extension or by filename (either
--- the "tail" or the full file path). The full file path is checked first,
--- followed by the file name. If a match is not found using the filename, then
---- the filename is matched against the list of patterns (sorted by priority)
+--- the filename is matched against the list of |lua-patterns| (sorted by priority)
--- until a match is found. Lastly, if pattern matching does not find a
--- filetype, then the file extension is used.
---
diff --git a/runtime/lua/vim/inspect.lua b/runtime/lua/vim/inspect.lua
index 0448ea487f..b19c215dbb 100644
--- a/runtime/lua/vim/inspect.lua
+++ b/runtime/lua/vim/inspect.lua
@@ -1,7 +1,7 @@
-local inspect ={
- _VERSION = 'inspect.lua 3.1.0',
- _URL = 'http://github.com/kikito/inspect.lua',
- _DESCRIPTION = 'human-readable representations of tables',
+local inspect = {
+ _VERSION = "inspect.lua 3.1.0",
+ _URL = "http://github.com/kikito/inspect.lua",
+ _DESCRIPTION = "human-readable representations of tables",
_LICENSE = [[
MIT LICENSE
@@ -25,13 +25,26 @@ local inspect ={
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ]]
+ ]],
}
-local tostring = tostring
+inspect.KEY = setmetatable({}, {
+ __tostring = function()
+ return "inspect.KEY"
+ end,
+})
+inspect.METATABLE = setmetatable({}, {
+ __tostring = function()
+ return "inspect.METATABLE"
+ end,
+})
-inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
-inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
+local tostring = tostring
+local rep = string.rep
+local match = string.match
+local char = string.char
+local gsub = string.gsub
+local fmt = string.format
local function rawpairs(t)
return next, t, nil
@@ -40,299 +53,289 @@ end
-- Apostrophizes the string if it has quotes, but not aphostrophes
-- Otherwise, it returns a regular quoted string
local function smartQuote(str)
- if str:match('"') and not str:match("'") then
+ if match(str, '"') and not match(str, "'") then
return "'" .. str .. "'"
end
- return '"' .. str:gsub('"', '\\"') .. '"'
+ return '"' .. gsub(str, '"', '\\"') .. '"'
end
-- \a => '\\a', \0 => '\\0', 31 => '\31'
local shortControlCharEscapes = {
- ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
- ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v"
+ ["\a"] = "\\a",
+ ["\b"] = "\\b",
+ ["\f"] = "\\f",
+ ["\n"] = "\\n",
+ ["\r"] = "\\r",
+ ["\t"] = "\\t",
+ ["\v"] = "\\v",
+ ["\127"] = "\\127",
}
-local longControlCharEscapes = {} -- \a => nil, \0 => \000, 31 => \031
-for i=0, 31 do
- local ch = string.char(i)
+local longControlCharEscapes = { ["\127"] = "\127" }
+for i = 0, 31 do
+ local ch = char(i)
if not shortControlCharEscapes[ch] then
- shortControlCharEscapes[ch] = "\\"..i
- longControlCharEscapes[ch] = string.format("\\%03d", i)
+ shortControlCharEscapes[ch] = "\\" .. i
+ longControlCharEscapes[ch] = fmt("\\%03d", i)
end
end
local function escape(str)
- return (str:gsub("\\", "\\\\")
- :gsub("(%c)%f[0-9]", longControlCharEscapes)
- :gsub("%c", shortControlCharEscapes))
+ return (gsub(gsub(gsub(str, "\\", "\\\\"), "(%c)%f[0-9]", longControlCharEscapes), "%c", shortControlCharEscapes))
end
local function isIdentifier(str)
- return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
+ return type(str) == "string" and not not str:match("^[_%a][_%a%d]*$")
end
+local flr = math.floor
local function isSequenceKey(k, sequenceLength)
- return type(k) == 'number'
- and 1 <= k
- and k <= sequenceLength
- and math.floor(k) == k
+ return type(k) == "number" and flr(k) == k and 1 <= k and k <= sequenceLength
end
local defaultTypeOrders = {
- ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
- ['function'] = 5, ['userdata'] = 6, ['thread'] = 7
+ ["number"] = 1,
+ ["boolean"] = 2,
+ ["string"] = 3,
+ ["table"] = 4,
+ ["function"] = 5,
+ ["userdata"] = 6,
+ ["thread"] = 7,
}
local function sortKeys(a, b)
local ta, tb = type(a), type(b)
-- strings and numbers are sorted numerically/alphabetically
- if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
+ if ta == tb and (ta == "string" or ta == "number") then
+ return a < b
+ end
- local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
+ local dta = defaultTypeOrders[ta] or 100
+ local dtb = defaultTypeOrders[tb] or 100
-- Two default types are compared according to the defaultTypeOrders table
- if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
- elseif dta then return true -- default types before custom ones
- elseif dtb then return false -- custom types after default ones
- end
-- custom types are sorted out alphabetically
- return ta < tb
+ return dta == dtb and ta < tb or dta < dtb
end
--- For implementation reasons, the behavior of rawlen & # is "undefined" when
--- tables aren't pure sequences. So we implement our own # operator.
-local function getSequenceLength(t)
- local len = 1
- local v = rawget(t,len)
- while v ~= nil do
- len = len + 1
- v = rawget(t,len)
+local function getKeys(t)
+ local seqLen = 1
+ while rawget(t, seqLen) ~= nil do
+ seqLen = seqLen + 1
end
- return len - 1
-end
+ seqLen = seqLen - 1
-local function getNonSequentialKeys(t)
- local keys, keysLength = {}, 0
- local sequenceLength = getSequenceLength(t)
- for k,_ in rawpairs(t) do
- if not isSequenceKey(k, sequenceLength) then
- keysLength = keysLength + 1
- keys[keysLength] = k
+ local keys, keysLen = {}, 0
+ for k in rawpairs(t) do
+ if not isSequenceKey(k, seqLen) then
+ keysLen = keysLen + 1
+ keys[keysLen] = k
end
end
table.sort(keys, sortKeys)
- return keys, keysLength, sequenceLength
+ return keys, keysLen, seqLen
end
-local function countTableAppearances(t, tableAppearances)
- tableAppearances = tableAppearances or {}
-
- if type(t) == 'table' then
- if not tableAppearances[t] then
- tableAppearances[t] = 1
- for k,v in rawpairs(t) do
- countTableAppearances(k, tableAppearances)
- countTableAppearances(v, tableAppearances)
- end
- countTableAppearances(getmetatable(t), tableAppearances)
+local function countCycles(x, cycles)
+ if type(x) == "table" then
+ if cycles[x] then
+ cycles[x] = cycles[x] + 1
else
- tableAppearances[t] = tableAppearances[t] + 1
+ cycles[x] = 1
+ for k, v in rawpairs(x) do
+ countCycles(k, cycles)
+ countCycles(v, cycles)
+ end
+ countCycles(getmetatable(x), cycles)
end
end
-
- return tableAppearances
-end
-
-local copySequence = function(s)
- local copy, len = {}, #s
- for i=1, len do copy[i] = s[i] end
- return copy, len
end
-local function makePath(path, ...)
- local keys = {...}
- local newPath, len = copySequence(path)
- for i=1, #keys do
- newPath[len + i] = keys[i]
+local function makePath(path, a, b)
+ local newPath = {}
+ local len = #path
+ for i = 1, len do
+ newPath[i] = path[i]
end
+
+ newPath[len + 1] = a
+ newPath[len + 2] = b
+
return newPath
end
local function processRecursive(process, item, path, visited)
- if item == nil then return nil end
- if visited[item] then return visited[item] end
+ if item == nil then
+ return nil
+ end
+ if visited[item] then
+ return visited[item]
+ end
local processed = process(item, path)
- if type(processed) == 'table' then
+ if type(processed) == "table" then
local processedCopy = {}
visited[item] = processedCopy
local processedKey
- for k,v in rawpairs(processed) do
+ for k, v in rawpairs(processed) do
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
if processedKey ~= nil then
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
end
end
- local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
- if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
+ local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
+ if type(mt) ~= "table" then
+ mt = nil
+ end
setmetatable(processedCopy, mt)
processed = processedCopy
end
return processed
end
-
-
--------------------------------------------------------------------
-
-local Inspector = {}
-local Inspector_mt = {__index = Inspector}
-
-function Inspector:puts(...)
- local args = {...}
- local buffer = self.buffer
- local len = #buffer
- for i=1, #args do
- len = len + 1
- buffer[len] = args[i]
- end
+local function puts(buf, str)
+ buf.n = buf.n + 1
+ buf[buf.n] = str
end
-function Inspector:down(f)
- self.level = self.level + 1
- f()
- self.level = self.level - 1
-end
+local Inspector = {}
-function Inspector:tabify()
- self:puts(self.newline, string.rep(self.indent, self.level))
-end
+local Inspector_mt = { __index = Inspector }
-function Inspector:alreadyVisited(v)
- return self.ids[v] ~= nil
+local function tabify(inspector)
+ puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level))
end
function Inspector:getId(v)
local id = self.ids[v]
+ local ids = self.ids
if not id then
local tv = type(v)
- id = (self.maxIds[tv] or 0) + 1
- self.maxIds[tv] = id
- self.ids[v] = id
+ id = (ids[tv] or 0) + 1
+ ids[v], ids[tv] = id, id
end
return tostring(id)
end
-function Inspector:putKey(k)
- if isIdentifier(k) then return self:puts(k) end
- self:puts("[")
- self:putValue(k)
- self:puts("]")
-end
+function Inspector:putValue(v)
+ local buf = self.buf
+ local tv = type(v)
+ if tv == "string" then
+ puts(buf, smartQuote(escape(v)))
+ elseif
+ tv == "number"
+ or tv == "boolean"
+ or tv == "nil"
+ or tv == "cdata"
+ or tv == "ctype"
+ or (vim and v == vim.NIL)
+ then
+ puts(buf, tostring(v))
+ elseif tv == "table" and not self.ids[v] then
+ local t = v
+
+ if t == inspect.KEY or t == inspect.METATABLE then
+ puts(buf, tostring(t))
+ elseif self.level >= self.depth then
+ puts(buf, "{...}")
+ else
+ if self.cycles[t] > 1 then
+ puts(buf, fmt("<%d>", self:getId(t)))
+ end
-function Inspector:putTable(t)
- if t == inspect.KEY or t == inspect.METATABLE then
- self:puts(tostring(t))
- elseif self:alreadyVisited(t) then
- self:puts('<table ', self:getId(t), '>')
- elseif self.level >= self.depth then
- self:puts('{...}')
- else
- if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
-
- local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t)
- local mt = getmetatable(t)
- if (vim and sequenceLength == 0 and nonSequentialKeysLength == 0
- and mt == vim._empty_dict_mt) then
- self:puts(tostring(t))
- return
- end
+ local keys, keysLen, seqLen = getKeys(t)
+ local mt = getmetatable(t)
- self:puts('{')
- self:down(function()
- local count = 0
- for i=1, sequenceLength do
- if count > 0 then self:puts(',') end
- self:puts(' ')
- self:putValue(t[i])
- count = count + 1
+ if vim and seqLen == 0 and keysLen == 0 and mt == vim._empty_dict_mt then
+ puts(buf, tostring(t))
+ return
end
- for i=1, nonSequentialKeysLength do
- local k = nonSequentialKeys[i]
- if count > 0 then self:puts(',') end
- self:tabify()
- self:putKey(k)
- self:puts(' = ')
- self:putValue(t[k])
- count = count + 1
+ puts(buf, "{")
+ self.level = self.level + 1
+
+ for i = 1, seqLen + keysLen do
+ if i > 1 then
+ puts(buf, ",")
+ end
+ if i <= seqLen then
+ puts(buf, " ")
+ self:putValue(t[i])
+ else
+ local k = keys[i - seqLen]
+ tabify(self)
+ if isIdentifier(k) then
+ puts(buf, k)
+ else
+ puts(buf, "[")
+ self:putValue(k)
+ puts(buf, "]")
+ end
+ puts(buf, " = ")
+ self:putValue(t[k])
+ end
end
- if type(mt) == 'table' then
- if count > 0 then self:puts(',') end
- self:tabify()
- self:puts('<metatable> = ')
+ if type(mt) == "table" then
+ if seqLen + keysLen > 0 then
+ puts(buf, ",")
+ end
+ tabify(self)
+ puts(buf, "<metatable> = ")
self:putValue(mt)
end
- end)
- if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing }
- self:tabify()
- elseif sequenceLength > 0 then -- array tables have one extra space before closing }
- self:puts(' ')
- end
+ self.level = self.level - 1
- self:puts('}')
- end
-end
-
-function Inspector:putValue(v)
- local tv = type(v)
+ if keysLen > 0 or type(mt) == "table" then
+ tabify(self)
+ elseif seqLen > 0 then
+ puts(buf, " ")
+ end
- if tv == 'string' then
- self:puts(smartQuote(escape(v)))
- elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or
- tv == 'cdata' or tv == 'ctype' or (vim and v == vim.NIL) then
- self:puts(tostring(v))
- elseif tv == 'table' then
- self:putTable(v)
+ puts(buf, "}")
+ end
else
- self:puts('<', tv, ' ', self:getId(v), '>')
+ puts(buf, fmt("<%s %d>", tv, self:getId(v)))
end
end
--------------------------------------------------------------------
-
function inspect.inspect(root, options)
- options = options or {}
+ options = options or {}
- local depth = options.depth or math.huge
- local newline = options.newline or '\n'
- local indent = options.indent or ' '
+ local depth = options.depth or math.huge
+ local newline = options.newline or "\n"
+ local indent = options.indent or " "
local process = options.process
if process then
root = processRecursive(process, root, {}, {})
end
+ local cycles = {}
+ countCycles(root, cycles)
+
local inspector = setmetatable({
- depth = depth,
- level = 0,
- buffer = {},
- ids = {},
- maxIds = {},
- newline = newline,
- indent = indent,
- tableAppearances = countTableAppearances(root)
+ buf = { n = 0 },
+ ids = {},
+ cycles = cycles,
+ depth = depth,
+ level = 0,
+ newline = newline,
+ indent = indent,
}, Inspector_mt)
inspector:putValue(root)
- return table.concat(inspector.buffer)
+ return table.concat(inspector.buf)
end
-setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
+setmetatable(inspect, {
+ __call = function(_, root, options)
+ return inspect.inspect(root, options)
+ end,
+})
return inspect
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
index 0986d21196..d07232f52f 100644
--- a/runtime/lua/vim/keymap.lua
+++ b/runtime/lua/vim/keymap.lua
@@ -40,6 +40,8 @@ local keymap = {}
--
---@param opts table A table of |:map-arguments| such as "silent". In addition to the options
--- listed in |nvim_set_keymap()|, this table also accepts the following keys:
+--- - buffer: (number or boolean) Add a mapping to the given buffer. When "true"
+--- or 0, use the current buffer.
--- - replace_keycodes: (boolean, default true) When both this and expr is "true",
--- |nvim_replace_termcodes()| is applied to the result of Lua expr maps.
--- - remap: (boolean) Make the mapping recursive. This is the
@@ -128,7 +130,6 @@ function keymap.del(modes, lhs, opts)
local buffer = false
if opts.buffer ~= nil then
buffer = opts.buffer == true and 0 or opts.buffer
- opts.buffer = nil
end
if buffer == false then
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index f9d539f028..55398d8180 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -90,7 +90,7 @@ function M.get_parser(bufnr, lang, opts)
lang = a.nvim_buf_get_option(bufnr, "filetype")
end
- if parsers[bufnr] == nil then
+ if parsers[bufnr] == nil or parsers[bufnr]:lang() ~= lang then
parsers[bufnr] = M._create_parser(bufnr, lang, opts)
end
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 4d914acea4..30bd37fe7f 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -466,6 +466,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
// When the buffer is no longer in a window, trigger BufWinLeave
if (buf->b_nwindows == 1) {
buf->b_locked++;
+ buf->b_locked_split++;
if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, false,
buf) && !bufref_valid(&bufref)) {
// Autocommands deleted the buffer.
@@ -473,6 +474,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
return false;
}
buf->b_locked--;
+ buf->b_locked_split--;
if (abort_if_last && last_nonfloat(win)) {
// Autocommands made this the only window.
emsg(_(e_auabort));
@@ -483,6 +485,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
// BufHidden
if (!unload_buf) {
buf->b_locked++;
+ buf->b_locked_split++;
if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, false,
buf) && !bufref_valid(&bufref)) {
// Autocommands deleted the buffer.
@@ -490,6 +493,7 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i
return false;
}
buf->b_locked--;
+ buf->b_locked_split--;
if (abort_if_last && last_nonfloat(win)) {
// Autocommands made this the only window.
emsg(_(e_auabort));
@@ -678,6 +682,7 @@ void buf_freeall(buf_T *buf, int flags)
// Make sure the buffer isn't closed by autocommands.
buf->b_locked++;
+ buf->b_locked_split++;
bufref_T bufref;
set_bufref(&bufref, buf);
@@ -703,6 +708,7 @@ void buf_freeall(buf_T *buf, int flags)
return;
}
buf->b_locked--;
+ buf->b_locked_split--;
// If the buffer was in curwin and the window has changed, go back to that
// window, if it still exists. This avoids that ":edit x" triggering a
@@ -1466,8 +1472,8 @@ void set_curbuf(buf_T *buf, int action)
set_bufref(&prevbufref, prevbuf);
set_bufref(&newbufref, buf);
- // Autocommands may delete the current buffer and/or the buffer we want to go
- // to. In those cases don't close the buffer.
+ // Autocommands may delete the current buffer and/or the buffer we want to
+ // go to. In those cases don't close the buffer.
if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf)
|| (bufref_valid(&prevbufref) && bufref_valid(&newbufref)
&& !aborting())) {
@@ -1742,21 +1748,14 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum, int fl
buf = curbuf;
// It's like this buffer is deleted. Watch out for autocommands that
// change curbuf! If that happens, allocate a new buffer anyway.
- if (curbuf->b_p_bl) {
- apply_autocmds(EVENT_BUFDELETE, NULL, NULL, false, curbuf);
- }
- if (buf == curbuf) {
- apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, false, curbuf);
+ buf_freeall(buf, BFA_WIPE | BFA_DEL);
+ if (buf != curbuf) { // autocommands deleted the buffer!
+ return NULL;
}
if (aborting()) { // autocmds may abort script processing
xfree(ffname);
return NULL;
}
- if (buf == curbuf) {
- // Make sure 'bufhidden' and 'buftype' are empty
- clear_string_option(&buf->b_p_bh);
- clear_string_option(&buf->b_p_bt);
- }
}
if (buf != curbuf || curbuf == NULL) {
buf = xcalloc(1, sizeof(buf_T));
@@ -1776,14 +1775,6 @@ buf_T *buflist_new(char_u *ffname_arg, char_u *sfname_arg, linenr_T lnum, int fl
buf->b_wininfo = xcalloc(1, sizeof(wininfo_T));
if (buf == curbuf) {
- // free all things allocated for this buffer
- buf_freeall(buf, 0);
- if (buf != curbuf) { // autocommands deleted the buffer!
- return NULL;
- }
- if (aborting()) { // autocmds may abort script processing
- return NULL;
- }
free_buffer_stuff(buf, kBffInitChangedtick); // delete local vars et al.
// Init the options.
@@ -4855,6 +4846,10 @@ void do_arg_all(int count, int forceit, int keep_tabs)
if (keep_tabs) {
new_curwin = wp;
new_curtab = curtab;
+ } else if (wp->w_frame->fr_parent != curwin->w_frame->fr_parent) {
+ emsg(_("E249: window layout changed unexpectedly"));
+ i = count;
+ break;
} else {
win_move_after(wp, curwin);
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 375bebc5ac..0a1c92a9a4 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -532,6 +532,8 @@ struct file_buffer {
int b_flags; // various BF_ flags
int b_locked; // Buffer is being closed or referenced, don't
// let autocommands wipe it out.
+ int b_locked_split; // Buffer is being closed, don't allow opening
+ // a new window with it.
int b_ro_locked; // Non-zero when the buffer can't be changed.
// Used for FileChangedRO
@@ -1024,6 +1026,7 @@ typedef struct {
colnr_T startcol; // in win_line() points to char where HL starts
colnr_T endcol; // in win_line() points to char where HL ends
bool is_addpos; // position specified directly by matchaddpos()
+ bool has_cursor; // true if the cursor is inside the match, used for CurSearch
proftime_T tm; // for a time limit
} match_T;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 3e855ece15..0c45f05640 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6401,6 +6401,9 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
{
dict_T *const dict = tv_dict_alloc();
+ // make sure w_botline is valid
+ validate_botline(wp);
+
tv_dict_add_nr(dict, S_LEN("tabnr"), tpnr);
tv_dict_add_nr(dict, S_LEN("winnr"), winnr);
tv_dict_add_nr(dict, S_LEN("winid"), wp->handle);
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 61bd9571b5..e16537c192 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -2497,16 +2497,19 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
if (buf->b_fname != NULL) {
new_name = vim_strsave(buf->b_fname);
}
+ const bufref_T save_au_new_curbuf = au_new_curbuf;
set_bufref(&au_new_curbuf, buf);
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf);
cmdwin_type = save_cmdwin_type;
if (!bufref_valid(&au_new_curbuf)) {
// New buffer has been deleted.
delbuf_msg(new_name); // Frees new_name.
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
if (aborting()) { // autocmds may abort script processing
xfree(new_name);
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
if (buf == curbuf) { // already in new buffer
@@ -2540,12 +2543,14 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
// autocmds may abort script processing
if (aborting() && curwin->w_buffer != NULL) {
xfree(new_name);
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
// Be careful again, like above.
if (!bufref_valid(&au_new_curbuf)) {
// New buffer has been deleted.
delbuf_msg(new_name); // Frees new_name.
+ au_new_curbuf = save_au_new_curbuf;
goto theend;
}
if (buf == curbuf) { // already in new buffer
@@ -2585,8 +2590,7 @@ int do_ecmd(int fnum, char_u *ffname, char_u *sfname, exarg_T *eap, linenr_T new
did_get_winopts = true;
}
xfree(new_name);
- au_new_curbuf.br_buf = NULL;
- au_new_curbuf.br_buf_free_count = 0;
+ au_new_curbuf = save_au_new_curbuf;
}
curwin->w_pcmark.lnum = 1;
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 91e93a236a..b7d75855d6 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -6376,6 +6376,7 @@ static int open_cmdwin(void)
// Create a window for the command-line buffer.
if (win_split((int)p_cwh, WSP_BOT) == FAIL) {
beep_flush();
+ ga_clear(&winsizes);
return K_IGNORE;
}
cmdwin_type = get_cmdline_type();
diff --git a/src/nvim/match.c b/src/nvim/match.c
index 4129e84fc2..ed320eb6fc 100644
--- a/src/nvim/match.c
+++ b/src/nvim/match.c
@@ -373,6 +373,7 @@ static int next_search_hl_pos(match_T *shl, linenr_T lnum, posmatch_T *posmatch,
shl->rm.endpos[0].lnum = 0;
shl->rm.endpos[0].col = end;
shl->is_addpos = true;
+ shl->has_cursor = false;
posmatch->cur = found + 1;
return 1;
}
@@ -559,6 +560,22 @@ void prepare_search_hl(win_T *wp, match_T *search_hl, linenr_T lnum)
}
}
+/// Update "shl->has_cursor" based on the match in "shl" and the cursor
+/// position.
+static void check_cur_search_hl(win_T *wp, match_T *shl)
+{
+ linenr_T linecount = shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum;
+
+ if (wp->w_cursor.lnum >= shl->lnum
+ && wp->w_cursor.lnum <= shl->lnum + linecount
+ && (wp->w_cursor.lnum > shl->lnum || wp->w_cursor.col >= shl->rm.startpos[0].col)
+ && (wp->w_cursor.lnum < shl->lnum + linecount || wp->w_cursor.col < shl->rm.endpos[0].col)) {
+ shl->has_cursor = true;
+ } else {
+ shl->has_cursor = false;
+ }
+}
+
/// Prepare for 'hlsearch' and match highlighting in one window line.
/// Return true if there is such highlighting and set "search_attr" to the
/// current highlight attribute.
@@ -584,6 +601,7 @@ bool prepare_search_hl_line(win_T *wp, linenr_T lnum, colnr_T mincol, char_u **l
shl->endcol = MAXCOL;
shl->attr_cur = 0;
shl->is_addpos = false;
+ shl->has_cursor = false;
if (cur != NULL) {
cur->pos.cur = 0;
}
@@ -606,6 +624,12 @@ bool prepare_search_hl_line(win_T *wp, linenr_T lnum, colnr_T mincol, char_u **l
} else {
shl->endcol = MAXCOL;
}
+
+ // check if the cursor is in the match before changing the columns
+ if (shl == search_hl) {
+ check_cur_search_hl(wp, shl);
+ }
+
// Highlight one character for an empty match.
if (shl->startcol == shl->endcol) {
if ((*line)[shl->endcol] != NUL) {
@@ -668,12 +692,9 @@ int update_search_hl(win_T *wp, linenr_T lnum, colnr_T col, char_u **line, match
if (shl->endcol < next_col) {
shl->endcol = next_col;
}
- // Use "CurSearch" highlight for current search match
- if (shl == search_hl
- && (HL_ATTR(HLF_LC) || wp->w_hl_ids[HLF_LC])
- && wp->w_cursor.lnum == lnum
- && wp->w_cursor.col >= shl->startcol
- && wp->w_cursor.col < shl->endcol) {
+ // Highlight the match were the cursor is using the CurSearch
+ // group.
+ if (shl == search_hl && shl->has_cursor && (HL_ATTR(HLF_LC) || wp->w_hl_ids[HLF_LC])) {
shl->attr_cur = win_hl_attr(wp, HLF_LC) ? win_hl_attr(wp, HLF_LC) : HL_ATTR(HLF_LC);
} else {
shl->attr_cur = shl->attr;
@@ -707,6 +728,11 @@ int update_search_hl(win_T *wp, linenr_T lnum, colnr_T col, char_u **line, match
shl->endcol = MAXCOL;
}
+ // check if the cursor is in the match
+ if (shl == search_hl) {
+ check_cur_search_hl(wp, shl);
+ }
+
if (shl->startcol == shl->endcol) {
// highlight empty match, try again after it
shl->endcol += utfc_ptr2len(*line + shl->endcol);
diff --git a/src/nvim/move.c b/src/nvim/move.c
index c55a9a296b..ae908e893c 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -2279,9 +2279,7 @@ void do_check_cursorbind(void)
int restart_edit_save = restart_edit;
restart_edit = true;
check_cursor();
- if (win_cursorline_standout(curwin) || curwin->w_p_cuc) {
- validate_cursor();
- }
+ validate_cursor();
restart_edit = restart_edit_save;
}
// Correct cursor for multi-byte character.
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index d6b3b53c86..d0926e6b9e 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -97,18 +97,14 @@ static inline void normal_state_init(NormalState *s)
s->state.execute = normal_execute;
}
-/*
- * nv_*(): functions called to handle Normal and Visual mode commands.
- * n_*(): functions called to handle Normal mode commands.
- * v_*(): functions called to handle Visual mode commands.
- */
+// nv_*(): functions called to handle Normal and Visual mode commands.
+// n_*(): functions called to handle Normal mode commands.
+// v_*(): functions called to handle Visual mode commands.
static char *e_noident = N_("E349: No identifier under cursor");
-/*
- * Function to be called for a Normal or Visual mode command.
- * The argument is a cmdarg_T.
- */
+/// Function to be called for a Normal or Visual mode command.
+/// The argument is a cmdarg_T.
typedef void (*nv_func_T)(cmdarg_T *cap);
// Values for cmd_flags.
@@ -124,26 +120,22 @@ typedef void (*nv_func_T)(cmdarg_T *cap);
#define NV_KEEPREG 0x100 // don't clear regname
#define NV_NCW 0x200 // not allowed in command-line window
-/*
- * Generally speaking, every Normal mode command should either clear any
- * pending operator (with *clearop*()), or set the motion type variable
- * oap->motion_type.
- *
- * When a cursor motion command is made, it is marked as being a character or
- * line oriented motion. Then, if an operator is in effect, the operation
- * becomes character or line oriented accordingly.
- */
-
-/*
- * This table contains one entry for every Normal or Visual mode command.
- * The order doesn't matter, init_normal_cmds() will create a sorted index.
- * It is faster when all keys from zero to '~' are present.
- */
+// Generally speaking, every Normal mode command should either clear any
+// pending operator (with *clearop*()), or set the motion type variable
+// oap->motion_type.
+//
+// When a cursor motion command is made, it is marked as being a character or
+// line oriented motion. Then, if an operator is in effect, the operation
+// becomes character or line oriented accordingly.
+
+/// This table contains one entry for every Normal or Visual mode command.
+/// The order doesn't matter, init_normal_cmds() will create a sorted index.
+/// It is faster when all keys from zero to '~' are present.
static const struct nv_cmd {
- int cmd_char; // (first) command character
- nv_func_T cmd_func; // function for this command
- uint16_t cmd_flags; // NV_ flags
- short cmd_arg; // value for ca.arg
+ int cmd_char; ///< (first) command character
+ nv_func_T cmd_func; ///< function for this command
+ uint16_t cmd_flags; ///< NV_ flags
+ int16_t cmd_arg; ///< value for ca.arg
} nv_cmds[] =
{
{ NUL, nv_error, 0, 0 },
@@ -341,23 +333,21 @@ static const struct nv_cmd {
#define NV_CMDS_SIZE ARRAY_SIZE(nv_cmds)
// Sorted index of commands in nv_cmds[].
-static short nv_cmd_idx[NV_CMDS_SIZE];
+static int16_t nv_cmd_idx[NV_CMDS_SIZE];
// The highest index for which
// nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char]
static int nv_max_linear;
-/*
- * Compare functions for qsort() below, that checks the command character
- * through the index in nv_cmd_idx[].
- */
+/// Compare functions for qsort() below, that checks the command character
+/// through the index in nv_cmd_idx[].
static int nv_compare(const void *s1, const void *s2)
{
int c1, c2;
// The commands are sorted on absolute value.
- c1 = nv_cmds[*(const short *)s1].cmd_char;
- c2 = nv_cmds[*(const short *)s2].cmd_char;
+ c1 = nv_cmds[*(const int16_t *)s1].cmd_char;
+ c2 = nv_cmds[*(const int16_t *)s2].cmd_char;
if (c1 < 0) {
c1 = -c1;
}
@@ -367,24 +357,22 @@ static int nv_compare(const void *s1, const void *s2)
return c1 - c2;
}
-/*
- * Initialize the nv_cmd_idx[] table.
- */
+/// Initialize the nv_cmd_idx[] table.
void init_normal_cmds(void)
{
assert(NV_CMDS_SIZE <= SHRT_MAX);
// Fill the index table with a one to one relation.
- for (short int i = 0; i < (short int)NV_CMDS_SIZE; ++i) {
+ for (int16_t i = 0; i < (int16_t)NV_CMDS_SIZE; i++) {
nv_cmd_idx[i] = i;
}
// Sort the commands by the command character.
- qsort(&nv_cmd_idx, NV_CMDS_SIZE, sizeof(short), nv_compare);
+ qsort(&nv_cmd_idx, NV_CMDS_SIZE, sizeof(int16_t), nv_compare);
// Find the first entry that can't be indexed by the command character.
- short int i;
- for (i = 0; i < (short int)NV_CMDS_SIZE; ++i) {
+ int16_t i;
+ for (i = 0; i < (int16_t)NV_CMDS_SIZE; i++) {
if (i != nv_cmds[nv_cmd_idx[i]].cmd_char) {
break;
}
@@ -392,10 +380,9 @@ void init_normal_cmds(void)
nv_max_linear = i - 1;
}
-/*
- * Search for a command in the commands table.
- * Returns -1 for invalid command.
- */
+/// Search for a command in the commands table.
+///
+/// @return -1 for invalid command.
static int find_command(int cmdchar)
{
int i;
@@ -841,10 +828,10 @@ static bool normal_get_command_count(NormalState *s)
no_mapping++;
}
- ++no_zero_mapping; // don't map zero here
+ no_zero_mapping++; // don't map zero here
s->c = plain_vgetc();
LANGMAP_ADJUST(s->c, true);
- --no_zero_mapping;
+ no_zero_mapping--;
if (s->ctrl_w) {
no_mapping--;
}
@@ -1419,10 +1406,8 @@ static int normal_check(VimState *state)
return 1;
}
-/*
- * Set v:count and v:count1 according to "cap".
- * Set v:prevcount only when "set_prevcount" is true.
- */
+/// Set v:count and v:count1 according to "cap".
+/// Set v:prevcount only when "set_prevcount" is true.
static void set_vcount_ca(cmdarg_T *cap, bool *set_prevcount)
{
long count = cap->count0;
@@ -1528,8 +1513,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
int save_mouse_row = mouse_row;
int save_mouse_col = mouse_col;
- /* Need to get the character, peeking doesn't get the actual
- * one. */
+ // Need to get the character, peeking doesn't get the actual one.
nc = safe_vgetc();
if (c == nc) {
continue;
@@ -1548,9 +1532,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
return false;
}
- /*
- * Ignore drag and release events if we didn't get a click.
- */
+ // Ignore drag and release events if we didn't get a click.
if (is_click) {
got_click = true;
} else {
@@ -1567,9 +1549,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
- /*
- * CTRL right mouse button does CTRL-T
- */
+ // CTRL right mouse button does CTRL-T
if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT) {
if (State & INSERT) {
stuffcharReadbuff(Ctrl_O);
@@ -1582,18 +1562,14 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
return false;
}
- /*
- * CTRL only works with left mouse button
- */
+ // CTRL only works with left mouse button
if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT) {
return false;
}
- /*
- * When a modifier is down, ignore drag and release events, as well as
- * multiple clicks and the middle mouse button.
- * Accept shift-leftmouse drags when 'mousemodel' is "popup.*".
- */
+ // When a modifier is down, ignore drag and release events, as well as
+ // multiple clicks and the middle mouse button.
+ // Accept shift-leftmouse drags when 'mousemodel' is "popup.*".
if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT
| MOD_MASK_META))
&& (!is_click
@@ -1608,11 +1584,9 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
return false;
}
- /*
- * If the button press was used as the movement command for an operator
- * (eg "d<MOUSE>"), or it is the middle button that is held down, ignore
- * drag/release events.
- */
+ // If the button press was used as the movement command for an operator (eg
+ // "d<MOUSE>"), or it is the middle button that is held down, ignore
+ // drag/release events.
if (!is_click && which_button == MOUSE_MIDDLE) {
return false;
}
@@ -1623,25 +1597,19 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
regname = 0;
}
- /*
- * Middle mouse button does a 'put' of the selected text
- */
+ // Middle mouse button does a 'put' of the selected text
if (which_button == MOUSE_MIDDLE) {
if (State == NORMAL) {
- /*
- * If an operator was pending, we don't know what the user wanted
- * to do. Go back to normal mode: Clear the operator and beep().
- */
+ // If an operator was pending, we don't know what the user wanted to do.
+ // Go back to normal mode: Clear the operator and beep().
if (oap != NULL && oap->op_type != OP_NOP) {
clearopbeep(oap);
return false;
}
- /*
- * If visual was active, yank the highlighted text and put it
- * before the mouse pointer position.
- * In Select mode replace the highlighted text with the clipboard.
- */
+ // If visual was active, yank the highlighted text and put it
+ // before the mouse pointer position.
+ // In Select mode replace the highlighted text with the clipboard.
if (VIsual_active) {
if (VIsual_select) {
stuffcharReadbuff(Ctrl_G);
@@ -1652,20 +1620,16 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
return false;
}
- /*
- * The rest is below jump_to_mouse()
- */
+ // The rest is below jump_to_mouse()
} else if ((State & INSERT) == 0) {
return false;
}
- /*
- * Middle click in insert mode doesn't move the mouse, just insert the
- * contents of a register. '.' register is special, can't insert that
- * with do_put().
- * Also paste at the cursor if the current mode isn't in 'mouse' (only
- * happens for the GUI).
- */
+ // Middle click in insert mode doesn't move the mouse, just insert the
+ // contents of a register. '.' register is special, can't insert that
+ // with do_put().
+ // Also paste at the cursor if the current mode isn't in 'mouse' (only
+ // happens for the GUI).
if ((State & INSERT)) {
if (regname == '.') {
insert_reg(regname, true);
@@ -1762,28 +1726,27 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
.v_lock = VAR_FIXED,
.v_type = VAR_NUMBER,
.vval = {
- .v_number = (((mod_mask & MOD_MASK_MULTI_CLICK)
- == MOD_MASK_4CLICK)
- ? 4
- : ((mod_mask & MOD_MASK_MULTI_CLICK)
- == MOD_MASK_3CLICK)
- ? 3
- : ((mod_mask & MOD_MASK_MULTI_CLICK)
- == MOD_MASK_2CLICK)
- ? 2
- : 1)
+ .v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK
+ ? 4
+ : ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK
+ ? 3
+ : ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK
+ ? 2
+ : 1)))
},
},
{
.v_lock = VAR_FIXED,
.v_type = VAR_STRING,
- .vval = { .v_string = (char_u *)(which_button == MOUSE_LEFT
- ? "l"
- : which_button == MOUSE_RIGHT
- ? "r"
- : which_button == MOUSE_MIDDLE
- ? "m"
- : "?") },
+ .vval = {
+ .v_string = (char_u *)(which_button == MOUSE_LEFT
+ ? "l"
+ : (which_button == MOUSE_RIGHT
+ ? "r"
+ : (which_button == MOUSE_MIDDLE
+ ? "m"
+ : "?")))
+ },
},
{
.v_lock = VAR_FIXED,
@@ -1818,19 +1781,15 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
- /*
- * When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
- * right button up -> pop-up menu
- * shift-left button -> right button
- * alt-left button -> alt-right button
- */
+ // When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
+ // right button up -> pop-up menu
+ // shift-left button -> right button
+ // alt-left button -> alt-right button
if (mouse_model_popup()) {
if (which_button == MOUSE_RIGHT
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
- /*
- * NOTE: Ignore right button down and drag mouse events.
- * Windows only shows the popup menu on the button up event.
- */
+ // NOTE: Ignore right button down and drag mouse events. Windows only
+ // shows the popup menu on the button up event.
return false;
}
if (which_button == MOUSE_LEFT
@@ -1844,8 +1803,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
if (which_button == MOUSE_LEFT) {
if (is_click) {
- /* stop Visual mode for a left click in a window, but not when
- * on a status line */
+ // stop Visual mode for a left click in a window, but not when on a status line
if (VIsual_active) {
jump_flags |= MOUSE_MAY_STOP_VIS;
}
@@ -1854,10 +1812,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
} else if (which_button == MOUSE_RIGHT) {
if (is_click && VIsual_active) {
- /*
- * Remember the start and end of visual before moving the
- * cursor.
- */
+ // Remember the start and end of visual before moving the cursor.
if (lt(curwin->w_cursor, VIsual)) {
start_visual = curwin->w_cursor;
end_visual = VIsual;
@@ -1871,10 +1826,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
}
- /*
- * If an operator is pending, ignore all drags and releases until the
- * next mouse click.
- */
+ // If an operator is pending, ignore all drags and releases until the next mouse click.
if (!is_drag && oap != NULL && oap->op_type != OP_NOP) {
got_click = false;
oap->motion_type = kMTCharWise;
@@ -1885,9 +1837,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
jump_flags |= MOUSE_RELEASED;
}
- /*
- * JUMP!
- */
+ // JUMP!
jump_flags = jump_to_mouse(jump_flags,
oap == NULL ? NULL : &(oap->inclusive),
which_button);
@@ -1897,8 +1847,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
in_sep_line = (jump_flags & IN_SEP_LINE);
- /* When jumping to another window, clear a pending operator. That's a bit
- * friendlier than beeping and not jumping to that window. */
+ // When jumping to another window, clear a pending operator. That's a bit
+ // friendlier than beeping and not jumping to that window.
if (curwin != old_curwin && oap != NULL && oap->op_type != OP_NOP) {
clearop(oap);
}
@@ -1920,8 +1870,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
- /* Set global flag that we are extending the Visual area with mouse
- * dragging; temporarily minimize 'scrolloff'. */
+ // Set global flag that we are extending the Visual area with mouse dragging;
+ // temporarily minimize 'scrolloff'.
if (VIsual_active && is_drag && get_scrolloff_value(curwin)) {
// In the very first line, allow scrolling one line
if (mouse_row == 0) {
@@ -1943,10 +1893,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
VIsual_mode = Ctrl_V;
}
- /*
- * In Visual-block mode, divide the area in four, pick up the corner
- * that is in the quarter that the cursor is in.
- */
+ // In Visual-block mode, divide the area in four, pick up the corner
+ // that is in the quarter that the cursor is in.
if (VIsual_mode == Ctrl_V) {
getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol);
if (curwin->w_curswant > (leftcol + rightcol) / 2) {
@@ -1966,11 +1914,9 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
VIsual = curwin->w_cursor;
curwin->w_cursor = start_visual; // restore the cursor
} else {
- /*
- * If the click is before the start of visual, change the start.
- * If the click is after the end of visual, change the end. If
- * the click is inside the visual, change the closest side.
- */
+ // If the click is before the start of visual, change the start.
+ // If the click is after the end of visual, change the end. If
+ // the click is inside the visual, change the closest side.
if (lt(curwin->w_cursor, start_visual)) {
VIsual = end_visual;
} else if (lt(end_visual, curwin->w_cursor)) {
@@ -1984,9 +1930,8 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
} else {
VIsual = end_visual;
}
- }
- // In different lines, compare line number
- else {
+ } else {
+ // In different lines, compare line number
diff = (curwin->w_cursor.lnum - start_visual.lnum) -
(end_visual.lnum - curwin->w_cursor.lnum);
@@ -2005,17 +1950,12 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
}
}
- }
- /*
- * If Visual mode started in insert mode, execute "CTRL-O"
- */
- else if ((State & INSERT) && VIsual_active) {
+ } else if ((State & INSERT) && VIsual_active) {
+ // If Visual mode started in insert mode, execute "CTRL-O"
stuffcharReadbuff(Ctrl_O);
}
- /*
- * Middle mouse click: Put text before cursor.
- */
+ // Middle mouse click: Put text before cursor.
if (which_button == MOUSE_MIDDLE) {
if (regname == 0 && eval_has_provider("clipboard")) {
regname = '*';
@@ -2037,49 +1977,34 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
prep_redo(regname, count, NUL, c1, NUL, c2, NUL);
- /*
- * Remember where the paste started, so in edit() Insstart can be set
- * to this position
- */
+ // Remember where the paste started, so in edit() Insstart can be set to this position
if (restart_edit != 0) {
where_paste_started = curwin->w_cursor;
}
do_put(regname, NULL, dir, count,
(fixindent ? PUT_FIXINDENT : 0)| PUT_CURSEND);
- }
- /*
- * Ctrl-Mouse click or double click in a quickfix window jumps to the
- * error under the mouse pointer.
- */
- else if (((mod_mask & MOD_MASK_CTRL)
- || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
- && bt_quickfix(curbuf)) {
+ } else if (((mod_mask & MOD_MASK_CTRL) || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
+ && bt_quickfix(curbuf)) {
+ // Ctrl-Mouse click or double click in a quickfix window jumps to the
+ // error under the mouse pointer.
if (curwin->w_llist_ref == NULL) { // quickfix window
do_cmdline_cmd(".cc");
} else { // location list window
do_cmdline_cmd(".ll");
}
got_click = false; // ignore drag&release now
- }
- /*
- * Ctrl-Mouse click (or double click in a help window) jumps to the tag
- * under the mouse pointer.
- */
- else if ((mod_mask & MOD_MASK_CTRL) || (curbuf->b_help
- && (mod_mask &
- MOD_MASK_MULTI_CLICK) ==
- MOD_MASK_2CLICK)) {
+ } else if ((mod_mask & MOD_MASK_CTRL)
+ || (curbuf->b_help && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)) {
+ // Ctrl-Mouse click (or double click in a help window) jumps to the tag
+ // under the mouse pointer.
if (State & INSERT) {
stuffcharReadbuff(Ctrl_O);
}
stuffcharReadbuff(Ctrl_RSB);
got_click = false; // ignore drag&release now
- }
- /*
- * Shift-Mouse click searches for the next occurrence of the word under
- * the mouse pointer
- */
- else if ((mod_mask & MOD_MASK_SHIFT)) {
+ } else if ((mod_mask & MOD_MASK_SHIFT)) {
+ // Shift-Mouse click searches for the next occurrence of the word under
+ // the mouse pointer
if (State & INSERT
|| (VIsual_active && VIsual_select)) {
stuffcharReadbuff(Ctrl_O);
@@ -2118,17 +2043,15 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
VIsual_mode = Ctrl_V;
}
}
- /*
- * A double click selects a word or a block.
- */
+ // A double click selects a word or a block.
if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) {
pos_T *pos = NULL;
int gc;
if (is_click) {
- /* If the character under the cursor (skipping white space) is
- * not a word character, try finding a match and select a (),
- * {}, [], #if/#endif, etc. block. */
+ // If the character under the cursor (skipping white space) is
+ // not a word character, try finding a match and select a (),
+ // {}, [], #if/#endif, etc. block.
end_visual = curwin->w_cursor;
while (gc = gchar_pos(&end_visual), ascii_iswhite(gc)) {
inc(&end_visual);
@@ -2155,8 +2078,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
}
if (pos == NULL && (is_click || is_drag)) {
- /* When not found a match or when dragging: extend to include
- * a word. */
+ // When not found a match or when dragging: extend to include a word.
if (lt(curwin->w_cursor, orig_cursor)) {
find_start_of_word(&curwin->w_cursor);
find_end_of_word(&VIsual);
@@ -2192,9 +2114,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
return moved;
}
-/*
- * Move "pos" back to the start of the word it's in.
- */
+/// Move "pos" back to the start of the word it's in.
static void find_start_of_word(pos_T *pos)
{
char_u *line;
@@ -2214,10 +2134,8 @@ static void find_start_of_word(pos_T *pos)
}
}
-/*
- * Move "pos" forward to the end of the word it's in.
- * When 'selection' is "exclusive", the position is just after the word.
- */
+/// Move "pos" forward to the end of the word it's in.
+/// When 'selection' is "exclusive", the position is just after the word.
static void find_end_of_word(pos_T *pos)
{
char_u *line;
@@ -2242,13 +2160,11 @@ static void find_end_of_word(pos_T *pos)
}
}
-/*
- * Get class of a character for selection: same class means same word.
- * 0: blank
- * 1: punctuation groups
- * 2: normal word character
- * >2: multi-byte word character.
- */
+/// Get class of a character for selection: same class means same word.
+/// 0: blank
+/// 1: punctuation groups
+/// 2: normal word character
+/// >2: multi-byte word character.
static int get_mouse_class(char_u *p)
{
if (MB_BYTE2LEN(p[0]) > 1) {
@@ -2263,23 +2179,19 @@ static int get_mouse_class(char_u *p)
return 2;
}
- /*
- * There are a few special cases where we want certain combinations of
- * characters to be considered as a single word. These are things like
- * "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc. Otherwise, each
- * character is in its own class.
- */
+ // There are a few special cases where we want certain combinations of
+ // characters to be considered as a single word. These are things like
+ // "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc. Otherwise, each
+ // character is in its own class.
if (c != NUL && vim_strchr((char_u *)"-+*/%<>&|^!=", c) != NULL) {
return 1;
}
return c;
}
-/*
- * End Visual mode.
- * This function should ALWAYS be called to end Visual mode, except from
- * do_pending_operator().
- */
+/// End Visual mode.
+/// This function should ALWAYS be called to end Visual mode, except from
+/// do_pending_operator().
void end_visual_mode(void)
{
VIsual_active = false;
@@ -2302,9 +2214,7 @@ void end_visual_mode(void)
may_trigger_modechanged();
}
-/*
- * Reset VIsual_active and VIsual_reselect.
- */
+/// Reset VIsual_active and VIsual_reselect.
void reset_VIsual_and_resel(void)
{
if (VIsual_active) {
@@ -2314,9 +2224,7 @@ void reset_VIsual_and_resel(void)
VIsual_reselect = false;
}
-/*
- * Reset VIsual_active and VIsual_reselect if it's set.
- */
+/// Reset VIsual_active and VIsual_reselect if it's set.
void reset_VIsual(void)
{
if (VIsual_active) {
@@ -2499,19 +2407,15 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char_u **te
return (size_t)col;
}
-/*
- * Prepare for redo of a normal command.
- */
+/// Prepare for redo of a normal command.
static void prep_redo_cmd(cmdarg_T *cap)
{
prep_redo(cap->oap->regname, cap->count0,
NUL, cap->cmdchar, NUL, NUL, cap->nchar);
}
-/*
- * Prepare for redo of any command.
- * Note that only the last argument can be a multi-byte char.
- */
+/// Prepare for redo of any command.
+/// Note that only the last argument can be a multi-byte char.
void prep_redo(int regname, long num, int cmd1, int cmd2, int cmd3, int cmd4, int cmd5)
{
ResetRedobuff();
@@ -2540,11 +2444,9 @@ void prep_redo(int regname, long num, int cmd1, int cmd2, int cmd3, int cmd4, in
}
}
-/*
- * check for operator active and clear it
- *
- * return true if operator was active
- */
+/// check for operator active and clear it
+///
+/// @return true if operator was active
static bool checkclearop(oparg_T *oap)
{
if (oap->op_type == OP_NOP) {
@@ -2554,11 +2456,9 @@ static bool checkclearop(oparg_T *oap)
return true;
}
-/*
- * Check for operator or Visual active. Clear active operator.
- *
- * Return true if operator or Visual was active.
- */
+/// Check for operator or Visual active. Clear active operator.
+///
+/// @return true if operator or Visual was active.
static bool checkclearopq(oparg_T *oap)
{
if (oap->op_type == OP_NOP
@@ -2584,9 +2484,7 @@ void clearopbeep(oparg_T *oap)
beep_flush();
}
-/*
- * Remove the shift modifier from a special key.
- */
+/// Remove the shift modifier from a special key.
static void unshift_special(cmdarg_T *cap)
{
switch (cap->cmdchar) {
@@ -2681,12 +2579,12 @@ void clear_showcmd(void)
while ((*p_sel != 'e') ? s <= e : s < e) {
l = utfc_ptr2len(s);
if (l == 0) {
- ++bytes;
- ++chars;
+ bytes++;
+ chars++;
break; // end of line
}
bytes += l;
- ++chars;
+ chars++;
s += l;
}
if (bytes == chars) {
@@ -2711,16 +2609,14 @@ void clear_showcmd(void)
display_showcmd();
}
-/*
- * Add 'c' to string of shown command chars.
- * Return true if output has been written (and setcursor() has been called).
- */
+/// Add 'c' to string of shown command chars.
+///
+/// @return true if output has been written (and setcursor() has been called).
bool add_to_showcmd(int c)
{
char_u *p;
int i;
- static int ignore[] =
- {
+ static int ignore[] = {
K_IGNORE,
K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE, K_MOUSEMOVE,
K_MIDDLEMOUSE, K_MIDDLEDRAG, K_MIDDLERELEASE,
@@ -2742,7 +2638,7 @@ bool add_to_showcmd(int c)
// Ignore keys that are scrollbar updates and mouse clicks
if (IS_SPECIAL(c)) {
- for (i = 0; ignore[i] != 0; ++i) {
+ for (i = 0; ignore[i] != 0; i++) {
if (ignore[i] == c) {
return false;
}
@@ -2777,9 +2673,7 @@ void add_to_showcmd_c(int c)
setcursor();
}
-/*
- * Delete 'len' characters from the end of the shown command.
- */
+/// Delete 'len' characters from the end of the shown command.
static void del_from_showcmd(int len)
{
int old_len;
@@ -2799,10 +2693,8 @@ static void del_from_showcmd(int len)
}
}
-/*
- * push_showcmd() and pop_showcmd() are used when waiting for the user to type
- * something and there is a partial mapping.
- */
+/// push_showcmd() and pop_showcmd() are used when waiting for the user to type
+/// something and there is a partial mapping.
void push_showcmd(void)
{
if (p_sc) {
@@ -2856,11 +2748,9 @@ static void display_showcmd(void)
grid_puts_line_flush(false);
}
-/*
- * When "check" is false, prepare for commands that scroll the window.
- * When "check" is true, take care of scroll-binding after the window has
- * scrolled. Called from normal_cmd() and edit().
- */
+/// When "check" is false, prepare for commands that scroll the window.
+/// When "check" is true, take care of scroll-binding after the window has
+/// scrolled. Called from normal_cmd() and edit().
void do_check_scrollbind(bool check)
{
static win_T *old_curwin = NULL;
@@ -2875,11 +2765,9 @@ void do_check_scrollbind(bool check)
if (did_syncbind) {
did_syncbind = false;
} else if (curwin == old_curwin) {
- /*
- * Synchronize other windows, as necessary according to
- * 'scrollbind'. Don't do this after an ":edit" command, except
- * when 'diff' is set.
- */
+ // Synchronize other windows, as necessary according to
+ // 'scrollbind'. Don't do this after an ":edit" command, except
+ // when 'diff' is set.
if ((curwin->w_buffer == old_buf
|| curwin->w_p_diff
)
@@ -2890,16 +2778,14 @@ void do_check_scrollbind(bool check)
(long)(curwin->w_leftcol - old_leftcol));
}
} else if (vim_strchr(p_sbo, 'j')) { // jump flag set in 'scrollopt'
- /*
- * When switching between windows, make sure that the relative
- * vertical offset is valid for the new window. The relative
- * offset is invalid whenever another 'scrollbind' window has
- * scrolled to a point that would force the current window to
- * scroll past the beginning or end of its buffer. When the
- * resync is performed, some of the other 'scrollbind' windows may
- * need to jump so that the current window's relative position is
- * visible on-screen.
- */
+ // When switching between windows, make sure that the relative
+ // vertical offset is valid for the new window. The relative
+ // offset is invalid whenever another 'scrollbind' window has
+ // scrolled to a point that would force the current window to
+ // scroll past the beginning or end of its buffer. When the
+ // resync is performed, some of the other 'scrollbind' windows may
+ // need to jump so that the current window's relative position is
+ // visible on-screen.
check_scrollbind(curwin->w_topline - curwin->w_scbind_pos, 0L);
}
curwin->w_scbind_pos = curwin->w_topline;
@@ -2912,11 +2798,9 @@ void do_check_scrollbind(bool check)
old_leftcol = curwin->w_leftcol;
}
-/*
- * Synchronize any windows that have "scrollbind" set, based on the
- * number of rows by which the current window has changed
- * (1998-11-02 16:21:01 R. Edward Ralston <eralston@computer.org>)
- */
+/// Synchronize any windows that have "scrollbind" set, based on the
+/// number of rows by which the current window has changed
+/// (1998-11-02 16:21:01 R. Edward Ralston <eralston@computer.org>)
void check_scrollbind(linenr_T topline_diff, long leftcol_diff)
{
bool want_ver;
@@ -2929,16 +2813,12 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff)
long topline;
long y;
- /*
- * check 'scrollopt' string for vertical and horizontal scroll options
- */
+ // check 'scrollopt' string for vertical and horizontal scroll options
want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0);
want_ver |= old_curwin->w_p_diff;
want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0));
- /*
- * loop through the scrollbound windows and scroll accordingly
- */
+ // loop through the scrollbound windows and scroll accordingly
VIsual_select = VIsual_active = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
curwin = wp;
@@ -2947,9 +2827,7 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff)
if (curwin == old_curwin || !curwin->w_p_scb) {
continue;
}
- /*
- * do the vertical scroll
- */
+ // do the vertical scroll
if (want_ver) {
if (old_curwin->w_p_diff && curwin->w_p_diff) {
diff_set_topline(old_curwin, curwin);
@@ -2976,53 +2854,41 @@ void check_scrollbind(linenr_T topline_diff, long leftcol_diff)
curwin->w_redr_status = true;
}
- /*
- * do the horizontal scroll
- */
+ // do the horizontal scroll
if (want_hor && curwin->w_leftcol != tgt_leftcol) {
curwin->w_leftcol = tgt_leftcol;
leftcol_changed();
}
}
- /*
- * reset current-window
- */
+ // reset current-window
VIsual_select = old_VIsual_select;
VIsual_active = old_VIsual_active;
curwin = old_curwin;
curbuf = old_curbuf;
}
-/*
- * Command character that's ignored.
- * Used for CTRL-Q and CTRL-S to avoid problems with terminals that use
- * xon/xoff.
- */
+/// Command character that's ignored.
+/// Used for CTRL-Q and CTRL-S to avoid problems with terminals that use
+/// xon/xoff.
static void nv_ignore(cmdarg_T *cap)
{
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
}
-/*
- * Command character that doesn't do anything, but unlike nv_ignore() does
- * start edit(). Used for "startinsert" executed while starting up.
- */
+/// Command character that doesn't do anything, but unlike nv_ignore() does
+/// start edit(). Used for "startinsert" executed while starting up.
static void nv_nop(cmdarg_T *cap)
{
}
-/*
- * Command character doesn't exist.
- */
+/// Command character doesn't exist.
static void nv_error(cmdarg_T *cap)
{
clearopbeep(cap->oap);
}
-/*
- * <Help> and <F1> commands.
- */
+/// <Help> and <F1> commands.
static void nv_help(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
@@ -3030,9 +2896,7 @@ static void nv_help(cmdarg_T *cap)
}
}
-/*
- * CTRL-A and CTRL-X: Add or subtract from letter or number under cursor.
- */
+/// CTRL-A and CTRL-X: Add or subtract from letter or number under cursor.
static void nv_addsub(cmdarg_T *cap)
{
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
@@ -3049,9 +2913,7 @@ static void nv_addsub(cmdarg_T *cap)
}
}
-/*
- * CTRL-F, CTRL-B, etc: Scroll page up or down.
- */
+/// CTRL-F, CTRL-B, etc: Scroll page up or down.
static void nv_page(cmdarg_T *cap)
{
if (!checkclearop(cap->oap)) {
@@ -3089,8 +2951,8 @@ static void nv_gd(oparg_T *oap, int nchar, int thisblock)
}
}
-// Return true if line[offset] is not inside a C-style comment or string, false
-// otherwise.
+/// @return true if line[offset] is not inside a C-style comment or string,
+/// false otherwise.
static bool is_ident(char_u *line, int offset)
{
bool incomment = false;
@@ -3156,11 +3018,9 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
p_ws = false; // don't wrap around end of file now
p_scs = false; // don't switch ignorecase off now
- /*
- * With "gD" go to line 1.
- * With "gd" Search back for the start of the current function, then go
- * back until a blank line. If this fails go to line 1.
- */
+ // With "gD" go to line 1.
+ // With "gd" Search back for the start of the current function, then go
+ // back until a blank line. If this fails go to line 1.
if (!locally || !findpar(&incll, BACKWARD, 1L, '{', false)) {
setpcmark(); // Set in findpar() otherwise
curwin->w_cursor.lnum = 1;
@@ -3169,7 +3029,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
par_pos = curwin->w_cursor;
while (curwin->w_cursor.lnum > 1
&& *skipwhite(get_cursor_line_ptr()) != NUL) {
- --curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum--;
}
}
curwin->w_cursor.col = 0;
@@ -3207,7 +3067,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
}
if (get_leader_len(get_cursor_line_ptr(), NULL, false, true) > 0) {
// Ignore this line, continue at start of next line.
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
continue;
}
@@ -3259,13 +3119,11 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
return retval;
}
-/*
- * Move 'dist' lines in direction 'dir', counting lines by *screen*
- * lines rather than lines in the file.
- * 'dist' must be positive.
- *
- * Return true if able to move cursor, false otherwise.
- */
+/// Move 'dist' lines in direction 'dir', counting lines by *screen*
+/// lines rather than lines in the file.
+/// 'dist' must be positive.
+///
+/// @return true if able to move cursor, false otherwise.
static bool nv_screengo(oparg_T *oap, int dir, long dist)
{
int linelen = linetabsize(get_cursor_line_ptr());
@@ -3388,11 +3246,9 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
}
if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) {
- /*
- * Check for landing on a character that got split at the end of the
- * last line. We want to advance a screenline, not end up in the same
- * screenline or move two screenlines.
- */
+ // Check for landing on a character that got split at the end of the
+ // last line. We want to advance a screenline, not end up in the same
+ // screenline or move two screenlines.
validate_virtcol();
colnr_T virtcol = curwin->w_virtcol;
if (virtcol > (colnr_T)width1 && *get_showbreak_value(curwin) != NUL) {
@@ -3411,7 +3267,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
? (curwin->w_curswant > (colnr_T)width1 / 2)
: ((curwin->w_curswant - width1) % width2
> (colnr_T)width2 / 2))) {
- --curwin->w_cursor.col;
+ curwin->w_cursor.col--;
}
}
@@ -3421,12 +3277,10 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
return retval;
}
-/*
- * Mouse scroll wheel: Default action is to scroll three lines, or one page
- * when Shift or Ctrl is used.
- * K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or
- * K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2)
- */
+/// Mouse scroll wheel: Default action is to scroll three lines, or one page
+/// when Shift or Ctrl is used.
+/// K_MOUSEUP (cap->arg == 1) or K_MOUSEDOWN (cap->arg == 0) or
+/// K_MOUSELEFT (cap->arg == -1) or K_MOUSERIGHT (cap->arg == -2)
static void nv_mousescroll(cmdarg_T *cap)
{
win_T *old_curwin = curwin;
@@ -3468,18 +3322,14 @@ static void nv_mousescroll(cmdarg_T *cap)
curbuf = curwin->w_buffer;
}
-/*
- * Mouse clicks and drags.
- */
+/// Mouse clicks and drags.
static void nv_mouse(cmdarg_T *cap)
{
(void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0);
}
-/*
- * Handle CTRL-E and CTRL-Y commands: scroll a line up or down.
- * cap->arg must be true for CTRL-E.
- */
+/// Handle CTRL-E and CTRL-Y commands: scroll a line up or down.
+/// cap->arg must be true for CTRL-E.
static void nv_scroll_line(cmdarg_T *cap)
{
if (!checkclearop(cap->oap)) {
@@ -3487,9 +3337,7 @@ static void nv_scroll_line(cmdarg_T *cap)
}
}
-/*
- * Scroll "count" lines up or down, and redraw.
- */
+/// Scroll "count" lines up or down, and redraw.
void scroll_redraw(int up, long count)
{
linenr_T prev_topline = curwin->w_topline;
@@ -3539,9 +3387,7 @@ void scroll_redraw(int up, long count)
redraw_later(curwin, VALID);
}
-/*
- * Commands that start with "z".
- */
+/// Commands that start with "z".
static void nv_zet(cmdarg_T *cap)
{
int n;
@@ -3554,9 +3400,7 @@ static void nv_zet(cmdarg_T *cap)
int l_p_siso = (int)get_sidescrolloff_value(curwin);
if (ascii_isdigit(nchar)) {
- /*
- * "z123{nchar}": edit the count before obtaining {nchar}
- */
+ // "z123{nchar}": edit the count before obtaining {nchar}
if (checkclearop(cap->oap)) {
return;
}
@@ -3600,10 +3444,8 @@ dozet:
return;
}
- /*
- * For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb":
- * If line number given, set cursor.
- */
+ // For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb":
+ // If line number given, set cursor.
if ((vim_strchr((char_u *)"+\r\nt.z^-b", nchar) != NULL)
&& cap->count0
&& cap->count0 != curwin->w_cursor.lnum) {
@@ -4026,9 +3868,7 @@ dozet:
}
-/*
- * "Q" command.
- */
+/// "Q" command.
static void nv_regreplay(cmdarg_T *cap)
{
if (checkclearop(cap->oap)) {
@@ -4106,9 +3946,7 @@ static void nv_colon(cmdarg_T *cap)
}
}
-/*
- * Handle CTRL-G command.
- */
+/// Handle CTRL-G command.
static void nv_ctrlg(cmdarg_T *cap)
{
if (VIsual_active) { // toggle Selection/Visual mode
@@ -4121,9 +3959,7 @@ static void nv_ctrlg(cmdarg_T *cap)
}
}
-/*
- * Handle CTRL-H <Backspace> command.
- */
+/// Handle CTRL-H <Backspace> command.
static void nv_ctrlh(cmdarg_T *cap)
{
if (VIsual_active && VIsual_select) {
@@ -4134,9 +3970,7 @@ static void nv_ctrlh(cmdarg_T *cap)
}
}
-/*
- * CTRL-L: clear screen and redraw.
- */
+/// CTRL-L: clear screen and redraw.
static void nv_clear(cmdarg_T *cap)
{
if (!checkclearop(cap->oap)) {
@@ -4149,10 +3983,8 @@ static void nv_clear(cmdarg_T *cap)
}
}
-/*
- * CTRL-O: In Select mode: switch to Visual mode for one command.
- * Otherwise: Go to older pcmark.
- */
+/// CTRL-O: In Select mode: switch to Visual mode for one command.
+/// Otherwise: Go to older pcmark.
static void nv_ctrlo(cmdarg_T *cap)
{
if (VIsual_active && VIsual_select) {
@@ -4176,9 +4008,7 @@ static void nv_hat(cmdarg_T *cap)
}
}
-/*
- * "Z" commands.
- */
+/// "Z" commands.
static void nv_Zet(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
@@ -4199,9 +4029,7 @@ static void nv_Zet(cmdarg_T *cap)
}
}
-/*
- * Call nv_ident() as if "c1" was used, with "c2" as next character.
- */
+/// Call nv_ident() as if "c1" was used, with "c2" as next character.
void do_nv_ident(int c1, int c2)
{
oparg_T oa;
@@ -4215,14 +4043,12 @@ void do_nv_ident(int c1, int c2)
nv_ident(&ca);
}
-/*
- * Handle the commands that use the word under the cursor.
- * [g] CTRL-] :ta to current identifier
- * [g] 'K' run program for current identifier
- * [g] '*' / to current identifier or string
- * [g] '#' ? to current identifier or string
- * g ']' :tselect for current identifier
- */
+/// Handle the commands that use the word under the cursor.
+/// [g] CTRL-] :ta to current identifier
+/// [g] 'K' run program for current identifier
+/// [g] '*' / to current identifier or string
+/// [g] '#' ? to current identifier or string
+/// g ']' :tselect for current identifier
static void nv_ident(cmdarg_T *cap)
{
char_u *ptr = NULL;
@@ -4245,9 +4071,7 @@ static void nv_ident(cmdarg_T *cap)
cmdchar = '#';
}
- /*
- * The "]", "CTRL-]" and "K" commands accept an argument in Visual mode.
- */
+ // The "]", "CTRL-]" and "K" commands accept an argument in Visual mode.
if (cmdchar == ']' || cmdchar == Ctrl_RSB || cmdchar == 'K') {
if (VIsual_active && get_visual_text(cap, &ptr, &n) == false) {
return;
@@ -4284,12 +4108,10 @@ static void nv_ident(cmdarg_T *cap)
switch (cmdchar) {
case '*':
case '#':
- /*
- * Put cursor at start of word, makes search skip the word
- * under the cursor.
- * Call setpcmark() first, so "*``" puts the cursor back where
- * it was.
- */
+ // Put cursor at start of word, makes search skip the word
+ // under the cursor.
+ // Call setpcmark() first, so "*``" puts the cursor back where
+ // it was.
setpcmark();
curwin->w_cursor.col = (colnr_T)(ptr - get_cursor_line_ptr());
@@ -4312,8 +4134,8 @@ static void nv_ident(cmdarg_T *cap)
// An external command will probably use an argument starting
// with "-" as an option. To avoid trouble we skip the "-".
while (*ptr == '-' && n > 0) {
- ++ptr;
- --n;
+ ptr++;
+ n--;
}
if (n == 0) {
emsg(_(e_noident)); // found dashes only
@@ -4415,9 +4237,7 @@ static void nv_ident(cmdarg_T *cap)
*p = NUL;
}
- /*
- * Execute the command.
- */
+ // Execute the command.
if (cmdchar == '*' || cmdchar == '#') {
if (!g_cmd
&& vim_iswordp(mb_prevptr(get_cursor_line_ptr(), ptr))) {
@@ -4484,9 +4304,7 @@ bool get_visual_text(cmdarg_T *cap, char_u **pp, size_t *lenp)
return true;
}
-/*
- * CTRL-T: backwards in tag stack
- */
+/// CTRL-T: backwards in tag stack
static void nv_tagpop(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
@@ -4494,9 +4312,7 @@ static void nv_tagpop(cmdarg_T *cap)
}
}
-/*
- * Handle scrolling command 'H', 'L' and 'M'.
- */
+/// Handle scrolling command 'H', 'L' and 'M'.
static void nv_scroll(cmdarg_T *cap)
{
int used = 0;
@@ -4516,10 +4332,10 @@ static void nv_scroll(cmdarg_T *cap)
if (hasAnyFolding(curwin)) {
// Count a fold for one screen line.
for (n = cap->count1 - 1; n > 0
- && curwin->w_cursor.lnum > curwin->w_topline; --n) {
+ && curwin->w_cursor.lnum > curwin->w_topline; n--) {
(void)hasFolding(curwin->w_cursor.lnum,
&curwin->w_cursor.lnum, NULL);
- --curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum--;
}
} else {
curwin->w_cursor.lnum -= cap->count1 - 1;
@@ -4575,9 +4391,7 @@ static void nv_scroll(cmdarg_T *cap)
beginline(BL_SOL | BL_FIX);
}
-/*
- * Cursor right commands.
- */
+/// Cursor right commands.
static void nv_right(cmdarg_T *cap)
{
long n;
@@ -4596,15 +4410,13 @@ static void nv_right(cmdarg_T *cap)
cap->oap->inclusive = false;
PAST_LINE = (VIsual_active && *p_sel != 'o');
- /*
- * In virtual mode, there's no such thing as "PAST_LINE", as lines are
- * (theoretically) infinitely long.
- */
+ // In virtual mode, there's no such thing as "PAST_LINE", as lines are
+ // (theoretically) infinitely long.
if (virtual_active()) {
PAST_LINE = 0;
}
- for (n = cap->count1; n > 0; --n) {
+ for (n = cap->count1; n > 0; n--) {
if ((!PAST_LINE && oneright() == false)
|| (PAST_LINE
&& *get_cursor_pos_ptr() == NUL)) {
@@ -4623,7 +4435,7 @@ static void nv_right(cmdarg_T *cap)
&& !LINEEMPTY(curwin->w_cursor.lnum)) {
cap->oap->inclusive = true;
} else {
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
curwin->w_cursor.coladd = 0;
curwin->w_set_curswant = true;
@@ -4657,11 +4469,9 @@ static void nv_right(cmdarg_T *cap)
}
}
-/*
- * Cursor left commands.
- *
- * Returns true when operator end should not be adjusted.
- */
+/// Cursor left commands.
+///
+/// @return true when operator end should not be adjusted.
static void nv_left(cmdarg_T *cap)
{
long n;
@@ -4677,7 +4487,7 @@ static void nv_left(cmdarg_T *cap)
cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
- for (n = cap->count1; n > 0; --n) {
+ for (n = cap->count1; n > 0; n--) {
if (oneleft() == false) {
// <BS> and <Del> wrap to previous line if 'whichwrap' has 'b'.
// 'h' wraps to previous line if 'whichwrap' has 'h'.
@@ -4705,9 +4515,8 @@ static void nv_left(cmdarg_T *cap)
cap->retval |= CA_NO_ADJ_OP_END;
}
continue;
- }
- // Only beep and flush if not moved at all
- else if (cap->oap->op_type == OP_NOP && n == cap->count1) {
+ } else if (cap->oap->op_type == OP_NOP && n == cap->count1) {
+ // Only beep and flush if not moved at all
beep_flush();
}
break;
@@ -4719,10 +4528,8 @@ static void nv_left(cmdarg_T *cap)
}
}
-/*
- * Cursor up commands.
- * cap->arg is true for "-": Move cursor to first non-blank.
- */
+/// Cursor up commands.
+/// cap->arg is true for "-": Move cursor to first non-blank.
static void nv_up(cmdarg_T *cap)
{
if (mod_mask & MOD_MASK_SHIFT) {
@@ -4739,10 +4546,8 @@ static void nv_up(cmdarg_T *cap)
}
}
-/*
- * Cursor down commands.
- * cap->arg is true for CR and "+": Move cursor to first non-blank.
- */
+/// Cursor down commands.
+/// cap->arg is true for CR and "+": Move cursor to first non-blank.
static void nv_down(cmdarg_T *cap)
{
if (mod_mask & MOD_MASK_SHIFT) {
@@ -4774,9 +4579,7 @@ static void nv_down(cmdarg_T *cap)
}
}
-/*
- * Grab the file name under the cursor and edit it.
- */
+/// Grab the file name under the cursor and edit it.
static void nv_gotofile(cmdarg_T *cap)
{
char_u *ptr;
@@ -4813,9 +4616,7 @@ static void nv_gotofile(cmdarg_T *cap)
}
}
-/*
- * <End> command: to end of current line or last line.
- */
+/// <End> command: to end of current line or last line.
static void nv_end(cmdarg_T *cap)
{
if (cap->arg || (mod_mask & MOD_MASK_CTRL)) { // CTRL-END = goto last line
@@ -4826,9 +4627,7 @@ static void nv_end(cmdarg_T *cap)
nv_dollar(cap);
}
-/*
- * Handle the "$" command.
- */
+/// Handle the "$" command.
static void nv_dollar(cmdarg_T *cap)
{
cap->oap->motion_type = kMTCharWise;
@@ -4848,10 +4647,8 @@ static void nv_dollar(cmdarg_T *cap)
}
}
-/*
- * Implementation of '?' and '/' commands.
- * If cap->arg is true don't set PC mark.
- */
+/// Implementation of '?' and '/' commands.
+/// If cap->arg is true don't set PC mark.
static void nv_search(cmdarg_T *cap)
{
oparg_T *oap = cap->oap;
@@ -4879,10 +4676,8 @@ static void nv_search(cmdarg_T *cap)
? 0 : SEARCH_MARK, NULL);
}
-/*
- * Handle "N" and "n" commands.
- * cap->arg is SEARCH_REV for "N", 0 for "n".
- */
+/// Handle "N" and "n" commands.
+/// cap->arg is SEARCH_REV for "N", 0 for "n".
static void nv_next(cmdarg_T *cap)
{
pos_T old = curwin->w_cursor;
@@ -4939,12 +4734,10 @@ static int normal_search(cmdarg_T *cap, int dir, char_u *pat, int opt, int *wrap
return i;
}
-/*
- * Character search commands.
- * cap->arg is BACKWARD for 'F' and 'T', FORWARD for 'f' and 't', true for
- * ',' and false for ';'.
- * cap->nchar is NUL for ',' and ';' (repeat the search)
- */
+/// Character search commands.
+/// cap->arg is BACKWARD for 'F' and 'T', FORWARD for 'f' and 't', true for
+/// ',' and false for ';'.
+/// cap->nchar is NUL for ',' and ';' (repeat the search)
static void nv_csearch(cmdarg_T *cap)
{
bool t_cmd;
@@ -4977,10 +4770,8 @@ static void nv_csearch(cmdarg_T *cap)
}
}
-/*
- * "[" and "]" commands.
- * cap->arg is BACKWARD for "[" and FORWARD for "]".
- */
+/// "[" and "]" commands.
+/// cap->arg is BACKWARD for "[" and FORWARD for "]".
static void nv_brackets(cmdarg_T *cap)
{
pos_T new_pos = { 0, 0, 0 };
@@ -4995,24 +4786,19 @@ static void nv_brackets(cmdarg_T *cap)
cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = false;
old_pos = curwin->w_cursor;
- curwin->w_cursor.coladd = 0; // TODO: don't do this for an error.
+ curwin->w_cursor.coladd = 0; // TODO(Unknown): don't do this for an error.
- /*
- * "[f" or "]f" : Edit file under the cursor (same as "gf")
- */
+ // "[f" or "]f" : Edit file under the cursor (same as "gf")
if (cap->nchar == 'f') {
nv_gotofile(cap);
- } else
- /*
- * Find the occurrence(s) of the identifier or define under cursor
- * in current and included files or jump to the first occurrence.
- *
- * search list jump
- * fwd bwd fwd bwd fwd bwd
- * identifier "]i" "[i" "]I" "[I" "]^I" "[^I"
- * define "]d" "[d" "]D" "[D" "]^D" "[^D"
- */
- if (vim_strchr((char_u *)"iI\011dD\004", cap->nchar) != NULL) {
+ } else if (vim_strchr((char_u *)"iI\011dD\004", cap->nchar) != NULL) {
+ // Find the occurrence(s) of the identifier or define under cursor
+ // in current and included files or jump to the first occurrence.
+ //
+ // search list jump
+ // fwd bwd fwd bwd fwd bwd
+ // identifier "]i" "[i" "]I" "[I" "]^I" "[^I"
+ // define "]d" "[d" "]D" "[D" "]^D" "[^D"
char_u *ptr;
size_t len;
@@ -5034,18 +4820,13 @@ static void nv_brackets(cmdarg_T *cap)
MAXLNUM);
curwin->w_set_curswant = true;
}
- } else
- /*
- * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
- * "[#", "]#": go to start/end of Nth innermost #if..#endif construct.
- * "[/", "[*", "]/", "]*": go to Nth comment start/end.
- * "[m" or "]m" search for prev/next start of (Java) method.
- * "[M" or "]M" search for prev/next end of (Java) method.
- */
- if ((cap->cmdchar == '['
- && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL)
- || (cap->cmdchar == ']'
- && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL)) {
+ } else if ((cap->cmdchar == '[' && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL)
+ || (cap->cmdchar == ']' && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL)) {
+ // "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
+ // "[#", "]#": go to start/end of Nth innermost #if..#endif construct.
+ // "[/", "[*", "]/", "]*": go to Nth comment start/end.
+ // "[m" or "]m" search for prev/next start of (Java) method.
+ // "[M" or "]M" search for prev/next end of (Java) method.
if (cap->nchar == '*') {
cap->nchar = '/';
}
@@ -5061,7 +4842,7 @@ static void nv_brackets(cmdarg_T *cap)
findc = cap->nchar;
n = cap->count1;
}
- for (; n > 0; --n) {
+ for (; n > 0; n--) {
if ((pos = findmatchlimit(cap->oap, findc,
(cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, 0)) == NULL) {
if (new_pos.lnum == 0) { // nothing found
@@ -5079,12 +4860,10 @@ static void nv_brackets(cmdarg_T *cap)
}
curwin->w_cursor = old_pos;
- /*
- * Handle "[m", "]m", "[M" and "[M". The findmatchlimit() only
- * brought us to the match for "[m" and "]M" when inside a method.
- * Try finding the '{' or '}' we want to be at.
- * Also repeat for the given count.
- */
+ // Handle "[m", "]m", "[M" and "[M". The findmatchlimit() only
+ // brought us to the match for "[m" and "]M" when inside a method.
+ // Try finding the '{' or '}' we want to be at.
+ // Also repeat for the given count.
if (cap->nchar == 'm' || cap->nchar == 'M') {
// norm is true for "]M" and "[m"
int norm = ((findc == '{') == (cap->nchar == 'm'));
@@ -5095,7 +4874,7 @@ static void nv_brackets(cmdarg_T *cap)
pos = &prev_pos;
curwin->w_cursor = prev_pos;
if (norm) {
- --n;
+ n--;
}
} else {
pos = NULL;
@@ -5123,11 +4902,10 @@ static void nv_brackets(cmdarg_T *cap)
// class and we're inside now. Just go on.
new_pos = curwin->w_cursor;
pos = &new_pos;
- }
- // found start/end of other method: go to match
- else if ((pos = findmatchlimit(cap->oap, findc,
- (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD,
- 0)) == NULL) {
+ } else if ((pos = findmatchlimit(cap->oap, findc,
+ (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD,
+ 0)) == NULL) {
+ // found start/end of other method: go to match
n = 0;
} else {
curwin->w_cursor = *pos;
@@ -5135,7 +4913,7 @@ static void nv_brackets(cmdarg_T *cap)
break;
}
}
- --n;
+ n--;
}
curwin->w_cursor = old_pos;
if (pos == NULL && new_pos.lnum != 0) {
@@ -5151,21 +4929,15 @@ static void nv_brackets(cmdarg_T *cap)
foldOpenCursor();
}
}
- }
- /*
- * "[[", "[]", "]]" and "][": move to start or end of function
- */
- else if (cap->nchar == '[' || cap->nchar == ']') {
+ } else if (cap->nchar == '[' || cap->nchar == ']') {
+ // "[[", "[]", "]]" and "][": move to start or end of function
if (cap->nchar == cap->cmdchar) { // "]]" or "[["
flag = '{';
} else {
flag = '}'; // "][" or "[]"
}
curwin->w_set_curswant = true;
- /*
- * Imitate strange Vi behaviour: When using "]]" with an operator
- * we also stop at '}'.
- */
+ // Imitate strange Vi behaviour: When using "]]" with an operator we also stop at '}'.
if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, flag,
(cap->oap->op_type != OP_NOP
&& cap->arg == FORWARD && flag == '{'))) {
@@ -5181,13 +4953,10 @@ static void nv_brackets(cmdarg_T *cap)
} else if (cap->nchar == 'p' || cap->nchar == 'P') {
// "[p", "[P", "]P" and "]p": put with indent adjustment
nv_put_opt(cap, true);
- }
- /*
- * "['", "[`", "]'" and "]`": jump to next mark
- */
- else if (cap->nchar == '\'' || cap->nchar == '`') {
+ } else if (cap->nchar == '\'' || cap->nchar == '`') {
+ // "['", "[`", "]'" and "]`": jump to next mark
pos = &curwin->w_cursor;
- for (n = cap->count1; n > 0; --n) {
+ for (n = cap->count1; n > 0; n--) {
prev_pos = *pos;
pos = getnextmark(pos, cap->cmdchar == '[' ? BACKWARD : FORWARD,
cap->nchar == '\'');
@@ -5199,40 +4968,28 @@ static void nv_brackets(cmdarg_T *cap)
pos = &prev_pos;
}
nv_cursormark(cap, cap->nchar == '\'', pos);
- }
- /*
- * [ or ] followed by a middle mouse click: put selected text with
- * indent adjustment. Any other button just does as usual.
- */
- else if (cap->nchar >= K_RIGHTRELEASE && cap->nchar <= K_LEFTMOUSE) {
+ } else if (cap->nchar >= K_RIGHTRELEASE && cap->nchar <= K_LEFTMOUSE) {
+ // [ or ] followed by a middle mouse click: put selected text with
+ // indent adjustment. Any other button just does as usual.
(void)do_mouse(cap->oap, cap->nchar,
(cap->cmdchar == ']') ? FORWARD : BACKWARD,
cap->count1, PUT_FIXINDENT);
- }
- /*
- * "[z" and "]z": move to start or end of open fold.
- */
- else if (cap->nchar == 'z') {
+ } else if (cap->nchar == 'z') {
+ // "[z" and "]z": move to start or end of open fold.
if (foldMoveTo(false, cap->cmdchar == ']' ? FORWARD : BACKWARD,
cap->count1) == false) {
clearopbeep(cap->oap);
}
- }
- /*
- * "[c" and "]c": move to next or previous diff-change.
- */
- else if (cap->nchar == 'c') {
+ } else if (cap->nchar == 'c') {
+ // "[c" and "]c": move to next or previous diff-change.
if (diff_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
cap->count1) == false) {
clearopbeep(cap->oap);
}
- }
- /*
- * "[s", "[S", "]s" and "]S": move to next spell error.
- */
- else if (cap->nchar == 's' || cap->nchar == 'S') {
+ } else if (cap->nchar == 's' || cap->nchar == 'S') {
+ // "[s", "[S", "]s" and "]S": move to next spell error.
setpcmark();
- for (n = 0; n < cap->count1; ++n) {
+ for (n = 0; n < cap->count1; n++) {
if (spell_move_to(curwin, cap->cmdchar == ']' ? FORWARD : BACKWARD,
cap->nchar == 's', false, NULL) == 0) {
clearopbeep(cap->oap);
@@ -5244,16 +5001,13 @@ static void nv_brackets(cmdarg_T *cap)
if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped) {
foldOpenCursor();
}
- }
- // Not a valid cap->nchar.
- else {
+ } else {
+ // Not a valid cap->nchar.
clearopbeep(cap->oap);
}
}
-/*
- * Handle Normal mode "%" command.
- */
+/// Handle Normal mode "%" command.
static void nv_percent(cmdarg_T *cap)
{
pos_T *pos;
@@ -5306,10 +5060,8 @@ static void nv_percent(cmdarg_T *cap)
}
}
-/*
- * Handle "(" and ")" commands.
- * cap->arg is BACKWARD for "(" and FORWARD for ")".
- */
+/// Handle "(" and ")" commands.
+/// cap->arg is BACKWARD for "(" and FORWARD for ")".
static void nv_brace(cmdarg_T *cap)
{
cap->oap->motion_type = kMTCharWise;
@@ -5330,9 +5082,7 @@ static void nv_brace(cmdarg_T *cap)
}
}
-/*
- * "m" command: Mark a position.
- */
+/// "m" command: Mark a position.
static void nv_mark(cmdarg_T *cap)
{
if (!checkclearop(cap->oap)) {
@@ -5342,10 +5092,8 @@ static void nv_mark(cmdarg_T *cap)
}
}
-/*
- * "{" and "}" commands.
- * cmd->arg is BACKWARD for "{" and FORWARD for "}".
- */
+/// "{" and "}" commands.
+/// cmd->arg is BACKWARD for "{" and FORWARD for "}".
static void nv_findpar(cmdarg_T *cap)
{
cap->oap->motion_type = kMTCharWise;
@@ -5362,9 +5110,7 @@ static void nv_findpar(cmdarg_T *cap)
}
}
-/*
- * "u" command: Undo or make lower case.
- */
+/// "u" command: Undo or make lower case.
static void nv_undo(cmdarg_T *cap)
{
if (cap->oap->op_type == OP_LOWER
@@ -5378,9 +5124,7 @@ static void nv_undo(cmdarg_T *cap)
}
}
-/*
- * <Undo> command.
- */
+/// <Undo> command.
static void nv_kundo(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
@@ -5393,9 +5137,7 @@ static void nv_kundo(cmdarg_T *cap)
}
}
-/*
- * Handle the "r" command.
- */
+/// Handle the "r" command.
static void nv_replace(cmdarg_T *cap)
{
char_u *ptr;
@@ -5486,14 +5228,12 @@ static void nv_replace(cmdarg_T *cap)
}
if (had_ctrl_v != Ctrl_V && (cap->nchar == '\r' || cap->nchar == '\n')) {
- /*
- * Replace character(s) by a single newline.
- * Strange vi behaviour: Only one newline is inserted.
- * Delete the characters here.
- * Insert the newline with an insert command, takes care of
- * autoindent. The insert command depends on being on the last
- * character of a line or not.
- */
+ // Replace character(s) by a single newline.
+ // Strange vi behaviour: Only one newline is inserted.
+ // Delete the characters here.
+ // Insert the newline with an insert command, takes care of
+ // autoindent. The insert command depends on being on the last
+ // character of a line or not.
(void)del_chars(cap->count1, false); // delete the characters
stuffcharReadbuff('\r');
stuffcharReadbuff(ESC);
@@ -5551,10 +5291,8 @@ static void nv_replace(cmdarg_T *cap)
foldUpdateAfterInsert();
}
-/*
- * 'o': Exchange start and end of Visual area.
- * 'O': same, but in block mode exchange left and right corners.
- */
+/// 'o': Exchange start and end of Visual area.
+/// 'O': same, but in block mode exchange left and right corners.
static void v_swap_corners(int cmdchar)
{
pos_T old_cursor;
@@ -5572,7 +5310,7 @@ static void v_swap_corners(int cmdchar)
// 'selection "exclusive" and cursor at right-bottom corner: move it
// right one column
if (old_cursor.lnum >= VIsual.lnum && *p_sel == 'e') {
- ++curwin->w_curswant;
+ curwin->w_curswant++;
}
coladvance(curwin->w_curswant);
if (curwin->w_cursor.col == old_cursor.col
@@ -5581,7 +5319,7 @@ static void v_swap_corners(int cmdchar)
old_cursor.coladd)) {
curwin->w_cursor.lnum = VIsual.lnum;
if (old_cursor.lnum <= VIsual.lnum && *p_sel == 'e') {
- ++right;
+ right++;
}
coladvance(right);
VIsual = curwin->w_cursor;
@@ -5598,9 +5336,7 @@ static void v_swap_corners(int cmdchar)
}
}
-/*
- * "R" (cap->arg is false) and "gR" (cap->arg is true).
- */
+/// "R" (cap->arg is false) and "gR" (cap->arg is true).
static void nv_Replace(cmdarg_T *cap)
{
if (VIsual_active) { // "R" is replace lines
@@ -5621,9 +5357,7 @@ static void nv_Replace(cmdarg_T *cap)
}
}
-/*
- * "gr".
- */
+/// "gr".
static void nv_vreplace(cmdarg_T *cap)
{
if (VIsual_active) {
@@ -5647,9 +5381,7 @@ static void nv_vreplace(cmdarg_T *cap)
}
}
-/*
- * Swap case for "~" command, when it does not work like an operator.
- */
+/// Swap case for "~" command, when it does not work like an operator.
static void n_swapchar(cmdarg_T *cap)
{
long n;
@@ -5672,13 +5404,13 @@ static void n_swapchar(cmdarg_T *cap)
}
startpos = curwin->w_cursor;
- for (n = cap->count1; n > 0; --n) {
+ for (n = cap->count1; n > 0; n--) {
did_change |= swapchar(cap->oap->op_type, &curwin->w_cursor);
inc_cursor();
if (gchar_cursor() == NUL) {
if (vim_strchr(p_ww, '~') != NULL
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- ++curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum++;
curwin->w_cursor.col = 0;
if (n > 1) {
if (u_savesub(curwin->w_cursor.lnum) == false) {
@@ -5701,14 +5433,12 @@ static void n_swapchar(cmdarg_T *cap)
curbuf->b_op_start = startpos;
curbuf->b_op_end = curwin->w_cursor;
if (curbuf->b_op_end.col > 0) {
- --curbuf->b_op_end.col;
+ curbuf->b_op_end.col--;
}
}
}
-/*
- * Move cursor to mark.
- */
+/// Move cursor to mark.
static void nv_cursormark(cmdarg_T *cap, int flag, pos_T *pos)
{
if (check_mark(pos) == false) {
@@ -5735,9 +5465,7 @@ static void nv_cursormark(cmdarg_T *cap, int flag, pos_T *pos)
curwin->w_set_curswant = true;
}
-/*
- * Handle commands that are operators in Visual mode.
- */
+/// Handle commands that are operators in Visual mode.
static void v_visop(cmdarg_T *cap)
{
static char_u trans[] = "YyDdCcxdXdAAIIrr";
@@ -5756,9 +5484,7 @@ static void v_visop(cmdarg_T *cap)
nv_operator(cap);
}
-/*
- * "s" and "S" commands.
- */
+/// "s" and "S" commands.
static void nv_subst(cmdarg_T *cap)
{
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
@@ -5777,9 +5503,7 @@ static void nv_subst(cmdarg_T *cap)
}
}
-/*
- * Abbreviated commands.
- */
+/// Abbreviated commands.
static void nv_abbrev(cmdarg_T *cap)
{
if (cap->cmdchar == K_DEL || cap->cmdchar == K_KDEL) {
@@ -5793,9 +5517,7 @@ static void nv_abbrev(cmdarg_T *cap)
}
}
-/*
- * Translate a command into another command.
- */
+/// Translate a command into another command.
static void nv_optrans(cmdarg_T *cap)
{
static const char *(ar[]) = { "dl", "dh", "d$", "c$", "cl", "cc", "yy",
@@ -5811,10 +5533,8 @@ static void nv_optrans(cmdarg_T *cap)
cap->opcount = 0;
}
-/*
- * "'" and "`" commands. Also for "g'" and "g`".
- * cap->arg is true for "'" and "g'".
- */
+/// "'" and "`" commands. Also for "g'" and "g`".
+/// cap->arg is true for "'" and "g'".
static void nv_gomark(cmdarg_T *cap)
{
pos_T *pos;
@@ -5897,9 +5617,7 @@ static void nv_pcmark(cmdarg_T *cap)
}
}
-/*
- * Handle '"' command.
- */
+/// Handle '"' command.
static void nv_regname(cmdarg_T *cap)
{
if (checkclearop(cap->oap)) {
@@ -5917,12 +5635,10 @@ static void nv_regname(cmdarg_T *cap)
}
}
-/*
- * Handle "v", "V" and "CTRL-V" commands.
- * Also for "gh", "gH" and "g^H" commands: Always start Select mode, cap->arg
- * is true.
- * Handle CTRL-Q just like CTRL-V.
- */
+/// Handle "v", "V" and "CTRL-V" commands.
+/// Also for "gh", "gH" and "g^H" commands: Always start Select mode, cap->arg
+/// is true.
+/// Handle CTRL-Q just like CTRL-V.
static void nv_visual(cmdarg_T *cap)
{
if (cap->cmdchar == Ctrl_Q) {
@@ -5963,10 +5679,8 @@ static void nv_visual(cmdarg_T *cap)
if (p_smd && msg_silent == 0) {
redraw_cmdline = true; // show visual mode later
}
- /*
- * For V and ^V, we multiply the number of lines even if there
- * was only one -- webb
- */
+ // For V and ^V, we multiply the number of lines even if there
+ // was only one -- webb
if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1) {
curwin->w_cursor.lnum += resel_VIsual_line_count * cap->count0 - 1;
check_cursor();
@@ -6003,7 +5717,7 @@ static void nv_visual(cmdarg_T *cap)
}
n_start_visual_mode(cap->cmdchar);
if (VIsual_mode != 'V' && *p_sel == 'e') {
- ++cap->count1; // include one more char
+ cap->count1++; // include one more char
}
if (cap->count0 > 0 && --cap->count1 > 0) {
// With a count select that many characters or lines.
@@ -6017,9 +5731,7 @@ static void nv_visual(cmdarg_T *cap)
}
}
-/*
- * Start selection for Shift-movement keys.
- */
+/// Start selection for Shift-movement keys.
void start_selection(void)
{
// if 'selectmode' contains "key", start Select mode
@@ -6027,19 +5739,15 @@ void start_selection(void)
n_start_visual_mode('v');
}
-/*
- * Start Select mode, if "c" is in 'selectmode' and not in a mapping or menu.
- */
+/// Start Select mode, if "c" is in 'selectmode' and not in a mapping or menu.
void may_start_select(int c)
{
VIsual_select = (stuff_empty() && typebuf_typed()
&& (vim_strchr(p_slm, c) != NULL));
}
-/*
- * Start Visual mode "c".
- * Should set VIsual_select before calling this.
- */
+/// Start Visual mode "c".
+/// Should set VIsual_select before calling this.
static void n_start_visual_mode(int c)
{
VIsual_mode = c;
@@ -6073,9 +5781,7 @@ static void n_start_visual_mode(int c)
}
-/*
- * CTRL-W: Window commands
- */
+/// CTRL-W: Window commands
static void nv_window(cmdarg_T *cap)
{
if (cap->nchar == ':') {
@@ -6088,9 +5794,7 @@ static void nv_window(cmdarg_T *cap)
}
}
-/*
- * CTRL-Z: Suspend
- */
+/// CTRL-Z: Suspend
static void nv_suspend(cmdarg_T *cap)
{
clearop(cap->oap);
@@ -6100,9 +5804,7 @@ static void nv_suspend(cmdarg_T *cap)
do_cmdline_cmd("st");
}
-/*
- * Commands starting with "g".
- */
+/// Commands starting with "g".
static void nv_g_cmd(cmdarg_T *cap)
{
oparg_T *oap = cap->oap;
@@ -6138,10 +5840,8 @@ static void nv_g_cmd(cmdarg_T *cap)
do_cmdline_cmd("%s//~/&");
break;
- /*
- * "gv": Reselect the previous Visual area. If Visual already active,
- * exchange previous and current Visual area.
- */
+ // "gv": Reselect the previous Visual area. If Visual already active,
+ // exchange previous and current Visual area.
case 'v':
if (checkclearop(oap)) {
break;
@@ -6197,19 +5897,14 @@ static void nv_g_cmd(cmdarg_T *cap)
showmode();
}
break;
- /*
- * "gV": Don't reselect the previous Visual area after a Select mode
- * mapping of menu.
- */
+ // "gV": Don't reselect the previous Visual area after a Select mode mapping of menu.
case 'V':
VIsual_reselect = false;
break;
- /*
- * "gh": start Select mode.
- * "gH": start Select line mode.
- * "g^H": start Select block mode.
- */
+ // "gh": start Select mode.
+ // "gH": start Select line mode.
+ // "g^H": start Select block mode.
case K_BS:
cap->nchar = Ctrl_H;
FALLTHROUGH;
@@ -6231,10 +5926,8 @@ static void nv_g_cmd(cmdarg_T *cap)
}
break;
- /*
- * "gj" and "gk" two new funny movement keys -- up and down
- * movement based on *screen* line rather than *file* line.
- */
+ // "gj" and "gk" two new funny movement keys -- up and down
+ // movement based on *screen* line rather than *file* line.
case 'j':
case K_DOWN:
// with 'nowrap' it works just like the normal "j" command.
@@ -6263,17 +5956,13 @@ static void nv_g_cmd(cmdarg_T *cap)
}
break;
- /*
- * "gJ": join two lines without inserting a space.
- */
+ // "gJ": join two lines without inserting a space.
case 'J':
nv_join(cap);
break;
- /*
- * "g0", "g^" and "g$": Like "0", "^" and "$" but for screen lines.
- * "gm": middle of "g0" and "g$".
- */
+ // "g0", "g^" and "g$": Like "0", "^" and "$" but for screen lines.
+ // "gm": middle of "g0" and "g$".
case '^':
flag = true;
FALLTHROUGH;
@@ -6328,8 +6017,7 @@ static void nv_g_cmd(cmdarg_T *cap)
break;
case '_':
- /* "g_": to the last non-blank character in the line or <count> lines
- * downward. */
+ // "g_": to the last non-blank character in the line or <count> lines downward.
cap->oap->motion_type = kMTCharWise;
cap->oap->inclusive = true;
curwin->w_curswant = MAXCOL;
@@ -6341,13 +6029,13 @@ static void nv_g_cmd(cmdarg_T *cap)
// In Visual mode we may end up after the line.
if (curwin->w_cursor.col > 0 && ptr[curwin->w_cursor.col] == NUL) {
- --curwin->w_cursor.col;
+ curwin->w_cursor.col--;
}
// Decrease the cursor column until it's on a non-blank.
while (curwin->w_cursor.col > 0
&& ascii_iswhite(ptr[curwin->w_cursor.col])) {
- --curwin->w_cursor.col;
+ curwin->w_cursor.col--;
}
curwin->w_set_curswant = true;
adjust_for_sel(cap);
@@ -6381,13 +6069,11 @@ static void nv_g_cmd(cmdarg_T *cap)
curwin->w_curswant = curwin->w_virtcol;
curwin->w_set_curswant = false;
if (curwin->w_cursor.col > 0 && curwin->w_p_wrap) {
- /*
- * Check for landing on a character that got split at
- * the end of the line. We do not want to advance to
- * the next screen line.
- */
+ // Check for landing on a character that got split at
+ // the end of the line. We do not want to advance to
+ // the next screen line.
if (curwin->w_virtcol > (colnr_T)i) {
- --curwin->w_cursor.col;
+ curwin->w_cursor.col--;
}
}
} else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == false) {
@@ -6409,9 +6095,7 @@ static void nv_g_cmd(cmdarg_T *cap)
}
break;
- /*
- * "g*" and "g#", like "*" and "#" but without using "\<" and "\>"
- */
+ // "g*" and "g#", like "*" and "#" but without using "\<" and "\>"
case '*':
case '#':
#if POUND != '#'
@@ -6422,9 +6106,7 @@ static void nv_g_cmd(cmdarg_T *cap)
nv_ident(cap);
break;
- /*
- * ge and gE: go back to end of word
- */
+ // ge and gE: go back to end of word
case 'e':
case 'E':
oap->motion_type = kMTCharWise;
@@ -6457,9 +6139,7 @@ static void nv_g_cmd(cmdarg_T *cap)
nv_edit(cap);
break;
- /*
- * "gI": Start insert in column 1.
- */
+ // "gI": Start insert in column 1.
case 'I':
beginline(0);
if (!checkclearopq(oap)) {
@@ -6467,10 +6147,8 @@ static void nv_g_cmd(cmdarg_T *cap)
}
break;
- /*
- * "gf": goto file, edit file under cursor
- * "]f" and "[f": can also be used.
- */
+ // "gf": goto file, edit file under cursor
+ // "]f" and "[f": can also be used.
case 'f':
case 'F':
nv_gotofile(cap);
@@ -6484,26 +6162,20 @@ static void nv_g_cmd(cmdarg_T *cap)
nv_gomark(cap);
break;
- /*
- * "gs": Goto sleep.
- */
+ // "gs": Goto sleep.
case 's':
do_sleep(cap->count1 * 1000L);
break;
- /*
- * "ga": Display the ascii value of the character under the
- * cursor. It is displayed in decimal, hex, and octal. -- webb
- */
+ // "ga": Display the ascii value of the character under the
+ // cursor. It is displayed in decimal, hex, and octal. -- webb
case 'a':
do_ascii(NULL);
break;
- /*
- * "g8": Display the bytes used for the UTF-8 character under the
- * cursor. It is displayed in hex.
- * "8g8" finds illegal byte sequence.
- */
+ // "g8": Display the bytes used for the UTF-8 character under the
+ // cursor. It is displayed in hex.
+ // "8g8" finds illegal byte sequence.
case '8':
if (cap->count0 == 8) {
utf_find_illegal();
@@ -6516,25 +6188,21 @@ static void nv_g_cmd(cmdarg_T *cap)
show_sb_text();
break;
- /*
- * "gg": Goto the first line in file. With a count it goes to
- * that line number like for "G". -- webb
- */
+ // "gg": Goto the first line in file. With a count it goes to
+ // that line number like for "G". -- webb
case 'g':
cap->arg = false;
nv_goto(cap);
break;
- /*
- * Two-character operators:
- * "gq" Format text
- * "gw" Format text and keep cursor position
- * "g~" Toggle the case of the text.
- * "gu" Change text to lower case.
- * "gU" Change text to upper case.
- * "g?" rot13 encoding
- * "g@" call 'operatorfunc'
- */
+ // Two-character operators:
+ // "gq" Format text
+ // "gw" Format text and keep cursor position
+ // "g~" Toggle the case of the text.
+ // "gu" Change text to lower case.
+ // "gU" Change text to upper case.
+ // "g?" rot13 encoding
+ // "g@" call 'operatorfunc'
case 'q':
case 'w':
oap->cursor_start = curwin->w_cursor;
@@ -6547,19 +6215,14 @@ static void nv_g_cmd(cmdarg_T *cap)
nv_operator(cap);
break;
- /*
- * "gd": Find first occurrence of pattern under the cursor in the
- * current function
- * "gD": idem, but in the current file.
- */
+ // "gd": Find first occurrence of pattern under the cursor in the current function
+ // "gD": idem, but in the current file.
case 'd':
case 'D':
nv_gd(oap, cap->nchar, (int)cap->count0);
break;
- /*
- * g<*Mouse> : <C-*mouse>
- */
+ // g<*Mouse> : <C-*mouse>
case K_MIDDLEMOUSE:
case K_MIDDLEDRAG:
case K_MIDDLERELEASE:
@@ -6583,9 +6246,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case K_IGNORE:
break;
- /*
- * "gP" and "gp": same as "P" and "p" but leave cursor just after new text
- */
+ // "gP" and "gp": same as "P" and "p" but leave cursor just after new text
case 'p':
case 'P':
nv_put(cap);
@@ -6649,9 +6310,7 @@ static void nv_g_cmd(cmdarg_T *cap)
}
}
-/*
- * Handle "o" and "O" commands.
- */
+/// Handle "o" and "O" commands.
static void n_opencmd(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
@@ -6681,17 +6340,13 @@ static void n_opencmd(cmdarg_T *cap)
}
}
-/*
- * "." command: redo last change.
- */
+/// "." command: redo last change.
static void nv_dot(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
- /*
- * If "restart_edit" is true, the last but one command is repeated
- * instead of the last command (inserting text). This is used for
- * CTRL-O <.> in insert mode.
- */
+ // If "restart_edit" is true, the last but one command is repeated
+ // instead of the last command (inserting text). This is used for
+ // CTRL-O <.> in insert mode.
if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == false) {
clearopbeep(cap->oap);
}
@@ -6724,9 +6379,7 @@ static void nv_redo_or_register(cmdarg_T *cap)
}
}
-/*
- * Handle "U" command.
- */
+/// Handle "U" command.
static void nv_Undo(cmdarg_T *cap)
{
// In Visual mode and typing "gUU" triggers an operator
@@ -6742,10 +6395,8 @@ static void nv_Undo(cmdarg_T *cap)
}
}
-/*
- * '~' command: If tilde is not an operator and Visual is off: swap case of a
- * single character.
- */
+/// '~' command: If tilde is not an operator and Visual is off: swap case of a
+/// single character.
static void nv_tilde(cmdarg_T *cap)
{
if (!p_to
@@ -6761,10 +6412,8 @@ static void nv_tilde(cmdarg_T *cap)
}
}
-/*
- * Handle an operator command.
- * The actual work is done by do_pending_operator().
- */
+/// Handle an operator command.
+/// The actual work is done by do_pending_operator().
static void nv_operator(cmdarg_T *cap)
{
int op_type;
@@ -6786,9 +6435,7 @@ static void nv_operator(cmdarg_T *cap)
}
}
-/*
- * Set v:operator to the characters for "optype".
- */
+/// Set v:operator to the characters for "optype".
static void set_op_var(int optype)
{
if (optype == OP_NOP) {
@@ -6808,15 +6455,13 @@ static void set_op_var(int optype)
}
}
-/*
- * Handle linewise operator "dd", "yy", etc.
- *
- * "_" is is a strange motion command that helps make operators more logical.
- * It is actually implemented, but not documented in the real Vi. This motion
- * command actually refers to "the current line". Commands like "dd" and "yy"
- * are really an alternate form of "d_" and "y_". It does accept a count, so
- * "d3_" works to delete 3 lines.
- */
+/// Handle linewise operator "dd", "yy", etc.
+///
+/// "_" is is a strange motion command that helps make operators more logical.
+/// It is actually implemented, but not documented in the real Vi. This motion
+/// command actually refers to "the current line". Commands like "dd" and "yy"
+/// are really an alternate form of "d_" and "y_". It does accept a count, so
+/// "d3_" works to delete 3 lines.
static void nv_lineop(cmdarg_T *cap)
{
cap->oap->motion_type = kMTLineWise;
@@ -6834,9 +6479,7 @@ static void nv_lineop(cmdarg_T *cap)
}
}
-/*
- * <Home> command.
- */
+/// <Home> command.
static void nv_home(cmdarg_T *cap)
{
// CTRL-HOME is like "gg"
@@ -6850,9 +6493,7 @@ static void nv_home(cmdarg_T *cap)
// one-character line).
}
-/*
- * "|" command.
- */
+/// "|" command.
static void nv_pipe(cmdarg_T *cap)
{
cap->oap->motion_type = kMTCharWise;
@@ -6869,10 +6510,8 @@ static void nv_pipe(cmdarg_T *cap)
curwin->w_set_curswant = false;
}
-/*
- * Handle back-word command "b" and "B".
- * cap->arg is 1 for "B"
- */
+/// Handle back-word command "b" and "B".
+/// cap->arg is 1 for "B"
static void nv_bck_word(cmdarg_T *cap)
{
cap->oap->motion_type = kMTCharWise;
@@ -6885,10 +6524,8 @@ static void nv_bck_word(cmdarg_T *cap)
}
}
-/*
- * Handle word motion commands "e", "E", "w" and "W".
- * cap->arg is true for "E" and "W".
- */
+/// Handle word motion commands "e", "E", "w" and "W".
+/// cap->arg is true for "E" and "W".
static void nv_wordcmd(cmdarg_T *cap)
{
int n;
@@ -6896,9 +6533,7 @@ static void nv_wordcmd(cmdarg_T *cap)
bool flag = false;
pos_T startpos = curwin->w_cursor;
- /*
- * Set inclusive for the "E" and "e" command.
- */
+ // Set inclusive for the "E" and "e" command.
if (cap->cmdchar == 'e' || cap->cmdchar == 'E') {
word_end = true;
} else {
@@ -6906,9 +6541,7 @@ static void nv_wordcmd(cmdarg_T *cap)
}
cap->oap->inclusive = word_end;
- /*
- * "cw" and "cW" are a special case.
- */
+ // "cw" and "cW" are a special case.
if (!word_end && cap->oap->op_type == OP_CHANGE) {
n = gchar_cursor();
if (n != NUL && !ascii_iswhite(n)) {
@@ -6952,11 +6585,9 @@ static void nv_wordcmd(cmdarg_T *cap)
}
}
-/*
- * Used after a movement command: If the cursor ends up on the NUL after the
- * end of the line, may move it back to the last character and make the motion
- * inclusive.
- */
+/// Used after a movement command: If the cursor ends up on the NUL after the
+/// end of the line, may move it back to the last character and make the motion
+/// inclusive.
static void adjust_cursor(oparg_T *oap)
{
// The cursor cannot remain on the NUL when:
@@ -6974,10 +6605,8 @@ static void adjust_cursor(oparg_T *oap)
}
}
-/*
- * "0" and "^" commands.
- * cap->arg is the argument for beginline().
- */
+/// "0" and "^" commands.
+/// cap->arg is the argument for beginline().
static void nv_beginline(cmdarg_T *cap)
{
cap->oap->motion_type = kMTCharWise;
@@ -6990,9 +6619,7 @@ static void nv_beginline(cmdarg_T *cap)
// one-character line).
}
-/*
- * In exclusive Visual mode, may include the last character.
- */
+/// In exclusive Visual mode, may include the last character.
static void adjust_for_sel(cmdarg_T *cap)
{
if (VIsual_active && cap->oap->inclusive && *p_sel == 'e'
@@ -7002,11 +6629,10 @@ static void adjust_for_sel(cmdarg_T *cap)
}
}
-/*
- * Exclude last character at end of Visual area for 'selection' == "exclusive".
- * Should check VIsual_mode before calling this.
- * Returns true when backed up to the previous line.
- */
+/// Exclude last character at end of Visual area for 'selection' == "exclusive".
+/// Should check VIsual_mode before calling this.
+///
+/// @return true when backed up to the previous line.
bool unadjust_for_sel(void)
{
pos_T *pp;
@@ -7023,7 +6649,7 @@ bool unadjust_for_sel(void)
pp->col--;
mark_mb_adjustpos(curbuf, pp);
} else if (pp->lnum > 1) {
- --pp->lnum;
+ pp->lnum--;
pp->col = (colnr_T)STRLEN(ml_get(pp->lnum));
return true;
}
@@ -7031,9 +6657,7 @@ bool unadjust_for_sel(void)
return false;
}
-/*
- * SELECT key in Normal or Visual mode: end of Select mode mapping.
- */
+/// SELECT key in Normal or Visual mode: end of Select mode mapping.
static void nv_select(cmdarg_T *cap)
{
if (VIsual_active) {
@@ -7047,10 +6671,8 @@ static void nv_select(cmdarg_T *cap)
}
-/*
- * "G", "gg", CTRL-END, CTRL-HOME.
- * cap->arg is true for "G".
- */
+/// "G", "gg", CTRL-END, CTRL-HOME.
+/// cap->arg is true for "G".
static void nv_goto(cmdarg_T *cap)
{
linenr_T lnum;
@@ -7079,9 +6701,7 @@ static void nv_goto(cmdarg_T *cap)
}
}
-/*
- * CTRL-\ in Normal mode.
- */
+/// CTRL-\ in Normal mode.
static void nv_normal(cmdarg_T *cap)
{
if (cap->nchar == Ctrl_N || cap->nchar == Ctrl_G) {
@@ -7106,10 +6726,8 @@ static void nv_normal(cmdarg_T *cap)
}
}
-/*
- * ESC in Normal mode: beep, but don't flush buffers.
- * Don't even beep if we are canceling a command.
- */
+/// ESC in Normal mode: beep, but don't flush buffers.
+/// Don't even beep if we are canceling a command.
static void nv_esc(cmdarg_T *cap)
{
int no_reason;
@@ -7271,9 +6889,7 @@ static void invoke_edit(cmdarg_T *cap, int repl, int cmd, int startln)
}
}
-/*
- * "a" or "i" while an operator is pending or in Visual mode: object motion.
- */
+/// "a" or "i" while an operator is pending or in Visual mode: object motion.
static void nv_object(cmdarg_T *cap)
{
bool flag;
@@ -7349,10 +6965,8 @@ static void nv_object(cmdarg_T *cap)
curwin->w_set_curswant = true;
}
-/*
- * "q" command: Start/stop recording.
- * "q:", "q/", "q?": edit command-line in command-line window.
- */
+/// "q" command: Start/stop recording.
+/// "q:", "q/", "q?": edit command-line in command-line window.
static void nv_record(cmdarg_T *cap)
{
if (cap->oap->op_type == OP_FORMAT) {
@@ -7374,9 +6988,7 @@ static void nv_record(cmdarg_T *cap)
}
}
-/*
- * Handle the "@r" command.
- */
+/// Handle the "@r" command.
static void nv_at(cmdarg_T *cap)
{
if (checkclearop(cap->oap)) {
@@ -7396,9 +7008,7 @@ static void nv_at(cmdarg_T *cap)
}
}
-/*
- * Handle the CTRL-U and CTRL-D commands.
- */
+/// Handle the CTRL-U and CTRL-D commands.
static void nv_halfpage(cmdarg_T *cap)
{
if ((cap->cmdchar == Ctrl_U && curwin->w_cursor.lnum == 1)
@@ -7410,9 +7020,7 @@ static void nv_halfpage(cmdarg_T *cap)
}
}
-/*
- * Handle "J" or "gJ" command.
- */
+/// Handle "J" or "gJ" command.
static void nv_join(cmdarg_T *cap)
{
if (VIsual_active) { // join the visual lines
@@ -7437,9 +7045,7 @@ static void nv_join(cmdarg_T *cap)
}
}
-/*
- * "P", "gP", "p" and "gp" commands.
- */
+/// "P", "gP", "p" and "gp" commands.
static void nv_put(cmdarg_T *cap)
{
nv_put_opt(cap, false);
@@ -7586,9 +7192,7 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
}
}
-/*
- * "o" and "O" commands.
- */
+/// "o" and "O" commands.
static void nv_open(cmdarg_T *cap)
{
// "do" is ":diffget"
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index badc00fb39..36c2513810 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -636,7 +636,7 @@ static void block_insert(oparg_T *oap, char_u *s, int b_insert, struct block_def
*/
void op_reindent(oparg_T *oap, Indenter how)
{
- long i;
+ long i = 0;
char_u *l;
int amount;
linenr_T first_changed = 0;
@@ -649,38 +649,41 @@ void op_reindent(oparg_T *oap, Indenter how)
return;
}
- for (i = oap->line_count - 1; i >= 0 && !got_int; i--) {
- /* it's a slow thing to do, so give feedback so there's no worry that
- * the computer's just hung. */
-
- if (i > 1
- && (i % 50 == 0 || i == oap->line_count - 1)
- && oap->line_count > p_report) {
- smsg(_("%" PRId64 " lines to indent... "), (int64_t)i);
- }
+ // Save for undo. Do this once for all lines, much faster than doing this
+ // for each line separately, especially when undoing.
+ if (u_savecommon(curbuf, start_lnum - 1, start_lnum + oap->line_count,
+ start_lnum + oap->line_count, false) == OK) {
+ for (i = oap->line_count - 1; i >= 0 && !got_int; i--) {
+ // it's a slow thing to do, so give feedback so there's no worry
+ // that the computer's just hung.
- /*
- * Be vi-compatible: For lisp indenting the first line is not
- * indented, unless there is only one line.
- */
- if (i != oap->line_count - 1 || oap->line_count == 1
- || how != get_lisp_indent) {
- l = skipwhite(get_cursor_line_ptr());
- if (*l == NUL) { // empty or blank line
- amount = 0;
- } else {
- amount = how(); // get the indent for this line
+ if (i > 1
+ && (i % 50 == 0 || i == oap->line_count - 1)
+ && oap->line_count > p_report) {
+ smsg(_("%" PRId64 " lines to indent... "), (int64_t)i);
}
- if (amount >= 0 && set_indent(amount, SIN_UNDO)) {
- // did change the indent, call changed_lines() later
- if (first_changed == 0) {
- first_changed = curwin->w_cursor.lnum;
+
+ // Be vi-compatible: For lisp indenting the first line is not
+ // indented, unless there is only one line.
+ if (i != oap->line_count - 1 || oap->line_count == 1
+ || how != get_lisp_indent) {
+ l = skipwhite(get_cursor_line_ptr());
+ if (*l == NUL) { // empty or blank line
+ amount = 0;
+ } else {
+ amount = how(); // get the indent for this line
+ }
+ if (amount >= 0 && set_indent(amount, 0)) {
+ // did change the indent, call changed_lines() later
+ if (first_changed == 0) {
+ first_changed = curwin->w_cursor.lnum;
+ }
+ last_changed = curwin->w_cursor.lnum;
}
- last_changed = curwin->w_cursor.lnum;
}
+ curwin->w_cursor.lnum++;
+ curwin->w_cursor.col = 0; // make sure it's valid
}
- ++curwin->w_cursor.lnum;
- curwin->w_cursor.col = 0; // make sure it's valid
}
// put cursor on first non-blank of indented line
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 3aa76f7767..37594340de 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -262,8 +262,8 @@ typedef struct vimoption {
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \
- "i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr," \
- "G:CursorLineSign,O:CursorLineFold" \
+ "i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow," \
+ "N:CursorLineNr,G:CursorLineSign,O:CursorLineFold" \
"r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg," \
"W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn," \
"-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar," \
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index f8d2d37a91..a12fb70388 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2313,7 +2313,10 @@ static bool qflist_valid(win_T *wp, unsigned int qf_id)
qf_info_T *qi = &ql_info;
if (wp) {
- qi = GET_LOC_LIST(wp);
+ if (!win_valid(wp)) {
+ return false;
+ }
+ qi = GET_LOC_LIST(wp); // Location list
if (!qi) {
return false;
}
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 228145ec4d..13be82a71d 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -2695,9 +2695,9 @@ func Test_autocmd_closes_window()
au BufNew,BufWinLeave * e %e
file yyy
au BufNew,BufWinLeave * ball
- call assert_fails('n xxx', 'E143:')
+ n xxx
- bwipe %
+ %bwipe
au! BufNew
au! BufWinLeave
endfunc
@@ -2713,9 +2713,34 @@ func Test_autocmd_quit_psearch()
augroup aucmd_win_test
au!
augroup END
+ new
+ pclose
+endfunc
+
+" Fuzzer found some strange combination that caused a crash.
+func Test_autocmd_normal_mess()
+ " For unknown reason this hangs on MS-Windows
+ CheckNotMSWindows
+
+ augroup aucmd_normal_test
+ au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc
+ augroup END
+ " Nvim has removed :open
+ " call assert_fails('o4', 'E1159')
+ call assert_fails('e4', 'E1159')
+ silent! H
+ call assert_fails('e xx', 'E1159')
+ normal G
+
+ augroup aucmd_normal_test
+ au!
+ augroup END
endfunc
func Test_autocmd_closing_cmdwin()
+ " For unknown reason this hangs on MS-Windows
+ CheckNotMSWindows
+
au BufWinLeave * nested q
call assert_fails("norm 7q?\n", 'E855:')
@@ -2724,6 +2749,20 @@ func Test_autocmd_closing_cmdwin()
only
endfunc
+func Test_autocmd_vimgrep()
+ augroup aucmd_vimgrep
+ au QuickfixCmdPre,BufNew,BufReadCmd * sb
+ " Nvim makes aucmd_win the last window
+ " au QuickfixCmdPre,BufNew,BufReadCmd * q9
+ au QuickfixCmdPre,BufNew,BufReadCmd * exe 'q' .. (winnr('$') - (win_gettype(winnr('$')) == 'autocmd'))
+ augroup END
+ call assert_fails('lv ?a? foo', 'E926:')
+
+ augroup aucmd_vimgrep
+ au!
+ augroup END
+endfunc
+
func Test_bufwipeout_changes_window()
" This should not crash, but we don't have any expectations about what
" happens, changing window in BufWipeout has unpredictable results.
@@ -2759,4 +2798,22 @@ func Test_v_event_readonly()
endfunc
+func Test_noname_autocmd()
+ augroup test_noname_autocmd_group
+ autocmd!
+ autocmd BufEnter * call add(s:li, ["BufEnter", expand("<afile>")])
+ autocmd BufDelete * call add(s:li, ["BufDelete", expand("<afile>")])
+ autocmd BufLeave * call add(s:li, ["BufLeave", expand("<afile>")])
+ autocmd BufUnload * call add(s:li, ["BufUnload", expand("<afile>")])
+ autocmd BufWipeout * call add(s:li, ["BufWipeout", expand("<afile>")])
+ augroup END
+
+ let s:li = []
+ edit foo
+ call assert_equal([['BufUnload', ''], ['BufDelete', ''], ['BufWipeout', ''], ['BufEnter', 'foo']], s:li)
+
+ au! test_noname_autocmd_group
+ augroup! test_noname_autocmd_group
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_bufwintabinfo.vim b/src/nvim/testdir/test_bufwintabinfo.vim
index a6eb93b4be..326aefb731 100644
--- a/src/nvim/testdir/test_bufwintabinfo.vim
+++ b/src/nvim/testdir/test_bufwintabinfo.vim
@@ -145,6 +145,13 @@ function Test_get_win_options()
endif
endfunc
+function Test_getbufinfo_lastused()
+ new Xfoo
+ let info = getbufinfo('Xfoo')[0]
+ call assert_equal(has_key(info, 'lastused'), 1)
+ call assert_equal(type(info.lastused), type(0))
+endfunc
+
func Test_getbufinfo_lines()
new Xfoo
call setline(1, ['a', 'bc', 'd'])
@@ -155,9 +162,26 @@ func Test_getbufinfo_lines()
bw!
endfunc
-function Test_getbufinfo_lastused()
- new Xfoo
- let info = getbufinfo('Xfoo')[0]
- call assert_equal(has_key(info, 'lastused'), 1)
- call assert_equal(type(info.lastused), type(0))
+func Test_getwininfo_au()
+ enew
+ call setline(1, range(1, 16))
+
+ let g:info = #{}
+ augroup T1
+ au!
+ au WinEnter * let g:info = getwininfo(win_getid())[0]
+ augroup END
+
+ 4split
+ " Check that calling getwininfo() from WinEnter returns fresh values for
+ " topline and botline.
+ call assert_equal(1, g:info.topline)
+ call assert_equal(4, g:info.botline)
+ close
+
+ unlet g:info
+ augroup! T1
+ bwipe!
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_cursorline.vim b/src/nvim/testdir/test_cursorline.vim
index 7e97df6027..e85e9304a3 100644
--- a/src/nvim/testdir/test_cursorline.vim
+++ b/src/nvim/testdir/test_cursorline.vim
@@ -314,5 +314,41 @@ func Test_cursorline_screenline_update()
call delete('Xcul_screenline')
endfunc
+func Test_cursorline_cursorbind_horizontal_scroll()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, 'aa bb cc dd ee ff gg hh ii jj kk ll mm' ..
+ \ ' nn oo pp qq rr ss tt uu vv ww xx yy zz')
+ set nowrap
+ " The following makes the cursor apparent on the screen dump
+ set sidescroll=1 cursorcolumn
+ " add empty lines, required for cursorcolumn
+ call append(1, ['','','',''])
+ 20vsp
+ windo :set cursorbind
+ END
+ call writefile(lines, 'Xhor_scroll')
+
+ let buf = RunVimInTerminal('-S Xhor_scroll', #{rows: 8})
+ call term_sendkeys(buf, "20l")
+ call VerifyScreenDump(buf, 'Test_hor_scroll_1', {})
+ call term_sendkeys(buf, "10l")
+ call VerifyScreenDump(buf, 'Test_hor_scroll_2', {})
+ call term_sendkeys(buf, ":windo :set cursorline\<cr>")
+ call term_sendkeys(buf, "0")
+ call term_sendkeys(buf, "20l")
+ call VerifyScreenDump(buf, 'Test_hor_scroll_3', {})
+ call term_sendkeys(buf, "10l")
+ call VerifyScreenDump(buf, 'Test_hor_scroll_4', {})
+ call term_sendkeys(buf, ":windo :set nocursorline nocursorcolumn\<cr>")
+ call term_sendkeys(buf, "0")
+ call term_sendkeys(buf, "40l")
+ call VerifyScreenDump(buf, 'Test_hor_scroll_5', {})
+
+ call StopVimInTerminal(buf)
+ call delete('Xhor_scroll')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_ex_mode.vim b/src/nvim/testdir/test_ex_mode.vim
index dcec5f7cc6..0ce333fa40 100644
--- a/src/nvim/testdir/test_ex_mode.vim
+++ b/src/nvim/testdir/test_ex_mode.vim
@@ -51,6 +51,13 @@ func Test_ex_mode()
call assert_equal([' foo', ' foo'], Ex(" foo\<C-d>"), e)
call assert_equal(['foo', ' foo0'], Ex(" foo0\<C-d>"), e)
call assert_equal(['foo', ' foo^'], Ex(" foo^\<C-d>"), e)
+ call assert_equal(['foo', 'foo'],
+ \ Ex("\<BS>\<C-H>\<Del>\<kDel>foo"), e)
+ " default wildchar <Tab> interferes with this test
+ set wildchar=<c-e>
+ call assert_equal(["a\tb", "a\tb"], Ex("a\t\t\<C-H>b"), e)
+ call assert_equal(["\t mn", "\tm\<C-T>n"], Ex("\tm\<C-T>n"), e)
+ set wildchar&
endfor
set sw&
diff --git a/src/nvim/testdir/test_expand_func.vim b/src/nvim/testdir/test_expand_func.vim
index 44d2c156d5..b48c2e8a19 100644
--- a/src/nvim/testdir/test_expand_func.vim
+++ b/src/nvim/testdir/test_expand_func.vim
@@ -37,15 +37,6 @@ func Test_expand_sflnum()
delcommand Flnum
endfunc
-func Test_expand()
- new
- call assert_equal("", expand('%:S'))
- call assert_equal('3', '<slnum>'->expand())
- call assert_equal(['4'], expand('<slnum>', v:false, v:true))
- " Don't add any line above this, otherwise <slnum> will change.
- quit
-endfunc
-
func Test_expand_sfile()
call assert_match('test_expand_func\.vim$', s:sfile)
call assert_match('^function .*\.\.Test_expand_sfile$', expand('<sfile>'))
@@ -77,6 +68,15 @@ func Test_expand_slnum()
delcommand Slnum
endfunc
+func Test_expand()
+ new
+ call assert_equal("", expand('%:S'))
+ call assert_equal('3', '<slnum>'->expand())
+ call assert_equal(['4'], expand('<slnum>', v:false, v:true))
+ " Don't add any line above this, otherwise <slnum> will change.
+ quit
+endfunc
+
func s:sid_test()
return 'works'
endfunc
@@ -87,4 +87,17 @@ func Test_expand_SID()
call assert_equal('works', g:sid_result)
endfunc
+
+" Test for 'wildignore' with expand()
+func Test_expand_wildignore()
+ set wildignore=*.vim
+ call assert_equal('', expand('test_expand_func.vim'))
+ call assert_equal('', expand('test_expand_func.vim', 0))
+ call assert_equal([], expand('test_expand_func.vim', 0, 1))
+ call assert_equal('test_expand_func.vim', expand('test_expand_func.vim', 1))
+ call assert_equal(['test_expand_func.vim'],
+ \ expand('test_expand_func.vim', 1, 1))
+ set wildignore&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index f2e635004e..7a52d0a044 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -337,6 +337,8 @@ let s:filename_checks = {
\ 'markdown': ['file.markdown', 'file.mdown', 'file.mkd', 'file.mkdn', 'file.mdwn', 'file.md'],
\ 'mason': ['file.mason', 'file.mhtml', 'file.comp'],
\ 'master': ['file.mas', 'file.master'],
+ \ 'maxima': ['file.demo', 'file.dmt', 'file.dm1', 'file.dm2', 'file.dm3',
+ \ 'file.wxm', 'maxima-init.mac'],
\ 'mel': ['file.mel'],
\ 'meson': ['meson.build', 'meson_options.txt'],
\ 'messages': ['/log/auth', '/log/cron', '/log/daemon', '/log/debug', '/log/kern', '/log/lpr', '/log/mail', '/log/messages', '/log/news/news', '/log/syslog', '/log/user',
diff --git a/src/nvim/testdir/test_indent.vim b/src/nvim/testdir/test_indent.vim
new file mode 100644
index 0000000000..516b3fbdd1
--- /dev/null
+++ b/src/nvim/testdir/test_indent.vim
@@ -0,0 +1,124 @@
+" Test for various indent options
+
+func Test_preserveindent()
+ new
+ " Test for autoindent copying indent from the previous line
+ setlocal autoindent
+ call setline(1, [repeat(' ', 16) .. 'line1'])
+ call feedkeys("A\nline2", 'xt')
+ call assert_equal("\t\tline2", getline(2))
+ setlocal autoindent&
+
+ " Test for using CTRL-T with and without 'preserveindent'
+ set shiftwidth=4
+ call cursor(1, 1)
+ call setline(1, " \t ")
+ call feedkeys("Al\<C-T>", 'xt')
+ call assert_equal("\t\tl", getline(1))
+ set preserveindent
+ call setline(1, " \t ")
+ call feedkeys("Al\<C-T>", 'xt')
+ call assert_equal(" \t \tl", getline(1))
+ set pi& sw&
+
+ " Test for using CTRL-T with 'expandtab' and 'preserveindent'
+ call cursor(1, 1)
+ call setline(1, "\t \t")
+ set shiftwidth=4 expandtab preserveindent
+ call feedkeys("Al\<C-T>", 'xt')
+ call assert_equal("\t \t l", getline(1))
+ set sw& et& pi&
+
+ close!
+endfunc
+
+" Test for indent()
+func Test_indent_func()
+ call assert_equal(-1, indent(-1))
+ new
+ call setline(1, "\tabc")
+ call assert_equal(8, indent(1))
+ call setline(1, " abc")
+ call assert_equal(4, indent(1))
+ call setline(1, " \t abc")
+ call assert_equal(12, indent(1))
+ close!
+endfunc
+
+" Test for reindenting a line using the '=' operator
+func Test_reindent()
+ new
+ call setline(1, 'abc')
+ set nomodifiable
+ call assert_fails('normal ==', 'E21:')
+ set modifiable
+
+ call setline(1, ['foo', 'bar'])
+ call feedkeys('ggVG=', 'xt')
+ call assert_equal(['foo', 'bar'], getline(1, 2))
+ close!
+endfunc
+
+" Test indent operator creating one undo entry
+func Test_indent_operator_undo()
+ enew
+ call setline(1, range(12)->map('"\t" .. v:val'))
+ func FoldExpr()
+ let g:foldcount += 1
+ return '='
+ endfunc
+ set foldmethod=expr foldexpr=FoldExpr()
+ let g:foldcount = 0
+ redraw
+ call assert_equal(12, g:foldcount)
+ normal gg=G
+ call assert_equal(24, g:foldcount)
+ undo
+ call assert_equal(38, g:foldcount)
+
+ bwipe!
+ set foldmethod& foldexpr=
+ delfunc FoldExpr
+ unlet g:foldcount
+endfunc
+
+" Test for shifting a line with a preprocessor directive ('#')
+func Test_preproc_indent()
+ new
+ set sw=4
+ call setline(1, '#define FOO 1')
+ normal >>
+ call assert_equal(' #define FOO 1', getline(1))
+
+ " with 'smartindent'
+ call setline(1, '#define FOO 1')
+ set smartindent
+ normal >>
+ call assert_equal('#define FOO 1', getline(1))
+ set smartindent&
+
+ " with 'cindent'
+ set cindent
+ normal >>
+ call assert_equal('#define FOO 1', getline(1))
+ set cindent&
+
+ close!
+endfunc
+
+" Test for 'copyindent'
+func Test_copyindent()
+ new
+ set shiftwidth=4 autoindent expandtab copyindent
+ call setline(1, " \t abc")
+ call feedkeys("ol", 'xt')
+ call assert_equal(" \t l", getline(2))
+ set noexpandtab
+ call setline(1, " \t abc")
+ call feedkeys("ol", 'xt')
+ call assert_equal(" \t l", getline(2))
+ set sw& ai& et& ci&
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_lispwords.vim b/src/nvim/testdir/test_lispwords.vim
index aa5a738bdf..ff710b2716 100644
--- a/src/nvim/testdir/test_lispwords.vim
+++ b/src/nvim/testdir/test_lispwords.vim
@@ -45,6 +45,7 @@ func Test_lisp_indent()
\ ])
call assert_equal(7, lispindent(2))
call assert_equal(5, 6->lispindent())
+ call assert_equal(-1, lispindent(-1))
set lisp
set lispwords&
@@ -83,3 +84,5 @@ func Test_lisp_indent()
let &cpoptions=save_copt
set nolisp
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim
index 8154bd9c4d..d359e69f91 100644
--- a/src/nvim/testdir/test_search.vim
+++ b/src/nvim/testdir/test_search.vim
@@ -946,6 +946,51 @@ func Test_incsearch_substitute()
call Incsearch_cleanup()
endfunc
+func Test_hlsearch_cursearch()
+ CheckScreendump
+
+ let lines =<< trim END
+ set hlsearch scrolloff=0
+ call setline(1, ['one', 'foo', 'bar', 'baz', 'foo the foo and foo', 'bar'])
+ hi Search ctermbg=yellow
+ hi CurSearch ctermbg=blue
+ END
+ call writefile(lines, 'Xhlsearch_cursearch')
+ let buf = RunVimInTerminal('-S Xhlsearch_cursearch', {'rows': 9, 'cols': 60})
+
+ call term_sendkeys(buf, "gg/foo\<CR>")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_1', {})
+
+ call term_sendkeys(buf, "n")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_2', {})
+
+ call term_sendkeys(buf, "n")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_2a', {})
+
+ call term_sendkeys(buf, "n")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_2b', {})
+
+ call term_sendkeys(buf, ":call setline(5, 'foo')\<CR>")
+ call term_sendkeys(buf, "0?\<CR>")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_3', {})
+
+ call term_sendkeys(buf, "gg/foo\\nbar\<CR>")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_multiple_line_1', {})
+
+ call term_sendkeys(buf, ":call setline(1, ['---', 'abcdefg', 'hijkl', '---', 'abcdefg', 'hijkl'])\<CR>")
+ call term_sendkeys(buf, "gg/efg\\nhij\<CR>")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_multiple_line_2', {})
+ call term_sendkeys(buf, "h\<C-L>")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_multiple_line_3', {})
+ call term_sendkeys(buf, "j\<C-L>")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_multiple_line_4', {})
+ call term_sendkeys(buf, "h\<C-L>")
+ call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_multiple_line_5', {})
+
+ call StopVimInTerminal(buf)
+ call delete('Xhlsearch_cursearch')
+endfunc
+
" Similar to Test_incsearch_substitute() but with a screendump halfway.
func Test_incsearch_substitute_dump()
CheckOption incsearch
diff --git a/src/nvim/testdir/test_smartindent.vim b/src/nvim/testdir/test_smartindent.vim
index e89ad19d34..dc0f99e93f 100644
--- a/src/nvim/testdir/test_smartindent.vim
+++ b/src/nvim/testdir/test_smartindent.vim
@@ -38,4 +38,27 @@ func Test_smartindent_has_no_effect()
bwipe!
endfunc
+" Test for inserting '{' and '} with smartindent
+func Test_smartindent_braces()
+ new
+ set smartindent shiftwidth=4
+ call setline(1, [' if (a)', "\tif (b)", "\t return 1"])
+ normal 2ggO{
+ normal 3ggA {
+ normal 4ggo}
+ normal o}
+ normal 4ggO#define FOO 1
+ call assert_equal([
+ \ ' if (a)',
+ \ ' {',
+ \ "\tif (b) {",
+ \ '#define FOO 1',
+ \ "\t return 1",
+ \ "\t}",
+ \ ' }'
+ \ ], getline(1, '$'))
+ set si& sw& ai&
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_vartabs.vim b/src/nvim/testdir/test_vartabs.vim
index 017bb6675d..6af199a512 100644
--- a/src/nvim/testdir/test_vartabs.vim
+++ b/src/nvim/testdir/test_vartabs.vim
@@ -92,6 +92,18 @@ func Test_vartabs()
let expect = "l\<tab> l\<tab>l l\<tab> l\<tab> l"
call assert_equal(expect, getline(1))
+ " Test for 'retab' with vts
+ set ts=8 sts=0 vts=5,3,6,2 vsts=
+ exe "norm! S l"
+ .retab!
+ call assert_equal("\t\t\t\tl", getline(1))
+
+ " Test for 'retab' with same vlaues as vts
+ set ts=8 sts=0 vts=5,3,6,2 vsts=
+ exe "norm! S l"
+ .retab! 5,3,6,2
+ call assert_equal("\t\t\t\tl", getline(1))
+
" Check that global and local values are set.
set ts=4 vts=6 sts=8 vsts=10
call assert_equal(&ts, 4)
@@ -389,3 +401,33 @@ func Test_vartabs_reset()
set all&
call assert_equal('', &vts)
endfunc
+
+func s:SaveCol(l)
+ call add(a:l, [col('.'), virtcol('.')])
+ return ''
+endfunc
+
+" Test for 'varsofttabstop'
+func Test_varsofttabstop()
+ new
+ inoremap <expr> <F2> s:SaveCol(g:cols)
+
+ set backspace=indent,eol,start
+ set varsofttabstop=6,2,5,3
+ let g:cols = []
+ call feedkeys("a\t\<F2>\t\<F2>\t\<F2>\t\<F2> ", 'xt')
+ call assert_equal("\t\t ", getline(1))
+ call assert_equal([[7, 7], [2, 9], [7, 14], [3, 17]], g:cols)
+
+ let g:cols = []
+ call feedkeys("a\<bs>\<F2>\<bs>\<F2>\<bs>\<F2>\<bs>\<F2>\<bs>\<F2>", 'xt')
+ call assert_equal('', getline(1))
+ call assert_equal([[3, 17], [7, 14], [2, 9], [7, 7], [1, 1]], g:cols)
+
+ set varsofttabstop&
+ set backspace&
+ iunmap <F2>
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim
index ef6dec580f..798122dc5d 100644
--- a/src/nvim/testdir/test_window_cmd.vim
+++ b/src/nvim/testdir/test_window_cmd.vim
@@ -513,14 +513,15 @@ func Test_window_colon_command()
endfunc
func Test_access_freed_mem()
+ call assert_equal(&columns, winwidth(0))
" This was accessing freed memory (but with what events?)
au BufEnter,BufLeave,WinEnter,WinLeave 0 vs xxx
arg 0
argadd
- all
- all
+ call assert_fails("all", "E242:")
au!
bwipe xxx
+ call assert_equal(&columns, winwidth(0))
endfunc
func Test_visual_cleared_after_window_split()
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 2ca5128445..f68cfe4c9c 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -72,8 +72,40 @@ typedef enum {
WEE_TRIGGER_LEAVE_AUTOCMDS = 0x10,
} wee_flags_T;
+static char e_cannot_split_window_when_closing_buffer[]
+ = N_("E1159: Cannot split a window when closing the buffer");
+
static char *m_onlyone = N_("Already only one window");
+/// When non-zero splitting a window is forbidden. Used to avoid that nasty
+/// autocommands mess up the window structure.
+static int split_disallowed = 0;
+
+// #define WIN_DEBUG
+#ifdef WIN_DEBUG
+/// Call this method to log the current window layout.
+static void log_frame_layout(frame_T *frame)
+{
+ DLOG("layout %s, wi: %d, he: %d, wwi: %d, whe: %d, id: %d",
+ frame->fr_layout == FR_LEAF ? "LEAF" : frame->fr_layout == FR_ROW ? "ROW" : "COL",
+ frame->fr_width,
+ frame->fr_height,
+ frame->fr_win == NULL ? -1 : frame->fr_win->w_width,
+ frame->fr_win == NULL ? -1 : frame->fr_win->w_height,
+ frame->fr_win == NULL ? -1 : frame->fr_win->w_id);
+ if (frame->fr_child != NULL) {
+ DLOG("children");
+ log_frame_layout(frame->fr_child);
+ if (frame->fr_next != NULL) {
+ DLOG("END of children");
+ }
+ }
+ if (frame->fr_next != NULL) {
+ log_frame_layout(frame->fr_next);
+ }
+}
+#endif
+
/// @return the current window, unless in the cmdline window and "prevwin" is
/// set, then return "prevwin".
win_T *prevwin_curwin(void)
@@ -909,6 +941,21 @@ void ui_ext_win_viewport(win_T *wp)
}
}
+/// If "split_disallowed" is set given an error and return FAIL.
+/// Otherwise return OK.
+static int check_split_disallowed(void)
+{
+ if (split_disallowed > 0) {
+ emsg(_("E242: Can't split a window while closing another"));
+ return FAIL;
+ }
+ if (curwin->w_buffer->b_locked_split) {
+ emsg(_(e_cannot_split_window_when_closing_buffer));
+ return FAIL;
+ }
+ return OK;
+}
+
/*
* split the current window, implements CTRL-W s and :split
*
@@ -926,6 +973,10 @@ void ui_ext_win_viewport(win_T *wp)
*/
int win_split(int size, int flags)
{
+ if (check_split_disallowed() == FAIL) {
+ return FAIL;
+ }
+
// When the ":tab" modifier was used open a new tab page instead.
if (may_open_tabpage() == OK) {
return OK;
@@ -1886,6 +1937,9 @@ static void win_totop(int size, int flags)
if (curwin == aucmd_win) {
return;
}
+ if (check_split_disallowed() == FAIL) {
+ return;
+ }
if (curwin->w_floating) {
ui_comp_remove_grid(&curwin->w_grid_alloc);
@@ -1929,6 +1983,11 @@ void win_move_after(win_T *win1, win_T *win2)
// check if there is something to do
if (win2->w_next != win1) {
+ if (win1->w_frame->fr_parent != win2->w_frame->fr_parent) {
+ iemsg("INTERNAL: trying to move a window into another frame");
+ return;
+ }
+
// may need move the status line, horizontal or vertical separator of the last window
if (win1 == lastwin) {
height = win1->w_prev->w_status_height;
@@ -2742,6 +2801,10 @@ int win_close(win_T *win, bool free_buf, bool force)
return FAIL;
}
+ // Now we are really going to close the window. Disallow any autocommand
+ // to split a window to avoid trouble.
+ split_disallowed++;
+
// let terminal buffers know that this window dimensions may be ignored
win->w_closing = true;
@@ -2809,6 +2872,8 @@ int win_close(win_T *win, bool free_buf, bool force)
}
}
+ split_disallowed--;
+
/*
* If last window has a status line now and we don't want one,
* remove the status line.
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index 6111654b5e..90254b7415 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -60,6 +60,23 @@ describe('autocmd', function()
eq(expected, eval('g:evs'))
end)
+ it('first edit causes BufUnload on NoName', function()
+ local expected = {
+ {'BufUnload', ''},
+ {'BufDelete', ''},
+ {'BufWipeout', ''},
+ {'BufEnter', 'testfile1'},
+ }
+ command('let g:evs = []')
+ command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])')
+ command('autocmd BufDelete * :call add(g:evs, ["BufDelete", expand("<afile>")])')
+ command('autocmd BufLeave * :call add(g:evs, ["BufLeave", expand("<afile>")])')
+ command('autocmd BufUnload * :call add(g:evs, ["BufUnload", expand("<afile>")])')
+ command('autocmd BufWipeout * :call add(g:evs, ["BufWipeout", expand("<afile>")])')
+ command('edit testfile1')
+ eq(expected, eval('g:evs'))
+ end)
+
it('WinClosed is non-recursive', function()
command('let g:triggered = 0')
command('autocmd WinClosed * :let g:triggered+=1 | :bdelete 2')
@@ -548,18 +565,6 @@ describe('autocmd', function()
neq({}, meths.get_autocmds { group = "filetypedetect" })
end)
- it('should not access freed mem', function()
- source [[
- au BufEnter,BufLeave,WinEnter,WinLeave 0 vs xxx
- arg 0
- argadd
- all
- all
- au!
- bwipe xxx
- ]]
- end)
-
it('should allow comma-separated patterns', function()
source [[
augroup TestingPatterns
diff --git a/test/functional/legacy/ex_mode_spec.lua b/test/functional/legacy/ex_mode_spec.lua
index 44719027a6..244b6bf00f 100644
--- a/test/functional/legacy/ex_mode_spec.lua
+++ b/test/functional/legacy/ex_mode_spec.lua
@@ -32,5 +32,11 @@ describe('Ex mode', function()
test_ex_edit(' foo', ' foo<C-d>')
test_ex_edit(' foo0', ' foo0<C-d>')
test_ex_edit(' foo^', ' foo^<C-d>')
+ test_ex_edit('foo', '<BS><C-H><Del><kDel>foo')
+ -- default wildchar <Tab> interferes with this test
+ command('set wildchar=<c-e>')
+ test_ex_edit('a\tb', 'a\t\t<C-H>b')
+ test_ex_edit('\tm<C-T>n', '\tm<C-T>n')
+ command('set wildchar&')
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 1547f3244e..ae6a1d5765 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2755,6 +2755,39 @@ describe('vim.keymap', function()
eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
end)
+ it('works with buffer-local mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end, {buffer=true})
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ exec_lua [[
+ vim.keymap.del('n', 'asdf', {buffer=true})
+ ]]
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
+ end)
+
+ it('does not mutate the opts parameter', function()
+ eq(true, exec_lua [[
+ opts = {buffer=true}
+ vim.keymap.set('n', 'asdf', function() end, opts)
+ return opts.buffer
+ ]])
+ eq(true, exec_lua [[
+ vim.keymap.del('n', 'asdf', opts)
+ return opts.buffer
+ ]])
+ end)
+
it('can do <Plug> mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
diff --git a/test/functional/options/cursorbind_spec.lua b/test/functional/options/cursorbind_spec.lua
new file mode 100644
index 0000000000..f762808dd6
--- /dev/null
+++ b/test/functional/options/cursorbind_spec.lua
@@ -0,0 +1,91 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local command = helpers.command
+local exec = helpers.exec
+local feed = helpers.feed
+
+before_each(clear)
+
+describe("'cursorbind'", function()
+ it("behaves consistently whether 'cursorline' is set or not vim-patch:8.2.4795", function()
+ local screen = Screen.new(60, 8)
+ screen:set_default_attr_ids({
+ [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [2] = {bold = true, reverse = true}, -- StatusLine
+ [3] = {reverse = true}, -- StatusLineNC, VertSplit
+ [4] = {background = Screen.colors.Grey90}, -- CursorLine, CursorColumn
+ })
+ screen:attach()
+ exec([[
+ call setline(1, 'aa bb cc dd ee ff gg hh ii jj kk ll mm' ..
+ \ ' nn oo pp qq rr ss tt uu vv ww xx yy zz')
+ set nowrap
+ " The following makes the cursor apparent on the screen dump
+ set sidescroll=1 cursorcolumn
+ " add empty lines, required for cursorcolumn
+ call append(1, ['','','',''])
+ 20vsp
+ windo :set cursorbind
+ ]])
+ feed('20l')
+ screen:expect([[
+ a bb cc dd ee ff gg {3:│}aa bb cc dd ee ff gg^ hh ii jj kk ll mm |
+ {4: }{3:│} {4: } |
+ {4: }{3:│} {4: } |
+ {4: }{3:│} {4: } |
+ {4: }{3:│} {4: } |
+ {1:~ }{3:│}{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ feed('10l')
+ screen:expect([[
+ hh ii jj kk ll mm n{3:│}aa bb cc dd ee ff gg hh ii jj ^kk ll mm |
+ {4: } {3:│} {4: } |
+ {4: } {3:│} {4: } |
+ {4: } {3:│} {4: } |
+ {4: } {3:│} {4: } |
+ {1:~ }{3:│}{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ command('windo :set cursorline')
+ feed('0')
+ feed('20l')
+ screen:expect([[
+ {4:a bb cc dd ee ff gg }{3:│}{4:aa bb cc dd ee ff gg^ hh ii jj kk ll mm }|
+ {4: }{3:│} {4: } |
+ {4: }{3:│} {4: } |
+ {4: }{3:│} {4: } |
+ {4: }{3:│} {4: } |
+ {1:~ }{3:│}{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ feed('10l')
+ screen:expect([[
+ {4: hh ii jj kk ll mm n}{3:│}{4:aa bb cc dd ee ff gg hh ii jj ^kk ll mm }|
+ {4: } {3:│} {4: } |
+ {4: } {3:│} {4: } |
+ {4: } {3:│} {4: } |
+ {4: } {3:│} {4: } |
+ {1:~ }{3:│}{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ command('windo :set nocursorline nocursorcolumn')
+ feed('0')
+ feed('40l')
+ screen:expect([[
+ kk ll mm nn oo pp qq{3:│} bb cc dd ee ff gg hh ii jj kk ll mm n^n|
+ {3:│} |
+ {3:│} |
+ {3:│} |
+ {3:│} |
+ {1:~ }{3:│}{1:~ }|
+ {3:[No Name] [+] }{2:[No Name] [+] }|
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua
index afb17dd2cf..84e4fa5c49 100644
--- a/test/functional/treesitter/language_spec.lua
+++ b/test/functional/treesitter/language_spec.lua
@@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
+local command = helpers.command
local exec_lua = helpers.exec_lua
local pcall_err = helpers.pcall_err
local matches = helpers.matches
@@ -67,5 +68,15 @@ describe('treesitter API', function()
end
eq({true,true}, {has_named,has_anonymous})
end)
+
+ it('checks if vim.treesitter.get_parser tries to create a new parser on filetype change', function ()
+ command("set filetype=c")
+ -- Should not throw an error when filetype is c
+ eq('c', exec_lua("return vim.treesitter.get_parser(0):lang()"))
+ command("set filetype=borklang")
+ -- Should throw an error when filetype changes to borklang
+ eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0)"))
+ end)
end)
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index 068a77a2e4..56ff8a4101 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -109,54 +109,144 @@ describe('search highlighting', function()
]])
end)
- it('works for match under cursor', function()
- screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Yellow},
- [2] = {foreground = Screen.colors.Gray100, background = Screen.colors.Gray0},
- [3] = {foreground = Screen.colors.Red},
- })
-
- command('highlight CurSearch guibg=Black guifg=White')
- insert([[
- There is no way that a bee should be
- able to fly. Its wings are too small
- to get its fat little body off the
- ground. The bee, of course, flies
- anyway because bees don't care what
- humans think is impossible.]])
-
- feed('/bee<CR>')
- screen:expect{grid=[[
- There is no way that a {2:^bee} should be |
- able to fly. Its wings are too small |
- to get its fat little body off the |
- ground. The {1:bee}, of course, flies |
- anyway because {1:bee}s don't care what |
- humans think is impossible. |
- {3:search hit BOTTOM, continuing at TOP} |
- ]]}
-
- feed('nn')
- screen:expect{grid=[[
- There is no way that a {1:bee} should be |
- able to fly. Its wings are too small |
- to get its fat little body off the |
- ground. The {1:bee}, of course, flies |
- anyway because {2:^bee}s don't care what |
- humans think is impossible. |
- /bee |
- ]]}
-
- feed('N')
- screen:expect{grid=[[
- There is no way that a {1:bee} should be |
- able to fly. Its wings are too small |
- to get its fat little body off the |
- ground. The {2:^bee}, of course, flies |
- anyway because {1:bee}s don't care what |
- humans think is impossible. |
- ?bee |
- ]]}
+ describe('CurSearch highlight', function()
+ before_each(function()
+ screen:set_default_attr_ids({
+ [1] = {background = Screen.colors.Yellow}, -- Search
+ [2] = {foreground = Screen.colors.White, background = Screen.colors.Black}, -- CurSearch
+ [3] = {foreground = Screen.colors.Red}, -- WarningMsg
+ })
+ command('highlight CurSearch guibg=Black guifg=White')
+ end)
+
+ it('works for match under cursor', function()
+ insert([[
+ There is no way that a bee should be
+ able to fly. Its wings are too small
+ to get its fat little body off the
+ ground. The bee, of course, flies
+ anyway because bees don't care what
+ humans think is impossible.]])
+
+ feed('/bee<CR>')
+ screen:expect{grid=[[
+ There is no way that a {2:^bee} should be |
+ able to fly. Its wings are too small |
+ to get its fat little body off the |
+ ground. The {1:bee}, of course, flies |
+ anyway because {1:bee}s don't care what |
+ humans think is impossible. |
+ {3:search hit BOTTOM, continuing at TOP} |
+ ]]}
+
+ feed('nn')
+ screen:expect{grid=[[
+ There is no way that a {1:bee} should be |
+ able to fly. Its wings are too small |
+ to get its fat little body off the |
+ ground. The {1:bee}, of course, flies |
+ anyway because {2:^bee}s don't care what |
+ humans think is impossible. |
+ /bee |
+ ]]}
+
+ feed('N')
+ screen:expect{grid=[[
+ There is no way that a {1:bee} should be |
+ able to fly. Its wings are too small |
+ to get its fat little body off the |
+ ground. The {2:^bee}, of course, flies |
+ anyway because {1:bee}s don't care what |
+ humans think is impossible. |
+ ?bee |
+ ]]}
+ end)
+
+ it('works for multiline match', function()
+ command([[call setline(1, ['one', 'foo', 'bar', 'baz', 'foo the foo and foo', 'bar'])]])
+ feed('gg/foo<CR>')
+ screen:expect([[
+ one |
+ {2:^foo} |
+ bar |
+ baz |
+ {1:foo} the {1:foo} and {1:foo} |
+ bar |
+ /foo |
+ ]])
+ feed('n')
+ screen:expect([[
+ one |
+ {1:foo} |
+ bar |
+ baz |
+ {2:^foo} the {1:foo} and {1:foo} |
+ bar |
+ /foo |
+ ]])
+ feed('n')
+ screen:expect([[
+ one |
+ {1:foo} |
+ bar |
+ baz |
+ {1:foo} the {2:^foo} and {1:foo} |
+ bar |
+ /foo |
+ ]])
+ feed('n')
+ screen:expect([[
+ one |
+ {1:foo} |
+ bar |
+ baz |
+ {1:foo} the {1:foo} and {2:^foo} |
+ bar |
+ /foo |
+ ]])
+ command([[call setline(5, 'foo')]])
+ feed('0?<CR>')
+ screen:expect([[
+ one |
+ {2:^foo} |
+ bar |
+ baz |
+ {1:foo} |
+ bar |
+ ?foo |
+ ]])
+ feed('gg/foo\\nbar<CR>')
+ screen:expect([[
+ one |
+ {2:^foo} |
+ {2:bar} |
+ baz |
+ {1:foo} |
+ {1:bar} |
+ /foo\nbar |
+ ]])
+ command([[call setline(1, ['---', 'abcdefg', 'hijkl', '---', 'abcdefg', 'hijkl'])]])
+ feed('gg/efg\\nhij<CR>')
+ screen:expect([[
+ --- |
+ abcd{2:^efg} |
+ {2:hij}kl |
+ --- |
+ abcd{1:efg} |
+ {1:hij}kl |
+ /efg\nhij |
+ ]])
+ feed('n')
+ screen:expect([[
+ --- |
+ abcd{1:efg} |
+ {1:hij}kl |
+ --- |
+ abcd{2:^efg} |
+ {2:hij}kl |
+ /efg\nhij |
+ ]])
+ end)
end)
it('highlights after EOL', function()