Regenerate nvim config
This commit is contained in:
21
config/neovim/store/lazy-plugins/cmp-cmdline/LICENSE
Normal file
21
config/neovim/store/lazy-plugins/cmp-cmdline/LICENSE
Normal 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.
|
||||
52
config/neovim/store/lazy-plugins/cmp-cmdline/README.md
Normal file
52
config/neovim/store/lazy-plugins/cmp-cmdline/README.md
Normal 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.
|
||||
@ -0,0 +1 @@
|
||||
require('cmp').register_source('cmdline', require('cmp_cmdline').new())
|
||||
@ -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
|
||||
Reference in New Issue
Block a user