Skip to content
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
22 changes: 11 additions & 11 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
types: [opened, synchronize]

concurrency:
group: github.head_ref
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
Expand Down Expand Up @@ -54,25 +54,25 @@ jobs:
matrix:
include:
- id: Neovim Nightly
os: ubuntu-20.04
url: https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.tar.gz
os: ubuntu-latest
url: https://github.com/neovim/neovim/releases/download/nightly/nvim-linux-x86_64.tar.gz
manager: sudo apt-get
packages: -y ripgrep
- id: Neovim 0.9
os: ubuntu-20.04
url: https://github.com/neovim/neovim/releases/download/v0.9.0/nvim-linux64.tar.gz
- id: Neovim 0.10.4
os: ubuntu-latest
url: https://github.com/neovim/neovim/releases/download/v0.10.4/nvim-linux-x86_64.tar.gz
manager: sudo apt-get
packages: -y ripgrep
- id: Neovim 0.8
os: ubuntu-20.04
url: https://github.com/neovim/neovim/releases/download/v0.8.0/nvim-linux64.tar.gz
- id: Neovim Stable
os: ubuntu-latest
url: https://github.com/neovim/neovim/releases/download/stable/nvim-linux-x86_64.tar.gz
manager: sudo apt-get
packages: -y ripgrep
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- run: date +%F > todays-date
- name: Restore from todays cache
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: _neovim
key: ${{ runner.os }}-${{ matrix.url }}-${{ hashFiles('todays-date') }}
Expand Down
94 changes: 51 additions & 43 deletions doc/explain-it.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*ExplainIt.setup()*
`ExplainIt.setup`({opts})
Sets up plugin with user-provided options
Parameters~
Parameters ~
{opts} `(any)`

------------------------------------------------------------------------------
Expand All @@ -12,14 +12,14 @@ Parameters~
Core function for preparing requests to external services. Based on input,
will either pull the contents of the full buffer into a variable or just the
visually selected text, then call call_chat_gpt with it.
Parameters~
Parameters ~
{opts} `(any)`

------------------------------------------------------------------------------
*ExplainIt.call_chat_gpt()*
`ExplainIt.call_chat_gpt`({opts})
Takes prepared input text and calls either the chat or the completion api on the chat-gpt module
Parameters~
Parameters ~
{opts} `(any)`


Expand All @@ -28,14 +28,14 @@ Parameters~
*M.options*
`M.options`
Plugin default config values:
>
>lua
M.options = {
append_current_buffer = false,
-- Prints useful logs about what event are triggered, and reasons actions are executed.
debug = false,
max_notification_width = 200,
max_retries = 3,
openai_chat_model = "gpt-3.5-turbo-16k-0613",
openai_chat_model = "gpt-5",
openai_completion_model = "text-davinci-003",
output_directory = "/tmp/explain_it_output",
split_responses = true,
Expand All @@ -49,14 +49,13 @@ Plugin default config values:
}

<

------------------------------------------------------------------------------
*M.setup()*
`M.setup`({options})
Parameters~
Parameters ~
{options} `(table)` Module config table. See |M.options|.

Usage~
Usage ~
`require("explain-it").setup()` (add `{}` with your |M.options| table)


Expand All @@ -66,18 +65,18 @@ Usage~
`M.make_system_call`({command})
Makes a call into the underlying operating system
and reads the response
Parameters~
Parameters ~
{command} `(string)` the command to run
Return~
Return ~
`(string|nil)` result result of the command

------------------------------------------------------------------------------
*M.make_system_call_with_retry()*
`M.make_system_call_with_retry`({command})
Wrapper around make_system_call that will retry failed requests
Parameters~
Parameters ~
{command} `(string)`
Return~
Return ~
`(table|lsp.ResponseError)`

------------------------------------------------------------------------------
Expand All @@ -92,17 +91,26 @@ Creates a temporary file on the operating system
*M.notify_response()*
`M.notify_response`({ai_response})
response using notify
Parameters~
{ai_response} AIResponse
Return~
Parameters ~
{ai_response} `(AIResponse)`
Return ~
`(nil)`

------------------------------------------------------------------------------
*M.append_buffer_response()*
`M.append_buffer_response`({ai_response})
response using notify
Parameters ~
{ai_response} `(AIResponse)`
Return ~
`(nil)`


==============================================================================
------------------------------------------------------------------------------
Class~
Class ~
{AIResponse}
Fields~
Fields ~
{question} `(string)`
{input} `(string)`
{response} `(string)`
Expand All @@ -124,57 +132,57 @@ commands
*M.parse_response()*
`M.parse_response`({response_json}, {split})
Formats a response string to extract the chat-gpt response (or error) from the API response. Includes logic to be API agnostic for either the completion or the chat API
Parameters~
Parameters ~
{response_json} `(table)`
{split} `(boolean)`
Return~
Return ~
`(string)`

------------------------------------------------------------------------------
*M.get_filetype()*
`M.get_filetype`()
Uses vim api to get filetype of current buffer
Return~
Return ~
`(string)`

------------------------------------------------------------------------------
*M.get_question()*
`M.get_question`({question})
Returns default question based on filetype of buffer
Parameters~
Parameters ~
{question} `(string|nil)`
Return~
Return ~
`(string)`

------------------------------------------------------------------------------
*M.get_formatted_command()*
`M.get_formatted_command`({escaped_input}, {question}, {command_type})
Uses a local command and replaces placeholder text with the ChatGPT API Key from an env var and placeholder text with the prompt
Parameters~
Parameters ~
{escaped_input} `(string)`
{question} `(string)`
{command_type} commands
Return~
{command_type} `(commands)`
Return ~
`(string)`

