Skip to content

Commit d9e435d

Browse files
committed
LSP
1 parent ca22192 commit d9e435d

4 files changed

Lines changed: 110 additions & 22 deletions

File tree

lua/fittencode/inline/controller.lua

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ local Log = require('fittencode.log')
2525
local CtrlObserver = require('fittencode.inline.ctrl_observer')
2626
local ProgressIndicator = require('fittencode.fn.progress_indicator')
2727
local Color = require('fittencode.color')
28-
local LspServer = require('fittencode.integrations.completion.lsp_server')
2928
local StateMachine = require('fittencode.fn.state_machine')
3029

3130
local StatusObserver = CtrlObserver.StatusObserver
@@ -124,19 +123,6 @@ function Controller:_initialize(options)
124123
self:sync_state()
125124
end,
126125
})
127-
if Config.integrations.completion.lsp_server then
128-
Log.debug('Completion integration: LSP server enabled')
129-
-- vim.lsp.enable('FittenCode')
130-
-- vim.api.nvim_create_autocmd({ 'FileType' }, {
131-
-- group = vim.api.nvim_create_augroup('FittenCode.Inline.LspServer', { clear = true }),
132-
-- callback = function(args)
133-
-- if F.is_filebuf(args.buf) then
134-
-- Log.debug('LspServer attach = {}', args)
135-
-- LspServer.attach(args.buf)
136-
-- end
137-
-- end
138-
-- })
139-
end
140126

