commit 22677e9b86fac102fa3ef8309bb4790dca1831a0
parent 623f647d9cf726fd9620e148a4f4c1d0d6792a02
Author: Alexander Balgavy <alexander.balgavy@spaceapplications.com>
Date: Fri, 27 Oct 2023 20:19:46 +0200
nvim: llm access via ollama
Diffstat:
3 files changed, 144 insertions(+), 23 deletions(-)
diff --git a/nvim/init.lua b/nvim/init.lua
@@ -74,6 +74,8 @@ vim.keymap.set('n', 'i', function()
end
end, {expr = true})
+require('llm')
+
vim.cmd ([[
nnoremap <leader><C-e><C-u> :<c-u>exe "vsplit ~/.vim/snippets/"..&filetype..".snippets"<CR>
]])
diff --git a/nvim/lazy-lock.json b/nvim/lazy-lock.json
@@ -1,30 +1,30 @@
{
- "Comment.nvim": { "branch": "master", "commit": "d0cbbfb539898a275dc4398446ab0ae3b94819bf" },
- "LuaSnip": { "branch": "master", "commit": "99a94cc35ec99bf06263d0346128e908a204575c" },
- "cellular-automaton.nvim": { "branch": "main", "commit": "679943b8e1e5ef79aaeeaf4b00782c52eb4e928f" },
+ "Comment.nvim": { "branch": "master", "commit": "0236521ea582747b58869cb72f70ccfa967d2e89" },
+ "LuaSnip": { "branch": "master", "commit": "80a8528f084a97b624ae443a6f50ff8074ba486b" },
+ "cellular-automaton.nvim": { "branch": "main", "commit": "b7d056dab963b5d3f2c560d92937cb51db61cb5b" },
"cmp-nvim-lsp": { "branch": "main", "commit": "44b16d11215dce86f253ce0c30949813c0a90765" },
- "cmp_luasnip": { "branch": "master", "commit": "18095520391186d634a0045dacaa346291096566" },
+ "cmp_luasnip": { "branch": "master", "commit": "05a9ab28b53f71d1aece421ef32fee2cb857a843" },
"fidget.nvim": { "branch": "main", "commit": "89b633f3bd0b7187f070236b348697de176860e2" },
- "flash.nvim": { "branch": "main", "commit": "967117690bd677cb7b6a87f0bc0077d2c0be3a27" },
- "gitsigns.nvim": { "branch": "main", "commit": "31178496552584e84fa9e74e087dec1f6c347f5d" },
- "indent-blankline.nvim": { "branch": "master", "commit": "4541d690816cb99a7fc248f1486aa87f3abce91c" },
- "lazy.nvim": { "branch": "main", "commit": "dac844ed617dda4f9ec85eb88e9629ad2add5e05" },
+ "flash.nvim": { "branch": "main", "commit": "48817af25f51c0590653bbc290866e4890fe1cbe" },
+ "gitsigns.nvim": { "branch": "main", "commit": "5a9a6ac29a7805c4783cda21b80a1e361964b3f2" },
+ "indent-blankline.nvim": { "branch": "master", "commit": "8a7b48f5823cc924f815129192288ec2e2b9288f" },
+ "lazy.nvim": { "branch": "main", "commit": "4c75c8eeb957a99aa44ce8e526c04340ab358c5e" },
"lsp-inlayhints.nvim": { "branch": "main", "commit": "d981f65c9ae0b6062176f0accb9c151daeda6f16" },
- "mason-lspconfig.nvim": { "branch": "main", "commit": "e86a4c84ff35240639643ffed56ee1c4d55f538e" },
- "mason.nvim": { "branch": "main", "commit": "fe9e34a9ab4d64321cdc3ecab4ea1809239bb73f" },
- "neodev.nvim": { "branch": "main", "commit": "9f0205a08757711f57589a1dffa8abf525f4a23b" },
- "null-ls.nvim": { "branch": "main", "commit": "db09b6c691def0038c456551e4e2772186449f35" },
- "nvim-cmp": { "branch": "main", "commit": "c4e491a87eeacf0408902c32f031d802c7eafce8" },
- "nvim-dap": { "branch": "master", "commit": "1c63f37f95cd4fb54512898168138d9a75d1516a" },
+ "mason-lspconfig.nvim": { "branch": "main", "commit": "e7b64c11035aa924f87385b72145e0ccf68a7e0a" },
+ "mason.nvim": { "branch": "main", "commit": "cd7835b15f5a4204fc37e0aa739347472121a54c" },
+ "neodev.nvim": { "branch": "main", "commit": "b094a663ccb71733543d8254b988e6bebdbdaca4" },
+ "null-ls.nvim": { "branch": "main", "commit": "0010ea927ab7c09ef0ce9bf28c2b573fc302f5a7" },
+ "nvim-cmp": { "branch": "main", "commit": "d3a3056204e1a9dbb7c7fe36c114dc43b681768c" },
+ "nvim-dap": { "branch": "master", "commit": "92dc531eea2c9a3ef504a5c8ac0decd1fa59a6a3" },
"nvim-dap-python": { "branch": "master", "commit": "37b4cba02e337a95cb62ad1609b3d1dccb2e5d42" },
- "nvim-dap-ui": { "branch": "master", "commit": "85b16ac2309d85c88577cd8ee1733ce52be8227e" },
+ "nvim-dap-ui": { "branch": "master", "commit": "34160a7ce6072ef332f350ae1d4a6a501daf0159" },
"nvim-dap-virtual-text": { "branch": "master", "commit": "57f1dbd0458dd84a286b27768c142e1567f3ce3b" },
- "nvim-lspconfig": { "branch": "master", "commit": "c0de180ddb3df36feef8ac3607670894d0e7497f" },
- "nvim-origami": { "branch": "main", "commit": "7bc3fd9e8cba3c3ccc64874b32568102eac7214e" },
- "nvim-treesitter": { "branch": "master", "commit": "8d5e5dc40a4c480483690777cefb8cf67e710702" },
- "nvim-treesitter-textobjects": { "branch": "master", "commit": "9e519b6146512c8e2e702faf8ac48420f4f5deec" },
- "plenary.nvim": { "branch": "master", "commit": "267282a9ce242bbb0c5dc31445b6d353bed978bb" },
- "telescope-fzf-native.nvim": { "branch": "main", "commit": "9bc8237565ded606e6c366a71c64c0af25cd7a50" },
- "telescope.nvim": { "branch": "master", "commit": "31b05ad3c313210039fae6958fb00449d72c259e" },
- "which-key.nvim": { "branch": "main", "commit": "7ccf476ebe0445a741b64e36c78a682c1c6118b7" }
+ "nvim-ghost.nvim": { "branch": "main", "commit": "a1ca0b2dac59881066d7ac9373cf64d59ba29d6a" },
+ "nvim-lspconfig": { "branch": "master", "commit": "e49b1e90c1781ce372013de3fa93a91ea29fc34a" },
+ "nvim-treesitter": { "branch": "master", "commit": "eb3faef3a44641e5875581e901b0a8df8da2bde4" },
+ "nvim-treesitter-textobjects": { "branch": "master", "commit": "78c49ca7d2f7ccba2115c11422c037713c978ad1" },
+ "plenary.nvim": { "branch": "master", "commit": "50012918b2fc8357b87cff2a7f7f0446e47da174" },
+ "telescope-fzf-native.nvim": { "branch": "main", "commit": "6c921ca12321edaa773e324ef64ea301a1d0da62" },
+ "telescope.nvim": { "branch": "master", "commit": "74ce793a60759e3db0d265174f137fb627430355" },
+ "which-key.nvim": { "branch": "main", "commit": "ce741eb559c924d72e3a67d2189ad3771a231414" }
}
\ No newline at end of file
diff --git a/nvim/lua/llm.lua b/nvim/lua/llm.lua
@@ -0,0 +1,119 @@
+local ESC_FEEDKEY = vim.api.nvim_replace_termcodes("<ESC>", true, false, true)
+local ollama = {
+
+ --- @param model string
+ --- @param context string
+ --- @param prompt string
+ --- @param buf_nr number
+ --- @param max_width number
+ --- @return number
+ run = function(model, context, prompt, buf_nr, max_width)
+ local cmd = ("ollama run $model $prompt")
+ :gsub("$model", model)
+ :gsub("$prompt", vim.fn.shellescape(context .. "\n" .. prompt))
+ local header = vim.split(prompt, "\n")
+ table.insert(header, "----------------------------------------")
+ vim.api.nvim_buf_set_lines(buf_nr, 0, -1, false, header)
+ local line = vim.tbl_count(header)
+ local line_char_count = 0
+ local words = {}
+ return vim.fn.jobstart(cmd, {
+ on_stdout = function(_, data, _)
+ for i, token in ipairs(data) do
+ if i > 1 or (string.match(token, "^%s") and line_char_count > max_width) then -- if returned data array has more than one element, a line break occured.
+ line = line + 1
+ words = {}
+ line_char_count = 0
+ end
+ line_char_count = line_char_count + #token
+ table.insert(words, token)
+ vim.api.nvim_buf_set_lines(buf_nr, line, line + 1, false, { table.concat(words, "") })
+ end
+ end,
+ })
+ end,
+
+ --- @return string
+ get_visual_lines = function(bufnr)
+ vim.api.nvim_feedkeys(ESC_FEEDKEY, "n", true)
+ vim.api.nvim_feedkeys("gv", "x", false)
+ vim.api.nvim_feedkeys(ESC_FEEDKEY, "n", true)
+
+ local start_row, start_col = unpack(vim.api.nvim_buf_get_mark(bufnr, "<"))
+ local end_row, end_col = unpack(vim.api.nvim_buf_get_mark(bufnr, ">"))
+ local lines = vim.api.nvim_buf_get_lines(bufnr, start_row - 1, end_row, false)
+
+ if start_row == 0 then
+ lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
+ start_row = 1
+ start_col = 0
+ end_row = #lines
+ end_col = #lines[#lines]
+ end
+
+ start_col = start_col + 1
+ end_col = math.min(end_col, #lines[#lines] - 1) + 1
+
+ lines[#lines] = lines[#lines]:sub(1, end_col)
+ lines[1] = lines[1]:sub(start_col)
+
+ return table.concat(lines, "\n")
+ end
+}
+local plen = require("plenary.window.float")
+-- define some styles and spawn a scratch buffer
+local win_options = {
+ winblend = 10,
+ border = "rounded",
+ bufnr = vim.api.nvim_create_buf(false, true)
+}
+
+vim.keymap.set("n", "<leader>cc", function()
+ local prompt = vim.fn.input("Prompt: ")
+ if prompt == "" then
+ return
+ end
+ plen.clear(win_options.bufnr)
+ local float = plen.percentage_range_window(0.8, 0.8, win_options)
+ local win_width = vim.api.nvim_win_get_width(float.win_id) - 5
+ ollama.run("mistral:instruct", "", prompt, float.bufnr, win_width)
+end, { silent = true, desc = "Mistral" })
+
+vim.keymap.set("v", "<leader>cp", function()
+ local prompt = ollama.get_visual_lines(0)
+ plen.clear(win_options.bufnr)
+ local float = plen.percentage_range_window(0.8, 0.8, win_options)
+ local win_width = vim.api.nvim_win_get_width(float.win_id) - 5
+ ollama.run("mistral:instruct", "", prompt, float.bufnr, win_width)
+end, { silent = true, desc = "Mistral" })
+
+------------------------------------------------------------------
+-- coding
+vim.keymap.set("v", "<leader>cc", function()
+ local prompt = ollama.get_visual_lines(0)
+ plen.clear(win_options.bufnr)
+ local float = plen.percentage_range_window(0.8, 0.8, win_options)
+ local win_width = vim.api.nvim_win_get_width(float.win_id) - 5
+ ollama.run("codellama:7b", "", prompt, float.bufnr, win_width)
+end, { silent = true, desc = "Codellama" })
+
+------------------------------------------------------------------
+-- general purpose math & logic questions
+vim.keymap.set("n", "<leader>cm", function()
+ local prompt = vim.fn.input("Prompt: ")
+ if prompt == "" then
+ return
+ end
+ plen.clear(win_options.bufnr)
+ local float = plen.percentage_range_window(0.8, 0.8, win_options)
+ local win_width = vim.api.nvim_win_get_width(float.win_id) - 5
+ ollama.run("wizard-math", "", prompt, float.bufnr, win_width)
+end, { silent = true, desc = "Math" })
+
+vim.keymap.set("v", "<leader>cm", function()
+ local prompt = ollama.get_visual_lines(0)
+ plen.clear(win_options.bufnr)
+ local float = plen.percentage_range_window(0.8, 0.8, win_options)
+ local win_width = vim.api.nvim_win_get_width(float.win_id) - 5
+ ollama.run("wizard-math", "", prompt, float.bufnr, win_width)
+end, { silent = true, desc = "Math" })