aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/CODEOWNERS3
-rwxr-xr-x.github/workflows/env.sh1
-rw-r--r--.github/workflows/labeler.yml86
-rw-r--r--CMakeLists.txt13
-rw-r--r--runtime/autoload/man.vim107
-rw-r--r--runtime/doc/lua.txt120
-rw-r--r--runtime/filetype.vim9
-rw-r--r--runtime/lua/vim/filetype.lua62
-rw-r--r--runtime/lua/vim/keymap.lua135
-rw-r--r--runtime/lua/vim/lsp.lua44
-rw-r--r--runtime/lua/vim/lsp/buf.lua15
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua42
-rw-r--r--runtime/lua/vim/lsp/util.lua16
-rw-r--r--runtime/scripts.vim2
-rw-r--r--runtime/syntax/checkhealth.vim4
-rwxr-xr-xscripts/gen_vimdoc.py3
-rw-r--r--src/nvim/api/private/helpers.c5
-rw-r--r--src/nvim/diff.c211
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/ex_docmd.c5
-rw-r--r--src/nvim/lua/executor.c4
-rw-r--r--src/nvim/lua/treesitter.c4
-rw-r--r--src/nvim/lua/vim.lua60
-rw-r--r--src/nvim/memfile.c6
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/screen.c4
-rw-r--r--src/nvim/state.c2
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_filetype.vim55
-rw-r--r--src/nvim/testdir/test_filetype_lua.vim2
-rw-r--r--src/nvim/testdir/test_search_stat.vim1
-rw-r--r--test/functional/api/keymap_spec.lua10
-rw-r--r--test/functional/core/startup_spec.lua23
-rw-r--r--test/functional/helpers.lua1
-rw-r--r--test/functional/lua/commands_spec.lua9
-rw-r--r--test/functional/lua/filetype_spec.lua571
-rw-r--r--test/functional/lua/vim_spec.lua113
-rw-r--r--test/functional/terminal/buffer_spec.lua5
38 files changed, 948 insertions, 814 deletions
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index 7d41c17894..0000000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-/.github/ @jamessan
-/ci/ @jamessan
-/scripts/ @jamessan
diff --git a/.github/workflows/env.sh b/.github/workflows/env.sh
index d1bc412399..acdbc5da1e 100755
--- a/.github/workflows/env.sh
+++ b/.github/workflows/env.sh
@@ -42,6 +42,7 @@ EOF
tsan)
cat <<EOF >> "$GITHUB_ENV"
TSAN_OPTIONS=log_path=$GITHUB_WORKSPACE/build/log/tsan
+CLANG_SANITIZER=TSAN
EOF
;;
lint)
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
index 76fc8793fa..a2e0566eb1 100644
--- a/.github/workflows/labeler.yml
+++ b/.github/workflows/labeler.yml
@@ -1,8 +1,9 @@
name: "Pull Request Labeler"
on:
pull_request_target:
- types: opened
+ types: [opened]
jobs:
+
triage:
runs-on: ubuntu-latest
permissions:
@@ -12,8 +13,10 @@ jobs:
- uses: actions/labeler@main
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
+
type-scope:
runs-on: ubuntu-latest
+ needs: ["triage"]
permissions:
contents: write
pull-requests: write
@@ -23,8 +26,81 @@ jobs:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
steps:
- # Extract type and try to add it as a label
- - run: gh pr edit "$PR_NUMBER" --add-label "$(echo "$PR_TITLE" | sed -E 's|([[:alpha:]]+)(\(.*\))?!?:.*|\1|')" || true
+ - name: "Extract commit type and add as label"
+ continue-on-error: true
+ run: gh pr edit "$PR_NUMBER" --add-label "$(echo "$PR_TITLE" | sed -E 's|([[:alpha:]]+)(\(.*\))?!?:.*|\1|')"
+ - name: "Extract commit scope and add as label"
+ continue-on-error: true
+ run: gh pr edit "$PR_NUMBER" --add-label "$(echo "$PR_TITLE" | sed -E 's|[[:alpha:]]+\((.+)\)!?:.*|\1|')"
+
+ add-reviewer:
+ # This job currently doesn't work due to a bug in GitHub CLI.
+ #
+ # Issue: https://github.com/cli/cli/issues/4844
+ # PR that will fix it: https://github.com/cli/cli/pull/4876
+ #
+ # The current workaround is to temporarily add "continue-on-error" flag so
+ # the whole workflow doesn't get flagged as a failure.
+ runs-on: ubuntu-latest
+ needs: ["triage", "type-scope"]
+ permissions:
+ contents: write
+ pull-requests: write
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_REPO: ${{ github.repository }}
+ PR_NUMBER: ${{ github.event.pull_request.number }}
+ continue-on-error: true
+ steps:
+ - name: Get labels
+ id: labels
+ run: echo "::set-output name=labels::$(gh pr view $PR_NUMBER --json labels --jq '.labels.[].name' | tr '\n' '%')"
+
+ # The % at the end of the label is a hack to avoid selecting a label that
+ # is substring of another label. So if there is a label "cinema" then we
+ # don't accidentally want to interpret that as the label "ci"
+
+ - if: contains(steps.labels.outputs.labels, 'api%')
+ run: gh pr edit $PR_NUMBER --add-reviewer bfredl,gpanders,muniter
+
+ - if: contains(steps.labels.outputs.labels, 'ci%')
+ run: gh pr edit $PR_NUMBER --add-reviewer jamessan
+
+ - if: contains(steps.labels.outputs.labels, 'diagnostic%')
+ run: gh pr edit $PR_NUMBER --add-reviewer gpanders
+
+ - if: contains(steps.labels.outputs.labels, 'distribution%')
+ run: gh pr edit $PR_NUMBER --add-reviewer jamessan
+
+ - if: contains(steps.labels.outputs.labels, 'documentation%')
+ run: gh pr edit $PR_NUMBER --add-reviewer clason
+
+ - if: contains(steps.labels.outputs.labels, 'extmarks%')
+ run: gh pr edit $PR_NUMBER --add-reviewer bfredl
+
+ - if: contains(steps.labels.outputs.labels, 'filetype%')
+ run: gh pr edit $PR_NUMBER --add-reviewer clason,gpanders
+
+ - if: contains(steps.labels.outputs.labels, 'gui%')
+ run: gh pr edit $PR_NUMBER --add-reviewer glacambre,smolck
+
+ - if: contains(steps.labels.outputs.labels, 'platform:windows%')
+ run: gh pr edit $PR_NUMBER --add-reviewer erw7
+
+ - if: contains(steps.labels.outputs.labels, 'lsp%')
+ run: gh pr edit $PR_NUMBER --add-reviewer mfussenegger,mjlbach
+
+ - if: contains(steps.labels.outputs.labels, 'terminal%')
+ run: gh pr edit $PR_NUMBER --add-reviewer erw7
+
+ - if: contains(steps.labels.outputs.labels, 'treesitter%')
+ run: gh pr edit $PR_NUMBER --add-reviewer bfredl,vigoux
+
+ - if: contains(steps.labels.outputs.labels, 'typo%')
+ run: gh pr edit $PR_NUMBER --add-reviewer dundargoc
+
+ - if: contains(steps.labels.outputs.labels, 'ui%')
+ run: gh pr edit $PR_NUMBER --add-reviewer bfredl
- # Extract scope and try to add it as a label
- - run: gh pr edit "$PR_NUMBER" --add-label "$(echo "$PR_TITLE" | sed -E 's|[[:alpha:]]+\((.+)\)!?:.*|\1|')" || true
+ - if: contains(steps.labels.outputs.labels, 'vim-patch%')
+ run: gh pr edit $PR_NUMBER --add-reviewer janlazo,seandewar
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0c43c5c494..e0f05e1205 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -408,6 +408,19 @@ main(void)
if(TS_HAS_SET_MATCH_LIMIT)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_TS_HAS_SET_MATCH_LIMIT")
endif()
+check_c_source_compiles("
+#include <stdlib.h>
+#include <tree_sitter/api.h>
+int
+main(void)
+{
+ ts_set_allocator(malloc, calloc, realloc, free);
+ return 0;
+}
+" TS_HAS_SET_ALLOCATOR)
+if(TS_HAS_SET_ALLOCATOR)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_TS_HAS_SET_ALLOCATOR")
+endif()
# Note: The test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
diff --git a/runtime/autoload/man.vim b/runtime/autoload/man.vim
index 90d353f9de..a954e1b1a3 100644
--- a/runtime/autoload/man.vim
+++ b/runtime/autoload/man.vim
@@ -7,7 +7,6 @@ let s:loaded_man = 1
let s:find_arg = '-w'
let s:localfile_arg = v:true " Always use -l if possible. #6683
-let s:section_arg = '-S'
function! man#init() abort
try
@@ -216,16 +215,38 @@ endfunction
function! s:get_path(sect, name) abort
" Some man implementations (OpenBSD) return all available paths from the
- " search command, so we get() the first one. #8341
- if empty(a:sect)
- return substitute(get(split(s:system(['man', s:find_arg, a:name])), 0, ''), '\n\+$', '', '')
+ " search command. Previously, this function would simply select the first one.
+ "
+ " However, some searches will report matches that are incorrect:
+ " man -w strlen may return string.3 followed by strlen.3, and therefore
+ " selecting the first would get us the wrong page. Thus, we must find the
+ " first matching one.
+ "
+ " There's yet another special case here. Consider the following:
+ " If you run man -w strlen and string.3 comes up first, this is a problem. We
+ " should search for a matching named one in the results list.
+ " However, if you search for man -w clock_gettime, you will *only* get
+ " clock_getres.2, which is the right page. Searching the resuls for
+ " clock_gettime will no longer work. In this case, we should just use the
+ " first one that was found in the correct section.
+ "
+ " Finally, we can avoid relying on -S or -s here since they are very
+ " inconsistently supported. Instead, call -w with a section and a name.
+ let results = split(s:system(['man', s:find_arg, a:sect, a:name]))
+
+ if empty(results)
+ return ''
endif
- " '-s' flag handles:
- " - tokens like 'printf(echo)'
- " - sections starting with '-'
- " - 3pcap section (found on macOS)
- " - commas between sections (for section priority)
- return substitute(get(split(s:system(['man', s:find_arg, s:section_arg, a:sect, a:name])), 0, ''), '\n\+$', '', '')
+
+ " find any that match the specified name
+ let namematches = filter(copy(results), 'fnamemodify(v:val, ":t") =~ a:name')
+ let sectmatches = []
+
+ if !empty(namematches) && !empty(a:sect)
+ let sectmatches = filter(copy(namematches), 'fnamemodify(v:val, ":e") == a:sect')
+ endif
+
+ return substitute(get(sectmatches, 0, get(namematches, 0, results[0])), '\n\+$', '', '')
endfunction
" s:verify_exists attempts to find the path to a manpage
@@ -243,40 +264,72 @@ endfunction
" then we don't do it again in step 2.
function! s:verify_exists(sect, name) abort
let sect = a:sect
- if empty(sect)
- let sect = get(b:, 'man_default_sects', '')
- endif
- try
- return s:get_path(sect, a:name)
- catch /^command error (/
- endtry
-
- if !empty(get(b:, 'man_default_sects', '')) && sect !=# b:man_default_sects
+ if empty(sect)
+ " no section specified, so search with b:man_default_sects
+ if exists('b:man_default_sects')
+ let sects = split(b:man_default_sects, ',')
+ for sec in sects
+ try
+ let res = s:get_path(sec, a:name)
+ if !empty(res)
+ return res
+ endif
+ catch /^command error (/
+ endtry
+ endfor
+ endif
+ else
+ " try with specified section
try
- return s:get_path(b:man_default_sects, a:name)
+ let res = s:get_path(sect, a:name)
+ if !empty(res)
+ return res
+ endif
catch /^command error (/
endtry
- endif
- if !empty(sect)
- try
- return s:get_path('', a:name)
- catch /^command error (/
- endtry
+ " try again with b:man_default_sects
+ if exists('b:man_default_sects')
+ let sects = split(b:man_default_sects, ',')
+ for sec in sects
+ try
+ let res = s:get_path(sec, a:name)
+ if !empty(res)
+ return res
+ endif
+ catch /^command error (/
+ endtry
+ endfor
+ endif
endif
+ " if none of the above worked, we will try with no section
+ try
+ let res = s:get_path('', a:name)
+ if !empty(res)
+ return res
+ endif
+ catch /^command error (/
+ endtry
+
+ " if that still didn't work, we will check for $MANSECT and try again with it
+ " unset
if !empty($MANSECT)
try
let MANSECT = $MANSECT
call setenv('MANSECT', v:null)
- return s:get_path('', a:name)
+ let res = s:get_path('', a:name)
+ if !empty(res)
+ return res
+ endif
catch /^command error (/
finally
call setenv('MANSECT', MANSECT)
endtry
endif
+ " finally, if that didn't work, there is no hope
throw 'no manual entry for ' . a:name
endfunction
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index 4f76c7c7a6..80c1f58323 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -1240,19 +1240,32 @@ inspect({object}, {options}) *vim.inspect()*
https://github.com/kikito/inspect.lua
https://github.com/mpeterv/vinspect
-notify({msg}, {log_level}, {opts}) *vim.notify()*
- Notification provider
+notify({msg}, {level}, {opts}) *vim.notify()*
+ Display a notification to the user.
- Without a runtime, writes to :Messages
+ This function can be overridden by plugins to display
+ notifications using a custom provider (such as the system
+ notification provider). By default, writes to |:messages|.
Parameters: ~
- {msg} string Content of the notification to show to
- the user
- {log_level} number|nil enum from vim.log.levels
- {opts} table|nil additional options (timeout, etc)
+ {msg} string Content of the notification to show to the
+ user.
+ {level} number|nil One of the values from
+ |vim.log.levels|.
+ {opts} table|nil Optional parameters. Unused by default.
- See also: ~
- :help nvim_notify
+notify_once({msg}, {level}, {opts}) *vim.notify_once()*
+ Display a notification only one time.
+
+ Like |vim.notify()|, but subsequent calls with the same
+ message will not display a notification.
+
+ Parameters: ~
+ {msg} string Content of the notification to show to the
+ user.
+ {level} number|nil One of the values from
+ |vim.log.levels|.
+ {opts} table|nil Optional parameters. Unused by default.
on_key({fn}, {ns_id}) *vim.on_key()*
Adds Lua function {fn} with namespace id {ns_id} as a listener
@@ -1316,6 +1329,18 @@ paste({lines}, {phase}) *vim.paste()*
See also: ~
|paste|
+pretty_print({...}) *vim.pretty_print()*
+ Prints given arguments in human-readable format. Example: >
+ -- Print highlight group Normal and store it's contents in a variable.
+ local hl_normal = vim.pretty_print(vim.api.nvim_get_hl_by_name("Normal", true))
+<
+
+ Return: ~
+ given arguments.
+
+ See also: ~
+ |vim.inspect()|
+
region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive}) *vim.region()*
Get a table of lines with start, end columns for a region
marked by two points
@@ -1847,4 +1872,81 @@ add({filetypes}) *vim.filetype.add()*
{filetypes} table A table containing new filetype maps
(see example).
+
+==============================================================================
+Lua module: keymap *lua-keymap*
+
+del({modes}, {lhs}, {opts}) *vim.keymap.del()*
+ Remove an existing mapping. Examples: >
+
+ vim.keymap.del('n', 'lhs')
+
+ vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
+<
+
+ Parameters: ~
+ {opts} table A table of optional arguments:
+ • buffer: (number or boolean) Remove a mapping
+ from the given buffer. When "true" or 0, use the
+ current buffer.
+
+ See also: ~
+ |vim.keymap.set()|
+
+set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
+ Add a new |mapping|. Examples: >
+
+ -- Can add mapping to Lua functions
+ vim.keymap.set('n', 'lhs', function() print("real lua function") end)
+
+ -- Can use it to map multiple modes
+ vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true })
+
+ -- Can add mapping for specific buffer
+ vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 })
+
+ -- Expr mappings
+ vim.keymap.set('i', '<Tab>', function()
+ return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
+ end, { expr = true })
+ -- <Plug> mappings
+ vim.keymap.set('n', '[%', '<Plug>(MatchitNormalMultiBackward)')
+<
+
+ Note that in a mapping like: >
+
+ vim.keymap.set('n', 'asdf', require('jkl').my_fun)
+<
+
+ the require('jkl') gets evaluated during this call in order to
+ access the function. If you want to avoid this cost at startup
+ you can wrap it in a function, for example: >
+
+ vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
+<
+
+ Parameters: ~
+ {mode} string|table Same mode short names as
+ |nvim_set_keymap()|. Can also be list of modes to
+ create mapping on multiple modes.
+ {lhs} string Left-hand side |{lhs}| of the mapping.
+ {rhs} string|function Right-hand side |{rhs}| of the
+ mapping. Can also be a Lua function.
+ {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:
+ • 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 inverse of the "noremap" option from
+ |nvim_set_keymap()|. Default `true` if `lhs` is
+ a string starting with `<plug>`
+ (case-insensitive), `false` otherwise.
+
+ See also: ~
+ |nvim_set_keymap()|
+
vim:tw=78:ts=8:ft=help:norl:
diff --git a/runtime/filetype.vim b/runtime/filetype.vim
index 7fdbfe32d8..907f806f31 100644
--- a/runtime/filetype.vim
+++ b/runtime/filetype.vim
@@ -493,7 +493,7 @@ au BufNewFile,BufRead */debian/patches/* call dist#ft#Dep3patch()
" Diff files
au BufNewFile,BufRead *.diff,*.rej setf diff
au BufNewFile,BufRead *.patch
- \ if getline(1) =~ '^From [0-9a-f]\{40\} Mon Sep 17 00:00:00 2001$' |
+ \ if getline(1) =~# '^From [0-9a-f]\{40,\} Mon Sep 17 00:00:00 2001$' |
\ setf gitsendemail |
\ else |
\ setf diff |
@@ -672,6 +672,7 @@ autocmd BufRead,BufNewFile *.gift setf gift
" Git
au BufNewFile,BufRead COMMIT_EDITMSG,MERGE_MSG,TAG_EDITMSG setf gitcommit
+au BufNewFile,BufRead NOTES_EDITMSG,EDIT_DESCRIPTION setf gitcommit
au BufNewFile,BufRead *.git/config,.gitconfig,/etc/gitconfig setf gitconfig
au BufNewFile,BufRead */.config/git/config setf gitconfig
au BufNewFile,BufRead .gitmodules,*.git/modules/*/config setf gitconfig
@@ -680,12 +681,8 @@ if !empty($XDG_CONFIG_HOME)
endif
au BufNewFile,BufRead git-rebase-todo setf gitrebase
au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail
-au BufNewFile,BufRead .msg.[0-9]*
- \ if getline(1) =~ '^From.*# This line is ignored.$' |
- \ setf gitsendemail |
- \ endif
au BufNewFile,BufRead *.git/*
- \ if getline(1) =~ '^\x\{40\}\>\|^ref: ' |
+ \ if getline(1) =~# '^\x\{40,\}\>\|^ref: ' |
\ setf git |
\ endif
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index 54b20f7391..28cffdf072 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -15,7 +15,7 @@ local function starsetf(ft)
end
end, {
-- Starset matches should always have lowest priority
- priority = -1,
+ priority = -math.huge,
}}
end
@@ -868,6 +868,8 @@ local filename = {
["TAG_EDITMSG"] = "gitcommit",
["MERGE_MSG"] = "gitcommit",
["COMMIT_EDITMSG"] = "gitcommit",
+ ["NOTES_EDITMSG"] = "gitcommit",
+ ["EDIT_DESCRIPTION"] = "gitcommit",
[".gitconfig"] = "gitconfig",
[".gitmodules"] = "gitconfig",
["/.config/git/config"] = "gitconfig",
@@ -1454,6 +1456,25 @@ local function dispatch(ft, path, bufnr, ...)
end
---@private
+local function match_pattern(name, path, tail, pat)
+ -- If the pattern contains a / match against the full path, otherwise just the tail
+ local fullpat = "^" .. pat .. "$"
+ local matches
+ if pat:find("/") then
+ -- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
+ -- both the short file name (as typed) and the full file name (after expanding to full path
+ -- and resolving symlinks)
+ matches = name:match(fullpat) or path:match(fullpat)
+ else
+ matches = tail:match(fullpat)
+ end
+ return matches
+end
+
+--- Set the filetype for the given buffer from a file name.
+---
+---@param name string File name (can be an absolute or relative path)
+---@param bufnr number|nil The buffer to set the filetype for. Defaults to the current buffer.
function M.match(name, bufnr)
-- When fired from the main filetypedetect autocommand the {bufnr} argument is omitted, so we use
-- the current buffer. The {bufnr} argument is provided to allow extensibility in case callers
@@ -1474,21 +1495,18 @@ function M.match(name, bufnr)
return
end
- -- Next, check the file path against available patterns
- for _, v in ipairs(pattern_sorted) do
+ -- Next, check the file path against available patterns with non-negative priority
+ local j = 1
+ for i, v in ipairs(pattern_sorted) do
local k = next(v)
- local ft = v[k][1]
- -- If the pattern contains a / match against the full path, otherwise just the tail
- local pat = "^" .. k .. "$"
- local matches
- if k:find("/") then
- -- Similar to |autocmd-pattern|, if the pattern contains a '/' then check for a match against
- -- both the short file name (as typed) and the full file name (after expanding to full path
- -- and resolving symlinks)
- matches = name:match(pat) or path:match(pat)
- else
- matches = tail:match(pat)
+ local opts = v[k][2]
+ if opts.priority < 0 then
+ j = i
+ break
end
+
+ local ft = v[k][1]
+ local matches = match_pattern(name, path, tail, k)
if matches then
if dispatch(ft, path, bufnr, matches) then
return
@@ -1496,11 +1514,25 @@ function M.match(name, bufnr)
end
end
- -- Finally, check file extension
+ -- Next, check file extension
local ext = vim.fn.fnamemodify(name, ":e")
if dispatch(extension[ext], path, bufnr) then
return
end
+
+ -- Finally, check patterns with negative priority
+ for i = j, #pattern_sorted do
+ local v = pattern_sorted[i]
+ local k = next(v)
+
+ local ft = v[k][1]
+ local matches = match_pattern(name, path, tail, k)
+ if matches then
+ if dispatch(ft, path, bufnr, matches) then
+ return
+ end
+ end
+ end
end
return M
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
new file mode 100644
index 0000000000..d53b790746
--- /dev/null
+++ b/runtime/lua/vim/keymap.lua
@@ -0,0 +1,135 @@
+local keymap = {}
+
+--- Add a new |mapping|.
+--- Examples:
+--- <pre>
+--- -- Can add mapping to Lua functions
+--- vim.keymap.set('n', 'lhs', function() print("real lua function") end)
+---
+--- -- Can use it to map multiple modes
+--- vim.keymap.set({'n', 'v'}, '<leader>lr', vim.lsp.buf.references, { buffer=true })
+---
+--- -- Can add mapping for specific buffer
+--- vim.keymap.set('n', '<leader>w', "<cmd>w<cr>", { silent = true, buffer = 5 })
+---
+--- -- Expr mappings
+--- vim.keymap.set('i', '<Tab>', function()
+--- return vim.fn.pumvisible() == 1 and "<C-n>" or "<Tab>"
+--- end, { expr = true })
+--- -- <Plug> mappings
+--- vim.keymap.set('n', '[%%', '<Plug>(MatchitNormalMultiBackward)')
+--- </pre>
+---
+--- Note that in a mapping like:
+--- <pre>
+--- vim.keymap.set('n', 'asdf', require('jkl').my_fun)
+--- </pre>
+---
+--- the require('jkl') gets evaluated during this call in order to access the function. If you want to
+--- avoid this cost at startup you can wrap it in a function, for example:
+--- <pre>
+--- vim.keymap.set('n', 'asdf', function() return require('jkl').my_fun() end)
+--- </pre>
+---
+---@param mode string|table Same mode short names as |nvim_set_keymap()|.
+--- Can also be list of modes to create mapping on multiple modes.
+---@param lhs string Left-hand side |{lhs}| of the mapping.
+---@param rhs string|function Right-hand side |{rhs}| of the mapping. Can also be a Lua function.
+--
+---@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:
+--- - 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
+--- inverse of the "noremap" option from |nvim_set_keymap()|.
+--- Default `true` if `lhs` is a string starting with `<plug>` (case-insensitive), `false` otherwise.
+---@see |nvim_set_keymap()|
+function keymap.set(mode, lhs, rhs, opts)
+ vim.validate {
+ mode = {mode, {'s', 't'}},
+ lhs = {lhs, 's'},
+ rhs = {rhs, {'s', 'f'}},
+ opts = {opts, 't', true}
+ }
+
+ opts = vim.deepcopy(opts) or {}
+ local is_rhs_luaref = type(rhs) == "function"
+ mode = type(mode) == 'string' and {mode} or mode
+
+ if is_rhs_luaref and opts.expr and opts.replace_keycodes ~= false then
+ local user_rhs = rhs
+ rhs = function ()
+ return vim.api.nvim_replace_termcodes(user_rhs(), true, true, true)
+ end
+ end
+ -- clear replace_keycodes from opts table
+ opts.replace_keycodes = nil
+
+ if opts.remap == nil then
+ -- remap by default on <plug> mappings and don't otherwise.
+ opts.noremap = is_rhs_luaref or rhs:lower():match("^<plug>") == nil
+ else
+ -- remaps behavior is opposite of noremap option.
+ opts.noremap = not opts.remap
+ opts.remap = nil
+ end
+
+ if is_rhs_luaref then
+ opts.callback = rhs
+ rhs = ''
+ end
+
+ if opts.buffer then
+ local bufnr = opts.buffer == true and 0 or opts.buffer
+ opts.buffer = nil
+ for _, m in ipairs(mode) do
+ vim.api.nvim_buf_set_keymap(bufnr, m, lhs, rhs, opts)
+ end
+ else
+ opts.buffer = nil
+ for _, m in ipairs(mode) do
+ vim.api.nvim_set_keymap(m, lhs, rhs, opts)
+ end
+ end
+end
+
+--- Remove an existing mapping.
+--- Examples:
+--- <pre>
+--- vim.keymap.del('n', 'lhs')
+---
+--- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
+--- </pre>
+---@param opts table A table of optional arguments:
+--- - buffer: (number or boolean) Remove a mapping from the given buffer.
+--- When "true" or 0, use the current buffer.
+---@see |vim.keymap.set()|
+---
+function keymap.del(modes, lhs, opts)
+ vim.validate {
+ mode = {modes, {'s', 't'}},
+ lhs = {lhs, 's'},
+ opts = {opts, 't', true}
+ }
+
+ opts = opts or {}
+ modes = type(modes) == 'string' and {modes} or modes
+
+ 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
+ for _, mode in ipairs(modes) do
+ vim.api.nvim_del_keymap(mode, lhs)
+ end
+ else
+ for _, mode in ipairs(modes) do
+ vim.api.nvim_buf_del_keymap(buffer, mode, lhs)
+ end
+ end
+end
+
+return keymap
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 7df0064b6b..fc9c991c05 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -306,7 +306,6 @@ local function once(fn)
end
end
-
local changetracking = {}
do
--@private
@@ -327,6 +326,7 @@ do
if not state then
state = {
pending_changes = {};
+ last_flush = {};
use_incremental_sync = (
if_nil(client.config.flags.allow_incremental_sync, true)
and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental
@@ -347,8 +347,11 @@ do
function changetracking.reset_buf(client, bufnr)
changetracking.flush(client)
local state = state_by_client[client.id]
- if state and state.buffers then
- state.buffers[bufnr] = nil
+ if state then
+ if state.buffers then
+ state.buffers[bufnr] = nil
+ end
+ state.last_flush = {}
end
end
@@ -362,6 +365,33 @@ do
end
---@private
+ --
+ -- Adjust debounce time by taking time of last didChange notification into
+ -- consideration. If the last didChange happened more than `debounce` time ago,
+ -- debounce can be skipped and otherwise maybe reduced.
+ --
+ -- This turns the debounce into a kind of client rate limiting
+ local function next_debounce(debounce, state, bufnr)
+ if debounce == 0 then
+ return 0
+ end
+ local ns_to_ms = 0.000001
+ local last_flush = state.last_flush[bufnr]
+ if not last_flush then
+ return debounce
+ end
+ local now = uv.hrtime()
+ local ms_since_last_flush = (now - last_flush) * ns_to_ms
+ local remaining_debounce = debounce - ms_since_last_flush
+ if remaining_debounce > 0 then
+ return remaining_debounce
+ else
+ state.last_flush[bufnr] = now
+ return 0
+ end
+ end
+
+ ---@private
function changetracking.prepare(bufnr, firstline, lastline, new_lastline)
local incremental_changes = function(client)
local cached_buffers = state_by_client[client.id].buffers
@@ -383,8 +413,12 @@ do
return
end
local state = state_by_client[client.id]
- local debounce = client.config.flags.debounce_text_changes or 150
+ changetracking._reset_timer(state)
+ local debounce = next_debounce(client.config.flags.debounce_text_changes or 150, state, bufnr)
if debounce == 0 then
+ if state.pending_change then
+ state.pending_change()
+ end
local changes = state.use_incremental_sync and incremental_changes(client) or full_changes()
client.notify("textDocument/didChange", {
textDocument = {
@@ -395,7 +429,6 @@ do
})
return
end
- changetracking._reset_timer(state)
if state.use_incremental_sync then
-- This must be done immediately and cannot be delayed
-- The contents would further change and startline/endline may no longer fit
@@ -406,6 +439,7 @@ do
end
state.pending_change = function()
state.pending_change = nil
+ state.last_flush[bufnr] = uv.hrtime()
if client.is_stopped() or not vim.api.nvim_buf_is_valid(bufnr) then
return
end
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index 543fdb0237..c1d777ae6c 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -627,14 +627,19 @@ end
--- Executes an LSP server command.
---
----@param command A valid `ExecuteCommandParams` object
+---@param command_params table A valid `ExecuteCommandParams` object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
-function M.execute_command(command)
+function M.execute_command(command_params)
validate {
- command = { command.command, 's' },
- arguments = { command.arguments, 't', true }
+ command = { command_params.command, 's' },
+ arguments = { command_params.arguments, 't', true }
}
- request('workspace/executeCommand', command)
+ command_params = {
+ command=command_params.command,
+ arguments=command_params.arguments,
+ workDoneToken=command_params.workDoneToken,
+ }
+ request('workspace/executeCommand', command_params )
end
return M
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index 8850d25233..f38b469f3c 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -243,7 +243,7 @@ end
---@param client_id number
---@private
function M.save(diagnostics, bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.save is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.save is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
end
@@ -257,7 +257,7 @@ end
--- If nil, diagnostics of all clients are included.
---@return table with diagnostics grouped by bufnr (bufnr: Diagnostic[])
function M.get_all(client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_all is deprecated. See :h deprecated', vim.log.levels.WARN)
local result = {}
local namespace
if client_id then
@@ -279,7 +279,7 @@ end
--- Else, return just the diagnostics associated with the client_id.
---@param predicate function|nil Optional function for filtering diagnostics
function M.get(bufnr, client_id, predicate)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get is deprecated. See :h deprecated', vim.log.levels.WARN)
predicate = predicate or function() return true end
if client_id == nil then
local all_diagnostics = {}
@@ -341,7 +341,7 @@ end
---@param severity DiagnosticSeverity
---@param client_id number the client id
function M.get_count(bufnr, severity, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_count is deprecated. See :h deprecated', vim.log.levels.WARN)
severity = severity_lsp_to_vim(severity)
local opts = { severity = severity }
if client_id ~= nil then
@@ -358,7 +358,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic
function M.get_prev(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -376,7 +376,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Previous diagnostic position
function M.get_prev_pos(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_prev_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -393,7 +393,7 @@ end
---
---@param opts table See |vim.lsp.diagnostic.goto_next()|
function M.goto_prev(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.goto_prev is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -411,7 +411,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic
function M.get_next(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_next is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -429,7 +429,7 @@ end
---@param opts table See |vim.lsp.diagnostic.goto_next()|
---@return table Next diagnostic position
function M.get_next_pos(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_next_pos is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -444,7 +444,7 @@ end
---
---@deprecated Prefer |vim.diagnostic.goto_next()|
function M.goto_next(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.goto_next is deprecated. See :h deprecated', vim.log.levels.WARN)
if opts then
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -468,7 +468,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_signs(diagnostics, bufnr, client_id, _, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_signs is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -489,7 +489,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_underline(diagnostics, bufnr, client_id, _, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_underline is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -511,7 +511,7 @@ end
--- - severity_limit (DiagnosticSeverity):
--- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
function M.set_virtual_text(diagnostics, bufnr, client_id, _, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_virtual_text is deprecated. See :h deprecated', vim.log.levels.WARN)
local namespace = M.get_namespace(client_id)
if opts and not opts.severity and opts.severity_limit then
opts.severity = {min=severity_lsp_to_vim(opts.severity_limit)}
@@ -530,7 +530,7 @@ end
---@return an array of [text, hl_group] arrays. This can be passed directly to
--- the {virt_text} option of |nvim_buf_set_extmark()|.
function M.get_virtual_text_chunks_for_line(bufnr, _, line_diags, opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.get_virtual_text_chunks_for_line is deprecated. See :h deprecated', vim.log.levels.WARN)
return vim.diagnostic._get_virt_text_chunks(diagnostic_lsp_to_vim(line_diags, bufnr), opts)
end
@@ -548,7 +548,7 @@ end
---@param position table|nil The (0,0)-indexed position
---@return table {popup_bufnr, win_id}
function M.show_position_diagnostics(opts, buf_nr, position)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.show_position_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
opts.scope = "cursor"
opts.pos = position
@@ -572,7 +572,7 @@ end
---@param client_id number|nil the client id
---@return table {popup_bufnr, win_id}
function M.show_line_diagnostics(opts, buf_nr, line_nr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.show_line_diagnostics is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
opts.scope = "line"
opts.pos = line_nr
@@ -596,7 +596,7 @@ end
--- client. The default is to redraw diagnostics for all attached
--- clients.
function M.redraw(bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.redraw is deprecated. See :h deprecated', vim.log.levels.WARN)
bufnr = get_bufnr(bufnr)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
@@ -624,7 +624,7 @@ end
--- - {workspace}: (boolean, default true)
--- - Set the list with workspace diagnostics
function M.set_qflist(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_qflist is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -656,7 +656,7 @@ end
--- - {workspace}: (boolean, default false)
--- - Set the list with workspace diagnostics
function M.set_loclist(opts)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.set_loclist is deprecated. See :h deprecated', vim.log.levels.WARN)
opts = opts or {}
if opts.severity then
opts.severity = severity_lsp_to_vim(opts.severity)
@@ -684,7 +684,7 @@ end
-- send diagnostic information and the client will still process it. The
-- diagnostics are simply not displayed to the user.
function M.disable(bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.disable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.disable is deprecated. See :h deprecated', vim.log.levels.WARN)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.disable(bufnr, client.id)
@@ -705,7 +705,7 @@ end
--- client. The default is to enable diagnostics for all attached
--- clients.
function M.enable(bufnr, client_id)
- vim.api.nvim_echo({{'vim.lsp.diagnostic.enable is deprecated. See :h deprecated', 'WarningMsg'}}, true, {})
+ vim.notify_once('vim.lsp.diagnostic.enable is deprecated. See :h deprecated', vim.log.levels.WARN)
if not client_id then
return vim.lsp.for_each_buffer_client(bufnr, function(client)
M.enable(bufnr, client.id)
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index dcd68a3433..89c5ebe8f7 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -10,14 +10,6 @@ local uv = vim.loop
local npcall = vim.F.npcall
local split = vim.split
-local _warned = {}
-local warn_once = function(message)
- if not _warned[message] then
- vim.api.nvim_err_writeln(message)
- _warned[message] = true
- end
-end
-
local M = {}
local default_border = {
@@ -201,6 +193,11 @@ end
local function get_lines(bufnr, rows)
rows = type(rows) == "table" and rows or { rows }
+ -- This is needed for bufload and bufloaded
+ if bufnr == 0 then
+ bufnr = vim.api.nvim_get_current_buf()
+ end
+
---@private
local function buf_lines()
local lines = {}
@@ -1822,7 +1819,7 @@ function M.make_given_range_params(start_pos, end_pos, bufnr, offset_encoding)
end_pos = {end_pos, 't', true};
offset_encoding = {offset_encoding, 's', true};
}
- bufnr = bufnr or 0
+ bufnr = bufnr or vim.api.nvim_get_current_buf()
offset_encoding = offset_encoding or M._get_offset_encoding(bufnr)
local A = list_extend({}, start_pos or api.nvim_buf_get_mark(bufnr, '<'))
local B = list_extend({}, end_pos or api.nvim_buf_get_mark(bufnr, '>'))
@@ -1928,7 +1925,6 @@ function M.lookup_section(settings, section)
end
M._get_line_byte_from_position = get_line_byte_from_position
-M._warn_once = warn_once
M.buf_versions = {}
diff --git a/runtime/scripts.vim b/runtime/scripts.vim
index 3790b1c10f..e41405a6c5 100644
--- a/runtime/scripts.vim
+++ b/runtime/scripts.vim
@@ -384,7 +384,7 @@ else
set ft=scheme
" Git output
- elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40\}\>\|^tag \S\+$'
+ elseif s:line1 =~# '^\(commit\|tree\|object\) \x\{40,\}\>\|^tag \S\+$'
set ft=git
" Gprof (gnu profiler)
diff --git a/runtime/syntax/checkhealth.vim b/runtime/syntax/checkhealth.vim
index dff880a0bc..37f1822740 100644
--- a/runtime/syntax/checkhealth.vim
+++ b/runtime/syntax/checkhealth.vim
@@ -12,7 +12,9 @@ unlet! b:current_syntax
syn case match
" We do not care about markdown syntax errors
-syn clear markdownError
+if hlexists('markdownError')
+ syn clear markdownError
+endif
syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine
syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
index 3810ebd9d0..3e9fb21039 100755
--- a/scripts/gen_vimdoc.py
+++ b/scripts/gen_vimdoc.py
@@ -129,6 +129,7 @@ CONFIG = {
'uri.lua',
'ui.lua',
'filetype.lua',
+ 'keymap.lua',
],
'files': ' '.join([
os.path.join(base_dir, 'src/nvim/lua/vim.lua'),
@@ -136,6 +137,7 @@ CONFIG = {
os.path.join(base_dir, 'runtime/lua/vim/uri.lua'),
os.path.join(base_dir, 'runtime/lua/vim/ui.lua'),
os.path.join(base_dir, 'runtime/lua/vim/filetype.lua'),
+ os.path.join(base_dir, 'runtime/lua/vim/keymap.lua'),
]),
'file_patterns': '*.lua',
'fn_name_prefix': '',
@@ -151,6 +153,7 @@ CONFIG = {
'uri': 'vim',
'ui': 'vim.ui',
'filetype': 'vim.filetype',
+ 'keymap': 'vim.keymap',
},
'append_only': [
'shared.lua',
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 38a82343c3..f9603acbda 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -1387,6 +1387,11 @@ void add_user_command(String name, Object command, Dict(user_command) *opts, int
LuaRef luaref = LUA_NOREF;
LuaRef compl_luaref = LUA_NOREF;
+ if (mb_islower(name.data[0])) {
+ api_set_error(err, kErrorTypeValidation, "'name' must begin with an uppercase letter");
+ goto err;
+ }
+
if (HAS_KEY(opts->range) && HAS_KEY(opts->count)) {
api_set_error(err, kErrorTypeValidation, "'range' and 'count' are mutually exclusive");
goto err;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 4f4da7c2a9..340fec230c 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -82,6 +82,14 @@ typedef struct {
garray_T dout_ga; // used for internal diff
} diffout_T;
+// used for recording hunks from xdiff
+typedef struct {
+ linenr_T lnum_orig;
+ long count_orig;
+ linenr_T lnum_new;
+ long count_new;
+} diffhunk_T;
+
// two diff inputs and one result
typedef struct {
diffin_T dio_orig; // original file input
@@ -852,7 +860,7 @@ static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
}
// Read the diff output and add each entry to the diff list.
- diff_read(idx_orig, idx_new, &dio->dio_diff);
+ diff_read(idx_orig, idx_new, dio);
clear_diffin(&dio->dio_new);
clear_diffout(&dio->dio_diff);
@@ -1078,7 +1086,7 @@ static int diff_file_internal(diffio_T *diffio)
emit_cfg.ctxlen = 0; // don't need any diff_context here
emit_cb.priv = &diffio->dio_diff;
- emit_cb.out_line = xdiff_out;
+ emit_cfg.hunk_func = xdiff_out;
if (xdl_diff(&diffio->dio_orig.din_mmfile,
&diffio->dio_new.din_mmfile,
&param, &emit_cfg, &emit_cb) < 0) {
@@ -1519,20 +1527,20 @@ void ex_diffoff(exarg_T *eap)
/// @param idx_orig idx of original file
/// @param idx_new idx of new file
/// @dout diff output
-static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
+static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
{
FILE *fd = NULL;
int line_idx = 0;
diff_T *dprev = NULL;
diff_T *dp = curtab->tp_first_diff;
diff_T *dn, *dpl;
+ diffout_T *dout = &dio->dio_diff;
char_u linebuf[LBUFLEN]; // only need to hold the diff line
char_u *line;
long off;
int i;
- linenr_T lnum_orig, lnum_new;
- long count_orig, count_new;
int notset = true; // block "*dp" not set yet
+ diffhunk_T *hunk;
enum {
DIFF_ED,
DIFF_UNIFIED,
@@ -1549,70 +1557,79 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
}
}
+ if (!dio->dio_internal) {
+ hunk = xmalloc(sizeof(*hunk));
+ }
+
for (;;) {
- if (fd == NULL) {
+ if (dio->dio_internal) {
if (line_idx >= dout->dout_ga.ga_len) {
break; // did last line
}
- line = ((char_u **)dout->dout_ga.ga_data)[line_idx++];
+ hunk = ((diffhunk_T **)dout->dout_ga.ga_data)[line_idx++];
} else {
- if (vim_fgets(linebuf, LBUFLEN, fd)) {
- break; // end of file
- }
- line = linebuf;
- }
-
- if (diffstyle == DIFF_NONE) {
- // Determine diff style.
- // ed like diff looks like this:
- // {first}[,{last}]c{first}[,{last}]
- // {first}a{first}[,{last}]
- // {first}[,{last}]d{first}
- //
- // unified diff looks like this:
- // --- file1 2018-03-20 13:23:35.783153140 +0100
- // +++ file2 2018-03-20 13:23:41.183156066 +0100
- // @@ -1,3 +1,5 @@
- if (isdigit(*line)) {
- diffstyle = DIFF_ED;
- } else if ((STRNCMP(line, "@@ ", 3) == 0)) {
- diffstyle = DIFF_UNIFIED;
- } else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
- && (STRNCMP(line, "+++ ", 4) == 0)
- && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
- && (STRNCMP(line, "@@ ", 3) == 0)) {
- diffstyle = DIFF_UNIFIED;
+ if (fd == NULL) {
+ if (line_idx >= dout->dout_ga.ga_len) {
+ break; // did last line
+ }
+ line = ((char_u **)dout->dout_ga.ga_data)[line_idx++];
} else {
- // Format not recognized yet, skip over this line. Cygwin diff
- // may put a warning at the start of the file.
- continue;
+ if (vim_fgets(linebuf, LBUFLEN, fd)) {
+ break; // end of file
+ }
+ line = linebuf;
}
- }
- if (diffstyle == DIFF_ED) {
- if (!isdigit(*line)) {
- continue; // not the start of a diff block
- }
- if (parse_diff_ed(line, &lnum_orig, &count_orig,
- &lnum_new, &count_new) == FAIL) {
- continue;
- }
- } else {
- assert(diffstyle == DIFF_UNIFIED);
- if (STRNCMP(line, "@@ ", 3) != 0) {
- continue; // not the start of a diff block
+ if (diffstyle == DIFF_NONE) {
+ // Determine diff style.
+ // ed like diff looks like this:
+ // {first}[,{last}]c{first}[,{last}]
+ // {first}a{first}[,{last}]
+ // {first}[,{last}]d{first}
+ //
+ // unified diff looks like this:
+ // --- file1 2018-03-20 13:23:35.783153140 +0100
+ // +++ file2 2018-03-20 13:23:41.183156066 +0100
+ // @@ -1,3 +1,5 @@
+ if (isdigit(*line)) {
+ diffstyle = DIFF_ED;
+ } else if ((STRNCMP(line, "@@ ", 3) == 0)) {
+ diffstyle = DIFF_UNIFIED;
+ } else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (STRNCMP(line, "+++ ", 4) == 0)
+ && (vim_fgets(linebuf, LBUFLEN, fd) == 0) // -V501
+ && (STRNCMP(line, "@@ ", 3) == 0)) {
+ diffstyle = DIFF_UNIFIED;
+ } else {
+ // Format not recognized yet, skip over this line. Cygwin diff
+ // may put a warning at the start of the file.
+ continue;
+ }
}
- if (parse_diff_unified(line, &lnum_orig, &count_orig,
- &lnum_new, &count_new) == FAIL) {
- continue;
+
+ if (diffstyle == DIFF_ED) {
+ if (!isdigit(*line)) {
+ continue; // not the start of a diff block
+ }
+ if (parse_diff_ed(line, hunk) == FAIL) {
+ continue;
+ }
+ } else {
+ assert(diffstyle == DIFF_UNIFIED);
+ if (STRNCMP(line, "@@ ", 3) != 0) {
+ continue; // not the start of a diff block
+ }
+ if (parse_diff_unified(line, hunk) == FAIL) {
+ continue;
+ }
}
}
// Go over blocks before the change, for which orig and new are equal.
// Copy blocks from orig to new.
while (dp != NULL
- && lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
+ && hunk->lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
if (notset) {
diff_copy_entry(dprev, dp, idx_orig, idx_new);
}
@@ -1622,19 +1639,19 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
}
if ((dp != NULL)
- && (lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
- && (lnum_orig + count_orig >= dp->df_lnum[idx_orig])) {
+ && (hunk->lnum_orig <= dp->df_lnum[idx_orig] + dp->df_count[idx_orig])
+ && (hunk->lnum_orig + hunk->count_orig >= dp->df_lnum[idx_orig])) {
// New block overlaps with existing block(s).
// First find last block that overlaps.
for (dpl = dp; dpl->df_next != NULL; dpl = dpl->df_next) {
- if (lnum_orig + count_orig < dpl->df_next->df_lnum[idx_orig]) {
+ if (hunk->lnum_orig + hunk->count_orig < dpl->df_next->df_lnum[idx_orig]) {
break;
}
}
// If the newly found block starts before the old one, set the
// start back a number of lines.
- off = dp->df_lnum[idx_orig] - lnum_orig;
+ off = dp->df_lnum[idx_orig] - hunk->lnum_orig;
if (off > 0) {
for (i = idx_orig; i < idx_new; ++i) {
@@ -1642,15 +1659,15 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
dp->df_lnum[i] -= off;
}
}
- dp->df_lnum[idx_new] = lnum_new;
- dp->df_count[idx_new] = count_new;
+ dp->df_lnum[idx_new] = hunk->lnum_new;
+ dp->df_count[idx_new] = hunk->count_new;
} else if (notset) {
// new block inside existing one, adjust new block
- dp->df_lnum[idx_new] = lnum_new + off;
- dp->df_count[idx_new] = count_new - off;
+ dp->df_lnum[idx_new] = hunk->lnum_new + off;
+ dp->df_count[idx_new] = hunk->count_new - off;
} else {
// second overlap of new block with existing block
- dp->df_count[idx_new] += count_new - count_orig
+ dp->df_count[idx_new] += hunk->count_new - hunk->count_orig
+ dpl->df_lnum[idx_orig] +
dpl->df_count[idx_orig]
- (dp->df_lnum[idx_orig] +
@@ -1659,7 +1676,7 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
// Adjust the size of the block to include all the lines to the
// end of the existing block or the new diff, whatever ends last.
- off = (lnum_orig + count_orig)
+ off = (hunk->lnum_orig + hunk->count_orig)
- (dpl->df_lnum[idx_orig] + dpl->df_count[idx_orig]);
if (off < 0) {
@@ -1691,10 +1708,10 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
// Allocate a new diffblock.
dp = diff_alloc_new(curtab, dprev, dp);
- dp->df_lnum[idx_orig] = lnum_orig;
- dp->df_count[idx_orig] = count_orig;
- dp->df_lnum[idx_new] = lnum_new;
- dp->df_count[idx_new] = count_new;
+ dp->df_lnum[idx_orig] = hunk->lnum_orig;
+ dp->df_count[idx_orig] = hunk->count_orig;
+ dp->df_lnum[idx_new] = hunk->lnum_new;
+ dp->df_count[idx_new] = hunk->count_new;
// Set values for other buffers, these must be equal to the
// original buffer, otherwise there would have been a change
@@ -1718,6 +1735,10 @@ static void diff_read(int idx_orig, int idx_new, diffout_T *dout)
notset = true;
}
+ if (!dio->dio_internal) {
+ xfree(hunk);
+ }
+
if (fd != NULL) {
fclose(fd);
}
@@ -3026,8 +3047,7 @@ linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
/// Handle an ED style diff line.
/// Return FAIL if the line does not contain diff info.
///
-static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, linenr_T *lnum_new,
- long *count_new)
+static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
{
char_u *p;
long f1, l1, f2, l2;
@@ -3061,18 +3081,18 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li
}
if (difftype == 'a') {
- *lnum_orig = f1 + 1;
- *count_orig = 0;
+ hunk->lnum_orig = f1 + 1;
+ hunk->count_orig = 0;
} else {
- *lnum_orig = f1;
- *count_orig = l1 - f1 + 1;
+ hunk->lnum_orig = f1;
+ hunk->count_orig = l1 - f1 + 1;
}
if (difftype == 'd') {
- *lnum_new = f2 + 1;
- *count_new = 0;
+ hunk->lnum_new = f2 + 1;
+ hunk->count_new = 0;
} else {
- *lnum_new = f2;
- *count_new = l2 - f2 + 1;
+ hunk->lnum_new = f2;
+ hunk->count_new = l2 - f2 + 1;
}
return OK;
}
@@ -3081,8 +3101,7 @@ static int parse_diff_ed(char_u *line, linenr_T *lnum_orig, long *count_orig, li
/// Parses unified diff with zero(!) context lines.
/// Return FAIL if there is no diff information in "line".
///
-static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_orig,
- linenr_T *lnum_new, long *count_new)
+static int parse_diff_unified(char_u *line, diffhunk_T *hunk)
{
char_u *p;
long oldline, oldcount, newline, newcount;
@@ -3120,10 +3139,10 @@ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_ori
newline = 1;
}
- *lnum_orig = oldline;
- *count_orig = oldcount;
- *lnum_new = newline;
- *count_new = newcount;
+ hunk->lnum_orig = oldline;
+ hunk->count_orig = oldcount;
+ hunk->lnum_new = newline;
+ hunk->count_new = newcount;
return OK;
}
@@ -3135,25 +3154,17 @@ static int parse_diff_unified(char_u *line, linenr_T *lnum_orig, long *count_ori
/// Callback function for the xdl_diff() function.
/// Stores the diff output in a grow array.
///
-static int xdiff_out(void *priv, mmbuffer_t *mb, int nbuf)
+static int xdiff_out(long start_a, long count_a, long start_b, long count_b,
+ void *priv)
{
diffout_T *dout = (diffout_T *)priv;
- char_u *p;
-
- // The header line always comes by itself, text lines in at least two
- // parts. We drop the text part.
- if (nbuf > 1) {
- return 0;
- }
-
- // sanity check
- if (STRNCMP(mb[0].ptr, "@@ ", 3) != 0) {
- return 0;
- }
+ diffhunk_T *p = xmalloc(sizeof(*p));
ga_grow(&dout->dout_ga, 1);
-
- p = vim_strnsave((char_u *)mb[0].ptr, mb[0].size);
- ((char_u **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p;
+ p->lnum_orig = start_a + 1;
+ p->count_orig = count_a;
+ p->lnum_new = start_b + 1;
+ p->count_new = count_b;
+ ((diffhunk_T **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p;
return 0;
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 5eef4350b7..aa37d1b2dd 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -3620,7 +3620,7 @@ static bool ins_compl_prep(int c)
// Ignore end of Select mode mapping and mouse scroll buttons.
if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
|| c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT
- || c == K_COMMAND) {
+ || c == K_COMMAND || c == K_LUA) {
return retval;
}
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 71c34f98ff..3a285cdf90 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -4370,7 +4370,7 @@ static char_u *replace_makeprg(exarg_T *eap, char_u *p, char_u **cmdlinep)
++i;
}
len = (int)STRLEN(p);
- new_cmdline = xmalloc(STRLEN(program) + i * (len - 2) + 1);
+ new_cmdline = xmalloc(STRLEN(program) + (size_t)i * (len - 2) + 1);
ptr = new_cmdline;
while ((pos = (char_u *)strstr((char *)program, "$*")) != NULL) {
i = (int)(pos - program);
@@ -6028,7 +6028,7 @@ static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd,
break;
}
- case ct_MODS: {
+ case ct_MODS:
result = quote ? 2 : 0;
if (buf != NULL) {
if (quote) {
@@ -6044,7 +6044,6 @@ static size_t uc_check_code(char_u *code, size_t len, char_u *buf, ucmd_T *cmd,
*buf = '"';
}
break;
- }
case ct_REGISTER:
result = eap->regname ? 1 : 0;
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index c814974fe7..cfdbe7b344 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -1131,12 +1131,12 @@ void ex_lua(exarg_T *const eap)
}
// When =expr is used transform it to print(vim.inspect(expr))
if (code[0] == '=') {
- len += sizeof("print(vim.inspect())") - sizeof("=");
+ len += sizeof("vim.pretty_print()") - sizeof("=");
// code_buf needs to be 1 char larger then len for null byte in the end.
// lua nlua_typval_exec doesn't expect null terminated string so len
// needs to end before null byte.
char *code_buf = xmallocz(len);
- vim_snprintf(code_buf, len+1, "print(vim.inspect(%s))", code+1);
+ vim_snprintf(code_buf, len+1, "vim.pretty_print(%s)", code+1);
xfree(code);
code = code_buf;
}
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 60a000843f..f4067ad02f 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -129,6 +129,10 @@ void tslua_init(lua_State *L)
build_meta(L, TS_META_QUERY, query_meta);
build_meta(L, TS_META_QUERYCURSOR, querycursor_meta);
build_meta(L, TS_META_TREECURSOR, treecursor_meta);
+
+#ifdef NVIM_TS_HAS_SET_ALLOCATOR
+ ts_set_allocator(xmalloc, xcalloc, xrealloc, xfree);
+#endif
}
int tslua_has_language(lua_State *L)
diff --git a/src/nvim/lua/vim.lua b/src/nvim/lua/vim.lua
index 6ef46ee844..731e7d8d36 100644
--- a/src/nvim/lua/vim.lua
+++ b/src/nvim/lua/vim.lua
@@ -115,6 +115,9 @@ setmetatable(vim, {
elseif key == 'ui' then
t.ui = require('vim.ui')
return t.ui
+ elseif key == 'keymap' then
+ t.keymap = require('vim.keymap')
+ return t.keymap
end
end
})
@@ -422,23 +425,43 @@ function vim.defer_fn(fn, timeout)
end
---- Notification provider
+--- Display a notification to the user.
---
---- Without a runtime, writes to :Messages
----@see :help nvim_notify
----@param msg string Content of the notification to show to the user
----@param log_level number|nil enum from |vim.log.levels|
----@param opts table|nil additional options (timeout, etc)
-function vim.notify(msg, log_level, opts) -- luacheck: no unused
- if log_level == vim.log.levels.ERROR then
+--- This function can be overridden by plugins to display notifications using a
+--- custom provider (such as the system notification provider). By default,
+--- writes to |:messages|.
+---
+---@param msg string Content of the notification to show to the user.
+---@param level number|nil One of the values from |vim.log.levels|.
+---@param opts table|nil Optional parameters. Unused by default.
+function vim.notify(msg, level, opts) -- luacheck: no unused args
+ if level == vim.log.levels.ERROR then
vim.api.nvim_err_writeln(msg)
- elseif log_level == vim.log.levels.WARN then
+ elseif level == vim.log.levels.WARN then
vim.api.nvim_echo({{msg, 'WarningMsg'}}, true, {})
else
vim.api.nvim_echo({{msg}}, true, {})
end
end
+do
+ local notified = {}
+
+ --- Display a notification only one time.
+ ---
+ --- Like |vim.notify()|, but subsequent calls with the same message will not
+ --- display a notification.
+ ---
+ ---@param msg string Content of the notification to show to the user.
+ ---@param level number|nil One of the values from |vim.log.levels|.
+ ---@param opts table|nil Optional parameters. Unused by default.
+ function vim.notify_once(msg, level, opts) -- luacheck: no unused args
+ if not notified[msg] then
+ vim.notify(msg, level, opts)
+ notified[msg] = true
+ end
+ end
+end
---@private
function vim.register_keystroke_callback()
@@ -666,4 +689,23 @@ vim._expand_pat_get_parts = function(lua_string)
return parts, search_index
end
+---Prints given arguments in human-readable format.
+---Example:
+---<pre>
+--- -- Print highlight group Normal and store it's contents in a variable.
+--- local hl_normal = vim.pretty_print(vim.api.nvim_get_hl_by_name("Normal", true))
+---</pre>
+---@see |vim.inspect()|
+---@return given arguments.
+function vim.pretty_print(...)
+ local objects = {}
+ for i = 1, select('#', ...) do
+ local v = select(i, ...)
+ table.insert(objects, vim.inspect(v))
+ end
+
+ print(table.concat(objects, ' '))
+ return ...
+end
+
return module
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 3397296b3a..2a72d1e6a0 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -247,7 +247,7 @@ bhdr_T *mf_new(memfile_T *mfp, bool negative, unsigned page_count)
} else { // need to allocate memory for this block
// If the number of pages matches use the bhdr_T from the free list and
// allocate the data.
- void *p = xmalloc(mfp->mf_page_size * page_count);
+ void *p = xmalloc((size_t)mfp->mf_page_size * page_count);
hp = mf_rem_free(mfp);
hp->bh_data = p;
}
@@ -269,7 +269,7 @@ bhdr_T *mf_new(memfile_T *mfp, bool negative, unsigned page_count)
// Init the data to all zero, to avoid reading uninitialized data.
// This also avoids that the passwd file ends up in the swap file!
- (void)memset(hp->bh_data, 0, mfp->mf_page_size * page_count);
+ (void)memset(hp->bh_data, 0, (size_t)mfp->mf_page_size * page_count);
return hp;
}
@@ -528,7 +528,7 @@ bool mf_release_all(void)
static bhdr_T *mf_alloc_bhdr(memfile_T *mfp, unsigned page_count)
{
bhdr_T *hp = xmalloc(sizeof(bhdr_T));
- hp->bh_data = xmalloc(mfp->mf_page_size * page_count);
+ hp->bh_data = xmalloc((size_t)mfp->mf_page_size * page_count);
hp->bh_page_count = page_count;
return hp;
}
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 08521c0dc3..9925971783 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -1032,9 +1032,9 @@ void ml_recover(bool checkext)
line_count = 0;
idx = 0; // start with first index in block 1
error = 0;
- buf->b_ml.ml_stack_top = 0;
+ buf->b_ml.ml_stack_top = 0; // -V1048
buf->b_ml.ml_stack = NULL;
- buf->b_ml.ml_stack_size = 0; // no stack yet
+ buf->b_ml.ml_stack_size = 0; // -V1048
if (curbuf->b_ffname == NULL) {
cannot_open = true;
@@ -4139,7 +4139,7 @@ long ml_find_line_or_offset(buf_T *buf, linenr_T lnum, long *offp, bool no_ff)
|| (offset != 0
&& offset > size +
buf->b_ml.ml_chunksize[curix].mlcs_totalsize
- + ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines))) {
+ + (long)ffdos * buf->b_ml.ml_chunksize[curix].mlcs_numlines))) {
curline += buf->b_ml.ml_chunksize[curix].mlcs_numlines;
size += buf->b_ml.ml_chunksize[curix].mlcs_totalsize;
if (offset && ffdos) {
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index b1ca8c5805..538604cf79 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -4130,7 +4130,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (((wp->w_p_cuc
&& (int)wp->w_virtcol >= VCOL_HLC - eol_hl_off
&& (int)wp->w_virtcol <
- grid->Columns * (row - startrow + 1) + v
+ (long)grid->Columns * (row - startrow + 1) + v
&& lnum != wp->w_cursor.lnum)
|| draw_color_col || line_attr_lowprio || line_attr
|| diff_hlf != (hlf_T)0 || has_virttext)) {
@@ -6762,7 +6762,7 @@ void grid_clear_line(ScreenGrid *grid, unsigned off, int width, bool valid)
void grid_invalidate(ScreenGrid *grid)
{
- (void)memset(grid->attrs, -1, grid->Rows * grid->Columns * sizeof(sattr_T));
+ (void)memset(grid->attrs, -1, sizeof(sattr_T) * grid->Rows * grid->Columns);
}
bool grid_invalid_row(ScreenGrid *grid, int row)
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 68bc76660d..1fe8bb671d 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -180,7 +180,7 @@ char *get_mode(void)
buf[1] = 'x';
}
}
- } else if (State & CMDLINE) {
+ } else if ((State & CMDLINE) || exmode_active) {
buf[0] = 'c';
if (exmode_active) {
buf[1] = 'v';
diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim
index cc767a9bcf..c0ac4393c4 100644
--- a/src/nvim/testdir/test_alot.vim
+++ b/src/nvim/testdir/test_alot.vim
@@ -27,6 +27,7 @@ source test_join.vim
source test_jumps.vim
source test_fileformat.vim
source test_filetype.vim
+source test_filetype_lua.vim
source test_lambda.vim
source test_menu.vim
source test_messages.vim
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index 4da68539fb..45a10cc193 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -195,7 +195,7 @@ let s:filename_checks = {
\ 'gedcom': ['file.ged', 'lltxxxxx.txt', '/tmp/lltmp', '/tmp/lltmp-file', 'any/tmp/lltmp', 'any/tmp/lltmp-file'],
\ 'gemtext': ['file.gmi', 'file.gemini'],
\ 'gift': ['file.gift'],
- \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG'],
+ \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG', 'NOTES_EDITMSG', 'EDIT_DESCRIPTION'],
\ 'gitconfig': ['file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'],
\ 'gitolite': ['gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'],
\ 'gitrebase': ['git-rebase-todo'],
@@ -1042,7 +1042,58 @@ func Test_dep3patch_file()
call assert_notequal('dep3patch', &filetype)
bwipe!
- call delete('debian/patches', 'rf')
+ call delete('debian', 'rf')
+endfunc
+
+func Test_patch_file()
+ filetype on
+
+ call writefile([], 'Xfile.patch')
+ split Xfile.patch
+ call assert_equal('diff', &filetype)
+ bwipe!
+
+ call writefile(['From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001'], 'Xfile.patch')
+ split Xfile.patch
+ call assert_equal('gitsendemail', &filetype)
+ bwipe!
+
+ call writefile(['From 0000000000000000000000000000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001'], 'Xfile.patch')
+ split Xfile.patch
+ call assert_equal('gitsendemail', &filetype)
+ bwipe!
+
+ call delete('Xfile.patch')
+ filetype off
+endfunc
+
+func Test_git_file()
+ filetype on
+
+ call assert_true(mkdir('Xrepo.git', 'p'))
+
+ call writefile([], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('', &filetype)
+ bwipe!
+
+ call writefile(['0000000000000000000000000000000000000000'], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('git', &filetype)
+ bwipe!
+
+ call writefile(['0000000000000000000000000000000000000000000000000000000000000000'], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('git', &filetype)
+ bwipe!
+
+ call writefile(['ref: refs/heads/master'], 'Xrepo.git/HEAD')
+ split Xrepo.git/HEAD
+ call assert_equal('git', &filetype)
+ bwipe!
+
+ call delete('Xrepo.git', 'rf')
+ filetype off
endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_filetype_lua.vim b/src/nvim/testdir/test_filetype_lua.vim
new file mode 100644
index 0000000000..f73e4ca33f
--- /dev/null
+++ b/src/nvim/testdir/test_filetype_lua.vim
@@ -0,0 +1,2 @@
+let g:do_filetype_lua = 1
+source test_filetype.vim
diff --git a/src/nvim/testdir/test_search_stat.vim b/src/nvim/testdir/test_search_stat.vim
index 335a51268d..f7f7467e91 100644
--- a/src/nvim/testdir/test_search_stat.vim
+++ b/src/nvim/testdir/test_search_stat.vim
@@ -73,7 +73,6 @@ func Test_search_stat()
let stat = '\[2/50\]'
let g:a = execute(':unsilent :norm! n')
call assert_notmatch(pat .. stat, g:a)
- call writefile(getline(1, '$'), 'sample.txt')
" n does not update search stat
call assert_equal(
\ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index bc2759ade7..450a76ddac 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -820,6 +820,16 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq(99, exec_lua[[return SomeValue]])
end)
+ it('does not reset pum in lua mapping', function()
+ eq(0, exec_lua [[
+ VisibleCount = 0
+ vim.api.nvim_set_keymap ('i', '<F2>', '', {callback = function() VisibleCount = VisibleCount + vim.fn.pumvisible() end})
+ return VisibleCount
+ ]])
+ feed('i<C-X><C-V><F2><F2><esc>')
+ eq(2, exec_lua[[return VisibleCount]])
+ end)
+
it('can overwrite lua mappings', function()
eq(0, exec_lua [[
GlobalCount = 0
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 4220d68ee1..2fa84e8313 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -224,6 +224,23 @@ describe('startup', function()
end
end)
+ it('-e sets ex mode', function()
+ local screen = Screen.new(25, 3)
+ clear('-e')
+ screen:attach()
+ -- Verify we set the proper mode both before and after :vi.
+ feed("put =mode(1)<CR>vi<CR>:put =mode(1)<CR>")
+ screen:expect([[
+ cv |
+ ^n |
+ :put =mode(1) |
+ ]])
+
+ eq('cv\n',
+ funcs.system({nvim_prog, '-n', '-es' },
+ { 'put =mode(1)', 'print', '' }))
+ end)
+
it('fails on --embed with -es/-Es', function()
matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es',
funcs.system({nvim_prog, '--embed', '-es' }))
@@ -651,11 +668,7 @@ describe('runtime:', function()
mkdir_p(ftdetect_folder)
write_file(ftdetect_file , [[vim.g.lua_ftdetect = 1]])
- -- TODO(shadmansaleh): Figure out why this test fails without
- -- setting VIMRUNTIME
- clear{ args_rm={'-u'}, env={XDG_CONFIG_HOME=xconfig,
- XDG_DATA_HOME=xdata,
- VIMRUNTIME='runtime/'}}
+ clear{ args_rm={'-u'}, env=xenv }
eq(1, eval('g:lua_ftdetect'))
rmdir(ftdetect_folder)
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index f152a487af..1845786c4b 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -451,6 +451,7 @@ function module.new_argv(...)
'GCOV_ERROR_FILE',
'XDG_DATA_DIRS',
'TMPDIR',
+ 'VIMRUNTIME',
}) do
if not env_tbl[k] then
env_tbl[k] = os.getenv(k)
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index b3c3f937ac..b8346df290 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -149,6 +149,15 @@ describe(':lua command', function()
eq([["hello"]], helpers.exec_capture(':lua = x()'))
helpers.exec_lua("x = {a = 1, b = 2}")
eq("{\n a = 1,\n b = 2\n}", helpers.exec_capture(':lua =x'))
+ helpers.exec_lua([[function x(success)
+ if success then
+ return true, "Return value"
+ else
+ return false, nil, "Error message"
+ end
+ end]])
+ eq([[true "Return value"]], helpers.exec_capture(':lua =x(true)'))
+ eq([[false nil "Error message"]], helpers.exec_capture(':lua =x(false)'))
end)
end)
diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua
index 756591571e..1b2cb61cc2 100644
--- a/test/functional/lua/filetype_spec.lua
+++ b/test/functional/lua/filetype_spec.lua
@@ -3,9 +3,6 @@ local exec_lua = helpers.exec_lua
local eq = helpers.eq
local clear = helpers.clear
local pathroot = helpers.pathroot
-local meths = helpers.meths
-local curbufmeths = helpers.curbufmeths
-local funcs = helpers.funcs
local root = pathroot()
@@ -98,572 +95,4 @@ describe('vim.filetype', function()
return vim.bo.filetype
]])
end)
-
- it('correctly detects filetypes from test_filetype', function()
- -- Checks copied from test_filetype.vim
- local filename_checks = {
- ['8th'] = {'file.8th'},
- ['a2ps'] = {'/etc/a2ps.cfg', '/etc/a2ps/file.cfg', 'a2psrc', '.a2psrc', 'any/etc/a2ps.cfg', 'any/etc/a2ps/file.cfg'},
- ['a65'] = {'file.a65'},
- ['aap'] = {'file.aap'},
- ['abap'] = {'file.abap'},
- ['abc'] = {'file.abc'},
- ['abel'] = {'file.abl'},
- ['acedb'] = {'file.wrm'},
- ['ada'] = {'file.adb', 'file.ads', 'file.ada', 'file.gpr'},
- ['ahdl'] = {'file.tdf'},
- ['aidl'] = {'file.aidl'},
- ['alsaconf'] = {'.asoundrc', '/usr/share/alsa/alsa.conf', '/etc/asound.conf', 'any/etc/asound.conf', 'any/usr/share/alsa/alsa.conf'},
- ['aml'] = {'file.aml'},
- ['ampl'] = {'file.run'},
- ['ant'] = {'build.xml'},
- ['apache'] = {'.htaccess', '/etc/httpd/file.conf', '/etc/apache2/sites-2/file.com', '/etc/apache2/some.config', '/etc/apache2/conf.file/conf', '/etc/apache2/mods-some/file', '/etc/apache2/sites-some/file', '/etc/httpd/conf.d/file.config', '/etc/apache2/conf.file/file', '/etc/apache2/file.conf', '/etc/apache2/file.conf-file', '/etc/apache2/mods-file/file', '/etc/apache2/sites-file/file', '/etc/apache2/sites-file/file.com', '/etc/httpd/conf.d/file.conf', '/etc/httpd/conf.d/file.conf-file', 'access.conf', 'access.conf-file', 'any/etc/apache2/conf.file/file', 'any/etc/apache2/file.conf', 'any/etc/apache2/file.conf-file', 'any/etc/apache2/mods-file/file', 'any/etc/apache2/sites-file/file', 'any/etc/apache2/sites-file/file.com', 'any/etc/httpd/conf.d/file.conf', 'any/etc/httpd/conf.d/file.conf-file', 'any/etc/httpd/file.conf', 'apache.conf', 'apache.conf-file', 'apache2.conf', 'apache2.conf-file', 'httpd.conf', 'httpd.conf-file', 'srm.conf', 'srm.conf-file', '/etc/httpd/mods-some/file', '/etc/httpd/sites-some/file', '/etc/httpd/conf.file/conf'},
- ['apachestyle'] = {'/etc/proftpd/file.config,/etc/proftpd/conf.file/file', '/etc/proftpd/conf.file/file', '/etc/proftpd/file.conf', '/etc/proftpd/file.conf-file', 'any/etc/proftpd/conf.file/file', 'any/etc/proftpd/file.conf', 'any/etc/proftpd/file.conf-file', 'proftpd.conf', 'proftpd.conf-file'},
- ['applescript'] = {'file.scpt'},
- ['aptconf'] = {'apt.conf', '/.aptitude/config', 'any/.aptitude/config'},
- ['arch'] = {'.arch-inventory', '=tagging-method'},
- ['arduino'] = {'file.ino', 'file.pde'},
- ['art'] = {'file.art'},
- ['asciidoc'] = {'file.asciidoc', 'file.adoc'},
- ['asn'] = {'file.asn', 'file.asn1'},
- ['asterisk'] = {'asterisk/file.conf', 'asterisk/file.conf-file', 'some-asterisk/file.conf', 'some-asterisk/file.conf-file'},
- ['atlas'] = {'file.atl', 'file.as'},
- ['autohotkey'] = {'file.ahk'},
- ['autoit'] = {'file.au3'},
- ['automake'] = {'GNUmakefile.am', 'makefile.am', 'Makefile.am'},
- ['ave'] = {'file.ave'},
- ['awk'] = {'file.awk', 'file.gawk'},
- ['b'] = {'file.mch', 'file.ref', 'file.imp'},
- ['bzl'] = {'file.bazel', 'file.bzl', 'WORKSPACE'},
- ['bc'] = {'file.bc'},
- ['bdf'] = {'file.bdf'},
- ['bib'] = {'file.bib'},
- ['beancount'] = {'file.beancount'},
- ['bindzone'] = {'named.root', '/bind/db.file', '/named/db.file', 'any/bind/db.file', 'any/named/db.file'},
- ['blank'] = {'file.bl'},
- ['bsdl'] = {'file.bsd', 'file.bsdl', 'bsd', 'some-bsd'},
- ['bst'] = {'file.bst'},
- ['bzr'] = {'bzr_log.any', 'bzr_log.file'},
- ['c'] = {'enlightenment/file.cfg', 'file.qc', 'file.c', 'some-enlightenment/file.cfg'},
- ['cabal'] = {'file.cabal'},
- ['cabalconfig'] = {'cabal.config'},
- ['cabalproject'] = {'cabal.project', 'cabal.project.local'},
- ['calendar'] = {'calendar', '/.calendar/file', '/share/calendar/any/calendar.file', '/share/calendar/calendar.file', 'any/share/calendar/any/calendar.file', 'any/share/calendar/calendar.file'},
- ['catalog'] = {'catalog', 'sgml.catalogfile', 'sgml.catalog', 'sgml.catalog-file'},
- ['cdl'] = {'file.cdl'},
- ['cdrdaoconf'] = {'/etc/cdrdao.conf', '/etc/defaults/cdrdao', '/etc/default/cdrdao', '.cdrdao', 'any/etc/cdrdao.conf', 'any/etc/default/cdrdao', 'any/etc/defaults/cdrdao'},
- ['cdrtoc'] = {'file.toc'},
- ['cf'] = {'file.cfm', 'file.cfi', 'file.cfc'},
- ['cfengine'] = {'cfengine.conf'},
- ['cfg'] = {'file.cfg', 'file.hgrc', 'filehgrc', 'hgrc', 'some-hgrc'},
- ['ch'] = {'file.chf'},
- ['chaiscript'] = {'file.chai'},
- ['chaskell'] = {'file.chs'},
- ['chill'] = {'file..ch'},
- ['chordpro'] = {'file.chopro', 'file.crd', 'file.cho', 'file.crdpro', 'file.chordpro'},
- ['cl'] = {'file.eni'},
- ['clean'] = {'file.dcl', 'file.icl'},
- ['clojure'] = {'file.clj', 'file.cljs', 'file.cljx', 'file.cljc'},
- ['cmake'] = {'CMakeLists.txt', 'file.cmake', 'file.cmake.in'},
- ['cmusrc'] = {'any/.cmus/autosave', 'any/.cmus/rc', 'any/.cmus/command-history', 'any/.cmus/file.theme', 'any/cmus/rc', 'any/cmus/file.theme', '/.cmus/autosave', '/.cmus/command-history', '/.cmus/file.theme', '/.cmus/rc', '/cmus/file.theme', '/cmus/rc'},
- ['cobol'] = {'file.cbl', 'file.cob', 'file.lib'},
- ['coco'] = {'file.atg'},
- ['conaryrecipe'] = {'file.recipe'},
- ['conf'] = {'auto.master'},
- ['config'] = {'configure.in', 'configure.ac', '/etc/hostname.file'},
- ['context'] = {'tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'},
- ['cpp'] = {'file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'},
- ['crm'] = {'file.crm'},
- ['crontab'] = {'crontab', 'crontab.file', '/etc/cron.d/file', 'any/etc/cron.d/file'},
- ['cs'] = {'file.cs', 'file.csx'},
- ['csc'] = {'file.csc'},
- ['csdl'] = {'file.csdl'},
- ['csp'] = {'file.csp', 'file.fdr'},
- ['css'] = {'file.css'},
- ['cterm'] = {'file.con'},
- ['cucumber'] = {'file.feature'},
- ['cuda'] = {'file.cu', 'file.cuh'},
- ['cupl'] = {'file.pld'},
- ['cuplsim'] = {'file.si'},
- ['cvs'] = {'cvs123'},
- ['cvsrc'] = {'.cvsrc'},
- ['cynpp'] = {'file.cyn'},
- ['dart'] = {'file.dart', 'file.drt'},
- ['datascript'] = {'file.ds'},
- ['dcd'] = {'file.dcd'},
- ['debchangelog'] = {'changelog.Debian', 'changelog.dch', 'NEWS.Debian', 'NEWS.dch', '/debian/changelog'},
- ['debcontrol'] = {'/debian/control', 'any/debian/control'},
- ['debcopyright'] = {'/debian/copyright', 'any/debian/copyright'},
- ['debsources'] = {'/etc/apt/sources.list', '/etc/apt/sources.list.d/file.list', 'any/etc/apt/sources.list', 'any/etc/apt/sources.list.d/file.list'},
- ['def'] = {'file.def'},
- ['denyhosts'] = {'denyhosts.conf'},
- ['desc'] = {'file.desc'},
- ['desktop'] = {'file.desktop', '.directory', 'file.directory'},
- ['dictconf'] = {'dict.conf', '.dictrc'},
- ['dictdconf'] = {'dictd.conf', 'dictdfile.conf', 'dictd-file.conf'},
- ['diff'] = {'file.diff', 'file.rej'},
- ['dircolors'] = {'.dir_colors', '.dircolors', '/etc/DIR_COLORS', 'any/etc/DIR_COLORS'},
- ['dnsmasq'] = {'/etc/dnsmasq.conf', '/etc/dnsmasq.d/file', 'any/etc/dnsmasq.conf', 'any/etc/dnsmasq.d/file'},
- ['dockerfile'] = {'Containerfile', 'Dockerfile', 'file.Dockerfile', 'Dockerfile.debian', 'Containerfile.something'},
- ['dosbatch'] = {'file.bat', 'file.sys'},
- ['dosini'] = {'.editorconfig', '/etc/pacman.conf', '/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/pacman.conf', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file', 'file.wrap'},
- ['dot'] = {'file.dot', 'file.gv'},
- ['dracula'] = {'file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'},
- ['dtd'] = {'file.dtd'},
- ['dts'] = {'file.dts', 'file.dtsi'},
- ['dune'] = {'jbuild', 'dune', 'dune-project', 'dune-workspace'},
- ['dylan'] = {'file.dylan'},
- ['dylanintr'] = {'file.intr'},
- ['dylanlid'] = {'file.lid'},
- ['ecd'] = {'file.ecd'},
- ['edif'] = {'file.edf', 'file.edif', 'file.edo'},
- ['elinks'] = {'elinks.conf'},
- ['elixir'] = {'file.ex', 'file.exs', 'mix.lock'},
- ['eelixir'] = {'file.eex', 'file.leex'},
- ['elm'] = {'file.elm'},
- ['elmfilt'] = {'filter-rules'},
- ['epuppet'] = {'file.epp'},
- ['erlang'] = {'file.erl', 'file.hrl', 'file.yaws'},
- ['eruby'] = {'file.erb', 'file.rhtml'},
- ['esmtprc'] = {'anyesmtprc', 'esmtprc', 'some-esmtprc'},
- ['esqlc'] = {'file.ec', 'file.EC'},
- ['esterel'] = {'file.strl'},
- ['eterm'] = {'anyEterm/file.cfg', 'Eterm/file.cfg', 'some-Eterm/file.cfg'},
- ['exim'] = {'exim.conf'},
- ['expect'] = {'file.exp'},
- ['exports'] = {'exports'},
- ['factor'] = {'file.factor'},
- ['falcon'] = {'file.fal'},
- ['fan'] = {'file.fan', 'file.fwt'},
- ['fennel'] = {'file.fnl'},
- ['fetchmail'] = {'.fetchmailrc'},
- ['fgl'] = {'file.4gl', 'file.4gh', 'file.m4gl'},
- ['fish'] = {'file.fish'},
- ['focexec'] = {'file.fex', 'file.focexec'},
- ['forth'] = {'file.ft', 'file.fth'},
- ['fortran'] = {'file.f', 'file.for', 'file.fortran', 'file.fpp', 'file.ftn', 'file.f77', 'file.f90', 'file.f95', 'file.f03', 'file.f08'},
- ['fpcmake'] = {'file.fpc'},
- ['framescript'] = {'file.fsl'},
- ['freebasic'] = {'file.fb', 'file.bi'},
- ['fsharp'] = {'file.fs', 'file.fsi', 'file.fsx'},
- ['fstab'] = {'fstab', 'mtab'},
- ['fvwm'] = {'/.fvwm/file', 'any/.fvwm/file'},
- ['gdb'] = {'.gdbinit', 'gdbinit'},
- ['gdmo'] = {'file.mo', 'file.gdmo'},
- ['gedcom'] = {'file.ged', 'lltxxxxx.txt', '/tmp/lltmp', '/tmp/lltmp-file', 'any/tmp/lltmp', 'any/tmp/lltmp-file'},
- ['gemtext'] = {'file.gmi', 'file.gemini'},
- ['gift'] = {'file.gift'},
- ['gitcommit'] = {'COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG'},
- ['gitconfig'] = {'file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'},
- ['gitolite'] = {'gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'},
- ['gitrebase'] = {'git-rebase-todo'},
- ['gitsendemail'] = {'.gitsendemail.msg.xxxxxx'},
- ['gkrellmrc'] = {'gkrellmrc', 'gkrellmrc_x'},
- ['gnash'] = {'gnashrc', '.gnashrc', 'gnashpluginrc', '.gnashpluginrc'},
- ['gnuplot'] = {'file.gpi'},
- ['go'] = {'file.go'},
- ['gomod'] = {'go.mod'},
- ['gp'] = {'file.gp', '.gprc'},
- ['gpg'] = {'/.gnupg/options', '/.gnupg/gpg.conf', '/usr/any/gnupg/options.skel', 'any/.gnupg/gpg.conf', 'any/.gnupg/options', 'any/usr/any/gnupg/options.skel'},
- ['grads'] = {'file.gs'},
- ['gretl'] = {'file.gretl'},
- ['groovy'] = {'file.gradle', 'file.groovy'},
- ['group'] = {'any/etc/group', 'any/etc/group-', 'any/etc/group.edit', 'any/etc/gshadow', 'any/etc/gshadow-', 'any/etc/gshadow.edit', 'any/var/backups/group.bak', 'any/var/backups/gshadow.bak', '/etc/group', '/etc/group-', '/etc/group.edit', '/etc/gshadow', '/etc/gshadow-', '/etc/gshadow.edit', '/var/backups/group.bak', '/var/backups/gshadow.bak'},
- ['grub'] = {'/boot/grub/menu.lst', '/boot/grub/grub.conf', '/etc/grub.conf', 'any/boot/grub/grub.conf', 'any/boot/grub/menu.lst', 'any/etc/grub.conf'},
- ['gsp'] = {'file.gsp'},
- ['gtkrc'] = {'.gtkrc', 'gtkrc', '.gtkrc-file', 'gtkrc-file'},
- ['haml'] = {'file.haml'},
- ['hamster'] = {'file.hsm'},
- ['haskell'] = {'file.hs', 'file.hsc', 'file.hs-boot', 'file.hsig'},
- ['haste'] = {'file.ht'},
- ['hastepreproc'] = {'file.htpp'},
- ['hb'] = {'file.hb'},
- ['hercules'] = {'file.vc', 'file.ev', 'file.sum', 'file.errsum'},
- ['hex'] = {'file.hex', 'file.h32'},
- ['hgcommit'] = {'hg-editor-file.txt'},
- ['hog'] = {'file.hog', 'snort.conf', 'vision.conf'},
- ['hollywood'] = {'file.hws'},
- ['hostconf'] = {'/etc/host.conf', 'any/etc/host.conf'},
- ['hostsaccess'] = {'/etc/hosts.allow', '/etc/hosts.deny', 'any/etc/hosts.allow', 'any/etc/hosts.deny'},
- ['i3config'] = {'/home/user/.i3/config', '/home/user/.config/i3/config', '/etc/i3/config', '/etc/xdg/i3/config'},
- ['logcheck'] = {'/etc/logcheck/file.d-some/file', '/etc/logcheck/file.d/file', 'any/etc/logcheck/file.d-some/file', 'any/etc/logcheck/file.d/file'},
- ['modula3'] = {'file.m3', 'file.mg', 'file.i3', 'file.ig'},
- ['natural'] = {'file.NSA', 'file.NSC', 'file.NSG', 'file.NSL', 'file.NSM', 'file.NSN', 'file.NSP', 'file.NSS'},
- ['neomuttrc'] = {'Neomuttrc', '.neomuttrc', '.neomuttrc-file', '/.neomutt/neomuttrc', '/.neomutt/neomuttrc-file', 'Neomuttrc', 'Neomuttrc-file', 'any/.neomutt/neomuttrc', 'any/.neomutt/neomuttrc-file', 'neomuttrc', 'neomuttrc-file'},
- ['opl'] = {'file.OPL', 'file.OPl', 'file.OpL', 'file.Opl', 'file.oPL', 'file.oPl', 'file.opL', 'file.opl'},
- ['pcmk'] = {'file.pcmk'},
- ['r'] = {'file.r'},
- ['rhelp'] = {'file.rd'},
- ['rmd'] = {'file.rmd', 'file.smd'},
- ['rnoweb'] = {'file.rnw', 'file.snw'},
- ['rrst'] = {'file.rrst', 'file.srst'},
- ['template'] = {'file.tmpl'},
- ['htmlm4'] = {'file.html.m4'},
- ['httest'] = {'file.htt', 'file.htb'},
- ['ibasic'] = {'file.iba', 'file.ibi'},
- ['icemenu'] = {'/.icewm/menu', 'any/.icewm/menu'},
- ['icon'] = {'file.icn'},
- ['indent'] = {'.indent.pro', 'indentrc'},
- ['inform'] = {'file.inf', 'file.INF'},
- ['initng'] = {'/etc/initng/any/file.i', 'file.ii', 'any/etc/initng/any/file.i'},
- ['inittab'] = {'inittab'},
- ['ipfilter'] = {'ipf.conf', 'ipf6.conf', 'ipf.rules'},
- ['iss'] = {'file.iss'},
- ['ist'] = {'file.ist', 'file.mst'},
- ['j'] = {'file.ijs'},
- ['jal'] = {'file.jal', 'file.JAL'},
- ['jam'] = {'file.jpl', 'file.jpr', 'JAM-file.file', 'JAM.file', 'Prl-file.file', 'Prl.file'},
- ['java'] = {'file.java', 'file.jav'},
- ['javacc'] = {'file.jj', 'file.jjt'},
- ['javascript'] = {'file.js', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs'},
- ['javascriptreact'] = {'file.jsx'},
- ['jess'] = {'file.clp'},
- ['jgraph'] = {'file.jgr'},
- ['jovial'] = {'file.jov', 'file.j73', 'file.jovial'},
- ['jproperties'] = {'file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file'},
- ['json'] = {'file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.babelrc', '.eslintrc', '.prettierrc', '.firebaserc', 'file.slnf'},
- ['jsonc'] = {'file.jsonc'},
- ['jsp'] = {'file.jsp'},
- ['julia'] = {'file.jl'},
- ['kconfig'] = {'Kconfig', 'Kconfig.debug', 'Kconfig.file'},
- ['kivy'] = {'file.kv'},
- ['kix'] = {'file.kix'},
- ['kotlin'] = {'file.kt', 'file.ktm', 'file.kts'},
- ['kscript'] = {'file.ks'},
- ['kwt'] = {'file.k'},
- ['lace'] = {'file.ace', 'file.ACE'},
- ['latte'] = {'file.latte', 'file.lte'},
- ['ld'] = {'file.ld'},
- ['ldif'] = {'file.ldif'},
- ['less'] = {'file.less'},
- ['lex'] = {'file.lex', 'file.l', 'file.lxx', 'file.l++'},
- ['lftp'] = {'lftp.conf', '.lftprc', 'anylftp/rc', 'lftp/rc', 'some-lftp/rc'},
- ['lhaskell'] = {'file.lhs'},
- ['libao'] = {'/etc/libao.conf', '/.libao', 'any/.libao', 'any/etc/libao.conf'},
- ['lifelines'] = {'file.ll'},
- ['lilo'] = {'lilo.conf', 'lilo.conf-file'},
- ['limits'] = {'/etc/limits', '/etc/anylimits.conf', '/etc/anylimits.d/file.conf', '/etc/limits.conf', '/etc/limits.d/file.conf', '/etc/some-limits.conf', '/etc/some-limits.d/file.conf', 'any/etc/limits', 'any/etc/limits.conf', 'any/etc/limits.d/file.conf', 'any/etc/some-limits.conf', 'any/etc/some-limits.d/file.conf'},
- ['liquid'] = {'file.liquid'},
- ['lisp'] = {'file.lsp', 'file.lisp', 'file.asd', 'file.el', 'file.cl', '.emacs', '.sawfishrc', 'sbclrc', '.sbclrc'},
- ['lite'] = {'file.lite', 'file.lt'},
- ['litestep'] = {'/LiteStep/any/file.rc', 'any/LiteStep/any/file.rc'},
- ['loginaccess'] = {'/etc/login.access', 'any/etc/login.access'},
- ['logindefs'] = {'/etc/login.defs', 'any/etc/login.defs'},
- ['logtalk'] = {'file.lgt'},
- ['lotos'] = {'file.lot', 'file.lotos'},
- ['lout'] = {'file.lou', 'file.lout'},
- ['lprolog'] = {'file.sig'},
- ['lsl'] = {'file.lsl'},
- ['lss'] = {'file.lss'},
- ['lua'] = {'file.lua', 'file.rockspec', 'file.nse'},
- ['lynx'] = {'lynx.cfg'},
- ['matlab'] = {'file.m'},
- ['m3build'] = {'m3makefile', 'm3overrides'},
- ['m3quake'] = {'file.quake', 'cm3.cfg'},
- ['m4'] = {'file.at'},
- ['mail'] = {'snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml', 'reportbug-file'},
- ['mailaliases'] = {'/etc/mail/aliases', '/etc/aliases', 'any/etc/aliases', 'any/etc/mail/aliases'},
- ['mailcap'] = {'.mailcap', 'mailcap'},
- ['make'] = {'file.mk', 'file.mak', 'file.dsp', 'makefile', 'Makefile', 'makefile-file', 'Makefile-file', 'some-makefile', 'some-Makefile'},
- ['mallard'] = {'file.page'},
- ['manconf'] = {'/etc/man.conf', 'man.config', 'any/etc/man.conf'},
- ['map'] = {'file.map'},
- ['maple'] = {'file.mv', 'file.mpl', 'file.mws'},
- ['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'},
- ['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',
- '/log/auth.log', '/log/cron.log', '/log/daemon.log', '/log/debug.log', '/log/kern.log', '/log/lpr.log', '/log/mail.log', '/log/messages.log', '/log/news/news.log', '/log/syslog.log', '/log/user.log',
- '/log/auth.err', '/log/cron.err', '/log/daemon.err', '/log/debug.err', '/log/kern.err', '/log/lpr.err', '/log/mail.err', '/log/messages.err', '/log/news/news.err', '/log/syslog.err', '/log/user.err',
- '/log/auth.info', '/log/cron.info', '/log/daemon.info', '/log/debug.info', '/log/kern.info', '/log/lpr.info', '/log/mail.info', '/log/messages.info', '/log/news/news.info', '/log/syslog.info', '/log/user.info',
- '/log/auth.warn', '/log/cron.warn', '/log/daemon.warn', '/log/debug.warn', '/log/kern.warn', '/log/lpr.warn', '/log/mail.warn', '/log/messages.warn', '/log/news/news.warn', '/log/syslog.warn', '/log/user.warn',
- '/log/auth.crit', '/log/cron.crit', '/log/daemon.crit', '/log/debug.crit', '/log/kern.crit', '/log/lpr.crit', '/log/mail.crit', '/log/messages.crit', '/log/news/news.crit', '/log/syslog.crit', '/log/user.crit',
- '/log/auth.notice', '/log/cron.notice', '/log/daemon.notice', '/log/debug.notice', '/log/kern.notice', '/log/lpr.notice', '/log/mail.notice', '/log/messages.notice', '/log/news/news.notice', '/log/syslog.notice', '/log/user.notice'},
- ['mf'] = {'file.mf'},
- ['mgl'] = {'file.mgl'},
- ['mgp'] = {'file.mgp'},
- ['mib'] = {'file.mib', 'file.my'},
- ['mix'] = {'file.mix', 'file.mixal'},
- ['mma'] = {'file.nb'},
- ['mmp'] = {'file.mmp'},
- ['modconf'] = {'/etc/modules.conf', '/etc/modules', '/etc/conf.modules', '/etc/modprobe.file', 'any/etc/conf.modules', 'any/etc/modprobe.file', 'any/etc/modules', 'any/etc/modules.conf'},
- ['modula2'] = {'file.m2', 'file.mi'},
- ['monk'] = {'file.isc', 'file.monk', 'file.ssc', 'file.tsc'},
- ['moo'] = {'file.moo'},
- ['mp'] = {'file.mp'},
- ['mplayerconf'] = {'mplayer.conf', '/.mplayer/config', 'any/.mplayer/config'},
- ['mrxvtrc'] = {'mrxvtrc', '.mrxvtrc'},
- ['msidl'] = {'file.odl', 'file.mof'},
- ['msql'] = {'file.msql'},
- ['mupad'] = {'file.mu'},
- ['mush'] = {'file.mush'},
- ['muttrc'] = {'Muttngrc', 'Muttrc', '.muttngrc', '.muttngrc-file', '.muttrc', '.muttrc-file', '/.mutt/muttngrc', '/.mutt/muttngrc-file', '/.mutt/muttrc', '/.mutt/muttrc-file', '/.muttng/muttngrc', '/.muttng/muttngrc-file', '/.muttng/muttrc', '/.muttng/muttrc-file', '/etc/Muttrc.d/file', '/etc/Muttrc.d/file.rc', 'Muttngrc-file', 'Muttrc-file', 'any/.mutt/muttngrc', 'any/.mutt/muttngrc-file', 'any/.mutt/muttrc', 'any/.mutt/muttrc-file', 'any/.muttng/muttngrc', 'any/.muttng/muttngrc-file', 'any/.muttng/muttrc', 'any/.muttng/muttrc-file', 'any/etc/Muttrc.d/file', 'muttngrc', 'muttngrc-file', 'muttrc', 'muttrc-file'},
- ['mysql'] = {'file.mysql'},
- ['n1ql'] = {'file.n1ql', 'file.nql'},
- ['named'] = {'namedfile.conf', 'rndcfile.conf', 'named-file.conf', 'named.conf', 'rndc-file.conf', 'rndc-file.key', 'rndc.conf', 'rndc.key'},
- ['nanorc'] = {'/etc/nanorc', 'file.nanorc', 'any/etc/nanorc'},
- ['ncf'] = {'file.ncf'},
- ['netrc'] = {'.netrc'},
- ['nginx'] = {'file.nginx', 'nginxfile.conf', 'filenginx.conf', 'any/etc/nginx/file', 'any/usr/local/nginx/conf/file', 'any/nginx/file.conf'},
- ['ninja'] = {'file.ninja'},
- ['nqc'] = {'file.nqc'},
- ['nroff'] = {'file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom', 'tmac.file'},
- ['nsis'] = {'file.nsi', 'file.nsh'},
- ['obj'] = {'file.obj'},
- ['ocaml'] = {'file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit', 'file.mlt', 'file.mlp', 'file.mlip', 'file.mli.cppo', 'file.ml.cppo'},
- ['occam'] = {'file.occ'},
- ['octave'] = {'octaverc', '.octaverc', 'octave.conf'},
- ['omnimark'] = {'file.xom', 'file.xin'},
- ['opam'] = {'opam', 'file.opam', 'file.opam.template'},
- ['openroad'] = {'file.or'},
- ['ora'] = {'file.ora'},
- ['pamconf'] = {'/etc/pam.conf', '/etc/pam.d/file', 'any/etc/pam.conf', 'any/etc/pam.d/file'},
- ['pamenv'] = {'/etc/security/pam_env.conf', '/home/user/.pam_environment', '.pam_environment', 'pam_env.conf'},
- ['papp'] = {'file.papp', 'file.pxml', 'file.pxsl'},
- ['pascal'] = {'file.pas', 'file.dpr', 'file.lpr'},
- ['passwd'] = {'any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak', '/etc/passwd', '/etc/passwd-', '/etc/passwd.edit', '/etc/shadow', '/etc/shadow-', '/etc/shadow.edit', '/var/backups/passwd.bak', '/var/backups/shadow.bak'},
- ['pbtxt'] = {'file.pbtxt'},
- ['pccts'] = {'file.g'},
- ['pdf'] = {'file.pdf'},
- ['perl'] = {'file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'},
- ['pf'] = {'pf.conf'},
- ['pfmain'] = {'main.cf'},
- ['php'] = {'file.php', 'file.php9', 'file.phtml', 'file.ctp'},
- ['lpc'] = {'file.lpc', 'file.ulpc'},
- ['pike'] = {'file.pike', 'file.pmod'},
- ['cmod'] = {'file.cmod'},
- ['pilrc'] = {'file.rcp'},
- ['pine'] = {'.pinerc', 'pinerc', '.pinercex', 'pinercex'},
- ['pinfo'] = {'/etc/pinforc', '/.pinforc', 'any/.pinforc', 'any/etc/pinforc'},
- ['pli'] = {'file.pli', 'file.pl1'},
- ['plm'] = {'file.plm', 'file.p36', 'file.pac'},
- ['plp'] = {'file.plp'},
- ['plsql'] = {'file.pls', 'file.plsql'},
- ['po'] = {'file.po', 'file.pot'},
- ['pod'] = {'file.pod'},
- ['poke'] = {'file.pk'},
- ['postscr'] = {'file.ps', 'file.pfa', 'file.afm', 'file.eps', 'file.epsf', 'file.epsi', 'file.ai'},
- ['pov'] = {'file.pov'},
- ['povini'] = {'.povrayrc'},
- ['ppd'] = {'file.ppd'},
- ['ppwiz'] = {'file.it', 'file.ih'},
- ['privoxy'] = {'file.action'},
- ['proc'] = {'file.pc'},
- ['procmail'] = {'.procmail', '.procmailrc'},
- ['prolog'] = {'file.pdb'},
- ['promela'] = {'file.pml'},
- ['proto'] = {'file.proto'},
- ['protocols'] = {'/etc/protocols', 'any/etc/protocols'},
- ['ps1'] = {'file.ps1', 'file.psd1', 'file.psm1', 'file.pssc'},
- ['ps1xml'] = {'file.ps1xml'},
- ['psf'] = {'file.psf'},
- ['psl'] = {'file.psl'},
- ['puppet'] = {'file.pp'},
- ['pyret'] = {'file.arr'},
- ['pyrex'] = {'file.pyx', 'file.pxd'},
- ['python'] = {'file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl', 'file.pyi', 'SConstruct'},
- ['quake'] = {'anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg', 'baseq2/file.cfg', 'id1/file.cfg', 'quake1/file.cfg', 'some-baseq2/file.cfg', 'some-id1/file.cfg', 'some-quake1/file.cfg'},
- ['radiance'] = {'file.rad', 'file.mat'},
- ['raku'] = {'file.pm6', 'file.p6', 'file.t6', 'file.pod6', 'file.raku', 'file.rakumod', 'file.rakudoc', 'file.rakutest'},
- ['ratpoison'] = {'.ratpoisonrc', 'ratpoisonrc'},
- ['rbs'] = {'file.rbs'},
- ['rc'] = {'file.rc', 'file.rch'},
- ['rcs'] = {'file,v'},
- ['readline'] = {'.inputrc', 'inputrc'},
- ['remind'] = {'.reminders', 'file.remind', 'file.rem', '.reminders-file'},
- ['rego'] = {'file.rego'},
- ['resolv'] = {'resolv.conf'},
- ['reva'] = {'file.frt'},
- ['rexx'] = {'file.rex', 'file.orx', 'file.rxo', 'file.rxj', 'file.jrexx', 'file.rexxj', 'file.rexx', 'file.testGroup', 'file.testUnit'},
- ['rib'] = {'file.rib'},
- ['rnc'] = {'file.rnc'},
- ['rng'] = {'file.rng'},
- ['robots'] = {'robots.txt'},
- ['routeros'] = {'file.rsc'},
- ['rpcgen'] = {'file.x'},
- ['rpl'] = {'file.rpl'},
- ['rst'] = {'file.rst'},
- ['rtf'] = {'file.rtf'},
- ['ruby'] = {'.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file', 'Puppetfile'},
- ['rust'] = {'file.rs'},
- ['samba'] = {'smb.conf'},
- ['sas'] = {'file.sas'},
- ['sass'] = {'file.sass'},
- ['sather'] = {'file.sa'},
- ['sbt'] = {'file.sbt'},
- ['scala'] = {'file.scala', 'file.sc'},
- ['scheme'] = {'file.scm', 'file.ss', 'file.sld', 'file.rkt', 'file.rktd', 'file.rktl'},
- ['scilab'] = {'file.sci', 'file.sce'},
- ['screen'] = {'.screenrc', 'screenrc'},
- ['sexplib'] = {'file.sexp'},
- ['scdoc'] = {'file.scd'},
- ['scss'] = {'file.scss'},
- ['sd'] = {'file.sd'},
- ['sdc'] = {'file.sdc'},
- ['sdl'] = {'file.sdl', 'file.pr'},
- ['sed'] = {'file.sed'},
- ['sensors'] = {'/etc/sensors.conf', '/etc/sensors3.conf', 'any/etc/sensors.conf', 'any/etc/sensors3.conf'},
- ['services'] = {'/etc/services', 'any/etc/services'},
- ['setserial'] = {'/etc/serial.conf', 'any/etc/serial.conf'},
- ['sh'] = {'.bashrc', 'file.bash', '/usr/share/doc/bash-completion/filter.sh','/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf'},
- ['sieve'] = {'file.siv', 'file.sieve'},
- ['simula'] = {'file.sim'},
- ['sinda'] = {'file.sin', 'file.s85'},
- ['sisu'] = {'file.sst', 'file.ssm', 'file.ssi', 'file.-sst', 'file._sst', 'file.sst.meta', 'file.-sst.meta', 'file._sst.meta'},
- ['skill'] = {'file.il', 'file.ils', 'file.cdf'},
- ['slang'] = {'file.sl'},
- ['slice'] = {'file.ice'},
- ['solution'] = {'file.sln'},
- ['slpconf'] = {'/etc/slp.conf', 'any/etc/slp.conf'},
- ['slpreg'] = {'/etc/slp.reg', 'any/etc/slp.reg'},
- ['slpspi'] = {'/etc/slp.spi', 'any/etc/slp.spi'},
- ['slrnrc'] = {'.slrnrc'},
- ['slrnsc'] = {'file.score'},
- ['sm'] = {'sendmail.cf'},
- ['svelte'] = {'file.svelte'},
- ['smarty'] = {'file.tpl'},
- ['smcl'] = {'file.hlp', 'file.ihlp', 'file.smcl'},
- ['smith'] = {'file.smt', 'file.smith'},
- ['sml'] = {'file.sml'},
- ['snobol4'] = {'file.sno', 'file.spt'},
- ['sparql'] = {'file.rq', 'file.sparql'},
- ['spec'] = {'file.spec'},
- ['spice'] = {'file.sp', 'file.spice'},
- ['spup'] = {'file.speedup', 'file.spdata', 'file.spd'},
- ['spyce'] = {'file.spy', 'file.spi'},
- ['sql'] = {'file.tyb', 'file.typ', 'file.tyc', 'file.pkb', 'file.pks'},
- ['sqlj'] = {'file.sqlj'},
- ['sqr'] = {'file.sqr', 'file.sqi'},
- ['squid'] = {'squid.conf'},
- ['squirrel'] = {'file.nut'},
- ['srec'] = {'file.s19', 'file.s28', 'file.s37', 'file.mot', 'file.srec'},
- ['sshconfig'] = {'ssh_config', '/.ssh/config', '/etc/ssh/ssh_config.d/file.conf', 'any/etc/ssh/ssh_config.d/file.conf', 'any/.ssh/config', 'any/.ssh/file.conf'},
- ['sshdconfig'] = {'sshd_config', '/etc/ssh/sshd_config.d/file.conf', 'any/etc/ssh/sshd_config.d/file.conf'},
- ['st'] = {'file.st'},
- ['stata'] = {'file.ado', 'file.do', 'file.imata', 'file.mata'},
- ['stp'] = {'file.stp'},
- ['sudoers'] = {'any/etc/sudoers', 'sudoers.tmp', '/etc/sudoers', 'any/etc/sudoers.d/file'},
- ['svg'] = {'file.svg'},
- ['svn'] = {'svn-commitfile.tmp', 'svn-commit-file.tmp', 'svn-commit.tmp'},
- ['swift'] = {'file.swift'},
- ['swiftgyb'] = {'file.swift.gyb'},
- ['sil'] = {'file.sil'},
- ['sysctl'] = {'/etc/sysctl.conf', '/etc/sysctl.d/file.conf', 'any/etc/sysctl.conf', 'any/etc/sysctl.d/file.conf'},
- ['systemd'] = {'any/systemd/file.automount', 'any/systemd/file.dnssd', 'any/systemd/file.link', 'any/systemd/file.mount', 'any/systemd/file.netdev', 'any/systemd/file.network', 'any/systemd/file.nspawn', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.slice', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/some.conf.d/file.conf', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file', '/etc/systemd/system/.#otherfile', '/home/user/.config/systemd/user/some.d/mine.conf', '/home/user/.config/systemd/user/some.d/.#file', '/home/user/.config/systemd/user/.#otherfile', '/.config/systemd/user/.#', '/.config/systemd/user/.#-file', '/.config/systemd/user/file.d/.#', '/.config/systemd/user/file.d/.#-file', '/.config/systemd/user/file.d/file.conf', '/etc/systemd/file.conf.d/file.conf', '/etc/systemd/system/.#', '/etc/systemd/system/.#-file', '/etc/systemd/system/file.d/.#', '/etc/systemd/system/file.d/.#-file', '/etc/systemd/system/file.d/file.conf', '/systemd/file.automount', '/systemd/file.dnssd', '/systemd/file.link', '/systemd/file.mount', '/systemd/file.netdev', '/systemd/file.network', '/systemd/file.nspawn', '/systemd/file.path', '/systemd/file.service', '/systemd/file.slice', '/systemd/file.socket', '/systemd/file.swap', '/systemd/file.target', '/systemd/file.timer', 'any/.config/systemd/user/.#', 'any/.config/systemd/user/.#-file', 'any/.config/systemd/user/file.d/.#', 'any/.config/systemd/user/file.d/.#-file', 'any/.config/systemd/user/file.d/file.conf', 'any/etc/systemd/file.conf.d/file.conf', 'any/etc/systemd/system/.#', 'any/etc/systemd/system/.#-file', 'any/etc/systemd/system/file.d/.#', 'any/etc/systemd/system/file.d/.#-file', 'any/etc/systemd/system/file.d/file.conf'},
- ['systemverilog'] = {'file.sv', 'file.svh'},
- ['tags'] = {'tags'},
- ['tak'] = {'file.tak'},
- ['taskdata'] = {'pending.data', 'completed.data', 'undo.data'},
- ['taskedit'] = {'file.task'},
- ['tcl'] = {'file.tcl', 'file.tm', 'file.tk', 'file.itcl', 'file.itk', 'file.jacl', '.tclshrc', 'tclsh.rc', '.wishrc'},
- ['teraterm'] = {'file.ttl'},
- ['terminfo'] = {'file.ti'},
- ['tex'] = {'file.latex', 'file.sty', 'file.dtx', 'file.ltx', 'file.bbl'},
- ['texinfo'] = {'file.texinfo', 'file.texi', 'file.txi'},
- ['texmf'] = {'texmf.cnf'},
- ['text'] = {'file.text', 'file.txt', 'README', 'LICENSE', 'COPYING', 'AUTHORS', '/usr/share/doc/bash-completion/AUTHORS', '/etc/apt/apt.conf.d/README', '/etc/Muttrc.d/README'},
- ['tf'] = {'file.tf', '.tfrc', 'tfrc'},
- ['tidy'] = {'.tidyrc', 'tidyrc', 'tidy.conf'},
- ['tilde'] = {'file.t.html'},
- ['tli'] = {'file.tli'},
- ['tmux'] = {'tmuxfile.conf', '.tmuxfile.conf', '.tmux-file.conf', '.tmux.conf', 'tmux-file.conf', 'tmux.conf', 'tmux.conf.local'},
- ['toml'] = {'file.toml', 'Gopkg.lock', 'Pipfile', '/home/user/.cargo/config'},
- ['tpp'] = {'file.tpp'},
- ['treetop'] = {'file.treetop'},
- ['trustees'] = {'trustees.conf'},
- ['tsalt'] = {'file.slt'},
- ['tsscl'] = {'file.tsscl'},
- ['tssgm'] = {'file.tssgm'},
- ['tssop'] = {'file.tssop'},
- ['twig'] = {'file.twig'},
- ['typescriptreact'] = {'file.tsx'},
- ['uc'] = {'file.uc'},
- ['udevconf'] = {'/etc/udev/udev.conf', 'any/etc/udev/udev.conf'},
- ['udevperm'] = {'/etc/udev/permissions.d/file.permissions', 'any/etc/udev/permissions.d/file.permissions'},
- ['udevrules'] = {'/etc/udev/rules.d/file.rules', '/usr/lib/udev/rules.d/file.rules', '/lib/udev/rules.d/file.rules'},
- ['uil'] = {'file.uit', 'file.uil'},
- ['updatedb'] = {'/etc/updatedb.conf', 'any/etc/updatedb.conf'},
- ['upstart'] = {'/usr/share/upstart/file.conf', '/usr/share/upstart/file.override', '/etc/init/file.conf', '/etc/init/file.override', '/.init/file.conf', '/.init/file.override', '/.config/upstart/file.conf', '/.config/upstart/file.override', 'any/.config/upstart/file.conf', 'any/.config/upstart/file.override', 'any/.init/file.conf', 'any/.init/file.override', 'any/etc/init/file.conf', 'any/etc/init/file.override', 'any/usr/share/upstart/file.conf', 'any/usr/share/upstart/file.override'},
- ['upstreamdat'] = {'upstream.dat', 'UPSTREAM.DAT', 'upstream.file.dat', 'UPSTREAM.FILE.DAT', 'file.upstream.dat', 'FILE.UPSTREAM.DAT'},
- ['upstreaminstalllog'] = {'upstreaminstall.log', 'UPSTREAMINSTALL.LOG', 'upstreaminstall.file.log', 'UPSTREAMINSTALL.FILE.LOG', 'file.upstreaminstall.log', 'FILE.UPSTREAMINSTALL.LOG'},
- ['upstreamlog'] = {'fdrupstream.log', 'upstream.log', 'UPSTREAM.LOG', 'upstream.file.log', 'UPSTREAM.FILE.LOG', 'file.upstream.log', 'FILE.UPSTREAM.LOG', 'UPSTREAM-file.log', 'UPSTREAM-FILE.LOG'},
- ['usserverlog'] = {'usserver.log', 'USSERVER.LOG', 'usserver.file.log', 'USSERVER.FILE.LOG', 'file.usserver.log', 'FILE.USSERVER.LOG'},
- ['usw2kagtlog'] = {'usw2kagt.log', 'USW2KAGT.LOG', 'usw2kagt.file.log', 'USW2KAGT.FILE.LOG', 'file.usw2kagt.log', 'FILE.USW2KAGT.LOG'},
- ['vb'] = {'file.sba', 'file.vb', 'file.vbs', 'file.dsm', 'file.ctl'},
- ['vera'] = {'file.vr', 'file.vri', 'file.vrh'},
- ['verilog'] = {'file.v'},
- ['verilogams'] = {'file.va', 'file.vams'},
- ['vgrindefs'] = {'vgrindefs'},
- ['vhdl'] = {'file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123', 'file.vho', 'some.vhdl_1', 'some.vhdl_1-file'},
- ['vim'] = {'file.vim', 'file.vba', '.exrc', '_exrc', 'some-vimrc', 'some-vimrc-file', 'vimrc', 'vimrc-file'},
- ['viminfo'] = {'.viminfo', '_viminfo'},
- ['vmasm'] = {'file.mar'},
- ['voscm'] = {'file.cm'},
- ['vrml'] = {'file.wrl'},
- ['vroom'] = {'file.vroom'},
- ['vue'] = {'file.vue'},
- ['wast'] = {'file.wast', 'file.wat'},
- ['webmacro'] = {'file.wm'},
- ['wget'] = {'.wgetrc', 'wgetrc'},
- ['winbatch'] = {'file.wbt'},
- ['wml'] = {'file.wml'},
- ['wsh'] = {'file.wsf', 'file.wsc'},
- ['wsml'] = {'file.wsml'},
- ['wvdial'] = {'wvdial.conf', '.wvdialrc'},
- ['xdefaults'] = {'.Xdefaults', '.Xpdefaults', '.Xresources', 'xdm-config', 'file.ad', '/Xresources/file', '/app-defaults/file', 'Xresources', 'Xresources-file', 'any/Xresources/file', 'any/app-defaults/file'},
- ['xhtml'] = {'file.xhtml', 'file.xht'},
- ['xinetd'] = {'/etc/xinetd.conf', '/etc/xinetd.d/file', 'any/etc/xinetd.conf', 'any/etc/xinetd.d/file'},
- ['xmath'] = {'file.msc', 'file.msf'},
- ['xml'] = {'/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.fsproj', 'file.fsproj.user', 'file.vbproj', 'file.vbproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu', 'file.atom', 'file.rss', 'file.cdxml', 'file.psc1', 'file.mpd'},
- ['xmodmap'] = {'anyXmodmap', 'Xmodmap', 'some-Xmodmap', 'some-xmodmap', 'some-xmodmap-file', 'xmodmap', 'xmodmap-file'},
- ['xf86conf'] = {'xorg.conf', 'xorg.conf-4'},
- ['xpm'] = {'file.xpm'},
- ['xpm2'] = {'file.xpm2'},
- ['xquery'] = {'file.xq', 'file.xql', 'file.xqm', 'file.xquery', 'file.xqy'},
- ['xs'] = {'file.xs'},
- ['xsd'] = {'file.xsd'},
- ['xslt'] = {'file.xsl', 'file.xslt'},
- ['yacc'] = {'file.yy', 'file.yxx', 'file.y++'},
- ['yaml'] = {'file.yaml', 'file.yml'},
- ['raml'] = {'file.raml'},
- ['z8a'] = {'file.z8a'},
- ['zig'] = {'file.zig'},
- ['zimbu'] = {'file.zu'},
- ['zimbutempl'] = {'file.zut'},
- ['zsh'] = {'.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh', '.zcompdump', '.zlogin', '.zlogout', '.zshenv', '.zshrc', '.zcompdump-file', '.zlog', '.zlog-file', '.zsh', '.zsh-file', 'any/etc/zprofile', 'zlog', 'zlog-file', 'zsh', 'zsh-file'},
- ['help'] = {funcs.getenv('VIMRUNTIME') .. '/doc/help.txt'},
- }
-
- local filename_case_checks = {
- ['modula2'] = {'file.DEF', 'file.MOD'},
- ['bzl'] = {'file.BUILD', 'BUILD'},
- }
-
- local function check_items(checks)
- meths.set_option('swapfile', false)
- for ft, names in pairs(checks) do
- for _, name in ipairs(names) do
- meths.command('new')
- meths.command('edit ' .. funcs.fnameescape(name))
- if curbufmeths.get_option('filetype') == '' and curbufmeths.get_option('readonly') then -- luacheck: ignore 542
- -- File exists but not able to edit it (permission denied)
- else
- eq(ft, curbufmeths.get_option('filetype'))
- end
- meths.command('bwipe!')
- end
- end
- meths.command('set swapfile&')
- end
-
- meths.set_var('do_filetype_lua', 1)
- meths.command('filetype on')
- check_items(filename_checks)
- if funcs.has('fname_case') == 1 then
- check_items(filename_case_checks)
- end
- meths.command('filetype off')
- end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 9bf376b6fe..642dc59bbc 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -2203,6 +2203,40 @@ describe('lua stdlib', function()
end)
end)
+ it('vim.notify_once', function()
+ local screen = Screen.new(60,5)
+ screen:set_default_attr_ids({
+ [0] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = {foreground=Screen.colors.Red},
+ })
+ screen:attach()
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ exec_lua [[vim.notify_once("I'll only tell you this once...", vim.log.levels.WARN)]]
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ {1:I'll only tell you this once...} |
+ ]]}
+ feed('<C-l>')
+ screen:expect{grid=[[
+ ^ |
+ {0:~ }|
+ {0:~ }|
+ {0:~ }|
+ |
+ ]]}
+ exec_lua [[vim.notify_once("I'll only tell you this once...")]]
+ screen:expect_unchanged()
+ end)
+
describe('vim.schedule_wrap', function()
it('preserves argument lists', function()
exec_lua [[
@@ -2298,3 +2332,82 @@ describe('lua: require("mod") from packages', function()
eq('I am fancy_z.lua', exec_lua [[ return require'fancy_z' ]])
end)
end)
+
+describe('vim.keymap', function()
+ it('can make a mapping', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ end)
+
+ it('can make an expr mapping', function()
+ exec_lua [[
+ vim.keymap.set('n', 'aa', function() return ':lua SomeValue = 99<cr>' end, {expr = true})
+ ]]
+
+ feed('aa')
+
+ eq(99, exec_lua[[return SomeValue]])
+ end)
+
+ it('can overwrite a mapping', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ exec_lua [[
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount - 1 end)
+ ]]
+
+ feed('asdf\n')
+
+ eq(0, exec_lua[[return GlobalCount]])
+ end)
+
+ it('can unmap a mapping', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
+ return GlobalCount
+ ]])
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+
+ exec_lua [[
+ vim.keymap.del('n', 'asdf')
+ ]]
+
+ feed('asdf\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
+ end)
+
+ it('can do <Plug> mappings', function()
+ eq(0, exec_lua [[
+ GlobalCount = 0
+ vim.keymap.set('n', '<plug>(asdf)', function() GlobalCount = GlobalCount + 1 end)
+ vim.keymap.set('n', 'ww', '<plug>(asdf)')
+ return GlobalCount
+ ]])
+
+ feed('ww\n')
+
+ eq(1, exec_lua[[return GlobalCount]])
+ end)
+
+end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 1ff451434d..beb43e0271 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -292,10 +292,9 @@ describe(':terminal buffer', function()
command('quit')
end)
- it('does not segfault when pasting empty buffer #13955', function()
- feed_command('terminal')
+ it('does not segfault when pasting empty register #13955', function()
feed('<c-\\><c-n>')
- feed_command('put a') -- buffer a is empty
+ feed_command('put a') -- register a is empty
helpers.assert_alive()
end)
end)