diff --git a/flake.lock b/flake.lock index c6d2f3f..3f6e7f2 100644 --- a/flake.lock +++ b/flake.lock @@ -389,13 +389,47 @@ "type": "github" } }, + "nvim-treesitter": { + "flake": false, + "locked": { + "lastModified": 1754498994, + "owner": "nvim-treesitter", + "repo": "nvim-treesitter", + "rev": "4eb35c03443742a4c3b2db13d36da9cddb6268c3", + "type": "github" + }, + "original": { + "owner": "nvim-treesitter", + "ref": "main", + "repo": "nvim-treesitter", + "type": "github" + } + }, + "nvim-treesitter-textobjects": { + "flake": false, + "locked": { + "lastModified": 1751128959, + "owner": "nvim-treesitter", + "repo": "nvim-treesitter-textobjects", + "rev": "b54cec389e98c5b0babbe618773acec927437cab", + "type": "github" + }, + "original": { + "owner": "nvim-treesitter", + "ref": "main", + "repo": "nvim-treesitter-textobjects", + "type": "github" + } + }, "root": { "inputs": { "dart": "dart", "flake-utils": "flake-utils", "gen-luarc": "gen-luarc", "neovim-nightly-overlay": "neovim-nightly-overlay", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs_2", + "nvim-treesitter": "nvim-treesitter", + "nvim-treesitter-textobjects": "nvim-treesitter-textobjects" } }, "systems": { diff --git a/flake.nix b/flake.nix index 488efc6..260a049 100644 --- a/flake.nix +++ b/flake.nix @@ -13,6 +13,14 @@ url = "github:iofq/dart.nvim"; flake = false; }; + nvim-treesitter = { + url = "github:nvim-treesitter/nvim-treesitter/main"; + flake = false; + }; + nvim-treesitter-textobjects = { + url = "github:nvim-treesitter/nvim-treesitter-textobjects/main"; + flake = false; + }; # Add bleeding-edge plugins here. # They can be updated with `nix flake update` (make sure to commit the generated flake.lock) # wf-nvim = { diff --git a/nix/neovim-overlay.nix b/nix/neovim-overlay.nix index 6dcb1b4..00e3dd1 100644 --- a/nix/neovim-overlay.nix +++ b/nix/neovim-overlay.nix @@ -15,6 +15,10 @@ let mkNeovim = pkgs.callPackage ./mkNeovim.nix { inherit pkgs-wrapNeovim; }; dart-nvim-git = mkNvimPlugin inputs.dart "dart.nvim"; + nvim-treesitter-textobjects-git = mkNvimPlugin inputs.nvim-treesitter-textobjects "nvim-treesitter-textobjects"; + nvim-treesitter-git = pkgs.vimPlugins.nvim-treesitter.overrideAttrs (old: { + src = inputs.nvim-treesitter; + }); all-plugins = with pkgs.vimPlugins; [ blink-cmp @@ -26,17 +30,17 @@ let friendly-snippets lazy-nvim mini-nvim + nvim-autopairs nvim-lint nvim-lspconfig + nvim-treesitter-git.withAllGrammars nvim-treesitter-context - nvim-treesitter-textobjects + nvim-treesitter-textobjects-git nvim-treesitter-textsubjects - nvim-treesitter.withAllGrammars quicker-nvim refactoring-nvim render-markdown-nvim snacks-nvim - trouble-nvim ]; basePackages = with pkgs; [ @@ -69,6 +73,7 @@ in appName = "nvim"; extraPackages = basePackages ++ extraPackages; withNodeJs = false; + withSqlite = true; }; nvim-min-pkg = mkNeovim { @@ -76,7 +81,7 @@ in appName = "nvim"; extraPackages = basePackages; withNodeJs = false; - withSqlite = false; + withSqlite = true; }; # This is meant to be used within a devshell. diff --git a/nvim/colors/iofq.lua b/nvim/colors/iofq.lua index 2f1ce70..0f9db6f 100644 --- a/nvim/colors/iofq.lua +++ b/nvim/colors/iofq.lua @@ -419,7 +419,7 @@ hi(0, 'MiniIndentscopeSymbol', { link = 'Delimiter' }) hi(0, 'MiniJump', { bg = '#ad5c7c', fg = '#0f1c1e' }) hi(0, 'MiniJump2dDim', { link = 'Comment' }) hi(0, 'MiniJump2dSpot', { bold = true, fg = '#a1cdd8' }) -hi(0, 'MiniJump2dSpotAhead', { bg = '#0f1c1e', fg = '#4d7d90', nocombine = true }) +hi(0, 'MiniJump2dSpotAhead', { bold = true, fg = '#a1cdd8' }) hi(0, 'MiniJump2dSpotUnique', { bold = true, fg = '#fda47f' }) hi(0, 'MiniMapNormal', { link = 'NormalFloat' }) hi(0, 'MiniMapSymbolCount', { link = 'Special' }) diff --git a/nvim/lua/config/autocmd.lua b/nvim/lua/config/autocmd.lua index 597b87d..038f3a4 100644 --- a/nvim/lua/config/autocmd.lua +++ b/nvim/lua/config/autocmd.lua @@ -1,7 +1,6 @@ -- create undopath -local undopath = vim.fn.stdpath('data') .. 'undo' vim.api.nvim_create_autocmd('VimEnter', { - command = 'silent !mkdir -p ' .. undopath, + command = 'silent !mkdir -p ' .. vim.fn.stdpath('data') .. 'undo', group = vim.api.nvim_create_augroup('Init', {}), }) @@ -55,3 +54,57 @@ vim.api.nvim_create_autocmd({ 'FocusGained', 'TermClose', 'TermLeave' }, { end end, }) + +-- Init treesitter +vim.api.nvim_create_autocmd('FileType', { + callback = function(event) + local bufnr = event.buf + local filetype = vim.api.nvim_get_option_value('filetype', { buf = bufnr }) + + if filetype == '' then + return + end + + local parser_name = vim.treesitter.language.get_lang(filetype) + if not parser_name then + return + end + local parser_installed = pcall(vim.treesitter.get_parser, bufnr, parser_name) + if not parser_installed then + return + end + + local function map(lhs, rhs, opts) + if lhs == '' then + return + end + opts = vim.tbl_deep_extend('force', { silent = true }, opts or {}) + vim.keymap.set({ 'v', 'n' }, lhs, rhs, opts) + end + + vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + vim.treesitter.start() + + map('[c', function() + require('treesitter-context').go_to_context(vim.v.count1) + end, { desc = 'jump to TS context' }) + map(']f', function() + require('nvim-treesitter-textobjects.move').goto_next_start('@function.outer', 'textobjects') + end, { desc = 'next function def' }) + map('[f', function() + require('nvim-treesitter-textobjects.move').goto_previous_start('@function.outer', 'textobjects') + end, { desc = 'prev function def' }) + map(']a', function() + require('nvim-treesitter-textobjects.move').goto_next_start('@parameter.inner', 'textobjects') + end, { desc = 'next param def' }) + map('[a', function() + require('nvim-treesitter-textobjects.move').goto_previous_start('@parameter.inner', 'textobjects') + end, { desc = 'prev param def' }) + map('a]', function() + require('nvim-treesitter-textobjects.swap').swap_next('@parameter.inner') + end, { desc = 'swap next arg' }) + map('a[', function() + require('nvim-treesitter-textobjects.swap').swap_previous('@parameter.inner') + end, { desc = 'swap prev arg' }) + end, +}) diff --git a/nvim/lua/config/init.lua b/nvim/lua/config/init.lua index 0fabd68..2e6a1fd 100644 --- a/nvim/lua/config/init.lua +++ b/nvim/lua/config/init.lua @@ -1,25 +1,24 @@ vim.opt.autowrite = true vim.opt.backspace = 'indent,eol,start' vim.opt.confirm = true -vim.opt.completeopt = { 'menu', 'menuone', 'noselect' } vim.opt.diffopt = 'internal,filler,closeoff,inline:char' vim.opt.expandtab = true -- insert tabs as spaces -vim.o.foldlevelstart = 99 vim.opt.inccommand = 'split' -- incremental live completion -vim.opt.list = true +vim.opt.laststatus = 1 -- statusline only if split vim.opt.nrformats:append('alpha') -- let Ctrl-a do letters as well vim.opt.path:append('**') -- enable fuzzy :find ing vim.opt.relativenumber = true -vim.opt.shadafile = 'NONE' -- disable shada +vim.opt.shadafile = 'NONE' -- disable shada (unless session) vim.opt.shiftwidth = 0 -- >> shifts by tabstop vim.opt.showmatch = true -- highlight matching brackets +vim.opt.showmode = true vim.opt.signcolumn = 'no' vim.opt.softtabstop = -1 -- backspace removes tabstop vim.opt.swapfile = false vim.opt.tabstop = 2 -- 2 space tabs are based vim.opt.updatetime = 250 -- decrease update time vim.opt.virtualedit = 'onemore' -vim.opt.winborder = 'single' +vim.opt.winborder = 'rounded' vim.cmd('colorscheme iofq') -- Configure Neovim diagnostic messages @@ -33,3 +32,5 @@ vim.diagnostic.config { source = 'if_many', }, } +require('config.keymaps') +require('config.autocmd') diff --git a/nvim/lua/config/keymaps.lua b/nvim/lua/config/keymaps.lua index 109879d..51a9f6e 100644 --- a/nvim/lua/config/keymaps.lua +++ b/nvim/lua/config/keymaps.lua @@ -3,7 +3,6 @@ vim.keymap.set('n', '\\t', function() vim.o.tabstop = vim.o.tabstop == 8 and 2 or 2 * vim.o.tabstop end, { silent = true, desc = 'toggle tabstop' }) vim.keymap.set({ 'v', 'i' }, 'wq', 'l', { noremap = true, silent = true }) -vim.keymap.set({ 'v', 'n' }, 'q:', '') vim.keymap.set('v', '<', '', '>gv') vim.keymap.set('n', 'n', 'nzz', { noremap = true }) diff --git a/nvim/lua/plugins/completion.lua b/nvim/lua/plugins/completion.lua index f084dba..20480dc 100644 --- a/nvim/lua/plugins/completion.lua +++ b/nvim/lua/plugins/completion.lua @@ -35,7 +35,7 @@ return { path = { opts = { get_cwd = function(_) - return vim.fn.getcwd() + return vim.fn.getcwd() -- use nvim pwd instead of current file pwd end, }, }, diff --git a/nvim/lua/plugins/lib/minipairs.lua b/nvim/lua/plugins/lib/minipairs.lua deleted file mode 100644 index f3b22f3..0000000 --- a/nvim/lua/plugins/lib/minipairs.lua +++ /dev/null @@ -1,38 +0,0 @@ --- ripped from lazyvim -return function(opts) - local pairs = require('mini.pairs') - pairs.setup(opts) - local open = pairs.open - pairs.open = function(pair, neigh_pattern) - if vim.fn.getcmdline() ~= '' then - return open(pair, neigh_pattern) - end - local o, c = pair:sub(1, 1), pair:sub(2, 2) - local line = vim.api.nvim_get_current_line() - local cursor = vim.api.nvim_win_get_cursor(0) - local next = line:sub(cursor[2] + 1, cursor[2] + 1) - local before = line:sub(1, cursor[2]) - if opts.markdown and o == '`' and vim.bo.filetype == 'markdown' and before:match('^%s*``') then - return '`\n```' .. vim.api.nvim_replace_termcodes('', true, true, true) - end - if opts.skip_next and next ~= '' and next:match(opts.skip_next) then - return o - end - if opts.skip_ts and #opts.skip_ts > 0 then - local ok, captures = pcall(vim.treesitter.get_captures_at_pos, 0, cursor[1] - 1, math.max(cursor[2] - 1, 0)) - for _, capture in ipairs(ok and captures or {}) do - if vim.tbl_contains(opts.skip_ts, capture.capture) then - return o - end - end - end - if opts.skip_unbalanced and next == c and c ~= o then - local _, count_open = line:gsub(vim.pesc(pair:sub(1, 1)), '') - local _, count_close = line:gsub(vim.pesc(pair:sub(2, 2)), '') - if count_close > count_open then - return o - end - end - return open(pair, neigh_pattern) - end -end diff --git a/nvim/lua/plugins/lib/session_jj.lua b/nvim/lua/plugins/lib/session_jj.lua index cf7d400..5e81803 100644 --- a/nvim/lua/plugins/lib/session_jj.lua +++ b/nvim/lua/plugins/lib/session_jj.lua @@ -1,5 +1,15 @@ local M = {} -local sessions = require('mini.sessions') + +M.setup = function() + local id = M.get_id() + if M.check_exists(id) then + vim.notify('Existing session for ' .. id) + end + + vim.keymap.set('n', 'fs', function() + require('plugins.lib.session_jj').load() + end, { noremap = true, desc = 'mini session select' }) +end M.get_id = function() local jj_root = vim.system({ 'jj', 'workspace', 'root' }):wait() @@ -27,7 +37,7 @@ M.get_id = function() end M.check_exists = function(id) - for name, _ in pairs(sessions.detected) do + for name, _ in pairs(MiniSessions.detected) do if name == id then return true end @@ -48,13 +58,14 @@ M.load = function() }, { prompt = 'Session found at ' .. id .. ', load it?' }, function(c) if c == 'Yes' then -- load session (buffers, etc) as well as shada (marks) - sessions.read(id) + MiniSessions.read(id) vim.notify('loaded jj session: ' .. id) end end) else - sessions.write(id) + MiniSessions.write(id) end end +_G.M = M return M diff --git a/nvim/lua/plugins/lsp.lua b/nvim/lua/plugins/lsp.lua index f077c71..49efddb 100644 --- a/nvim/lua/plugins/lsp.lua +++ b/nvim/lua/plugins/lsp.lua @@ -2,21 +2,6 @@ return { { 'neovim/nvim-lspconfig', event = 'VeryLazy', - dependencies = { - 'folke/trouble.nvim', - event = 'VeryLazy', - opts = { - pinned = true, - focus = true, - follow = false, - auto_close = false, - win = { - size = 0.33, - position = 'right', - type = 'split', - }, - }, - }, config = function() vim.lsp.enable { 'nil_ls', @@ -93,7 +78,7 @@ return { '\\f', function() vim.b.disable_autoformat = not vim.b.disable_autoformat - vim.notify(string.format('Buffer formatting disabled: %s', vim.b.disable_autoformat)) + Snacks.notify(string.format('Buffer formatting disabled: %s', vim.b.disable_autoformat)) end, mode = { 'n', 'x' }, desc = 'toggle buffer formatting', @@ -102,7 +87,7 @@ return { '\\F', function() vim.g.disable_autoformat = not vim.g.disable_autoformat - vim.notify(string.format('Global formatting disabled: %s', vim.g.disable_autoformat)) + Snacks.notify(string.format('Global formatting disabled: %s', vim.g.disable_autoformat)) end, mode = { 'n', 'x' }, desc = 'toggle global formatting', diff --git a/nvim/lua/plugins/mini.lua b/nvim/lua/plugins/mini.lua index 756b1ae..136521a 100644 --- a/nvim/lua/plugins/mini.lua +++ b/nvim/lua/plugins/mini.lua @@ -29,50 +29,9 @@ return { ':Git ', desc = 'git command', }, - { - 'fs', - function() - require('plugins.lib.session_jj').load() - end, - noremap = true, - desc = 'mini session select', - }, - { - '\\z', - function() - require('mini.misc').zoom() - end, - desc = 'mini zoom', - }, }, config = function() require('mini.basics').setup { mappings = { windows = true } } - require('mini.statusline').setup { - content = { - active = function() - local mode, mode_hl = MiniStatusline.section_mode {} - -- local filename = MiniStatusline.section_filename { trunc_width = 140 } - local diagnostics = MiniStatusline.section_diagnostics { trunc_width = 75 } - local lsp = MiniStatusline.section_lsp { trunc_width = 75 } - local search = MiniStatusline.section_searchcount { trunc_width = 75 } - - return MiniStatusline.combine_groups { - '%<', -- Mark general truncate point - '%=', -- End left alignment - -- { hl = 'MiniStatuslineDevinfo', strings = { filename } }, - { hl = 'MiniStatuslineDevinfo', strings = { diagnostics, lsp } }, - { hl = 'MiniStatuslineDevinfo', strings = { search } }, - { hl = mode_hl, strings = { mode } }, - } - end, - inactive = function() - local filename = MiniStatusline.section_filename { trunc_width = 140 } - return MiniStatusline.combine_groups { - { hl = 'MiniStatuslineFilename', strings = { filename } }, - } - end, - }, - } vim.schedule(function() local ai = require('mini.ai') local extra_ai = require('mini.extra').gen_ai_spec @@ -81,6 +40,7 @@ return { custom_textobjects = { i = extra_ai.indent(), g = extra_ai.buffer(), + l = extra_ai.line(), u = ai.gen_spec.function_call(), a = ai.gen_spec.treesitter { a = '@parameter.outer', i = '@parameter.inner' }, k = ai.gen_spec.treesitter { a = '@assignment.lhs', i = '@assignment.lhs' }, @@ -114,15 +74,8 @@ return { end, }, }, - verbose = { - write = false, - }, } - local jj_sesh = require('plugins.lib.session_jj') - local jj_id = jj_sesh.get_id() - if jj_sesh.check_exists(jj_id) then - vim.notify('Existing session for ' .. jj_id) - end + require('plugins.lib.session_jj').setup() local jump = require('mini.jump2d') jump.setup { @@ -130,14 +83,6 @@ return { spotter = jump.gen_spotter.vimpattern(), } - require('plugins.lib.minipairs') { - modes = { insert = true, command = false, terminal = false }, - skip_next = [=[[%w%%%'%[%"%.%`%$]]=], - skip_ts = { 'string' }, - skip_unbalanced = true, - markdown = true, - } - local diff = require('mini.diff') diff.setup { options = { wrap_goto = true }, @@ -210,7 +155,6 @@ return { }) local multi = require('mini.keymap').map_multistep - multi({ 'i' }, '', { 'minipairs_bs' }) multi({ 'i', 's' }, '', { 'blink_accept', 'vimsnippet_next', 'increase_indent' }) multi({ 'i', 's' }, '', { 'vimsnippet_prev', 'decrease_indent' }) end) diff --git a/nvim/lua/plugins/misc.lua b/nvim/lua/plugins/misc.lua index 8313182..d8b1a5f 100644 --- a/nvim/lua/plugins/misc.lua +++ b/nvim/lua/plugins/misc.lua @@ -4,13 +4,37 @@ return { event = 'VeryLazy', config = true, }, + { + 'windwp/nvim-autopairs', + event = 'VeryLazy', + config = true, + }, + { + 'nvim-treesitter/nvim-treesitter', + event = 'VeryLazy', + branch = 'main', + main = 'nvim-treesitter.configs', + config = true, + dependencies = { + { + 'nvim-treesitter/nvim-treesitter-textobjects', + branch = 'main', + config = true, + }, + 'RRethy/nvim-treesitter-textsubjects', + { + 'nvim-treesitter/nvim-treesitter-context', + opts = { + max_lines = 5, + min_window_height = 50, + }, + }, + }, + }, { 'jinh0/eyeliner.nvim', event = 'VeryLazy', - init = function() - vim.api.nvim_set_hl(0, 'EyelinerPrimary', { underline = true }) - vim.api.nvim_set_hl(0, 'EyelinerSecondary', { underline = true, bold = true }) - end, + config = true, }, { 'MeanderingProgrammer/render-markdown.nvim', diff --git a/nvim/lua/plugins/snacks.lua b/nvim/lua/plugins/snacks.lua index 346fc95..248937b 100644 --- a/nvim/lua/plugins/snacks.lua +++ b/nvim/lua/plugins/snacks.lua @@ -5,7 +5,6 @@ return { priority = 1000, opts = { bigfile = { enabled = true }, - quickfile = { enabled = true }, notifier = { enabled = true, timeout = 4000, @@ -14,16 +13,16 @@ return { notification = { wo = { wrap = true }, }, + terminal = { + border = 'rounded', + }, }, terminal = { enabled = true }, indent = { enabled = true }, input = { enabled = true }, - words = { enabled = true }, picker = { enabled = true, - jump = { - reuse_win = true, - }, + jump = { reuse_win = true }, matcher = { frecency = true, history_bonus = true, @@ -31,19 +30,23 @@ return { }, layout = 'ivy_split', sources = { - files = { hidden = true }, grep = { hidden = true }, explorer = { hidden = true }, - git_files = { untracked = true }, lsp_symbols = { filter = { default = true }, layout = 'left', }, smart = { + sort = { + fields = { + 'score:desc', + 'idx', + '#text', + }, + }, multi = { 'marks', { source = 'buffers', current = false }, - 'recent', { source = 'files', hidden = true }, { source = 'git_files', untracked = true }, }, @@ -51,14 +54,10 @@ return { }, win = { input = { - keys = { - ['wq'] = { 'close', mode = 'i' }, - }, + keys = { ['wq'] = { 'close', mode = 'i' } }, }, list = { - keys = { - ['wq'] = { 'close', mode = 'i' }, - }, + keys = { ['wq'] = { 'close', mode = 'i' } }, }, }, }, @@ -75,7 +74,7 @@ return { { '', function() - Snacks.terminal.toggle('$SHELL') + Snacks.terminal.toggle('command -v fish >/dev/null && exec fish || exec bash') end, mode = { 'n', 't' }, desc = 'terminal open', diff --git a/nvim/lua/plugins/treesitter.lua b/nvim/lua/plugins/treesitter.lua deleted file mode 100644 index cb8bbb1..0000000 --- a/nvim/lua/plugins/treesitter.lua +++ /dev/null @@ -1,53 +0,0 @@ -return { - { - "nvim-treesitter/nvim-treesitter", - event = "VeryLazy", - dependencies = { - { - "nvim-treesitter/nvim-treesitter-context", - opts = { - max_lines = 2, - min_window_height = 50, - }, - }, - "nvim-treesitter/nvim-treesitter-textobjects", - "RRethy/nvim-treesitter-textsubjects", - }, - main = "nvim-treesitter.configs", - opts = { - ensure_installed = {}, - auto_install = false, - highlight = { - enable = true, - }, - indent = { - enable = true, - }, - matchup = { - enable = true, - }, - textobjects = { - move = { - enable = true, - goto_next_start = { - ["]a"] = "@parameter.inner", - ["]f"] = "@function.outer", - }, - goto_previous_start = { - ["[a"] = "@parameter.inner", - ["[f"] = "@function.outer", - }, - }, - swap = { - enable = true, - swap_next = { - ["a]"] = "@parameter.inner", - }, - swap_previous = { - ["a["] = "@parameter.inner", - }, - }, - }, - }, - }, -}