summaryrefslogtreecommitdiff
path: root/lua/99/extensions/cmp.lua
blob: 30575bd03ffd0f3b816f9209db339ac900f0183f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
local Agents = require("99.extensions.agents")
local Files = require("99.extensions.files")
local Completions = require("99.extensions.completions")
local SOURCE = "99"

--- @class CmpSource
--- @field _99 _99.State
local CmpSource = {}
CmpSource.__index = CmpSource

--- @param _99 _99.State
function CmpSource.new(_99)
  return setmetatable({
    _99 = _99,
  }, CmpSource)
end

function CmpSource.is_available()
  return true
end

function CmpSource.get_debug_name()
  return SOURCE
end

function CmpSource.get_keyword_pattern()
  return Completions.get_keyword_pattern()
end

function CmpSource.get_trigger_characters()
  return Completions.get_trigger_characters()
end

function CmpSource.complete(_, params, callback)
  local before = params.context.cursor_before_line or ""

  -- Find which trigger is active
  local trigger = nil
  for _, char in ipairs(Completions.get_trigger_characters()) do
    local pattern = Completions.escape_pattern(char) .. "%S*$"
    if before:match(pattern) then
      trigger = char
      break
    end
  end

  if not trigger then
    callback({ items = {}, isIncomplete = false })
    return
  end

  local items = Completions.get_completions(trigger)
  callback({ items = items, isIncomplete = false })
end

function CmpSource.resolve(_, completion_item, callback)
  callback(completion_item)
end

function CmpSource.execute(_, completion_item, callback)
  callback(completion_item)
end

--- @type CmpSource | nil
local source = nil

--- @param _ _99.State
local function init_for_buffer(_)
  local buf = vim.api.nvim_get_current_buf()

  -- Set filetype for syntax highlighting
  vim.bo[buf].filetype = "99prompt"

  local cmp = require("cmp")
  cmp.setup.buffer({
    sources = { { name = SOURCE } },
    window = {
      completion = { zindex = 1001 },
      documentation = { zindex = 1001 },
    },
  })
end

--- @param _99 _99.State
local function register_providers(_99)
  Completions.register(Agents.completion_provider(_99))
  Completions.register(Files.completion_provider())
end

--- @param _99 _99.State
local function init(_99)
  assert(
    source == nil,
    "the source must be nil when calling init on an completer"
  )

  -- Collect rule directories to exclude from file search
  local rule_dirs = {}
  if _99.completion then
    if _99.completion.custom_rules then
      for _, dir in ipairs(_99.completion.custom_rules) do
        table.insert(rule_dirs, dir)
      end
    end
  end

  if _99.completion and _99.completion.files then
    Files.setup(_99.completion.files, rule_dirs)
  else
    Files.setup({ enabled = true }, rule_dirs)
  end

  register_providers(_99)

  local cmp = require("cmp")
  source = CmpSource.new(_99)
  cmp.register_source(SOURCE, source)
end

--- @param _99 _99.State
local function refresh_state(_99)
  if not source then
    return
  end
  register_providers(_99)
end

--- @type _99.Extensions.Source
local source_wrapper = {
  init_for_buffer = init_for_buffer,
  init = init,
  refresh_state = refresh_state,
}
return source_wrapper