cmp.lua 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. local M = {}
  2. local check_backspace = function()
  3. local col = vim.fn.col "." - 1
  4. return col == 0 or vim.fn.getline("."):sub(col, col):match "%s"
  5. end
  6. local function T(str)
  7. return vim.api.nvim_replace_termcodes(str, true, true, true)
  8. end
  9. local is_emmet_active = function()
  10. local clients = vim.lsp.buf_get_clients()
  11. for _, client in pairs(clients) do
  12. if client.name == "emmet_ls" then
  13. return true
  14. end
  15. end
  16. return false
  17. end
  18. M.config = function()
  19. local status_cmp_ok, cmp = pcall(require, "cmp")
  20. if not status_cmp_ok then
  21. return
  22. end
  23. local status_luasnip_ok, luasnip = pcall(require, "luasnip")
  24. if not status_luasnip_ok then
  25. return
  26. end
  27. lvim.builtin.cmp = {
  28. confirm_opts = {
  29. behavior = cmp.ConfirmBehavior.Replace,
  30. select = true,
  31. },
  32. experimental = {
  33. ghost_text = false,
  34. native_menu = true,
  35. },
  36. formatting = {
  37. kind_icons = {
  38. Class = " ",
  39. Color = " ",
  40. Constant = "ﲀ ",
  41. Constructor = " ",
  42. Enum = "練",
  43. EnumMember = " ",
  44. Event = " ",
  45. Field = " ",
  46. File = "",
  47. Folder = " ",
  48. Function = " ",
  49. Interface = "ﰮ ",
  50. Keyword = " ",
  51. Method = " ",
  52. Module = " ",
  53. Operator = "",
  54. Property = " ",
  55. Reference = " ",
  56. Snippet = " ",
  57. Struct = " ",
  58. Text = " ",
  59. TypeParameter = " ",
  60. Unit = "塞",
  61. Value = " ",
  62. Variable = " ",
  63. },
  64. format = function(entry, vim_item)
  65. vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind]
  66. vim_item.menu = ({
  67. nvim_lsp = "(LSP)",
  68. emoji = "(Emoji)",
  69. path = "(Path)",
  70. calc = "(Calc)",
  71. cmp_tabnine = "(Tabnine)",
  72. vsnip = "(Snippet)",
  73. luasnip = "(Snippet)",
  74. buffer = "(Buffer)",
  75. })[entry.source.name]
  76. vim_item.dup = ({
  77. buffer = 1,
  78. path = 1,
  79. nvim_lsp = 0,
  80. })[entry.source.name] or 0
  81. return vim_item
  82. end,
  83. },
  84. snippet = {
  85. expand = function(args)
  86. require("luasnip").lsp_expand(args.body)
  87. end,
  88. },
  89. documentation = {
  90. border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" },
  91. },
  92. sources = {
  93. { name = "nvim_lsp" },
  94. { name = "path" },
  95. { name = "luasnip" },
  96. { name = "cmp_tabnine" },
  97. { name = "nvim_lua" },
  98. { name = "buffer" },
  99. { name = "calc" },
  100. { name = "emoji" },
  101. { name = "treesitter" },
  102. { name = "crates" },
  103. },
  104. mapping = {
  105. ["<C-d>"] = cmp.mapping.scroll_docs(-4),
  106. ["<C-f>"] = cmp.mapping.scroll_docs(4),
  107. -- TODO: potentially fix emmet nonsense
  108. ["<Tab>"] = cmp.mapping(function()
  109. if vim.fn.pumvisible() == 1 then
  110. vim.fn.feedkeys(T "<down>", "n")
  111. elseif luasnip.expand_or_jumpable() then
  112. vim.fn.feedkeys(T "<Plug>luasnip-expand-or-jump", "")
  113. elseif check_backspace() then
  114. vim.fn.feedkeys(T "<Tab>", "n")
  115. elseif is_emmet_active() then
  116. return vim.fn["cmp#complete"]()
  117. else
  118. vim.fn.feedkeys(T "<Tab>", "n")
  119. end
  120. end, {
  121. "i",
  122. "s",
  123. }),
  124. ["<S-Tab>"] = cmp.mapping(function(fallback)
  125. if vim.fn.pumvisible() == 1 then
  126. vim.fn.feedkeys(T "<up>", "n")
  127. elseif luasnip.jumpable(-1) then
  128. vim.fn.feedkeys(T "<Plug>luasnip-jump-prev", "")
  129. else
  130. fallback()
  131. end
  132. end, {
  133. "i",
  134. "s",
  135. }),
  136. ["<C-Space>"] = cmp.mapping.complete(),
  137. ["<C-e>"] = cmp.mapping.close(),
  138. ["<CR>"] = cmp.mapping(function(fallback)
  139. if not require("cmp").confirm(lvim.builtin.cmp.confirm_opts) then
  140. if luasnip.jumpable() then
  141. vim.fn.feedkeys(T "<Plug>luasnip-jump-next", "")
  142. else
  143. fallback()
  144. end
  145. end
  146. end),
  147. },
  148. }
  149. end
  150. M.setup = function()
  151. require("luasnip/loaders/from_vscode").lazy_load()
  152. require("cmp").setup(lvim.builtin.cmp)
  153. end
  154. return M