summaryrefslogtreecommitdiff
path: root/mut/neovim/lua/my/packages/cmp.lua
blob: 6a22d7385c617ed8ecb25312b78f1cdb372381e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
local cmp = require("cmp")
local cmp_types = require("cmp.types")
local luasnip = require("luasnip")

vim.keymap.set("n", "<leader>xf",
  function()
    local fname = vim.fn.fnamemodify(vim.fn.bufname(vim.api.nvim_get_current_buf()), ":p:h")
    vim.api.nvim_feedkeys(":e " .. fname, "c", false)
    vim.defer_fn(function()
      vim.api.nvim_feedkeys("/", "c", false)
    end, 10)
  end)

function snip(args)
  luasnip.lsp_expand(args.body)
end

function has_words_before()
  local line, col = unpack(vim.api.nvim_win_get_cursor(0))
  local word = unpack(vim.api.nvim_buf_get_lines(0, line-1, line, true))
  local before = word:sub(col, col)
  local is_string = before:match("%s")
  return (not (col == 0)) and is_string
end

function in_edit_mode(line)
  return line:match("^.* %.?.*$") or line:match("^ed?i?t? .*$")
end

function endswith(line, char)
  return line:match(".*" .. char .. "$")
end

function replace_tail(line)
  local result, n = line:gsub("(.*/)[^/]*/$","%1")
  if n then
    return result
  else
    return line
  end
end

cmp.setup({
  experimental={ghost_text= true},
  snippet={expand="snip"},
  preselect=cmp.PreselectMode.None,
  sources=cmp.config.sources({
    {name= "nvim_lsp"},
    {name= "path"},
    {name= "luasnip"}
  }),
  mapping={
    ["<Tab>"]=cmp.mapping(
      function(fallback)
        if cmp.visible() then
          cmp.select_next_item()
        elseif luasnip.expand_or_jumpable() then
          luasnip.expand_or_jump()
        elseif has_words_before() then
          cmp.complete()
        else
          fallback()
        end
      end, {"i", "s"}),
    ["<S-Tab>"]=cmp.mapping(
      function(fallback)
        if cmp.visible() then
          cmp.select_prev_item()
        elseif luasnip.jumpable(-1) then
          luasnip.jump (1)
        else
          fallback()
        end
      end, { "i", "s" }),
    ["<C-b>"]=cmp.mapping.scroll_docs(-4),
    [ "<C-f>" ]= cmp.mapping.scroll_docs(4),
    [ "<C-j>" ]= cmp.mapping.complete(),
    [ "<CR>" ]= cmp.mapping.confirm({
      behavior=cmp.ConfirmBehavior.Insert,
      select=true}),
    },
})

-- This tries to emulate somewhat ido mode to find files
-- todo sorting based on least recently used
cmp.setup.cmdline(":",
{enabled=function()
  local val = in_edit_mode(vim.fn.getcmdline())
  if not val then cmp.close() end
  return val
end,
sources=cmp.config.sources({ {name="path"} }),
completion={completeopt="menu,menuone,noinsert"},
mapping={
  ["<C-n>"]=cmp.mapping(
    function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      else
        cmp.complete()
      end
    end, { "i", "c" }),
  ["<C-p>"]=cmp.mapping(
    function(fallback)
      if cmp.visible() then
        cmp.select_prev_item()
      else
        cmp.complete()
      end
    end, { "i", "c" }),
  ["<BS>"]=cmp.mapping(
    function(fallback)
      local line = vim.fn.getcmdline()
      if not endswith(line, "/") then
        fallback()
      else
        vim.fn.setcmdline(replace_tail(line))
        vim.fn.feedkeys(vim.api.nvim_replace_termcodes("<C-g><BS>", true, false, true), false)
        vim.defer_fn(cmp.complete, 10)
      end
    end, { "i", "c" }),
  ["<CR>"]=cmp.mapping(
    function(fallback)
      local entry = cmp.get_selected_entry()
      local line = vim.fn.getcmdline()
      if entry and (not in_edit_mode(line)) then
        vim.schedule(fallback)
      else
        cmp.confirm {select=true, behavior=cmp.ConfirmBehavior.Replace}
        if entry and entry.completion_item.label:match("%.*/$") then
          vim.defer_fn(cmp.complete, 10)
        else
          vim.schedule(fallback)
        end
      end
    end, { "i", "c"})
  }
})