Skip to content

Commit

Permalink
feat: inline can be run from the command line
Browse files Browse the repository at this point in the history
  • Loading branch information
olimorris committed Feb 17, 2024
1 parent 5b268db commit 8642549
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 30 deletions.
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,10 @@ The plugin sets the highlight groups during setup:

The plugin has a number of commands:

- `CodeCompanionChat` - To open up a new chat buffer
- `CodeCompanionToggle` - Toggle a chat buffer
- `CodeCompanionActions` - To open up the action palette window
- `:CodeCompanion` - Inline code writing and refactoring
- `:CodeCompanionChat` - To open up a new chat buffer
- `:CodeCompanionToggle` - Toggle a chat buffer
- `:CodeCompanionActions` - To open up the action palette window

For an optimum workflow, the plugin author recommendeds the following keymaps:

Expand Down Expand Up @@ -273,6 +274,18 @@ Chat Buffers are not saved to disk by default, but can be by pressing `gs` in th

If `display.chat.show_settings` is set to `true`, at the very top of the chat buffer will be the OpenAI parameters which can be changed to affect the API's response back to you. This enables fine-tuning and parameter tweaking throughout the chat. You can find more detail about them by moving the cursor over them or referring to the [Chat Completions reference guide](https://platform.openai.com/docs/api-reference/chat) if you're using OpenAI.

### Inline Editing

The plugin allows you to utilise the OpenAI APIs to create inline code in Neovim. Run the `:CodeCompanion` command followed by a prompt. For example:

```
:CodeCompanion create a table of 5 fruits
:'<,'>CodeCompanion refactor the code to make it more concise
:'<,'>CodeCompanion can you fix this lsp warning? "unpack" is the culprit
```

The command can detect if you've made a visual selection and send any code as context to the API, alongside the filetype of the buffer.

### In-Built Actions

