🪴 my neovim config:)
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ember: create buffer and spell completion lsp

robin b848d06e db2f16e0

+167 -1
+4
config/lsp/ember_ls.lua
··· 1 + ---@type vim.lsp.Config 2 + return { 3 + filetypes = { "markdown", "typst" }, 4 + }
+1
config/lua/ivy/config/lsp.lua
··· 10 10 "cssls", 11 11 "denols", 12 12 "dockerls", 13 + "ember_ls", 13 14 "emmet_language_server", 14 15 "gopls", 15 16 "hls",
+1 -1
config/lua/ivy/config/options.lua
··· 47 47 vim.o.pummaxwidth = 42 48 48 vim.opt.wildoptions = { "pum", "tagfile" } 49 49 vim.opt.wildmode = { "list", "full" } 50 - vim.o.complete = "." 50 + vim.o.complete = "" 51 51 vim.opt.completeopt = { "menuone", "noinsert" } 52 52 vim.o.autocomplete = true 53 53 vim.opt.shortmess:append("c") -- don't show autocomplete messages
+161
config/plugin/ember_ls.lua
··· 1 + if vim.g.loaded_ember then 2 + return 3 + end 4 + 5 + vim.g.loaded_ember = true 6 + 7 + ---@type table<vim.lsp.protocol.Method, fun(params: table, callback:fun(err: lsp.ResponseError?, result: any))> 8 + local handlers = {} 9 + local ms = vim.lsp.protocol.Methods 10 + 11 + local chars = {} 12 + for i = 32, 126 do 13 + table.insert(chars, string.char(i)) 14 + end 15 + 16 + ---@type lsp.InitializeResult 17 + local initializeResult = { 18 + capabilities = { 19 + hoverProvider = true, 20 + definitionProvider = true, 21 + referencesProvider = true, 22 + completionProvider = { 23 + triggerCharacters = chars, 24 + }, 25 + }, 26 + serverInfo = { 27 + name = "ember_ls", 28 + version = "0.0.1", 29 + }, 30 + } 31 + 32 + handlers[ms.initialize] = function(_, callback) 33 + callback(nil, initializeResult) 34 + end 35 + 36 + -- hover ====================================================================== 37 + 38 + ---@param _ lsp.HoverParams 39 + ---@param callback fun(err?: lsp.ResponseError, result: lsp.Hover) 40 + handlers[ms.textDocument_hover] = function(_, callback) 41 + local word = vim.fn.expand("<cword>") 42 + local url_format = "https://api.dictionaryapi.dev/api/v2/entries/en/%s" 43 + 44 + vim.system( 45 + { "curl", url_format:format(word) }, 46 + vim.schedule_wrap(function(out) 47 + local contents 48 + if out.code ~= 0 then 49 + contents = "word fetch failed" 50 + else 51 + local ok, decoded = pcall(vim.json.decode, out.stdout) 52 + if ok and decoded and decoded[1] then 53 + contents = decoded[1].meanings[1].definitions[1].definition 54 + else 55 + contents = decoded.message -- this api gives a nice message if no result 56 + end 57 + end 58 + callback(nil, { contents = contents }) 59 + end) 60 + ) 61 + end 62 + 63 + -- completion ================================================================= 64 + 65 + ---@param params lsp.CompletionParams 66 + ---@return string word_to_complete 67 + local get_word_to_complete = function(params) 68 + local col = params.position.character + 1 69 + local line = vim.api.nvim_get_current_line() 70 + local line_to_cursor = line:sub(1, col) 71 + local regex = vim.regex("\\k*$") 72 + 73 + return line:sub(regex:match_str(line_to_cursor) + 1, col) 74 + end 75 + 76 + ---@return vim.lsp.inline_completion.Item[] 77 + local function completion_buffer(params) 78 + local word = get_word_to_complete(params) 79 + 80 + local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) 81 + local matches = vim.fn.matchstrlist(lines, [[\<\k\+\>]]) 82 + vim.list.unique(matches, function(x) 83 + ---@diagnostic disable-next-line: undefined-field 84 + return x.text 85 + end) 86 + matches = vim.fn.matchfuzzy(matches, word, { key = "text" }) 87 + return vim 88 + .iter(matches) 89 + :map(function(v) 90 + -- dont match current word 91 + if v.text == word then 92 + return 93 + end 94 + return { 95 + label = v.text, 96 + kind = vim.lsp.protocol.CompletionItemKind["Text"], 97 + } 98 + end) 99 + :totable() 100 + end 101 + 102 + local get_spell_candidates = vim.func._memoize("concat", function(w) 103 + local entries = vim.fn.spellsuggest(w) 104 + entries = vim.fn.matchfuzzy(entries, w, { limit = 5 }) 105 + 106 + return vim 107 + .iter(entries) 108 + :map(function(v) 109 + if string.find(v, "[ ']") ~= nil then 110 + return 111 + end 112 + return { 113 + label = v, 114 + kind = vim.lsp.protocol.CompletionItemKind["Text"], 115 + } 116 + end) 117 + :totable() 118 + end) 119 + 120 + ---@return vim.lsp.inline_completion.Item[] 121 + local function completion_spell(params) 122 + local word = get_word_to_complete(params) 123 + 124 + return get_spell_candidates(word) 125 + end 126 + 127 + ---@param params lsp.CompletionParams 128 + ---@param callback fun(err?: lsp.ResponseError, result: lsp.CompletionItem[]) 129 + handlers[ms.textDocument_completion] = function(params, callback) 130 + local items = {} 131 + if vim.wo.spell then 132 + vim.list_extend(items, completion_spell(params)) 133 + end 134 + vim.list_extend(items, completion_buffer(params)) 135 + 136 + callback(nil, { 137 + items = items, 138 + isIncomplete = #items > 0, 139 + }) 140 + end 141 + 142 + -- init ======================================================================= 143 + 144 + ---@type vim.lsp.ClientConfig 145 + local cfg = { 146 + name = "ember_ls", 147 + cmd = function() 148 + return { 149 + request = function(method, params, callback) 150 + if handlers[method] then 151 + handlers[method](params, callback) 152 + end 153 + end, 154 + notify = function() end, 155 + is_closing = function() end, 156 + terminate = function() end, 157 + } 158 + end, 159 + } 160 + 161 + vim.lsp.config("ember_ls", cfg)