Skip to content

Commit

Permalink
Merge pull request #60 from luozhiya/vregion
Browse files Browse the repository at this point in the history
Implement charwise and blockwise in virtual mode
  • Loading branch information
luozhiya authored May 18, 2024
2 parents 2e3a5a5 + 470563c commit 94bce11
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 44 deletions.
73 changes: 52 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,27 +190,58 @@ require('cmp').setup({

`fittencode.nvim` provides a set of APIs to help you integrate it with other plugins or scripts.

| API | Description |
|--------------------------|----------------------------------------|
| `login` | Login to Fitten |
| `logout` | Logout from Fitten |
| `register` | Register to Fitten |
| `set_log_level` | Set the log level |
| `get_current_status` | Get the current status of the `Engine` |
| `has_suggestion` | Check if there is a suggestion |
| `accept_all_suggestions` | Accept all suggestions |
| `accept_line` | Accept line |
| `accept_word` | Accept word |
| `document_code` | Document code |
| `edit_code` | Edit code |
| `explain_code` | Explain code |
| `find_bugs` | Find bugs |
| `generate_unit_test` | Generate unit test |
| `implement_features` | Implement features |
| `improve_code` | Improve code |
| `refactor_code` | Refactor code |
| `start_chat` | Start chat |
| `stop_eval` | Stop the evaluation |
- Access the APIs by calling `require('fittencode').<api_name>()`.

### Parameters Types

```lua
-- Log levels
vim.log = {
levels = {
TRACE = 0,
DEBUG = 1,
INFO = 2,
WARN = 3,
ERROR = 4,
OFF = 5,
},
}

---@class ActionOptions
---@field prompt? string
---@field content? string
---@field language? string

---@class GenerateUnitTestOptions : ActionOptions
---@field test_framework string

---@class ImplementFeaturesOptions : ActionOptions
---@field feature_type string
```

### List of APIs

| API | Prototype | Description |
|--------------------------|------------------------------------------------|-----------------------------------------------------------------|
| `login` | `login(username, password)` | Login to Fitten Code AI |
| `logout` | `logout()` | Logout from Fitten Code AI |
| `register` | `register()` | Register to Fitten Code AI |
| `set_log_level` | `set_log_level(level)` | Set the log level |
| `get_current_status` | `get_current_status()` | Get the current status of the `InlineEngine` and `ActionEngine` |
| `has_suggestion` | `has_suggestion()` | Check if there is a suggestion |
| `accept_all_suggestions` | `accept_all_suggestions()` | Accept all suggestions |
| `accept_line` | `accept_line()` | Accept line |
| `accept_word` | `accept_word()` | Accept word |
| `document_code` | `document_code(ActionOptions)` | Document code |
| `edit_code` | `edit_code(ActionOptions)` | Edit code |
| `explain_code` | `explain_code(ActionOptions)` | Explain code |
| `find_bugs` | `find_bugs(ActionOptions)` | Find bugs |
| `generate_unit_test` | `generate_unit_test(GenerateUnitTestOptions)` | Generate unit test |
| `implement_features` | `implement_features(ImplementFeaturesOptions)` | Implement features |
| `improve_code` | `improve_code(ActionOptions)` | Improve code |
| `refactor_code` | `refactor_code(ActionOptions)` | Refactor code |
| `start_chat` | `start_chat(ActionOptions)` | Start chat |
| `stop_eval` | `stop_eval()` | Stop the evaluation |

## 🎉 Special Thanks

Expand Down
56 changes: 42 additions & 14 deletions lua/fittencode/engines/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,12 @@ local function find_nospace(line)
end

---@param buffer number
---@param start_row number
---@param end_row number
---@param range ActionRange
---@return string[]
local function get_tslangs(buffer, start_row, end_row)
local function get_tslangs(buffer, range)
local start_row = range.start[1] - 1
local end_row = range['end'][1] - 1

local row = start_row
local col = 0

Expand All @@ -208,7 +210,38 @@ local function get_tslangs(buffer, start_row, end_row)
return langs
end

local vmode = { ['v']=true, ['V']=true, ['<C-V>']=true }
---@class ActionRange
---@field start integer[]
---@field end integer[]
---@field vmode boolean
---@field region string[]

local VMODE = { ['v'] = true, ['V'] = true, [api.nvim_replace_termcodes('<C-V>', true, true, true)] = true }

local function make_range(buffer)
local in_v = false
local region = {}

local mode = api.nvim_get_mode().mode
Log.debug('Action mode: {}', mode)
if VMODE[mode] then
in_v = true
region = fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() })
end

api.nvim_feedkeys(api.nvim_replace_termcodes('<ESC>', true, true, true), 'nx', false)

local start = api.nvim_buf_get_mark(buffer, '<')
local end_ = api.nvim_buf_get_mark(buffer, '>')

local range = {
start = start,
['end'] = end_,
vmode = in_v,
region = region,
}
return range
end

---@param action number
---@param opts? ActionOptions
Expand Down Expand Up @@ -237,21 +270,16 @@ function ActionsEngine.start_action(action, opts)