The plugin comes with a number of [in-built actions](https://github.com/olimorris/codecompanion.nvim/blob/main/lua/codecompanion/actions.lua) which aim to improve your Neovim workflow. Actions make use of either a _chat_ or an _inline_ strategy, which are abstractions built around Neovim and OpenAI. The chat strategy opens up a chat buffer whilst an inline strategy will write any output into the Neovim buffer.
Expand Down
22 changes: 19 additions & 3 deletions doc/codecompanion.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,10 @@ USAGE *codecompanion-usage*

The plugin has a number of commands:

- `CodeCompanionChat` - To open up a new chat buffer
- `CodeCompanionToggle` - Toggle a chat buffer
- `CodeCompanionActions` - To open up the action palette window
- `:CodeCompanion` - Inline code writing and refactoring
- `:CodeCompanionChat` - To open up a new chat buffer
- `:CodeCompanionToggle` - Toggle a chat buffer
- `:CodeCompanionActions` - To open up the action palette window

For an optimum workflow, the plugin author recommendeds the following keymaps:

Expand Down Expand Up @@ -275,6 +276,21 @@ over them or referring to the Chat Completions reference guide
<https://platform.openai.com/docs/api-reference/chat> if you’re using OpenAI.


INLINE EDITING ~

The plugin allows you to utilise the OpenAI APIs to create inline code in
Neovim. Run the `:CodeCompanion` command followed by a prompt. For example:

>
:CodeCompanion create a table of 5 fruits
:'<,'>CodeCompanion refactor the code to make it more concise
:'<,'>CodeCompanion can you fix this lsp warning? "unpack" is the culprit
<

The command can detect if you’ve made a visual selection and send any code as
context to the API, alongside the filetype of the buffer.


IN-BUILT ACTIONS ~

The plugin comes with a number of in-built actions
Expand Down
3 changes: 0 additions & 3 deletions lua/codecompanion/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,6 @@ M.static.actions = {
description = "Custom user input",
opts = {
user_prompt = true,
send_visual_selection = true,
},
prompts = {
{
Expand Down Expand Up @@ -393,7 +392,6 @@ M.static.actions = {
modes = { "v" },
auto_submit = true,
user_prompt = true,
send_visual_selection = true,
},
prompts = {
{
Expand Down Expand Up @@ -421,7 +419,6 @@ M.static.actions = {
modes = { "v" },
auto_submit = true, -- Automatically submit the chat
user_prompt = false, -- Prompt the user for their own input
send_visual_selection = false, -- No need to send the visual selection as we do this in prompt 3
},
prompts = {
{
Expand Down
26 changes: 26 additions & 0 deletions lua/codecompanion/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,32 @@ M.buf_get_chat = function(bufnr)
return require("codecompanion.strategy.chat").buf_get_chat(bufnr)
end

M.inline = function(opts)
local client = M.get_client()
if not client then
return
end

local context = util.get_context(vim.api.nvim_get_current_buf(), opts)

return require("codecompanion.strategy.inline")
.new({
context = context,
client = client,
prompts = {
{
role = "system",
content = function()
return "I want you to act as a senior "
.. context.filetype
.. " developer. I will ask you specific questions and I want you to return raw code only (no codeblocks and no explanations). If you can't respond with code, respond with nothing"
end,
},
},
})
:start(opts.args)
end

---@param args? table
M.chat = function(args)
local client = M.get_client()
Expand Down
34 changes: 21 additions & 13 deletions lua/codecompanion/strategy/inline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ local function code_block(filetype, lines)
end

---@param inline CodeCompanion.Inline
---@param user_prompt? string
---@param user_input? string
---@return table
local get_action = function(inline, user_prompt)
local get_action = function(inline, user_input)
local output = {}

for _, prompt in ipairs(inline.prompts) do
Expand All @@ -35,15 +35,15 @@ local get_action = function(inline, user_prompt)
end

-- Add the user prompt
if inline.opts.user_prompt and user_prompt then
if user_input then
table.insert(output, {
role = "user",
content = user_prompt,
content = user_input,
})
end

-- Send code as context
if config.options.send_code and inline.opts.send_visual_selection and inline.context.is_visual then
if config.options.send_code and inline.context.is_visual then
table.insert(output, {
role = "user",
content = code_block(inline.context.filetype, inline.context.lines),
Expand Down Expand Up @@ -95,12 +95,15 @@ function Inline.new(opts)
}, { __index = Inline })
end

---@param user_prompt string|nil
function Inline:execute(user_prompt)
local messages = get_action(self, user_prompt)
---@param user_input string|nil
function Inline:execute(user_input)
local messages = get_action(self, user_input)

-- Overwrite any visual selection
if self.context.is_visual and self.opts.placement == "replace" then
if
(self.context.is_visual and self.opts and self.opts.placement == "replace")
or (self.context.is_visual and not self.opts)
then
log:trace("Overwriting selection")
overwrite_selection(self.context)
end
Expand All @@ -113,7 +116,7 @@ function Inline:execute(user_prompt)
log:debug("Cursor position: %s", pos)

-- Adjust the cursor position based on the command
if self.opts.placement and self.context.is_visual then
if self.opts and self.opts.placement and self.context.is_visual then
if self.opts.placement == "before" then
log:debug("Placing before selection: %s", self.context)
pos.line = self.context.start_line - 1
Expand Down Expand Up @@ -194,7 +197,7 @@ function Inline:execute(user_prompt)
table.insert(output, delta.content)
else
stream_buffer_text(delta.content)
if self.opts.placement == "new" then
if self.opts and self.opts.placement == "new" then
ui.buf_scroll_to_end(self.context.bufnr)
end
end
Expand All @@ -212,8 +215,13 @@ function Inline:execute(user_prompt)
)
end

function Inline:start()
if self.opts.user_prompt then
---@param input? string
function Inline:start(input)
if input then
return self:execute(input)
end

if self.opts and self.opts.user_prompt then
local title
if self.context.buftype == "terminal" then
title = "Terminal"
Expand Down
21 changes: 16 additions & 5 deletions lua/codecompanion/utils/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ function M.get_visual_selection(bufnr)

local start_line, start_col = unpack(api.nvim_buf_get_mark(bufnr, "<"))
local end_line, end_col = unpack(api.nvim_buf_get_mark(bufnr, ">"))

local lines = api.nvim_buf_get_lines(bufnr, start_line - 1, end_line, false)

-- get whole buffer if there is no current/previous visual selection
Expand Down Expand Up @@ -95,20 +94,32 @@ function M.get_context(bufnr, args)
bufnr = bufnr or api.nvim_get_current_buf()
local winid = api.nvim_get_current_win()
local mode = vim.fn.mode()
local cursor_pos = api.nvim_win_get_cursor(api.nvim_get_current_win())
local cursor_pos = api.nvim_win_get_cursor(winid)

local lines, start_line, start_col, end_line, end_col = {}, cursor_pos[1], cursor_pos[2], cursor_pos[1], cursor_pos[2]

if (args and args.range > 0) or is_visual_mode(mode) then
local is_visual = false
local is_normal = true

if args and args.range and args.range > 0 then
is_visual = true
is_normal = false
mode = "v"
lines, start_line, start_col, end_line, end_col = M.get_visual_selection(bufnr)
elseif is_visual_mode(mode) then
is_visual = true
is_normal = false
lines, start_line, start_col, end_line, end_col = M.get_visual_selection(bufnr)
end

-- Consider adjustment here for is_normal if there are scenarios where it doesn't align appropriately

return {
winid = winid,
bufnr = bufnr,
mode = mode,
is_visual = (args and args.range > 0) or is_visual_mode(mode),
is_normal = (args and args.range == 0) or is_normal_mode(mode),
is_visual = is_visual,
is_normal = is_normal,
buftype = api.nvim_buf_get_option(bufnr, "buftype") or "",
filetype = M.get_filetype(bufnr),
cursor_pos = cursor_pos,
Expand Down
10 changes: 7 additions & 3 deletions plugin/codecompanion.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,20 @@ end

local codecompanion = require("codecompanion")

vim.api.nvim_create_user_command("CodeCompanion", function(opts)
codecompanion.inline(opts)
end, { desc = "Trigger CodeCompanion inline", range = true, nargs = "*" })

vim.api.nvim_create_user_command("CodeCompanionChat", function(opts)
codecompanion.chat(opts)
end, { desc = "Open a Code Companion chat buffer", range = true })
end, { desc = "Open a CodeCompanion chat buffer", range = true })

vim.api.nvim_create_user_command("CodeCompanionActions", function(opts)
codecompanion.actions(opts)
end, { desc = "Open the Code Companion actions palette", range = true })
end, { desc = "Open the CodeCompanion actions palette", range = true })

vim.api.nvim_create_user_command("CodeCompanionToggle", function()
codecompanion.toggle()
end, { desc = "Toggle a Code Companion chat buffer" })
end, { desc = "Toggle a CodeCompanion chat buffer" })

vim.g.loaded_codecompanion = true

0 comments on commit 8642549

Please sign in to comment.