cmp.lua 4.0 KB

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