From d250c63aa13ead745e3a40f61fdd3470efde3923 Mon Sep 17 00:00:00 2001 From: hrsh7th <629908+hrsh7th@users.noreply.github.com> Date: Fri, 22 Mar 2024 13:17:30 +0900 Subject: [PATCH 1/3] add treat_trailing_slash --- README.md | 7 +++++++ lua/cmp_cmdline/init.lua | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/README.md b/README.md index 1b5849d..9107a98 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,10 @@ 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. diff --git a/lua/cmp_cmdline/init.lua b/lua/cmp_cmdline/init.lua index 78bd80d..53e7593 100644 --- a/lua/cmp_cmdline/init.lua +++ b/lua/cmp_cmdline/init.lua @@ -11,7 +11,11 @@ local function create_regex(patterns, head) 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', '!' } } @@ -77,6 +81,7 @@ local definitions = { 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 @@ -125,6 +130,7 @@ local definitions = { -- 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 @@ -138,11 +144,26 @@ local definitions = { })) 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 }, From 9910967fa9a44637b07899e23dbe514ca07dc245 Mon Sep 17 00:00:00 2001 From: Kyle Butt Date: Sat, 25 Feb 2023 10:41:18 -0700 Subject: [PATCH 2/3] Handle completion of % and # completion correctly. The current behavior if you try to complete :e %:p:h or something similar replaces only the h with the path, which isn't the desired behavior, because then nvim tries to open the wrong filename. Detect this case and produce edits that will replace the entire `%` chain with modifiers. --- lua/cmp_cmdline/init.lua | 47 +++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/lua/cmp_cmdline/init.lua b/lua/cmp_cmdline/init.lua index 53e7593..1756d24 100644 --- a/lua/cmp_cmdline/init.lua +++ b/lua/cmp_cmdline/init.lua @@ -83,6 +83,8 @@ local definitions = { isIncomplete = true, ---@param option cmp-cmdline.Option exec = function(option, arglead, cmdline, force) + -- Any edits we produce are relative to the whole command line. + local cmdline_length = #cmdline -- Ignore range only cmdline. (e.g.: 4, '<,'>) if not force and ONLY_RANGE_REGEX:match_str(cmdline) then return {} @@ -120,11 +122,7 @@ local definitions = { -- 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 + local fixed_input = arglead -- The `vim.fn.getcompletion` does not return `*no*cursorline` option. -- cmp-cmdline corrects `no` prefix for option name. @@ -133,6 +131,13 @@ local definitions = { --- create items. local items = {} local escaped = cmdline:gsub([[\\]], [[\\\\]]); + local is_magic_file = false + local input_start = string.sub(fixed_input, 1, 1) + if input_start == '%' then + is_magic_file = true + elseif input_start == '#' then + is_magic_file = true + end 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 } @@ -147,9 +152,25 @@ local definitions = { -- fix label with `fixed_input` for _, item in ipairs(items) do - if not string.find(item.label, fixed_input, 1, true) then + if not is_magic_file and not string.find(item.label, fixed_input, 1, true) then item.label = fixed_input .. item.label end + if is_magic_file then + local replace_range = { + start = { + character = cmdline_length - #fixed_input - 1 + }, + ['end'] = { + character = cmdline_length - 1 + } + } + item.textEdit = { + replace = replace_range, + range = replace_range, + newText = item.label + } + item.label = fixed_input .. ' → ' .. item.label + end end -- fix trailing slash for path like item @@ -217,6 +238,20 @@ source.complete = function(self, params, callback) for _, item in ipairs(items) do item.kind = kind labels[item.label] = true + if item['textEdit'] ~= nil then + local new_range = { + start = { + character = item.textEdit.range.start.character, + line = params.context.cursor.line + }, + ['end'] = { + character = item.textEdit.range['end'].character, + line = params.context.cursor.line + } + } + item.textEdit.replace = new_range + item.textEdit.range = new_range + end end -- `vim.fn.getcompletion` does not handle fuzzy matches. So, we must return all items, including items that were matched in the previous input. From 8161865075be178cd7e84984dd574c8394813031 Mon Sep 17 00:00:00 2001 From: Elwardi Date: Tue, 23 Apr 2024 17:43:47 +0200 Subject: [PATCH 3/3] fix visual mode bug for cmd completion --- lua/cmp_cmdline/init.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lua/cmp_cmdline/init.lua b/lua/cmp_cmdline/init.lua index 1756d24..5451d3a 100644 --- a/lua/cmp_cmdline/init.lua +++ b/lua/cmp_cmdline/init.lua @@ -122,7 +122,11 @@ local definitions = { -- 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 = arglead + 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.