local window = api.nvim_get_current_win()
local buffer = api.nvim_win_get_buf(window)
local sln, eln = api.nvim_buf_get_mark(buffer, '<')[1], api.nvim_buf_get_mark(buffer, '>')[1]

Log.debug('mode: {}', api.nvim_get_mode().mode)
if vmode[api.nvim_get_mode().mode] then
api.nvim_feedkeys('', 'nx', false)
end
sln, eln = api.nvim_buf_get_mark(buffer, '<')[1], api.nvim_buf_get_mark(buffer, '>')[1]
Log.debug('sln: {}, eln: {}', sln, eln)
local range = make_range(buffer)
Log.debug('Action range: {}', range)

chat:show()
fn.win_gotoid(window)

local filetype = api.nvim_get_option_value('filetype', { buf = buffer })
Log.debug('Action filetype: {}', filetype)
local langs = get_tslangs(buffer, sln - 1, eln - 1)
local langs = get_tslangs(buffer, range)
Log.debug('Action langs: {}', langs)
if filetype == 'markdown' and #langs >= 2 then
filetype = vim.tbl_filter(function(lang) return lang ~= 'markdown' end, langs)[1]
Expand All @@ -261,7 +289,7 @@ function ActionsEngine.start_action(action, opts)
local prompt_opts = {
window = window,
buffer = buffer,
range = { sln - 1, eln - 1 },
range = range,
filetype = filetype,
prompt_ty = get_action_type(action),
solved_content = opts and opts.content,
Expand All @@ -273,7 +301,7 @@ function ActionsEngine.start_action(action, opts)
if #prompt_preview.filename == 0 then
prompt_preview.filename = 'unnamed'
end
local source_info = ' (' .. prompt_preview.filename .. ' ' .. sln .. ':' .. eln .. ')'
local source_info = ' (' .. prompt_preview.filename .. ' ' .. range.start[1] .. ':' .. range['end'][1] .. ')'

local c_in = '# In`[' .. current_eval .. ']`:= ' .. action_name .. source_info
chat:commit(c_in)
Expand Down
35 changes: 29 additions & 6 deletions lua/fittencode/prompt_providers/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@ function M:get_priority()
return self.priority
end

local function max_len(buffer, row, len)
local max = string.len(api.nvim_buf_get_lines(buffer, row - 1, row, false)[1])
if len > max then
return max
end
return len
end

---@param buffer integer
---@param range ActionRange
---@return string
local function get_range_content(buffer, range)
local lines = {}
if range.vmode then
lines = range.region
else
-- lines = api.nvim_buf_get_text(buffer, range.start[1] - 1, 0, range.start[1] - 1, -1, {})
local end_col = max_len(buffer, range['end'][1], range['end'][2])
lines = api.nvim_buf_get_text(
buffer,
range.start[1] - 1,
range.start[2],
range['end'][1] - 1,
end_col + 1, {})
end
return table.concat(lines, '\n')
end

---@param ctx PromptContext
---@return Prompt?
function M:execute(ctx)
Expand All @@ -47,15 +75,10 @@ function M:execute(ctx)
if ctx.solved_prefix then
prefix = ctx.solved_prefix
else
-- FIXME: Improve prompt construction! full content with line:col info?
---@diagnostic disable-next-line: param-type-mismatch
if ctx.solved_content then
content = ctx.solved_content
else
-- if ctx.range[1] == ctx.range[2] then
-- content = api.nvim_buf_get_lines(ctx.buffer, ctx.range[1], ctx.range[1] + 1, false)[1]
-- content = table.concat(api.nvim_buf_get_text(ctx.buffer, 0, 0, -1, -1, {}), '\n')
content = table.concat(api.nvim_buf_get_text(ctx.buffer, ctx.range[1], 0, ctx.range[2], -1, {}), '\n')
content = get_range_content(ctx.buffer, ctx.range)
end
local name = ctx.prompt_ty:sub(#NAME + 2)
Log.debug('Action Name: {}', name)
Expand Down
2 changes: 1 addition & 1 deletion lua/fittencode/prompt_providers/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ local M = {}
---@field prompt_ty? string
---@field row? integer
---@field col? integer
---@field range? table
---@field range? ActionRange
---@field prompt? string
---@field solved_prefix? string
---@field solved_content? string
Expand Down
9 changes: 7 additions & 2 deletions lua/fittencode/views/chat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ function M:close()
if self.win == nil then
return
end
api.nvim_win_close(self.win, true)
if api.nvim_win_is_valid(self.win) then
api.nvim_win_close(self.win, true)
end
self.win = nil
-- api.nvim_buf_delete(self.buffer, { force = true })
-- self.buffer = nil
Expand Down Expand Up @@ -92,7 +94,10 @@ function M:commit(text, linebreak)
api.nvim_set_option_value('modifiable', false, { buf = self.buffer })
end
table.move(lines, 1, #lines, #self.text + 1, self.text)
api.nvim_win_set_cursor(self.win, { #self.text, 0 })

if api.nvim_win_is_valid(self.win) then
api.nvim_win_set_cursor(self.win, { #self.text, 0 })
end
end

local function _sub_match(s, pattern)
Expand Down

0 comments on commit 94bce11

Please sign in to comment.