1

Regenerate nvim config

This commit is contained in:
2024-06-02 03:29:20 +02:00
parent 75eea0c030
commit ef2e28883d
5576 changed files with 604886 additions and 503 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 hrsh7th
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,52 @@
# cmp-cmdline
nvim-cmp source for vim's cmdline.
# Setup
Completions for `/` search based on current buffer:
```lua
-- `/` cmdline setup.
cmp.setup.cmdline('/', {
mapping = cmp.mapping.preset.cmdline(),
sources = {
{ name = 'buffer' }
}
})
```
Completions for command mode:
```lua
-- `:` cmdline setup.
cmp.setup.cmdline(':', {
mapping = cmp.mapping.preset.cmdline(),
sources = cmp.config.sources({
{ name = 'path' }
}, {
{
name = 'cmdline',
option = {
ignore_cmds = { 'Man', '!' }
}
}
})
})
```
For the buffer source to work, [cmp-buffer](https://github.com/hrsh7th/cmp-buffer) is needed.
# Option
### ignore_cmds: string[]
Default: `{ "Man", "!" }`
You can specify ignore command name.
### treat_trailing_slash: boolean
Default: `true`
`vim.fn.getcompletion` can return path items.
unfortunately, that items has trailing slash so we don't narrowing with next directory with pressing `/`.
if you turnd on this option, `cmp-cmdline` removes trailing slash automatically.

View File

@ -0,0 +1 @@
require('cmp').register_source('cmdline', require('cmp_cmdline').new())

View File

@ -0,0 +1,248 @@
local cmp = require('cmp')
---@param patterns string[]
---@param head boolean
---@return table #regex object
local function create_regex(patterns, head)
local pattern = [[\%(]] .. table.concat(patterns, [[\|]]) .. [[\)]]
if head then
pattern = '^' .. pattern
end
return vim.regex(pattern)
end
---@class cmp-cmdline.Option
---@field treat_trailing_slash boolean
---@field ignore_cmds string[]
local DEFAULT_OPTION = {
treat_trailing_slash = true,
ignore_cmds = { 'Man', '!' }
}
local MODIFIER_REGEX = create_regex({
[=[\s*abo\%[veleft]\s*]=],
[=[\s*bel\%[owright]\s*]=],
[=[\s*bo\%[tright]\s*]=],
[=[\s*bro\%[wse]\s*]=],
[=[\s*conf\%[irm]\s*]=],
[=[\s*hid\%[e]\s*]=],
[=[\s*keepal\s*t]=],
[=[\s*keeppa\%[tterns]\s*]=],
[=[\s*lefta\%[bove]\s*]=],
[=[\s*loc\%[kmarks]\s*]=],
[=[\s*nos\%[wapfile]\s*]=],
[=[\s*rightb\%[elow]\s*]=],
[=[\s*sil\%[ent]\s*]=],
[=[\s*tab\s*]=],
[=[\s*to\%[pleft]\s*]=],
[=[\s*verb\%[ose]\s*]=],
[=[\s*vert\%[ical]\s*]=],
}, true)
local COUNT_RANGE_REGEX = create_regex({
[=[\s*\%(\d\+\|\$\)\%[,\%(\d\+\|\$\)]\s*]=],
[=[\s*'\%[<,'>]\s*]=],
[=[\s*\%(\d\+\|\$\)\s*]=],
}, true)
local ONLY_RANGE_REGEX = create_regex({
[=[^\s*\%(\d\+\|\$\)\%[,\%(\d\+\|\$\)]\s*$]=],
[=[^\s*'\%[<,'>]\s*$]=],
[=[^\s*\%(\d\+\|\$\)\s*$]=],
}, true)
local OPTION_NAME_COMPLETION_REGEX = create_regex({
[=[se\%[tlocal][^=]*$]=],
}, true)
---@param word string
---@return boolean?
local function is_boolean_option(word)
local ok, opt = pcall(function()
return vim.opt[word]:get()
end)
if ok then
return type(opt) == 'boolean'
end
end
---@class cmp.Cmdline.Definition
---@field ctype string
---@field regex string
---@field kind lsp.CompletionItemKind
---@field isIncomplete boolean
---@field exec fun(option: table, arglead: string, cmdline: string, force: boolean): lsp.CompletionItem[]
---@field fallback boolean?
---@type cmp.Cmdline.Definition[]
local definitions = {
{
ctype = 'cmdline',
regex = [=[[^[:blank:]]*$]=],
kind = cmp.lsp.CompletionItemKind.Variable,
isIncomplete = true,
---@param option cmp-cmdline.Option
exec = function(option, arglead, cmdline, force)
-- Ignore range only cmdline. (e.g.: 4, '<,'>)
if not force and ONLY_RANGE_REGEX:match_str(cmdline) then
return {}
end
local _, parsed = pcall(function()
local target = cmdline
local s, e = COUNT_RANGE_REGEX:match_str(target)
if s and e then
target = target:sub(e + 1)
end
-- nvim_parse_cmd throw error when the cmdline contains range specifier.
return vim.api.nvim_parse_cmd(target, {}) or {}
end)
parsed = parsed or {}
-- Check ignore cmd.
if vim.tbl_contains(option.ignore_cmds, parsed.cmd) then
return {}
end
-- Cleanup modifiers.
-- We can just remove modifiers because modifiers is always separated by space.
if arglead ~= cmdline then
while true do
local s, e = MODIFIER_REGEX:match_str(cmdline)
if s == nil then
break
end
cmdline = string.sub(cmdline, e + 1)
end
end
-- Support `lua vim.treesitter._get|` or `'<,'>del|` completion.
-- In this case, the `vim.fn.getcompletion` will return only `get_query` for `vim.treesitter.get_|`.
-- We should detect `vim.treesitter.` and `get_query` separately.
-- TODO: The `\h\w*` was choosed by huristic. We should consider more suitable detection.
local fixed_input
do
local suffix_pos = vim.regex([[\h\w*$]]):match_str(arglead)
fixed_input = string.sub(arglead, 1, suffix_pos or #arglead)
end
-- The `vim.fn.getcompletion` does not return `*no*cursorline` option.
-- cmp-cmdline corrects `no` prefix for option name.
local is_option_name_completion = OPTION_NAME_COMPLETION_REGEX:match_str(cmdline) ~= nil
--- create items.
local items = {}
local escaped = cmdline:gsub([[\\]], [[\\\\]]);
for _, word_or_item in ipairs(vim.fn.getcompletion(escaped, 'cmdline')) do
local word = type(word_or_item) == 'string' and word_or_item or word_or_item.word
local item = { label = word }
table.insert(items, item)
if is_option_name_completion and is_boolean_option(word) then
table.insert(items, vim.tbl_deep_extend('force', {}, item, {
label = 'no' .. word,
filterText = word,
}))
end
end
-- fix label with `fixed_input`
for _, item in ipairs(items) do
if not string.find(item.label, fixed_input, 1, true) then
item.label = fixed_input .. item.label
end
end
-- fix trailing slash for path like item
if option.treat_trailing_slash then
for _, item in ipairs(items) do
local is_target = string.match(item.label, [[/$]])
is_target = is_target and not (string.match(item.label, [[~/$]]))
is_target = is_target and not (string.match(item.label, [[%./$]]))
is_target = is_target and not (string.match(item.label, [[%.%./$]]))
if is_target then
item.label = item.label:sub(1, -2)
end
end
end
return items
end
},
}
local source = {}
source.new = function()
return setmetatable({
before_line = '',
offset = -1,
ctype = '',
items = {},
}, { __index = source })
end
source.get_keyword_pattern = function()
return [=[[^[:blank:]]*]=]
end
source.get_trigger_characters = function()
return { ' ', '.', '#', '-' }
end
source.complete = function(self, params, callback)
local offset = 0
local ctype = ''
local items = {}
local kind
local isIncomplete = false
for _, def in ipairs(definitions) do
local s, e = vim.regex(def.regex):match_str(params.context.cursor_before_line)
if s and e then
offset = s
ctype = def.ctype
items = def.exec(
vim.tbl_deep_extend('keep', params.option or {}, DEFAULT_OPTION),
string.sub(params.context.cursor_before_line, s + 1),
params.context.cursor_before_line,
params.context:get_reason() == cmp.ContextReason.Manual
)
kind = def.kind
isIncomplete = def.isIncomplete
if not (#items == 0 and def.fallback) then
break
end
end
end
local labels = {}
for _, item in ipairs(items) do
item.kind = kind
labels[item.label] = true
end
-- `vim.fn.getcompletion` does not handle fuzzy matches. So, we must return all items, including items that were matched in the previous input.
local should_merge_previous_items = false
if #params.context.cursor_before_line > #self.before_line then
should_merge_previous_items = string.find(params.context.cursor_before_line, self.before_line, 1, true) == 1
elseif #params.context.cursor_before_line < #self.before_line then
should_merge_previous_items = string.find(self.before_line, params.context.cursor_before_line, 1, true) == 1
end
if should_merge_previous_items and self.offset == offset and self.ctype == ctype then
for _, item in ipairs(self.items) do
if not labels[item.label] then
table.insert(items, item)
end
end
end
self.before_line = params.context.cursor_before_line
self.offset = offset
self.ctype = ctype
self.items = items
callback({
isIncomplete = isIncomplete,
items = items,
})
end
return source