Skip to content
This repository has been archived by the owner on Jul 22, 2023. It is now read-only.

Commit

Permalink
Merge pull request #25 from jameshiew/changes
Browse files Browse the repository at this point in the history
0.2.3
  • Loading branch information
jameshiew authored Sep 18, 2021
2 parents f3ab2ab + d772c8d commit f459b48
Show file tree
Hide file tree
Showing 17 changed files with 113 additions and 101 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

## [0.2.3] - 2021-09-18

### Added
* Predefined `<Plug>` commands to make mapping custom key sequences to flows easier

## [0.2.2] - 2021-09-16

### Changed
Expand Down Expand Up @@ -34,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.1.0] - 2021-09-13

[0.2.3]: https://github.com/jameshiew/nvim-magic/compare/v0.2.2...0.2.3
[0.2.2]: https://github.com/jameshiew/nvim-magic/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/jameshiew/nvim-magic/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/jameshiew/nvim-magic/compare/v0.1.0...v0.2.0
Expand Down
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# nvim-magic

[![Pipeline Status](https://gitlab.com/jameshiew/nvim-magic/badges/master/pipeline.svg)](https://gitlab.com/jameshiew/nvim-magic/-/pipelines)

A pluggable framework for integrating AI code assistance into Neovim. The goals are to make using AI code assistance unobtrusive, and to make it easy to create and share new flows that use AI code assistance. Go to [quickstart](#quickstart) for how to install. It currently works with [OpenAI Codex](https://openai.com/blog/openai-codex/).
Expand Down Expand Up @@ -30,15 +31,15 @@ A pluggable framework for integrating AI code assistance into Neovim. The goals

### Prerequisites

* Neovim (v0.5+)
* `curl`
- Neovim (v0.5+)
- `curl`

### Installation

At the moment, only a backend for [OpenAI](https://beta.openai.com/) is implemented, which is bundled in this repo and used by default. Your API key should be made available to your Neovim session in an environment variable `OPENAI_API_KEY`. See [docs/openai.md](docs/openai.md) for more details.

```shell
export OPENAI_API_KEY='your-api-key-here'
export OPENAI_API_KEY='your-api-key-here'
```

Install like any other plugin. It is necessary to call `setup()` once see [docs/config.md](docs/config.md) if you want to override the default configuration e.g. to turn off the default keymaps.
Expand All @@ -50,21 +51,22 @@ use({
config = function()
require('nvim-magic').setup()
end,
tag = 'v0.2.2', -- recommended to pin to a tag and update manually as there may be breaking changes
tag = '0.2.3', -- recommended to pin to a tag and update manually as there may be breaking changes
requires = {
'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim'
}
})
```

### Default Keymaps
### Keymaps

These keys are mapped for visual mode selections by default (though you can disable this by passing `use_default_keymap = false` in the setup config).
These flows have keymaps set by default for visual mode selections (though you can disable this by passing `use_default_keymap = false` in the setup config).

| keys | mode | action|
|--|--|--|
|`<Leader>mcs`| visual | Fetch and append completion|
|`<Leader>mss`| visual | Ask for an alteration to the selected text|
|`<Leader>mds`| visual | Generate a docstring|
You can map your own key sequences to the predefined `<Plug>`s if you don't want to use the default keymaps.

| `<Plug>` | default keymap | mode | action |
| ------------------------------------- | -------------- | ------ | ------------------------------------------ |
| `<Plug>nvim-magic-append-completion` | `<Leader>mcs` | visual | Fetch and append completion |
| `<Plug>nvim-magic-suggest-alteration` | `<Leader>mss` | visual | Ask for an alteration to the selected text |
| `<Plug>nvim-magic-suggest-docstring` | `<Leader>mds` | visual | Generate a docstring |
6 changes: 3 additions & 3 deletions lua/nvim-magic-openai/backend.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local M = {}
local backend = {}

local completion = require('nvim-magic-openai.completion')

Expand Down Expand Up @@ -29,12 +29,12 @@ end

local BackendMt = { __index = BackendMethods }

function M.new(api_endpoint, http, api_key_fn)
function backend.new(api_endpoint, http, api_key_fn)
return setmetatable({
api_endpoint = api_endpoint,
get_api_key = api_key_fn,
http = http,
}, BackendMt)
end

return M
return backend
8 changes: 4 additions & 4 deletions lua/nvim-magic-openai/cache.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local M = {}
local cache = {}

local log = require('nvim-magic.log')
local pathlib = require('plenary.path')
Expand All @@ -19,7 +19,7 @@ end

local CacheMt = { __index = CacheMethods }

function M.new(directory)
function cache.new(directory)
assert(type(directory) == 'string' and directory ~= '')
local directory_path = DIR:joinpath(directory)
directory_path:mkdir({ parents = true, exist_ok = true })
Expand All @@ -38,8 +38,8 @@ end

local DummyCacheMt = { __index = DummyCacheMethods }

function M.new_dummy()
function cache.new_dummy()
return setmetatable({}, DummyCacheMt)
end

return M
return cache
8 changes: 4 additions & 4 deletions lua/nvim-magic-openai/completion.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local M = {}
local completion = {}

function M.new_request(prompt, max_tokens, stops)
function completion.new_request(prompt, max_tokens, stops)
assert(type(prompt) == 'string', 'prompt must be a string')
assert(type(max_tokens) == 'number', 'max tokens must be a number')
if stops then
Expand All @@ -19,11 +19,11 @@ function M.new_request(prompt, max_tokens, stops)
}
end

function M.extract_from(res_body)
function completion.extract_from(res_body)
local decoded = vim.fn.json_decode(res_body)
assert(decoded ~= nil, "couldn't decode body")
assert(decoded.choices ~= nil, 'no choices returned')
return decoded.choices[1].text
end

return M
return completion
6 changes: 3 additions & 3 deletions lua/nvim-magic-openai/http.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local M = {}
local http = {}

local curl = require('nvim-magic-openai.curl')
local random = require('nvim-magic-openai.random')
Expand Down Expand Up @@ -81,11 +81,11 @@ end

local ClientMt = { __index = ClientMethods }

function M.new(cache)
function http.new(cache)
assert(type(cache) == 'table', 'cache must be a table with a method save(filename, contents)')
return setmetatable({
cache = cache,
}, ClientMt)
end

return M
return http
10 changes: 5 additions & 5 deletions lua/nvim-magic-openai/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local M = {}
local openai = {}

local cache = require('nvim-magic-openai.cache')
local backend = require('nvim-magic-openai.backend')
Expand All @@ -15,7 +15,7 @@ local function env_get_api_key()
return api_key
end

function M.default_cfg()
function openai.default_cfg()
return {
api_endpoint = DEFAULT_API_ENDPOINT,
cache = {
Expand All @@ -24,8 +24,8 @@ function M.default_cfg()
}
end

function M.new(override)
local config = M.default_cfg()
function openai.new(override)
local config = openai.default_cfg()

if override then
assert(type(override) == 'table', 'config must be a table')
Expand Down Expand Up @@ -63,4 +63,4 @@ function M.new(override)
return backend.new(config.api_endpoint, http.new(http_cache), env_get_api_key)
end

return M
return openai
6 changes: 3 additions & 3 deletions lua/nvim-magic-openai/random.lua
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
local M = {}
local random = {}

math.randomseed(os.time())

local A_ORD = 97
local Z_ORD = 122

function M.generate_timestamped_string()
function random.generate_timestamped_string()
local s = ''
for _ = 1, 8 do
s = s .. string.char(math.random(A_ORD, Z_ORD))
end
return os.date('%Y-%m-%d-%H-%M-%S-') .. s
end

return M
return random
22 changes: 11 additions & 11 deletions lua/nvim-magic/buffer.lua
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
local M = {}
local buffer = {}

local log = require('nvim-magic.log')

local ESC_FEEDKEY = vim.api.nvim_replace_termcodes('<ESC>', true, false, true)

function M.get_handles()
function buffer.get_handles()
local winnr = vim.api.nvim_get_current_win()
local bufnr = vim.api.nvim_win_get_buf(winnr)
return bufnr, winnr
end

function M.get_filename()
function buffer.get_filename()
return vim.fn.expand('%:t')
end

function M.get_filetype(bufnr)
function buffer.get_filetype(bufnr)
if not bufnr then
bufnr = 0
end
return vim.api.nvim_buf_get_option(bufnr, 'filetype')
end

function M.append(bufnr, row, col, lines)
function buffer.append(bufnr, row, col, lines)
vim.api.nvim_buf_set_text(bufnr, row - 1, col - 1, row - 1, col - 1, lines)
log.fmt_debug('Appended lines count=%s row=%s col=%s)', #lines, row, col)
end

function M.get_visual_lines(bufnr)
function buffer.get_visual_lines(bufnr)
if not bufnr then
bufnr = 0
end

local start_row, start_col, end_row, end_col = M.get_visual_start_end()
local start_row, start_col, end_row, end_col = buffer.get_visual_start_end()
if start_row == end_row and start_col == end_col then
return nil
end
Expand All @@ -43,13 +43,13 @@ function M.get_visual_lines(bufnr)
end_col
)

local visual_lines = M.get_lines(bufnr, start_row, start_col, end_row, end_col)
local visual_lines = buffer.get_lines(bufnr, start_row, start_col, end_row, end_col)

return visual_lines, start_row, start_col, end_row, end_col
end

-- should be called while in visual mode only
function M.get_visual_start_end()
function buffer.get_visual_start_end()
-- NB: switches out of visual mode then back again to ensure marks are current
vim.api.nvim_feedkeys(ESC_FEEDKEY, 'n', true)
vim.api.nvim_feedkeys('gv', 'x', false)
Expand All @@ -62,7 +62,7 @@ function M.get_visual_start_end()
end

-- gets full and partial lines between start and end
function M.get_lines(bufnr, start_row, start_col, end_row, end_col)
function buffer.get_lines(bufnr, start_row, start_col, end_row, end_col)
if not bufnr then
bufnr = 0
end
Expand All @@ -80,4 +80,4 @@ function M.get_lines(bufnr, start_row, start_col, end_row, end_col)
return lines
end

return M
return buffer
10 changes: 5 additions & 5 deletions lua/nvim-magic/flows.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-- helpful flows that can be mapped to key bindings
-- they can assume sensible defaults and/or interact with the user
local M = {}
local flows = {}

local buffer = require('nvim-magic.buffer')
local keymaps = require('nvim-magic.keymaps')
Expand All @@ -18,7 +18,7 @@ local function notify_prefix(filename)
return prefix
end

function M.append_completion(backend, max_tokens, stops)
function flows.append_completion(backend, max_tokens, stops)
assert(backend ~= nil, 'backend must be provided')
if max_tokens then
assert(type(max_tokens) == 'number', 'max tokens must be a number')
Expand Down Expand Up @@ -57,7 +57,7 @@ function M.append_completion(backend, max_tokens, stops)
end)
end

function M.suggest_alteration(backend, language)
function flows.suggest_alteration(backend, language)
assert(backend ~= nil, 'backend must be provided')
if not language then
language = buffer.get_filetype()
Expand Down Expand Up @@ -141,7 +141,7 @@ function M.suggest_alteration(backend, language)
end)
end

function M.suggest_docstring(backend, language)
function flows.suggest_docstring(backend, language)
assert(backend ~= nil, 'backend must be provided')
if not language then
language = buffer.get_filetype()
Expand Down Expand Up @@ -222,4 +222,4 @@ function M.suggest_docstring(backend, language)
end)
end

return M
return flows
6 changes: 3 additions & 3 deletions lua/nvim-magic/fs.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local M = {}
local fs = {}

function M.read(path)
function fs.read(path)
-- @returns [string]
assert(path ~= nil, 'path cannot be nil')
assert(type(path) == 'string', 'path must be a string')
Expand All @@ -11,4 +11,4 @@ function M.read(path)
return contents
end

return M
return fs
14 changes: 7 additions & 7 deletions lua/nvim-magic/init.lua
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
local M = {}
local magic = {}

local log = require('nvim-magic.log')

M.backends = {} -- should be set during setup()
magic.backends = {} -- should be set during setup()

function M.default_cfg()
function magic.default_cfg()
return {
backends = {
default = require('nvim-magic-openai').new(),
Expand All @@ -13,8 +13,8 @@ function M.default_cfg()
}
end

function M.setup(override)
local config = M.default_cfg()
function magic.setup(override)
local config = magic.default_cfg()

if override then
if override.backends then
Expand All @@ -33,7 +33,7 @@ function M.setup(override)

log.fmt_debug('Got config=%s ', config)

M.backends = config.backends
magic.backends = config.backends

if config.use_default_keymap then
require('nvim-magic.keymaps').set_default()
Expand All @@ -42,4 +42,4 @@ function M.setup(override)
end
end

return M
return magic
Loading

0 comments on commit f459b48

Please sign in to comment.