2a94c1d864192de6f10338f86fc14361de87ba4f — Thomas Vigouroux 6 months ago b8798de
feat: add snippy source
M lua/complementree/defaults.lua => lua/complementree/defaults.lua +4 -0
@@ 21,6 21,10 @@ if sources.luasnip_matches then
  Defaults.luasnip = comb.pipeline(sources.luasnip_matches({}), filters.prefix, comp.alphabetic)

if sources.snippy_matches then
  Defaults.snippy = comb.pipeline(sources.snippy_matches({}), filters.prefix, comp.alphabetic)

Defaults.lsp = comb.pipeline(sources.lsp_matches({}), filters.prefix, comp.alphabetic)

Defaults.ctags = comb.pipeline(sources.ctags_matches({}), filters.prefix, comp.alphabetic)

M lua/complementree/init.lua => lua/complementree/init.lua +2 -0
@@ 17,6 17,8 @@ local M = {}
---@field empty boolean Add even if it is an empty string
---@field user_data any? Custom data

---@alias complementree.Source fun(line_to_cursor: string, lnum: integer): CompleteItem[], string

local user_config = {
  default = defaults.dummy,
  vim = defaults.ins_completion('C-V'),

M lua/complementree/sources.lua => lua/complementree/sources.lua +39 -1
@@ 41,6 41,11 @@ end
local apply_snippet = function(...)

---@class LSPMatchesOpts

---Gets the source corresponding to the LSPs in the current buffer
---@param opts LSPMatchesOpts Options for the source
---@return complementree.Source source The LSP source
function Sources.lsp_matches(opts)
  opts = options.get({}, opts)
  return cached('lsp', function(line_to_cursor, lnum)

@@ 189,13 194,20 @@ local lsnip_present, luasnip = pcall(require, "luasnip")
local snippy_present, snippy = pcall(require, "snippy")

if lsnip_present then
  ---@class LuasnipMatchesOpts
  ---@field exclude_defaults boolean Exclude snippets in `default` key
  ---@field filetype string Only get snippet from this filetype

  --- Gets the matches from LuaSnip
  ---@param opts LuasnipMatchesOpts Options to configure the matches
  ---@return complementree.Source source The LuaSnip source
  function Sources.luasnip_matches(opts)
    opts = options.get(opts, {
      exclude_defaults = false,
      filetype = nil,

    local function add_snippet(items, s)
      table.insert(items, {
        word = s.trigger,

@@ 250,6 262,32 @@ if lsnip_present then

elseif snippy_present then
  ---@class SnippyMatchesOpts

  --- Source for the snippy matches
  ---@param opts SnippyMatchesOpts
  ---@return complementree.Source source The snippy source
  function Sources.snippy_matches(opts)
    return cached('snippy', function(line_to_cursor, _)
      local prefix = utils.prefix.lua_regex('%w*$', line_to_cursor)

      ---@type CompleteItem[]
      local items = snippy.get_completion_items()

      for _, item in pairs(items) do
        item.user_data.source = 'snippy'

      return items, prefix

  -- These two complete_done handlers are stolen from snippy's code

  Sources.complete_done_cbs.snippy = function(completed_item)
    snippy.expand_snippet(completed_item.user_data.snippy.snippet, completed_item.word)

  Sources.complete_done_cbs.lsp = function(completed_item)
    local lsp_item = completed_item.user_data.extra.item
    local snippet

M lua/complementree/utils.lua => lua/complementree/utils.lua +4 -0
@@ 2,6 2,10 @@ local api = vim.api

local Prefix = {}

---Get the prefix corresponding to a lua regex
---@param regex string The regex used to extract the prefix
---@param line string Line to match
---@return string prefix The matching prefix
function Prefix.lua_regex(regex, line)
  local pref_start = line:find(regex)
  local prefix = line:sub(pref_start)