Skip to content

Commit

Permalink
Object 120
Browse files Browse the repository at this point in the history
  • Loading branch information
luozhiya committed Jan 8, 2025
1 parent ddec963 commit 8081b8f
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 145 deletions.
1 change: 1 addition & 0 deletions lua/fittencode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ local defaults = {
},
log = {
level = vim.log.levels.WARN,
developer_mode = true,
},
hash = {
md5 = {
Expand Down
94 changes: 38 additions & 56 deletions lua/fittencode/inline/controller.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,23 +74,10 @@ function Controller:dismiss_suggestions()
end
end

local function make_context(buf, e, r, chars_size)
local i = Editor.wordcount(buf).chars
local s = Editor.offset_at(buf, e) or 0
local o = Editor.offset_at(buf, r) or 0
local a = math.max(0, s - chars_size)
local A = math.min(i, o + chars_size)
local l = Editor.position_at(buf, a) or { row = 0, col = 0 }
local u = Editor.position_at(buf, A) or { row = 0, col = 0 }
local c = vim.api.nvim_buf_get_text(buf, l.row, l.col, e.row, e.col, {})
local h = vim.api.nvim_buf_get_text(buf, r.row, r.col, u.row, u.col, {})
return table.concat(c, '\n') .. '<fim_middle>' .. table.concat(h, '\n')
end

---@param buf number
---@param position FittenCode.Position?
---@return FittenCode.Inline.Prompt?
function Controller:generate_prompt(buf, position)
function Controller:generate_prompt(buf, position, on_success, on_error)
if not position then
return
end
Expand All @@ -107,23 +94,11 @@ function Controller:generate_prompt(buf, position)
-- notify install lsp
end

local A = ''
local max_chars = 22e4
local wc = Editor.wordcount(buf)
local prefix
local suffix
if wc.chars <= max_chars then
prefix = table.concat(vim.api.nvim_buf_get_text(buf, 0, 0, position.row, position.col, {}), '\n')
suffix = table.concat(vim.api.nvim_buf_get_text(buf, position.row, position.col, -1, -1, {}), '\n')
local a = position:clone()
local b = position:clone()
A = make_context(buf, a, b, 100)
Log.debug('Context: {}', A)
end
local WL = '<((fim_((prefix)|(suffix)|(middle)))|(%|[a-z]*%|))>'
prefix = vim.fn.substitute(prefix, WL, '', 'g')
suffix = vim.fn.substitute(suffix, WL, '', 'g')
local prompt = Prompt:new({ Editor.filename(buf), prefix, suffix, A })
local prompt = Prompt.make({
buf = buf,
filename = Editor.filename(buf),
position = position,
})
end

---@class FittenCode.Inline.Completion
Expand Down Expand Up @@ -214,35 +189,42 @@ function Controller:triggering_completion(options)
self.session.timing.on_create = vim.uv.hrtime()

Promise:new(function(resolve, reject)
local gcv_options = {
on_create = function()
self.session.timing.get_completion_version.on_create = vim.uv.hrtime()
end,
on_once = function(stdout)
self.session.timing.get_completion_version.on_once = vim.uv.hrtime()
local json = table.concat(stdout, '')
local _, version = pcall(vim.fn.json_decode, json)
if not _ or version == nil then
Log.error('Failed to get completion version: {}', json)
Log.debug('Triggering completion for position {}', position)
self:generate_prompt(buf, position, function(prompt)
resolve(prompt)
end, function()
Fn.schedule_call(options.on_error)
end)
end):forward(function(prompt)
Promise:new(function(resolve, reject)
local gcv_options = {
on_create = function()
self.session.timing.get_completion_version.on_create = vim.uv.hrtime()
end,
on_once = function(stdout)
self.session.timing.get_completion_version.on_once = vim.uv.hrtime()
local json = table.concat(stdout, '')
local _, version = pcall(vim.fn.json_decode, json)
if not _ or version == nil then
Log.error('Failed to get completion version: {}', json)
reject()
else
resolve({ version = version, prompt = prompt })
end
end,
on_error = function()
self.session.timing.get_completion_version.on_error = vim.uv.hrtime()
reject()
else
resolve(version)
end
end,
on_error = function()
self.session.timing.get_completion_version.on_error = vim.uv.hrtime()
reject()
end
}
self.session.request_handles[#self.session.request_handles + 1] = Client.get_completion_version(gcv_options)
end):forward(function(version)
}
self.session.request_handles[#self.session.request_handles + 1] = Client.get_completion_version(gcv_options)
end)
end):forward(function(_)
return Promise:new(function(resolve, reject)
Log.debug('Got completion version {}', version)
Log.debug('Triggering completion for position {}', position)
local prompt = self:generate_prompt(buf, position)
Log.debug('Got completion version {}', _.version)
local gos_options = {
completion_version = version,
prompt = prompt,
completion_version = _.version,
prompt = _.prompt,
on_create = function()
self.session.timing.generate_one_stage.on_create = vim.uv.hrtime()
end,
Expand Down
99 changes: 48 additions & 51 deletions lua/fittencode/inline/prompt.lua
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
local Hash = require('fittencode.hash')
local Promise = require('fittencode.promise')
local Fn = require('fittencode.fn')
local Editor = require('fittencode.editor')
local Log = require('fittencode.log')
local Position = require('fittencode.position')

---@class FittenCode.Inline.Prompt
---@field inputs string
---@field meta_datas FittenCode.Inline.Prompt.MetaDatas

local Prompt = {}
Prompt.__index = Prompt

function Prompt.new(options)
---@return FittenCode.Inline.Prompt
function Prompt:new(options)
local obj = {
filename = options.filename,
prefix = options.prefix,
Expand All @@ -19,49 +20,64 @@ function Prompt.new(options)
return obj
end

---@class FittenCode.Inline.Prompt.MetaDatas
---@field plen number
---@field slen number
---@field bplen number
---@field bslen number
---@field pmd5 string
---@field nmd5 string
---@field diff string
---@field filename string
---@field cpos number
---@field bcpos number
---@field pc_available boolean
---@field pc_prompt string
---@field pc_prompt_type string

local WL = '<((fim_((prefix)|(suffix)|(middle)))|(|[a-z]*|))>'
local _ie = 100
local JL = true
local context_threshold = 100
local last_filename = ''
local last_text = ''
local last_ciphertext = ''

local function aVe(filename, text, on_success, on_error)
local function make_context(buf, e, r, chars_size)
local i = Editor.wordcount(buf).chars
local s = Editor.offset_at(buf, e) or 0
local o = Editor.offset_at(buf, r) or 0
local a = math.max(0, s - chars_size)
local A = math.min(i, o + chars_size)
local l = Editor.position_at(buf, a) or { row = 0, col = 0 }
local u = Editor.position_at(buf, A) or { row = 0, col = 0 }
local c = vim.api.nvim_buf_get_text(buf, l.row, l.col, e.row, e.col, {})
local h = vim.api.nvim_buf_get_text(buf, r.row, r.col, u.row, u.col, {})
return table.concat(c, '\n') .. '<fim_middle>' .. table.concat(h, '\n')
end

-- Make a prompt for the given filename and prefix/suffix.
---@return FittenCode.Inline.Prompt?
function Prompt.make(options)
local A = ''
local max_chars = 22e4
local wc = Editor.wordcount(options.buf)
local prefix
local suffix
if wc.chars <= max_chars then
prefix = table.concat(vim.api.nvim_buf_get_text(options.buf, 0, 0, options.position.row, options.position.col, {}), '\n')
suffix = table.concat(vim.api.nvim_buf_get_text(options.buf, options.position.row, options.position.col, -1, -1, {}), '\n')
local a = options.position:clone()
local b = options.position:clone()
A = make_context(options.buf, a, b, 100)
Log.debug('Context: {}', A)
end
prefix = vim.fn.substitute(prefix, WL, '', 'g')
suffix = vim.fn.substitute(suffix, WL, '', 'g')
local text = prefix .. suffix
Promise:new(function(resolve, reject)
Hash.hash('MD5', text, function(ciphertext)
resolve(ciphertext)
end, function()
reject()
Fn.schedule_call(options.on_error)
end)
end):forward(function(ciphertext)
if filename ~= last_filename then
last_filename = filename
if options.filename ~= last_filename then
last_filename = options.filename
last_text = text
last_ciphertext = ciphertext
Fn.schedule_call(on_success, {
Fn.schedule_call(options.on_success, {
plen = 0,
slen = 0,
bplen = 0,
bslen = 0,
pmd5 = '',
nmd5 = ciphertext,
diff = text,
filename = filename
filename = options.filename
})
else
local indices = vim.diff(last_text, text, { result_type = 'indices' })
Expand All @@ -80,42 +96,23 @@ local function aVe(filename, text, on_success, on_error)
local o = #encoder(text:sub(1, n))
local a = #encoder(text:sub(#text - i + 1))

local A = {
local AA = {
plen = n,
slen = i,
bplen = o,
bslen = a,
pmd5 = last_ciphertext,
nmd5 = ciphertext,
diff = text:sub(n + 1, #text - i),
filename = filename
filename = options.filename
}

last_text = text
last_ciphertext = ciphertext

Fn.schedule_call(options.on_success, AA)
end
end)
end

local function make_prompt(filename, prefix, suffix)
local e = prefix .. suffix
-- return aVe(filename, e)
return {
inputs = '',
meta_datas = {
plen = 0,
slen = 0,
bplen = 0,
bslen = 0,
pmd5 = '',
nmd5 = 'cfcd208495d565ef66e7dff9f98764da',
diff = '0',
filename = 'Untitled-1',
cpos = 1,
bcpos = 1,
pc_available = false,
pc_prompt = '',
pc_prompt_type = '4',
}
}
end
return Prompt
70 changes: 32 additions & 38 deletions lua/fittencode/log.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ local M = {}
]]
local levels = vim.deepcopy(vim.log.levels)

local log_path = vim.fn.stdpath('log') .. '/fittencode' .. '/fittencode.log'
local logfile = vim.fn.stdpath('log') .. '/fittencode' .. '/fittencode.log'
local max_size = 2 * 1024 * 1024 -- 2MB

local preface = true
Expand Down Expand Up @@ -57,48 +57,46 @@ local function neovim_version()
}
end

local function write_preface(f)
if not preface then
return
end
preface = false

local edge = string.rep('=', 80) .. '\n'
f:write(edge)

local info = {
{ 'Verbose logging started', os.date('%Y-%m-%d %H:%M:%S') },
{ 'Log level', level_name(Config.log.level) },
{ 'Calling process', vim.uv.exepath() },
{ 'Neovim', vim.inspect(neovim_version()) },
{ 'Process ID', vim.uv.os_getpid() },
{ 'Parent process ID', vim.uv.os_getppid() },
{ 'OS', vim.inspect(vim.uv.os_uname()) }
}

for _, entry in ipairs(info) do
f:write(string.format('%s: %s\n', entry[1], entry[2]))
end
f:write(edge)
local function async_log(msg)
vim.schedule(function()
local content = {}
if preface then
preface = false
vim.fn.mkdir(vim.fn.fnamemodify(logfile, ':h'), 'p')
if Config.log.developer_mode or vim.fn.getfsize(logfile) > max_size then
vim.fn.delete(logfile)
end
local edge = string.rep('=', 80)
local info = {
{ 'Verbose logging started', os.date('%Y-%m-%d %H:%M:%S') },
{ 'Log level', level_name(Config.log.level) },
{ 'Calling process', vim.uv.exepath() },
{ 'Neovim', vim.inspect(neovim_version()) },
{ 'Process ID', vim.uv.os_getpid() },
{ 'Parent process ID', vim.uv.os_getppid() },
{ 'OS', vim.inspect(vim.uv.os_uname()) }
}
content[#content + 1] = edge
for _, entry in ipairs(info) do
content[#content + 1] = string.format('%s: %s', entry[1], entry[2])
end
content[#content + 1] = edge
end
local f = assert(io.open(logfile, 'a'))
content[#content + 1] = string.format('%s', msg)
f:write(table.concat(content, '\n') .. '\n')
f:close()
end)
end

local function log(level, msg, ...)
if level >= Config.log.level and Config.log.level ~= levels.OFF then
if preface then
vim.fn.mkdir(vim.fn.fnamemodify(log_path, ':h'), 'p')
if vim.fn.getfsize(log_path) > max_size then
vim.fn.delete(log_path)
end
end
msg = Fn.format(msg, ...)
local ms = string.format('%03d', math.floor((vim.uv.hrtime() / 1e6) % 1000))
local timestamp = os.date('%Y-%m-%d %H:%M:%S') .. '.' .. ms
local tag = string.format('[%-5s %s] ', level_name(level), timestamp)
msg = tag .. (msg or '')
local f = assert(io.open(log_path, 'a'))
write_preface(f)
f:write(string.format('%s\n', msg))
f:close()
async_log(msg)
end
end

Expand Down Expand Up @@ -126,8 +124,4 @@ for level, name in pairs(names) do
end
end

if vim.fn.filereadable(log_path) then
vim.fn.delete(log_path)
end

return M
Loading

0 comments on commit 8081b8f

Please sign in to comment.