diff --git a/nix/neovim-overlay.nix b/nix/neovim-overlay.nix index 0b33a56..8049a98 100644 --- a/nix/neovim-overlay.nix +++ b/nix/neovim-overlay.nix @@ -58,6 +58,7 @@ with final.pkgs.lib; let lexima-vim (mkNvimPlugin inputs.neotab-nvim "neotab.nvim") ts-comments-nvim + mini-ai # Treesitter nvim-treesitter-textobjects diff --git a/nvim/lua/colors.lua b/nvim/lua/colors.lua index e51cc55..0352d3d 100644 --- a/nvim/lua/colors.lua +++ b/nvim/lua/colors.lua @@ -1,5 +1,6 @@ ---@type {[string]:"azure" | "blue" | "cyan" | "green" | "grey" | "orange" | "purple" | "red" | "yellow"} return { + around = 'purple', buffers = 'cyan', change = 'cyan', delete = 'red', @@ -9,6 +10,7 @@ return { format = 'purple', git = 'orange', go_to = 'cyan', + inner = 'purple', notifications = 'orange', replace = 'blue', search = 'green', diff --git a/nvim/lua/icons.lua b/nvim/lua/icons.lua index 019c312..60ef4dc 100644 --- a/nvim/lua/icons.lua +++ b/nvim/lua/icons.lua @@ -1,4 +1,5 @@ return { + around = '󰅪', bottom = '', center = '󰘢', change = '', @@ -35,9 +36,47 @@ return { right = '󰉶', increase = '󰉶', }, + inner = '󰅩', last = '󰘁', lazygit = '', left = '', + lsp = { + array = '', + boolean = '󰨙', + class = '', + color = '', + control = '', + constant = '󰏿', + constructor = '', + enum = '', + enummember = '', + event = '', + field = '', + file = '', + folder = '', + ['function'] = '󰊕', + interface = '', + key = '', + keyword = '', + method = '󰊕', + module = '', + namespace = '󰦮', + null = '', + number = '󰎠', + object = '', + operator = '', + package = '', + property = '', + reference = '', + snippet = '󱄽', + string = '', + struct = '', + text = '', + typeparameter = '', + unit = '', + value = '', + variable = '', + }, next = '', notifications = '󰈸', prev = '', diff --git a/nvim/lua/plugins/coding/init.lua b/nvim/lua/plugins/coding/init.lua index 74a362a..3313ca1 100644 --- a/nvim/lua/plugins/coding/init.lua +++ b/nvim/lua/plugins/coding/init.lua @@ -5,4 +5,5 @@ return { req('lexima-vim'), req('neotab-nvim'), req('ts-comments-nvim'), + req('mini-ai'), } diff --git a/nvim/lua/plugins/coding/mini-ai.lua b/nvim/lua/plugins/coding/mini-ai.lua new file mode 100644 index 0000000..c7f4016 --- /dev/null +++ b/nvim/lua/plugins/coding/mini-ai.lua @@ -0,0 +1,124 @@ +return { + 'mini.ai', + event = 'DeferredUIEnter', + before = function() + require('lz.n').trigger_load('which-key.nvim') + end, + after = function() + local ai = require('mini.ai') + + ai.setup({ + n_lines = 500, + custom_textobjects = { + -- code blOck + o = ai.gen_spec.treesitter({ + a = { '@block.outer', '@conditional.outer', '@loop.outer' }, + i = { '@block.inner', '@conditional.inner', '@loop.inner' }, + }), + + -- Class + c = ai.gen_spec.treesitter({ + a = '@class.outer', + i = '@class.inner', + }), + + -- Usage (fn call) + u = ai.gen_spec.function_call(), + + -- Usage (to last .) + U = ai.gen_spec.function_call({ name_pattern = '[%w_]' }), + + -- Digit + d = { '%f[%d]%d+' }, + + -- word within casE (snake_case, CamelCase, etc) + e = { + { + '%u[%l%d]+%f[^%l%d]', + '%f[%S][%l%d]+%f[^%l%d]', + '%f[%P][%l%d]+%f[^%l%d]', + '^[%l%d]+%f[^%l%d]', + }, + '^().*()$', + }, + + -- buffer + g = { + from = { line = 1, col = 1 }, + to = { + line = vim.fn.line('$'), + col = math.max(vim.fn.getline('$'):len(), 1), + }, + }, + }, + }) + + local i = require('icons') + local c = require('colors') + local mkA = MarleyVim.wkSpec(c.around) + local mkI = MarleyVim.wkSpec(c.inner) + + ---@param lhs string + ---@param icon string + ---@param opts table + local function mkKey(lhs, icon, opts) + if lhs:sub(1, 1) == 'a' then + return mkA(lhs, nil, icon, opts) + else + return mkI(lhs, nil, icon, opts) + end + end + + local groups = { + around = { 'a', i.around }, + around_last = { 'al', i.around }, + around_next = { 'an', i.around }, + inner = { 'i', i.inner }, + inner_last = { 'il', i.inner }, + inner_next = { 'in', i.inner }, + } + + local mappings = { + { '', '', 'whitespace' }, + { '"', '', 'double quotes' }, + { "'", '', 'single quotes' }, + { '`', '', 'backticks' }, + { '(', '󰅲', '()' }, + { ')', '󰅲', '() with ws' }, + { '[', '󰅪', '[] block' }, + { ']', '󰅪', '[] block with ws' }, + { '{', '󰅩', '{} block' }, + { '}', '󰅩', '{} block with ws' }, + { '<', '󰅴', '<>' }, + { '>', '󰅴', '<> with ws' }, + { '_', '󱁐', 'underscores' }, + { '?', '󰘎', 'user prompt' }, + { 'a', i.lsp.variable, 'argument' }, + { 'b', '󰅲', ')]} block' }, + { 'c', i.lsp.class, 'class' }, + { 'd', i.lsp.number, 'numbers' }, + { 'e', i.lsp.variable, 'word within case' }, + { 'f', i.lsp['function'], 'function' }, + { 'g', i.lsp.file, 'entire buffer' }, + { 'o', i.lsp.control, 'block, conditional, loop' }, + { 'q', i.lsp.string, 'quotes/backticks' }, + { 't', '󰅴', 'tags' }, + { 'u', i.lsp.method, 'use/call' }, + { 'U', i.lsp.method, 'use/call without dot' }, + } + + local spec = { mode = { 'o', 'x' } } + + for name, data in pairs(groups) do + name = name:gsub('^around_', ''):gsub('^insude_', '') + + spec[#spec + 1] = mkKey(data[1], data[2], { group = name }) + + for _, item in ipairs(mappings) do + spec[#spec + 1] = mkKey(data[1] .. item[1], item[2], { desc = item[3] }) + end + end + + require('which-key').add({ spec }) + end, +}