Skip to content

Commit

Permalink
Identify programming language for current buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
luozhiya committed Jun 7, 2024
1 parent ceedc0d commit b4017c6
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 10 deletions.
94 changes: 94 additions & 0 deletions lua/fittencode/actions/identify_programming_language.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
local api = vim.api

local API = require('fittencode.api').api
local Base = require('fittencode.base')
local Config = require('fittencode.config')
local Log = require('fittencode.log')

local M = {}

local DEFER = 1000

-- milliseconds
local IPL_DEBOUNCE_TIME = 500

---@type uv_timer_t
local ipl_timer = nil

local function _identify_current_buffer()
local buffer = api.nvim_get_current_buf()
local name = api.nvim_buf_get_name(buffer)
local ext = vim.fn.fnamemodify(name, ':e')
if #name > 0 and #ext > 0 then
return
end
local ipl = ''
local success, result = pcall(api.nvim_buf_get_var, buffer, 'fittencode_identify_programming_language')
if success and result and #result > 0 then
ipl = result
end
local filetype = api.nvim_get_option_value('filetype', {
buf = buffer,
})
if #filetype > 0 and #ipl == 0 then
return
end

local content = table.concat(api.nvim_buf_get_lines(buffer, 0, -1, false), '\n')
API.identify_programming_language({
headless = true,
commit = false,
content = content,
on_success = function(suggestions)
if not suggestions or #suggestions == 0 then
return
end
local lang = suggestions[1]
if #lang == 0 then
return
end
lang = lang:lower()
lang = lang:gsub('^%s*(.-)%s*$', '%1')
if #lang == 0 then
return
end
lang = lang:gsub('c%+%+', 'cpp')
lang = lang:match('^(%w+)')
api.nvim_set_option_value('filetype', lang, {
buf = buffer,
})
api.nvim_buf_set_var(buffer, 'fittencode_identify_programming_language', lang)
end,
})
end

local function _ipl_wrap()
Base.debounce(ipl_timer, function()
_identify_current_buffer()
end, IPL_DEBOUNCE_TIME)
end

local function register_identify_current_buffer()
api.nvim_create_autocmd({ 'TextChangedI', 'BufReadPost' }, {
group = Base.augroup('IdentifyProgrammingLanguage'),
pattern = '*',
callback = function(params)
if not API.ready_for_generate() then
vim.defer_fn(function()
_ipl_wrap()
end, DEFER)
return
end
_ipl_wrap()
end,
desc = 'Identify programming language for current buffer',
})
end

function M.setup()
if Config.options.action.identify_programming_language.identify_buffer then
register_identify_current_buffer()
end
end

return M
7 changes: 7 additions & 0 deletions lua/fittencode/actions/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
local M = {}

function M.setup()
require('fittencode.actions.identify_programming_language').setup()
end

