Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding ChatCommitOptions #66

Merged
merged 4 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions lua/fittencode/engines/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ local function filter_suggestions(window, buffer, task_id, suggestions)
if not suggestions then
return nil, ms
end
return SuggestionsPreprocessing.run(window, buffer, suggestions), ms
return SuggestionsPreprocessing.run({
window = window,
buffer = buffer,
suggestions = suggestions,
condense_nl = 'all'
}), ms
end

---@param action integer
Expand Down Expand Up @@ -143,7 +148,12 @@ local function chain_actions(window, buffer, action, solved_prefix, on_error)
else
elapsed_time = elapsed_time + ms
depth = depth + 1
chat:commit(lines)
chat:commit({
lines = lines,
format = {
-- firstlinebreak = true,
}
})
local new_solved_prefix = prompt.prefix .. table.concat(lines, '\n')
chain_actions(window, buffer, action, new_solved_prefix, on_error)
end
Expand All @@ -170,8 +180,18 @@ local function on_error(err)
end
Log.debug('Action elapsed time: {}', elapsed_time)
Log.debug('Action depth: {}', depth)
local qed = '\n\n' .. '> Q.E.D.' .. '(' .. elapsed_time .. ' ms)' .. '\n\n'
chat:commit(qed)
chat:commit({
lines = {
'',
'> Q.E.D.' .. '(' .. elapsed_time .. ' ms)',
'',
'',
},
format = {
firstlinebreak = true,
fenced_code = true,
}
})
current_eval = current_eval + 1
end

Expand Down Expand Up @@ -278,7 +298,12 @@ local function _start_action(window, buffer, action, prompt_opts)
reject()
else
depth = depth + 1
chat:commit(lines)
chat:commit({
lines = lines,
format = {
firstlinecompress = true,
}
})
local solved_prefix = prompt.prefix .. table.concat(lines, '\n')
resolve(solved_prefix)
end
Expand Down
6 changes: 5 additions & 1 deletion lua/fittencode/engines/inline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ local function process_suggestions(task_id, suggestions)

Log.debug('Suggestions received; task_id: {}, suggestions: {}', task_id, suggestions)

return SuggestionsPreprocessing.run(window, buffer, suggestions)
return SuggestionsPreprocessing.run({
window = window,
buffer = buffer,
suggestions = suggestions,
})
end

local function apply_suggestion(task_id, row, col, suggestion)
Expand Down
6 changes: 3 additions & 3 deletions lua/fittencode/prompt_providers/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ end
local NO_LANG_ACTIONS = { 'StartChat', 'GuessProgrammingLanguage', 'AnalyzeData' }

