|
@@ -1,24 +1,23 @@
|
|
|
local M = {}
|
|
|
M.methods = {}
|
|
|
|
|
|
----checks if the character preceding the cursor is a space character
|
|
|
----@return boolean true if it is a space character, false otherwise
|
|
|
-local check_backspace = function()
|
|
|
- local col = vim.fn.col "." - 1
|
|
|
- return col == 0 or vim.fn.getline("."):sub(col, col):match "%s"
|
|
|
+local has_words_before = function()
|
|
|
+ local line, col = unpack(vim.api.nvim_win_get_cursor(0))
|
|
|
+ return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match "%s" == nil
|
|
|
end
|
|
|
-M.methods.check_backspace = check_backspace
|
|
|
+M.methods.has_words_before = has_words_before
|
|
|
|
|
|
-local function T(str)
|
|
|
+---@deprecated use M.methods.has_words_before instead
|
|
|
+M.methods.check_backspace = function()
|
|
|
+ return not has_words_before()
|
|
|
+end
|
|
|
+
|
|
|
+local T = function(str)
|
|
|
return vim.api.nvim_replace_termcodes(str, true, true, true)
|
|
|
end
|
|
|
|
|
|
----wraps vim.fn.feedkeys while replacing key codes with escape codes
|
|
|
----Ex: feedkeys("<CR>", "n") becomes feedkeys("^M", "n")
|
|
|
----@param key string
|
|
|
----@param mode string
|
|
|
local function feedkeys(key, mode)
|
|
|
- vim.fn.feedkeys(T(key), mode)
|
|
|
+ vim.api.nvim_feedkeys(T(key), mode, true)
|
|
|
end
|
|
|
M.methods.feedkeys = feedkeys
|
|
|
|
|
@@ -28,39 +27,21 @@ M.methods.feedkeys = feedkeys
|
|
|
local function jumpable(dir)
|
|
|
local luasnip_ok, luasnip = pcall(require, "luasnip")
|
|
|
if not luasnip_ok then
|
|
|
- return
|
|
|
+ return false
|
|
|
end
|
|
|
|
|
|
local win_get_cursor = vim.api.nvim_win_get_cursor
|
|
|
local get_current_buf = vim.api.nvim_get_current_buf
|
|
|
|
|
|
- local function inside_snippet()
|
|
|
- -- for outdated versions of luasnip
|
|
|
- if not luasnip.session.current_nodes then
|
|
|
- return false
|
|
|
- end
|
|
|
-
|
|
|
- local node = luasnip.session.current_nodes[get_current_buf()]
|
|
|
- if not node then
|
|
|
- return false
|
|
|
- end
|
|
|
-
|
|
|
- local snip_begin_pos, snip_end_pos = node.parent.snippet.mark:pos_begin_end()
|
|
|
- local pos = win_get_cursor(0)
|
|
|
- pos[1] = pos[1] - 1 -- LuaSnip is 0-based not 1-based like nvim for rows
|
|
|
- return pos[1] >= snip_begin_pos[1] and pos[1] <= snip_end_pos[1]
|
|
|
- end
|
|
|
-
|
|
|
---sets the current buffer's luasnip to the one nearest the cursor
|
|
|
---@return boolean true if a node is found, false otherwise
|
|
|
local function seek_luasnip_cursor_node()
|
|
|
+ -- TODO(kylo252): upstream this
|
|
|
-- for outdated versions of luasnip
|
|
|
if not luasnip.session.current_nodes then
|
|
|
return false
|
|
|
end
|
|
|
|
|
|
- local pos = win_get_cursor(0)
|
|
|
- pos[1] = pos[1] - 1
|
|
|
local node = luasnip.session.current_nodes[get_current_buf()]
|
|
|
if not node then
|
|
|
return false
|
|
@@ -69,6 +50,9 @@ local function jumpable(dir)
|
|
|
local snippet = node.parent.snippet
|
|
|
local exit_node = snippet.insert_nodes[0]
|
|
|
|
|
|
+ local pos = win_get_cursor(0)
|
|
|
+ pos[1] = pos[1] - 1
|
|
|
+
|
|
|
-- exit early if we're past the exit node
|
|
|
if exit_node then
|
|
|
local exit_pos_end = exit_node.mark:pos_end()
|
|
@@ -124,9 +108,9 @@ local function jumpable(dir)
|
|
|
end
|
|
|
|
|
|
if dir == -1 then
|
|
|
- return inside_snippet() and luasnip.jumpable(-1)
|
|
|
+ return luasnip.in_snippet() and luasnip.jumpable(-1)
|
|
|
else
|
|
|
- return inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable()
|
|
|
+ return luasnip.in_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable(1)
|
|
|
end
|
|
|
end
|
|
|
M.methods.jumpable = jumpable
|
|
@@ -241,48 +225,61 @@ M.config = function()
|
|
|
mapping = cmp.mapping.preset.insert {
|
|
|
["<C-k>"] = cmp.mapping.select_prev_item(),
|
|
|
["<C-j>"] = cmp.mapping.select_next_item(),
|
|
|
+ ["<Down>"] = cmp.mapping(cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Select }, { "i" }),
|
|
|
+ ["<Up>"] = cmp.mapping(cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Select }, { "i" }),
|
|
|
["<C-d>"] = cmp.mapping.scroll_docs(-4),
|
|
|
["<C-f>"] = cmp.mapping.scroll_docs(4),
|
|
|
+ ["<C-y>"] = cmp.mapping {
|
|
|
+ i = cmp.mapping.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false },
|
|
|
+ c = function(fallback)
|
|
|
+ if cmp.visible() then
|
|
|
+ cmp.confirm { behavior = cmp.ConfirmBehavior.Replace, select = false }
|
|
|
+ else
|
|
|
+ fallback()
|
|
|
+ end
|
|
|
+ end,
|
|
|
+ },
|
|
|
["<Tab>"] = cmp.mapping(function(fallback)
|
|
|
if cmp.visible() then
|
|
|
cmp.select_next_item()
|
|
|
- elseif luasnip.expandable() then
|
|
|
- luasnip.expand()
|
|
|
- elseif jumpable() then
|
|
|
+ elseif luasnip.expand_or_locally_jumpable() then
|
|
|
+ luasnip.expand_or_jump()
|
|
|
+ elseif jumpable(1) then
|
|
|
luasnip.jump(1)
|
|
|
- elseif check_backspace() then
|
|
|
- fallback()
|
|
|
+ elseif has_words_before() then
|
|
|
+ cmp.complete()
|
|
|
else
|
|
|
fallback()
|
|
|
end
|
|
|
- end, {
|
|
|
- "i",
|
|
|
- "s",
|
|
|
- }),
|
|
|
+ end, { "i", "s" }),
|
|
|
["<S-Tab>"] = cmp.mapping(function(fallback)
|
|
|
if cmp.visible() then
|
|
|
cmp.select_prev_item()
|
|
|
- elseif jumpable(-1) then
|
|
|
+ elseif luasnip.jumpable(-1) then
|
|
|
luasnip.jump(-1)
|
|
|
else
|
|
|
fallback()
|
|
|
end
|
|
|
- end, {
|
|
|
- "i",
|
|
|
- "s",
|
|
|
- }),
|
|
|
-
|
|
|
+ end, { "i", "s" }),
|
|
|
["<C-Space>"] = cmp.mapping.complete(),
|
|
|
["<C-e>"] = cmp.mapping.abort(),
|
|
|
["<CR>"] = cmp.mapping(function(fallback)
|
|
|
- if cmp.visible() and cmp.confirm(lvim.builtin.cmp.confirm_opts) then
|
|
|
- if jumpable() then
|
|
|
+ if cmp.visible() then
|
|
|
+ local confirm_opts = lvim.builtin.cmp.confirm_opts
|
|
|
+ local is_insert_mode = function()
|
|
|
+ return vim.api.nvim_get_mode().mode:sub(1, 1) == "i"
|
|
|
+ end
|
|
|
+ if is_insert_mode() then -- prevent overwriting brackets
|
|
|
+ confirm_opts.behavior = cmp.ConfirmBehavior.Insert
|
|
|
+ end
|
|
|
+ cmp.confirm(confirm_opts)
|
|
|
+ if jumpable(1) then
|
|
|
luasnip.jump(1)
|
|
|
end
|
|
|
return
|
|
|
end
|
|
|
|
|
|
- if jumpable() then
|
|
|
+ if jumpable(1) then
|
|
|
if not luasnip.jump(1) then
|
|
|
fallback()
|
|
|
end
|