cmp.lua 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. formatting = {
  29. format = function(entry, vim_item)
  30. local icons = require("lsp.kind").icons
  31. vim_item.kind = icons[vim_item.kind]
  32. vim_item.menu = ({
  33. nvim_lsp = "(LSP)",
  34. emoji = "(Emoji)",
  35. path = "(Path)",
  36. calc = "(Calc)",
  37. cmp_tabnine = "(Tabnine)",
  38. vsnip = "(Snippet)",
  39. luasnip = "(Snippet)",
  40. buffer = "(Buffer)",
  41. })[entry.source.name]
  42. vim_item.dup = ({
  43. buffer = 1,
  44. path = 1,
  45. nvim_lsp = 0,
  46. })[entry.source.name] or 0
  47. return vim_item
  48. end,
  49. },
  50. snippet = {
  51. expand = function(args)
  52. require("luasnip").lsp_expand(args.body)
  53. end,
  54. },
  55. documentation = {
  56. border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" },
  57. },
  58. sources = {
  59. { name = "nvim_lsp" },
  60. { name = "path" },
  61. { name = "luasnip" },
  62. { name = "cmp_tabnine" },
  63. { name = "nvim_lua" },
  64. { name = "buffer" },
  65. { name = "calc" },
  66. { name = "emoji" },
  67. { name = "treesitter" },
  68. { name = "crates" },
  69. },
  70. mapping = {
  71. ["<C-d>"] = cmp.mapping.scroll_docs(-4),
  72. ["<C-f>"] = cmp.mapping.scroll_docs(4),
  73. -- TODO: potentially fix emmet nonsense
  74. ["<Tab>"] = cmp.mapping(function()
  75. if vim.fn.pumvisible() == 1 then
  76. vim.fn.feedkeys(T "<C-n>", "n")
  77. elseif luasnip.expand_or_jumpable() then
  78. vim.fn.feedkeys(T "<Plug>luasnip-expand-or-jump", "")
  79. elseif check_backspace() then
  80. vim.fn.feedkeys(T "<Tab>", "n")
  81. elseif is_emmet_active() then
  82. return vim.fn["cmp#complete"]()
  83. else
  84. vim.fn.feedkeys(T "<Tab>", "n")
  85. end
  86. end, {
  87. "i",
  88. "s",
  89. }),
  90. ["<S-Tab>"] = cmp.mapping(function(fallback)
  91. if vim.fn.pumvisible() == 1 then
  92. vim.fn.feedkeys(T "<C-p>", "n")
  93. elseif luasnip.jumpable(-1) then
  94. vim.fn.feedkeys(T "<Plug>luasnip-jump-prev", "")
  95. else
  96. fallback()
  97. end
  98. end, {
  99. "i",
  100. "s",
  101. }),
  102. ["<C-Space>"] = cmp.mapping.complete(),
  103. ["<C-e>"] = cmp.mapping.close(),
  104. ["<CR>"] = cmp.mapping.confirm {
  105. behavior = cmp.ConfirmBehavior.Replace,
  106. select = true,
  107. },
  108. },
  109. }
  110. M.setup = function()
  111. require("luasnip/loaders/from_vscode").lazy_load()
  112. require("cmp").setup(lvim.builtin.cmp)
  113. end
  114. end
  115. return M