local MAP_ACTION_PROMPTS = {
StartChat = 'Answers the question above',
DocumentCode = 'Document the code above, commenting line by line',
StartChat = 'Answer the question above',
DocumentCode = 'Document the code above, Comment each line to show the results',
EditCode = function(ctx)
return ctx.prompt
end,
ExplainCode = 'Explain the code above',
ExplainCode = 'Explain the code above, Break it down step by step',
FindBugs = 'Find bugs in the code above',
GenerateUnitTest = function(ctx)
local opts = ctx.action_opts or {}
Expand Down
93 changes: 75 additions & 18 deletions lua/fittencode/suggestions_preprocessing.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,19 @@ local Log = require('fittencode.log')

local M = {}

---@param suggestions string[]
local function condense_nl(window, buffer, suggestions)
---@class SuggestionsPreprocessingOptions
---@field window number
---@field buffer number
---@field suggestions string[]
---@field condense_nl? string

---@param opts SuggestionsPreprocessingOptions
local function condense_nl(opts)
local window = opts.window
local buffer = opts.buffer
local suggestions = opts.suggestions
local mode = opts.condense_nl

if not suggestions or #suggestions == 0 then
return
end
Expand All @@ -18,20 +29,28 @@ local function condense_nl(window, buffer, suggestions)
break
end
end

if is_all_empty then
return {}
end

local non_empty = 0
for i = #suggestions, 1, -1 do
if #suggestions[i] ~= 0 then
non_empty = i
break
end
end
for i = non_empty + 3, #suggestions do
table.remove(suggestions, non_empty + 3)
end

local row, col = Base.get_cursor(window)
local prev_line = nil
local cur_line = api.nvim_buf_get_lines(buffer, row, row + 1, false)[1]
if row > 1 then
prev_line = api.nvim_buf_get_lines(buffer, row - 1, row, false)[1]
end

Log.debug('prev_line: {}, cur_line: {}, col: {}', prev_line, cur_line, col)

local nls = {}
local remove_all = false
local keep_first = true
Expand All @@ -49,20 +68,54 @@ local function condense_nl(window, buffer, suggestions)

Log.debug('remove_all: {}, keep_first: {}', remove_all, keep_first)

local count = 0
for _, suggestion in ipairs(suggestions) do
if #suggestion == 0 then
if remove_all then
-- ignore
elseif keep_first and count ~= 0 then
-- ignore
mode = mode or 'first'

if mode == 'all' then
for i, suggestion in ipairs(suggestions) do
if #suggestion == 0 then
if remove_all then
-- ignore
elseif keep_first and i ~= 1 then
-- ignore
else
table.insert(nls, suggestion)
end
else
table.insert(nls, suggestion)
end
count = count + 1
else
count = 0
table.insert(nls, suggestion)
end
elseif mode == 'per-segments' then
local count = 0
for i, suggestion in ipairs(suggestions) do
if #suggestion == 0 then
if remove_all then
-- ignore
elseif keep_first and count ~= 0 then
-- ignore
else
table.insert(nls, suggestion)
end
count = count + 1
else
count = 0
table.insert(nls, suggestion)
end
end
elseif mode == 'first' then
local is_processed = false
for i, suggestion in ipairs(suggestions) do
if #suggestion == 0 and not is_processed then
if remove_all then
-- ignore
elseif keep_first and i ~= 1 then
-- ignore
else
table.insert(nls, suggestion)
end
else
is_processed = true
table.insert(nls, suggestion)
end
end
end

Expand Down Expand Up @@ -104,8 +157,12 @@ local function replace_slash(suggestions)
return slash
end

function M.run(window, buffer, suggestions)
local nls = condense_nl(window, buffer, suggestions)
---@param opts SuggestionsPreprocessingOptions
function M.run(opts)
local buffer = opts.buffer
local suggestions = opts.suggestions

local nls = condense_nl(opts)
if nls then
suggestions = nls
end
Expand Down
82 changes: 78 additions & 4 deletions lua/fittencode/views/chat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ local function set_option_value(window, buffer)
api.nvim_set_option_value('number', false, { win = window })
api.nvim_set_option_value('relativenumber', false, { win = window })
api.nvim_set_option_value('conceallevel', 3, { win = window })
-- api.nvim_set_option_value('scrolloff', 8, { win = window })
end

function M:show()
Expand Down Expand Up @@ -100,13 +101,86 @@ function M:close()
-- self.buffer = nil
end

function M:commit(lines)
if type(lines) == 'string' then
lines = vim.split(lines, '\n')
---@class ChatCommitFormat
---@field firstlinebreak? boolean
---@field firstlinecompress? boolean
---@field fenced_code? boolean

---@class ChatCommitOptions
---@field lines? string|string[]
---@field format? ChatCommitFormat

local fenced_code_open = false

---@param opts? ChatCommitOptions|string
---@param content string[]
---@return string[]?
local function format_lines(opts, content)
if not opts then
return
end

if type(opts) == 'string' then
---@diagnostic disable-next-line: param-type-mismatch
opts = { lines = vim.split(opts, '\n') }
end

---@type string[]
---@diagnostic disable-next-line: assign-type-mismatch
local lines = opts.lines or {}
local firstlinebreak = opts.format and opts.format.firstlinebreak
local fenced_code = opts.format and opts.format.fenced_code
local firstlinecompress = opts.format and opts.format.firstlinecompress

if #lines == 0 then
return
end

vim.tbl_map(function(x)
if x:match('^```') then
fenced_code_open = not fenced_code_open
end
end, lines)

local fenced_sloved = false
if fenced_code_open then
if fenced_code then
if lines[1] ~= '' then
table.insert(lines, 1, '')
end
table.insert(lines, 2, '```')
fenced_code_open = false
fenced_sloved = true
end
end

if not fenced_code_open and not fenced_sloved and firstlinebreak and
#content > 0 and #lines > 1 then
local last_lines = content[#content]
local last_line = last_lines[#last_lines]
if not string.match(lines[2], '^```') and not string.match(last_line, '^```') then
table.insert(lines, 1, '')
end
end

if firstlinecompress and #lines > 1 then
if lines[1] == '' and string.match(lines[2], '^```') then
table.remove(lines, 1)
end
end

return lines
end

---@param opts? ChatCommitOptions|string
function M:commit(opts)
local lines = format_lines(opts, self.content)
if not lines then
return
end

table.insert(self.content, lines)
_commit(self.window, self.buffer, lines)
Log.debug('Chat text: {}', self.content)
end

local function _sub_match(s, pattern)
Expand Down