return M
3 changes: 3 additions & 0 deletions lua/fittencode/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ M.api = {
get_current_status = function()
return Engines.get_status()
end,
ready_for_generate = function()
return Sessions.ready_for_generate()
end,
triggering_completion = function()
InlineEngine.triggering_completion()
end,
Expand Down
6 changes: 6 additions & 0 deletions lua/fittencode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ local defaults = {
-- Show "Fitten Code - Start Chat" in the editor context menu, when you right-click on the code.
show_in_editor_context_menu = true,
},
identify_programming_language = {
-- Identify programming language of the current buffer
-- - Unamed buffer
-- - Buffer without file extension
identify_buffer = true,
}
},
disable_specific_inline_completion = {
-- Disable auto-completion for some specific file suffixes by entering them below
Expand Down
16 changes: 16 additions & 0 deletions lua/fittencode/engines/actions/content.lua
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ function M:on_start(opts)
self.conversations[self.current_eval] = Conversation:new(self.current_eval, opts.action)
self.conversations[self.current_eval].location = opts.location
self.conversations[self.current_eval].prompt = opts.prompt
self.conversations[self.current_eval].commit = opts.commit

if self.conversations[self.current_eval].commit == false then
return
end

local source_info = ' (' .. opts.location[1] .. ' ' .. opts.location[2] .. ':' .. opts.location[3] .. ')'
local c_in = '# In`[' .. self.current_eval .. ']`:= ' .. opts.action .. source_info
Expand Down Expand Up @@ -182,6 +187,10 @@ function M:on_end(opts)
self.conversations[self.current_eval].elapsed_time = opts.elapsed_time
self.conversations[self.current_eval].depth = opts.depth

if self.conversations[self.current_eval].commit == false then
return
end

self:commit({
lines = {
'',
Expand Down Expand Up @@ -214,6 +223,10 @@ function M:on_suggestions(suggestions)
end
self.conversations[self.current_eval].suggestions[#self.conversations[self.current_eval].suggestions + 1] = suggestions

if self.conversations[self.current_eval].commit == false then
return
end

if not self.has_suggestions[self.current_eval] then
self.has_suggestions[self.current_eval] = true
local cursor = self:commit({
Expand All @@ -236,6 +249,9 @@ function M:on_status(msg)
if not msg then
return
end
if self.conversations[self.current_eval].commit == false then
return
end
self:commit({
lines = {
'',
Expand Down
1 change: 1 addition & 0 deletions lua/fittencode/engines/actions/conversation.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
---@field elapsed_time integer
---@field depth integer
---@field location table -- [filename, row_start, row_end]
---@field commit boolean
local M = {}

function M:new(id, actions, references)
Expand Down
29 changes: 21 additions & 8 deletions lua/fittencode/engines/actions/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ local status = nil
---@field content? string
---@field language? string
---@field headless? boolean
---@field commit? boolean
---@field on_success? function @function Callback when suggestions are ready
---@field on_error? function @function Callback when an error occurs

Expand Down Expand Up @@ -138,6 +139,7 @@ local function on_stage_end(is_error, on_success, on_error)
Log.debug('Action elapsed time: {}', elapsed_time)
Log.debug('Action depth: {}', depth)

local ready = false
if is_error then
status:update(SC.ERROR)
local err_msg = 'Error: fetch failed.'
Expand All @@ -151,7 +153,7 @@ local function on_stage_end(is_error, on_success, on_error)
schedule(on_success)
else
status:update(SC.SUGGESTIONS_READY)
schedule(on_success, content:get_current_suggestions())
ready = true
end
end

Expand All @@ -160,6 +162,10 @@ local function on_stage_end(is_error, on_success, on_error)
depth = depth,
})

if ready then
schedule(on_success, content:get_current_suggestions())
end

current_eval = current_eval + 1
lock = false
end
Expand Down Expand Up @@ -395,6 +401,7 @@ local function start_content(action_name, prompt_opts, range)
current_eval = current_eval,
action = action_name,
prompt = vim.split(prompt_preview.content, '\n'),
commit = prompt_opts.action_opts.commit,
location = {
prompt_preview.filename,
range.start[1],
Expand All @@ -408,16 +415,18 @@ end
---@return nil
function ActionsEngine.start_action(action, opts)
opts = opts or {}
opts.commit = opts.commit == nil and true or opts.commit
if not opts.commit then
opts.headless = true
end

local action_name = get_action_name(action)
if not action_name then
Log.error('Invalid Action: {}', action)
return
end
Log.debug('Start Action({})...', action_name)

if lock then
Log.debug('Action is locked, skipping')
return
end

Expand All @@ -438,11 +447,16 @@ function ActionsEngine.start_action(action, opts)
fn.win_gotoid(window)
end

local range = make_range(buffer)
Log.debug('Action range: {}', range)
local range = {
start = { 0, 0 },
['end'] = { 0, 0 },
}
local filetype = ''

local filetype = make_filetype(buffer, range)
Log.debug('Action real filetype: {}', filetype)
if not opts.content then
range = make_range(buffer)
filetype = make_filetype(buffer, range)
end

local prompt_opts = {
window = window,
Expand All @@ -455,7 +469,6 @@ function ActionsEngine.start_action(action, opts)
prompt = opts and opts.prompt,
action_opts = opts,
}
Log.debug('Action prompt_opts: {}', prompt_opts)

start_content(action_name, prompt_opts, range)
_start_action(chat.window, chat.buffer, action, prompt_opts)
Expand Down
1 change: 1 addition & 0 deletions lua/fittencode/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function M.setup(opts)
local sessions = require('fittencode.sessions')
sessions.setup()
require('fittencode.engines').setup()
require('fittencode.actions').setup()
require('fittencode.prompt_providers').setup()
require('fittencode.color').setup_highlight()
require('fittencode.commands').setup()
Expand Down
2 changes: 1 addition & 1 deletion lua/fittencode/prompt_providers/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ local MAP_ACTION_PROMPTS = {
end,
OptimizeCode = 'Optimize the code above to make it faster and more efficient',
RefactorCode = 'Refactor the code above',
IdentifyProgrammingLanguage = 'Identify the language used in the code above',
IdentifyProgrammingLanguage = 'Identify the language used in the code above and Give the name in short',
AnalyzeData = 'Analyze the data above and Give the pattern of the data',
TranslateText = function(ctx)
assert(ctx.action_opts)
Expand Down
2 changes: 1 addition & 1 deletion lua/fittencode/views/chat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ function M:show()
end

vim.cmd('topleft vsplit')
vim.cmd('vertical resize ' .. 42)
self.window = api.nvim_get_current_win()
vim.api.nvim_win_set_width(self.window, 42)
api.nvim_win_set_buf(self.window, self.buffer)
set_option_value_win(self.window)

Expand Down

0 comments on commit b4017c6

Please sign in to comment.