@@ -46,6 +46,7 @@ local default = {
4646 throttle_delay_ms = 200 , -- Wait 200ms between updates
4747 ignore_patterns = {}, -- No ignore patterns by default
4848 },
49+ snippet = ' ' ,
4950}
5051
5152-- @type PhoenixConfig
227228
228229local scan_cache = LRUCache :new (100 )
229230
230- local async = {}
231-
232- function async .throttle (fn , delay )
233- local timer = nil
234- return function (...)
235- local args = { ... }
236- if timer and not timer :is_closing () then
237- timer :stop ()
238- timer :close ()
239- end
240- timer = assert (vim .uv .new_timer ())
241- timer :start (
242- delay ,
243- 0 ,
244- vim .schedule_wrap (function ()
245- if timer and not timer :is_closing () then
246- timer :stop ()
247- timer :close ()
248- fn (unpack (args ))
249- end
250- end )
251- )
252- end
253- end
254-
255231local server = {}
256232
257233local function get_root (filename )
@@ -500,6 +476,8 @@ local function process_lines_batch(lines, start_idx, batch_size, seen, dict_conf
500476 return end_idx
501477end
502478
479+ local async = require (' phoenix.async' )
480+
503481-- Initialize dictionary with full content
504482local initialize_dict = async .throttle (function (content )
505483 local dict_config = Config .dict
@@ -563,6 +541,88 @@ local update_dict = async.throttle(function(new, old)
563541 end
564542end , Config .scanner .throttle_delay_ms )
565543
544+ local Snippet = {
545+ cache = {},
546+ loading = {},
547+ }
548+
549+ function Snippet :preload ()
550+ local ft = vim .bo .filetype
551+ if self .cache [ft ] or self .loading [ft ] then
552+ return
553+ end
554+ local path = vim .fs .joinpath (Config .snippet , (' %s.json' ):format (ft ))
555+ if vim .fn .filereadable (path ) == 1 then
556+ self .loading [ft ] = true
557+ async .read_file (path , function (data )
558+ local success , snippets = pcall (vim .json .decode , data )
559+ if success then
560+ self .cache [ft ] = snippets
561+ self .loading [ft ] = nil
562+ else
563+ vim .notify (
564+ string.format (' Error parsing snippet file for %s: %s' , ft , snippets ),
565+ vim .log .levels .ERROR
566+ )
567+ self .cache [ft ] = {}
568+ self .loading [ft ] = nil
569+ end
570+ end )
571+ end
572+ end
573+
574+ local function parse_snippet (input )
575+ local ok , parsed = pcall (function ()
576+ return vim .lsp ._snippet_grammar .parse (input )
577+ end )
578+ return ok and tostring (parsed ) or input
579+ end
580+
581+ function Snippet :get_completions (prefix )
582+ local ft = vim .bo .filetype
583+ local results = {}
584+
585+ if not self .cache [ft ] then
586+ return results
587+ end
588+
589+ local snippets = self .cache [ft ]
590+ for trigger , snippet_data in pairs (snippets ) do
591+ if vim .startswith (trigger :lower (), prefix :lower ()) then
592+ local body = snippet_data .body
593+ local insert_text = body
594+
595+ if type (body ) == ' table' then
596+ insert_text = table.concat (body , ' \n ' )
597+ end
598+
599+ table.insert (results , {
600+ label = trigger ,
601+ kind = 15 ,
602+ insertText = insert_text ,
603+ documentation = {
604+ kind = ' markdown' ,
605+ value = snippet_data .description
606+ .. ' \n\n ```'
607+ .. ft
608+ .. ' \n '
609+ .. parse_snippet (insert_text )
610+ .. ' \n ```' ,
611+ },
612+ detail = ' Snippet: ' .. (snippet_data .description or ' ' ),
613+ sortText = string.format (' 001%s' , trigger ),
614+ insertTextFormat = 2 ,
615+ })
616+ end
617+ end
618+
619+ table.sort (results , function (a , b )
620+ return a .label < b .label
621+ end )
622+
623+ return results
624+ end
625+
566626local function collect_completions (prefix )
567627 local results = Trie .search_prefix (dict .trie , prefix )
568628 local now = vim .uv .now ()
@@ -742,7 +802,8 @@ function server.create()
742802 end
743803
744804 local items = collect_completions (prefix )
745- schedule_result (callback , items )
805+ local snippets = Snippet :get_completions (prefix )
806+ schedule_result (callback , vim .list_extend (items , snippets ))
746807 end
747808 end
748809
@@ -791,12 +852,19 @@ return {
791852 register = function ()
792853 vim .api .nvim_create_autocmd (' FileType' , {
793854 pattern = Config .filetypes ,
794- callback = function ()
855+ callback = function (args )
795856 vim .lsp .start ({
796857 name = ' phoenix' ,
797858 cmd = server .create (),
798859 root_dir = vim .uv .cwd (),
860+ reuse_client = function ()
861+ return true
862+ end ,
799863 })
864+
865+ if # Config .snippet > 0 then
866+ Snippet :preload ()
867+ end
800868 end ,
801869 })
802870 end ,
0 commit comments