141127
local filtered = {}
142128
vim.tbl_map(function(key)

lua/fittencode/integrations/completion/_lsp.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function M.lsp_completion_items_from_fim(trigger_character, position, fim_comple
6767
local item = {
6868
label = trigger_character .. generated_text,
6969
-- labelDetails = nil,
70-
-- kind = 1, -- Text
70+
kind = 1, -- Text
7171
-- tags = nil,
7272
-- detail = nil,
7373
documentation = 'FittenCode...',

lua/fittencode/integrations/completion/blink/source.lua

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ end
1919

2020
function source:enabled() return true end
2121

22-
function source.get_trigger_characters()
22+
function source:get_trigger_characters()
2323
return { '@', '.', '(', '[', ':', '{' }
2424
end
2525

@@ -44,6 +44,94 @@ local function prepend_to_complete_word(a, b)
4444
return a
4545
end
4646

47+
local function make_cmp_context(blink_context)
48+
local self = {}
49+
local cursor
50+
if blink_context then
51+
cursor = blink_context.cursor
52+
self.cursor_line = blink_context.line
53+
else
54+
cursor = vim.api.nvim_win_get_cursor(0)
55+
self.cursor_line = vim.api.nvim_get_current_line()
56+
end
57+
58+
self.cursor = {}
59+
self.cursor.row = cursor[1]
60+
self.cursor.col = cursor[2] + 1
61+
self.cursor.line = self.cursor.row - 1
62+
-- self.cursor.character = require('cmp.utils.misc').to_utfindex(self.cursor_line, self.cursor.col)
63+
self.cursor_before_line = string.sub(self.cursor_line, 1, self.cursor.col - 1)
64+
self.cursor_after_line = string.sub(self.cursor_line, self.cursor.col)
65+
return self
66+
end
67+
68+
--- Get the context around the cursor position for code completion
69+
---@param cmp_context table The completion context object containing cursor position and line info
70+
---@return table Context information with the following fields:
71+
--- - lines_before: string - Text content before cursor, truncated based on context window size
72+
--- - lines_after: string - Text content after cursor, truncated based on context window size
73+
--- - opts: table - Options indicating if context was truncated:
74+
--- - is_incomplete_before: boolean - True if content before cursor was truncated
75+
--- - is_incomplete_after: boolean - True if content after cursor was truncated
76+
local function get_context(cmp_context)
77+
local context_window = 128
78+
local context_ratio = 0.75
79+
80+
local cursor = cmp_context.cursor
81+
local lines_before_list = vim.api.nvim_buf_get_lines(0, 0, cursor.line, false)
82+
local lines_after_list = vim.api.nvim_buf_get_lines(0, cursor.line + 1, -1, false)
83+
84+
local lines_before = table.concat(lines_before_list, '\n')
85+
local lines_after = table.concat(lines_after_list, '\n')
86+
87+
lines_before = lines_before .. '\n' .. cmp_context.cursor_before_line
88+
lines_after = cmp_context.cursor_after_line .. '\n' .. lines_after
89+
90+
Log.debug('lines_before: {}', lines_before)
91+
Log.debug('lines_after: {}', lines_after)
92+
93+
local n_chars_before = vim.fn.strchars(lines_before)
94+
local n_chars_after = vim.fn.strchars(lines_after)
95+
96+
local opts = {
97+
is_incomplete_before = false,
98+
is_incomplete_after = false,
99+
}
100+
101+
if n_chars_before + n_chars_after > context_window then
102+
-- use some heuristic to decide the context length of before cursor and after cursor
103+
if n_chars_before < context_window * context_ratio then
104+
-- If the context length before cursor does not exceed the maximum
105+
-- size, we include the full content before the cursor.
106+
lines_after = vim.fn.strcharpart(lines_after, 0, context_window - n_chars_before)
107+
opts.is_incomplete_after = true
108+
elseif n_chars_after < context_window * (1 - context_ratio) then
109+
-- if the context length after cursor does not exceed the maximum
110+
-- size, we include the full content after the cursor.
111+
lines_before = vim.fn.strcharpart(lines_before, n_chars_before + n_chars_after - context_window)
112+
opts.is_incomplete_before = true
113+
else
114+
-- at the middle of the file, use the context_ratio to determine the allocation
115+
lines_after =
116+
vim.fn.strcharpart(lines_after, 0, math.floor(context_window * (1 - context_ratio)))
117+
118+
lines_before = vim.fn.strcharpart(
119+
lines_before,
120+
n_chars_before - math.floor(context_window * context_ratio)
121+
)
122+
123+
opts.is_incomplete_before = true
124+
opts.is_incomplete_after = true
125+
end
126+
end
127+
128+
return {
129+
lines_before = lines_before,
130+
lines_after = lines_after,
131+
opts = opts,
132+
}
133+
end
134+
47135
---@param ctx blink.cmp.Context
48136
function source:get_completions(ctx, callback)
49137
-- ctx (context) contains the current keyword, cursor position, bufnr, etc.
@@ -64,8 +152,10 @@ function source:get_completions(ctx, callback)
64152
return
65153
end
66154

155+
local context = get_context(make_cmp_context(ctx))
156+
67157
generated_text = vim.tbl_map(function(item)
68-
return prepend_to_complete_word(item, ctx.lines_before)
158+
return prepend_to_complete_word(item, context.lines_before)
69159
end, generated_text)
70160

71161
local max_label_width = 60
@@ -94,14 +184,13 @@ function source:get_completions(ctx, callback)
94184
},
95185
})
96186
end
97-
callback {
187+
Log.debug('items: {}', items)
188+
callback({
98189
is_incomplete_forward = false,
99190
is_incomplete_backward = false,
100191
items = items,
101-
}
192+
})
102193
end)
103-
104-
return function() end
105194
end
106195

107196
return source

lua/fittencode/integrations/init.lua

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
local Config = require('fittencode.config')
2+
local Log = require('fittencode.log')
3+
local F = require('fittencode.fn.buf')
24

35
if Config.integrations.completion.lsp_server then
4-
require('fittencode.integrations.completion.lsp_server').setup()
6+
local LspServer = require('fittencode.integrations.completion.lsp_server')
7+
LspServer.setup()
8+
vim.lsp.enable('FittenCode')
9+
vim.api.nvim_create_autocmd({ 'FileType' }, {
10+
group = vim.api.nvim_create_augroup('FittenCode.Inline.LspServer', { clear = true }),
11+
callback = function(args)
12+
if F.is_filebuf(args.buf) then
13+
Log.debug('LspServer attach = {}', args)
14+
LspServer.attach(args.buf)
15+
end
16+
end
17+
})
518
end
619

720
if Config.integrations.completion.blink then

0 commit comments

Comments
 (0)