------------------------------------------------------------------------------
*M.call_gpt()*
`M.call_gpt`({escaped_input}, {optional_question}, {prompt_type})
Formats input in order to make an API call to ChatGPT, makes the API call, writes the prompt and response to a file, then returns the response
Parameters~
Parameters ~
{escaped_input} `(any)`
{optional_question} `(any)`
{prompt_type} `(any)`
Return~
AIResponse
Return ~
`(AIResponse)`

------------------------------------------------------------------------------
*M.write_ai_response_to_file()*
`M.write_ai_response_to_file`({ai_response})
Writes the prompt and response to a file so that Chat-GPT responses can be persisted
Parameters~
{ai_response} AIResponse
Return~
Parameters ~
{ai_response} `(AIResponse)`
Return ~
`(string)`


Expand All @@ -185,21 +193,21 @@ Return~
Yank current visual selection into the 'v' register
Note that this makes no effort to preserve this register
Credit: tjdevries
Return~
Return ~
`(string)`

------------------------------------------------------------------------------
*M.get_buffer_lines()*
`M.get_buffer_lines`()
Get all lines in current buffer
Return~
Return ~
`(string)`

------------------------------------------------------------------------------
*M.append_buffer_lines()*
`M.append_buffer_lines`({bufnr}, {content})
content to buffer
Parameters~
Parameters ~
{bufnr} `(number)`
{content} `(string)`

Expand All @@ -209,18 +217,18 @@ Parameters~
*M.escape()*
`M.escape`({input})
Escapes characters so that they can be included in a JSON body
Parameters~
Parameters ~
{input} `(any)`
Return~
Return ~
`(string)`

------------------------------------------------------------------------------
*M.get_escaped_string()*
`M.get_escaped_string`({input})
Escapes a string value or all string values on an input table
Parameters~
{input} `(string|{)` [string]: string }
Return~
Parameters ~
{input} `(string|{ [string]: string })`
Return ~
`(string)`


Expand All @@ -229,18 +237,18 @@ Return~
*M.format_string_with_line_breaks()*
`M.format_string_with_line_breaks`({str})
Takes a string of variable length as input, then formats the string by splitting it into words and inserting line breaks to ensure that each line is no longer than the max_width as defined in global settings
Parameters~
Parameters ~
{str} `(string)`
Return~
Return ~
`(string)`

------------------------------------------------------------------------------
*M.truncate_string()*
`M.truncate_string`({str}, {len})
Takes a string as input and returns a truncated version of the string if it is longer than 77 characters. The truncated version includes an ellipsis ("...") at the end. If the string is 77 characters or shorter, the function simply returns the original string. The code also includes comments that describe the function's input and output parameters. Finally, the code returns the module "M".
Parameters~
Parameters ~
{str} `(string)`
Return~
Return ~
`(string)`


Expand Down
1 change: 1 addition & 0 deletions doc/tags
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ExplainIt.call_chat_gpt() explain-it.txt /*ExplainIt.call_chat_gpt()*
ExplainIt.explain_it() explain-it.txt /*ExplainIt.explain_it()*
ExplainIt.setup() explain-it.txt /*ExplainIt.setup()*
M.append_buffer_lines() explain-it.txt /*M.append_buffer_lines()*
M.append_buffer_response() explain-it.txt /*M.append_buffer_response()*
M.call_gpt() explain-it.txt /*M.call_gpt()*
M.escape() explain-it.txt /*M.escape()*
M.format_string_with_line_breaks() explain-it.txt /*M.format_string_with_line_breaks()*
Expand Down
2 changes: 1 addition & 1 deletion lua/explain-it/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ M.options = {
debug = false,
max_notification_width = 200,
max_retries = 3,
openai_chat_model = "gpt-4o",
openai_chat_model = "gpt-5",
openai_completion_model = "text-davinci-003",
output_directory = "/tmp/explain_it_output",
split_responses = true,
Expand Down
20 changes: 16 additions & 4 deletions lua/tests/handlers/response_spec.lua
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
local stub = require "luassert.stub"

-- Clear loaded modules to ensure we can mock properly
package.loaded["notify"] = nil
package.loaded["explain-it.handlers.response"] = nil

-- Create stub for notify
local notify_stub = stub()
package.loaded["notify"] = notify_stub

local response_handler = require "explain-it.handlers.response"
local notify = require "notify"

describe("notify", function()
before_each(function()
stub(notify, "notify")
require("explain-it").setup {
token_limit = 2000,
}
end)

after_each(function()
notify_stub:clear()
end)

it("should notify response", function()
local ai_response = {
question = "What is your name?",
Expand All @@ -25,11 +37,11 @@ describe("notify", function()
Nice to meet you John
]]
response_handler.notify_response(ai_response)
assert.stub(notify.notify).was_called_with(expected_notification, nil, nil)
assert.stub(notify_stub).was_called_with(expected_notification)
end)

it("should not notify response if ai_response is nil", function()
response_handler.notify_response(nil)
assert.stub(notify.notify).was_not_called()
assert.stub(notify_stub).was_not_called()
end)
end)
2 changes: 2 additions & 0 deletions lua/tests/init_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ describe("ExplainIt", function()
custom_prompt = false,
text = "escaped string",
is_visual = false,
output_to_buffer = false,
}
end)

Expand All @@ -52,6 +53,7 @@ describe("ExplainIt", function()
custom_prompt = false,
text = "escaped string",
is_visual = true,
output_to_buffer = false,
}
end)

Expand Down