From dc3d0435c06a1f5c08ebc028e9b344f520761beb Mon Sep 17 00:00:00 2001 From: yimhuang Date: Wed, 11 Mar 2026 17:21:11 +0800 Subject: [PATCH 01/24] Add opencode to nvim --- init.lua | 2 +- lua/custom/plugins/opencode.lua | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 lua/custom/plugins/opencode.lua diff --git a/init.lua b/init.lua index cacc5b7b1c3..92088787fe4 100644 --- a/init.lua +++ b/init.lua @@ -940,7 +940,7 @@ require('lazy').setup({ -- This is the easiest way to modularize your config. -- -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. - -- { import = 'custom.plugins' }, + { import = 'custom.plugins' }, -- -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` -- Or use telescope! diff --git a/lua/custom/plugins/opencode.lua b/lua/custom/plugins/opencode.lua new file mode 100644 index 00000000000..68b7fd4d6f3 --- /dev/null +++ b/lua/custom/plugins/opencode.lua @@ -0,0 +1,50 @@ +return { + "nickjvandyke/opencode.nvim", + version = "*", -- Latest stable release + dependencies = { + { + -- `snacks.nvim` integration is recommended, but optional + ---@module "snacks" <- Loads `snacks.nvim` types for configuration intellisense + "folke/snacks.nvim", + optional = true, + opts = { + input = {}, -- Enhances `ask()` + picker = { -- Enhances `select()` + actions = { + opencode_send = function(...) return require("opencode").snacks_picker_send(...) end, + }, + win = { + input = { + keys = { + [""] = { "opencode_send", mode = { "n", "i" } }, + }, + }, + }, + }, + }, + }, + }, + config = function() + ---@type opencode.Opts + vim.g.opencode_opts = { + -- Your configuration, if any; goto definition on the type or field for details + } + + vim.o.autoread = true -- Required for `opts.events.reload` + + -- Recommended/example keymaps + vim.keymap.set({ "n", "x" }, "", function() require("opencode").ask("@this: ", { submit = true }) end, { desc = "Ask opencode…" }) + vim.keymap.set({ "n", "x" }, "", function() require("opencode").select() end, { desc = "Execute opencode action…" }) + vim.keymap.set({ "n", "t" }, "", function() require("opencode").toggle() end, { desc = "Toggle opencode" }) + + vim.keymap.set({ "n", "x" }, "go", function() return require("opencode").operator("@this ") end, { desc = "Add range to opencode", expr = true }) + vim.keymap.set("n", "goo", function() return require("opencode").operator("@this ") .. "_" end, { desc = "Add line to opencode", expr = true }) + + vim.keymap.set("n", "", function() require("opencode").command("session.half.page.up") end, { desc = "Scroll opencode up" }) + vim.keymap.set("n", "", function() require("opencode").command("session.half.page.down") end, { desc = "Scroll opencode down" }) + + -- You may want these if you use the opinionated `` and `` keymaps above — otherwise consider `o…` (and remove terminal mode from the `toggle` keymap) + vim.keymap.set("n", "+", "", { desc = "Increment under cursor", noremap = true }) + vim.keymap.set("n", "-", "", { desc = "Decrement under cursor", noremap = true }) + end, +} From cad782112ee0d05a513d54dfdcc9b9a90e90a4d6 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Sat, 14 Mar 2026 07:39:51 +0800 Subject: [PATCH 02/24] Update prettier --- init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/init.lua b/init.lua index 92088787fe4..7a63a05aeb2 100644 --- a/init.lua +++ b/init.lua @@ -653,6 +653,7 @@ require('lazy').setup({ local ensure_installed = vim.tbl_keys(servers or {}) vim.list_extend(ensure_installed, { -- You can add other tools here that you want Mason to install + 'prettier', }) require('mason-tool-installer').setup { ensure_installed = ensure_installed } @@ -696,6 +697,7 @@ require('lazy').setup({ end, formatters_by_ft = { lua = { 'stylua' }, + yaml = { 'prettier' }, -- Conform can also run multiple formatters sequentially -- python = { "isort", "black" }, -- From 421e743bff1e901339af1b67ff2549225dd00e11 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 16 Mar 2026 10:17:11 +0800 Subject: [PATCH 03/24] Add nvim.tree --- lua/custom/plugins/tree.lua | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 lua/custom/plugins/tree.lua diff --git a/lua/custom/plugins/tree.lua b/lua/custom/plugins/tree.lua new file mode 100644 index 00000000000..49926caa038 --- /dev/null +++ b/lua/custom/plugins/tree.lua @@ -0,0 +1,9 @@ +return { + 'nvim-tree/nvim-tree.lua', + version = '*', + lazy = false, + dependencies = { + 'nvim-tree/nvim-web-devicons', + }, + config = function() require('nvim-tree').setup {} end, +} From 32aa7dcbd1aaaec2f7090aa5006b00f41eb792da Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 16 Mar 2026 15:48:18 +0800 Subject: [PATCH 04/24] Add json fmt --- init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/init.lua b/init.lua index 7a63a05aeb2..23ed21e8e44 100644 --- a/init.lua +++ b/init.lua @@ -697,6 +697,7 @@ require('lazy').setup({ end, formatters_by_ft = { lua = { 'stylua' }, + json = { 'prettier' }, yaml = { 'prettier' }, -- Conform can also run multiple formatters sequentially -- python = { "isort", "black" }, From cfdcf8e2d91df44bfbefbd7245f56b25c5d5a0b0 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 16 Mar 2026 15:49:43 +0800 Subject: [PATCH 05/24] Add codediff --- lua/custom/plugins/codediff.lua | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 lua/custom/plugins/codediff.lua diff --git a/lua/custom/plugins/codediff.lua b/lua/custom/plugins/codediff.lua new file mode 100644 index 00000000000..a189ffdb14a --- /dev/null +++ b/lua/custom/plugins/codediff.lua @@ -0,0 +1,4 @@ +return { + 'esmuellert/codediff.nvim', + cmd = 'CodeDiff', +} From 4cee729300f36562c9baded09e38df3326ac7187 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Tue, 17 Mar 2026 20:33:34 +0800 Subject: [PATCH 06/24] Try different file explore and neotree wins --- lua/custom/plugins/neotree.lua | 12 +++ lua/custom/plugins/oil.lua.disable | 91 +++++++++++++++++++ .../plugins/{tree.lua => tree.lua.disable} | 0 3 files changed, 103 insertions(+) create mode 100644 lua/custom/plugins/neotree.lua create mode 100644 lua/custom/plugins/oil.lua.disable rename lua/custom/plugins/{tree.lua => tree.lua.disable} (100%) diff --git a/lua/custom/plugins/neotree.lua b/lua/custom/plugins/neotree.lua new file mode 100644 index 00000000000..543003d9631 --- /dev/null +++ b/lua/custom/plugins/neotree.lua @@ -0,0 +1,12 @@ +return { + { + 'nvim-neo-tree/neo-tree.nvim', + branch = 'v3.x', + dependencies = { + 'nvim-lua/plenary.nvim', + 'MunifTanjim/nui.nvim', + 'nvim-tree/nvim-web-devicons', -- optional, but recommended + }, + lazy = false, -- neo-tree will lazily load itself + }, +} diff --git a/lua/custom/plugins/oil.lua.disable b/lua/custom/plugins/oil.lua.disable new file mode 100644 index 00000000000..024555303e7 --- /dev/null +++ b/lua/custom/plugins/oil.lua.disable @@ -0,0 +1,91 @@ +return { + 'stevearc/oil.nvim', + ---@module 'oil' + ---@type oil.SetupOpts + opts = { + default_file_explorer = true, + columns = { 'icon' }, + keymaps = { + [''] = function() + local oil = require('oil') + local actions = require('oil.actions') + local entry = oil.get_cursor_entry() + + if not entry then + return + end + + if entry.type == 'directory' then + actions.select.callback() + return + end + + local sidebar_win = vim.api.nvim_get_current_win() + local sidebar_pos = vim.api.nvim_win_get_position(sidebar_win) + local target_win = nil + + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if win ~= sidebar_win then + local buf = vim.api.nvim_win_get_buf(win) + if vim.bo[buf].filetype ~= 'oil' then + local pos = vim.api.nvim_win_get_position(win) + if pos[2] > sidebar_pos[2] then + if not target_win then + target_win = win + else + local target_pos = vim.api.nvim_win_get_position(target_win) + if pos[2] < target_pos[2] then + target_win = win + end + end + end + end + end + end + + if not target_win then + vim.cmd('vsplit') + target_win = vim.api.nvim_get_current_win() + vim.api.nvim_set_current_win(sidebar_win) + end + + local dir = oil.get_current_dir() + if not dir then + return + end + + local path = vim.fs.joinpath(dir, entry.name) + vim.api.nvim_set_current_win(target_win) + vim.cmd.edit(vim.fn.fnameescape(path)) + end, + }, + }, + keys = { + { + 'e', + function() + for _, win in ipairs(vim.api.nvim_list_wins()) do + local buf = vim.api.nvim_win_get_buf(win) + if vim.bo[buf].filetype == 'oil' then + vim.api.nvim_win_close(win, true) + return + end + end + + local current_win = vim.api.nvim_get_current_win() + vim.cmd('topleft vsplit') + local sidebar_win = vim.api.nvim_get_current_win() + require('oil').open() + vim.api.nvim_win_set_width(sidebar_win, 20) + vim.wo[sidebar_win].winfixwidth = true + vim.api.nvim_set_current_win(current_win) + end, + desc = 'Toggle Oil sidebar', + }, + }, + -- Optional dependencies + dependencies = { { 'nvim-mini/mini.icons', opts = {} } }, + -- dependencies = { "nvim-tree/nvim-web-devicons" }, -- use if you prefer nvim-web-devicons + -- Lazy loading is not recommended because it is very tricky to make it work correctly in all situations. + lazy = false, +} diff --git a/lua/custom/plugins/tree.lua b/lua/custom/plugins/tree.lua.disable similarity index 100% rename from lua/custom/plugins/tree.lua rename to lua/custom/plugins/tree.lua.disable From faf0e46498e9ce61914bf5ee07ae205be1b75a51 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Wed, 25 Mar 2026 11:35:11 +0800 Subject: [PATCH 07/24] Add beancount --- init.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/init.lua b/init.lua index 23ed21e8e44..71052a91357 100644 --- a/init.lua +++ b/init.lua @@ -138,6 +138,8 @@ vim.o.timeoutlen = 300 -- Configure how new splits should be opened vim.o.splitright = true vim.o.splitbelow = true +-- Doesn't work well with WezTerm mux server; disable for now and revisit later. +vim.opt.termsync = false -- Sets how neovim will display certain whitespace characters in the editor. -- See `:help 'list'` @@ -230,6 +232,17 @@ vim.api.nvim_create_autocmd('TextYankPost', { callback = function() vim.hl.on_yank() end, }) +local warned_missing_bean_format = false +vim.api.nvim_create_autocmd('FileType', { + pattern = 'beancount', + group = vim.api.nvim_create_augroup('beancount-format-check', { clear = true }), + callback = function() + if warned_missing_bean_format or vim.fn.executable 'bean-format' == 1 then return end + warned_missing_bean_format = true + vim.notify('bean-format not found. Install it with: uv tool install beancount', vim.log.levels.WARN, { title = 'conform.nvim' }) + end, +}) + -- [[ Install `lazy.nvim` plugin manager ]] -- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' @@ -699,6 +712,7 @@ require('lazy').setup({ lua = { 'stylua' }, json = { 'prettier' }, yaml = { 'prettier' }, + beancount = { 'bean-format' }, -- Conform can also run multiple formatters sequentially -- python = { "isort", "black" }, -- From ad28ce231d3e15600c9587c4cc04522bdad70f71 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Wed, 25 Mar 2026 11:39:04 +0800 Subject: [PATCH 08/24] Add lazy-lock --- .gitignore | 2 +- lazy-lock.json | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 lazy-lock.json diff --git a/.gitignore b/.gitignore index 68486fc3d35..bfc720f63cc 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,6 @@ spell/ # lazy-lock.json in version control - see https://lazy.folke.io/usage/lockfile # For the official `nvim-lua/kickstart.nvim` git repository, we leave it ignored to avoid unneeded # merge conflicts. -lazy-lock.json +# lazy-lock.json .DS_Store diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 00000000000..54001ae18fb --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,26 @@ +{ + "LuaSnip": { "branch": "master", "commit": "5a1e39223db9a0498024a77b8441169d260c8c25" }, + "blink.cmp": { "branch": "main", "commit": "451168851e8e2466bc97ee3e026c3dcb9141ce07" }, + "codediff.nvim": { "branch": "main", "commit": "93cd80c56f71af4671388c568a37d4c84c3ddefa" }, + "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, + "fidget.nvim": { "branch": "main", "commit": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970" }, + "gitsigns.nvim": { "branch": "main", "commit": "7c4faa3540d0781a28588cafbd4dd187a28ac6e3" }, + "guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "a676ab7282da8d651e175118bcf54483ca11e46d" }, + "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, + "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, + "mini.nvim": { "branch": "main", "commit": "9990c41f10f54f29a888d13024c9f765037bde23" }, + "neo-tree.nvim": { "branch": "v3.x", "commit": "9d6826582a3e8c84787bd7355df22a2812a1ad59" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-lspconfig": { "branch": "master", "commit": "dd261ad5266ab5bbec249d21efeceda98ff3e1a6" }, + "nvim-treesitter": { "branch": "main", "commit": "2f5d4c3f3c675962242096bcc8e586d76dd72eb2" }, + "opencode.nvim": { "branch": "main", "commit": "1088ee70dd997d785a1757d351c07407f0abfc9f" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, + "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, + "telescope.nvim": { "branch": "master", "commit": "5255aa27c422de944791318024167ad5d40aad20" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} From 5ccdba3fac6b148ad5c3601c27df79797cc3332e Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 30 Mar 2026 09:06:40 +0800 Subject: [PATCH 09/24] opencode size --- lua/custom/plugins/opencode.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lua/custom/plugins/opencode.lua b/lua/custom/plugins/opencode.lua index 68b7fd4d6f3..9a61f6cfe51 100644 --- a/lua/custom/plugins/opencode.lua +++ b/lua/custom/plugins/opencode.lua @@ -27,7 +27,23 @@ return { config = function() ---@type opencode.Opts vim.g.opencode_opts = { - -- Your configuration, if any; goto definition on the type or field for details + server = { + start = function() + require("opencode.terminal").open("opencode --port", { + split = "right", + width = math.max(40, math.floor(vim.o.columns * 0.25)), + }) + end, + stop = function() + require("opencode.terminal").close() + end, + toggle = function() + require("opencode.terminal").toggle("opencode --port", { + split = "right", + width = math.max(40, math.floor(vim.o.columns * 0.25)), + }) + end, + }, } vim.o.autoread = true -- Required for `opts.events.reload` From b098a3ffe02ea294a930dbdc207d71dcbc4db77d Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 30 Mar 2026 12:52:57 +0800 Subject: [PATCH 10/24] Add toggleterm --- lazy-lock.json | 1 + lua/custom/plugins/opencode.lua | 44 +++++++++++++++---------------- lua/custom/plugins/toggleterm.lua | 19 +++++++++++++ 3 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 lua/custom/plugins/toggleterm.lua diff --git a/lazy-lock.json b/lazy-lock.json index 54001ae18fb..92d1ba41833 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -21,6 +21,7 @@ "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, "telescope.nvim": { "branch": "master", "commit": "5255aa27c422de944791318024167ad5d40aad20" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } } diff --git a/lua/custom/plugins/opencode.lua b/lua/custom/plugins/opencode.lua index 9a61f6cfe51..39a1394c9f3 100644 --- a/lua/custom/plugins/opencode.lua +++ b/lua/custom/plugins/opencode.lua @@ -1,22 +1,22 @@ return { - "nickjvandyke/opencode.nvim", - version = "*", -- Latest stable release + 'nickjvandyke/opencode.nvim', + version = '*', -- Latest stable release dependencies = { { -- `snacks.nvim` integration is recommended, but optional ---@module "snacks" <- Loads `snacks.nvim` types for configuration intellisense - "folke/snacks.nvim", + 'folke/snacks.nvim', optional = true, opts = { input = {}, -- Enhances `ask()` picker = { -- Enhances `select()` actions = { - opencode_send = function(...) return require("opencode").snacks_picker_send(...) end, + opencode_send = function(...) return require('opencode').snacks_picker_send(...) end, }, win = { input = { keys = { - [""] = { "opencode_send", mode = { "n", "i" } }, + [''] = { 'opencode_send', mode = { 'n', 'i' } }, }, }, }, @@ -29,18 +29,16 @@ return { vim.g.opencode_opts = { server = { start = function() - require("opencode.terminal").open("opencode --port", { - split = "right", - width = math.max(40, math.floor(vim.o.columns * 0.25)), + require('opencode.terminal').open('opencode --port', { + split = 'right', + width = math.max(40, math.floor(vim.o.columns * 0.4)), }) end, - stop = function() - require("opencode.terminal").close() - end, + stop = function() require('opencode.terminal').close() end, toggle = function() - require("opencode.terminal").toggle("opencode --port", { - split = "right", - width = math.max(40, math.floor(vim.o.columns * 0.25)), + require('opencode.terminal').toggle('opencode --port', { + split = 'right', + width = math.max(40, math.floor(vim.o.columns * 0.4)), }) end, }, @@ -49,18 +47,18 @@ return { vim.o.autoread = true -- Required for `opts.events.reload` -- Recommended/example keymaps - vim.keymap.set({ "n", "x" }, "", function() require("opencode").ask("@this: ", { submit = true }) end, { desc = "Ask opencode…" }) - vim.keymap.set({ "n", "x" }, "", function() require("opencode").select() end, { desc = "Execute opencode action…" }) - vim.keymap.set({ "n", "t" }, "", function() require("opencode").toggle() end, { desc = "Toggle opencode" }) + vim.keymap.set({ 'n', 'x' }, '', function() require('opencode').ask('@this: ', { submit = true }) end, { desc = 'Ask opencode…' }) + vim.keymap.set({ 'n', 'x' }, '', function() require('opencode').select() end, { desc = 'Execute opencode action…' }) + vim.keymap.set({ 'n', 't' }, '', function() require('opencode').toggle() end, { desc = 'Toggle opencode' }) - vim.keymap.set({ "n", "x" }, "go", function() return require("opencode").operator("@this ") end, { desc = "Add range to opencode", expr = true }) - vim.keymap.set("n", "goo", function() return require("opencode").operator("@this ") .. "_" end, { desc = "Add line to opencode", expr = true }) + vim.keymap.set({ 'n', 'x' }, 'go', function() return require('opencode').operator '@this ' end, { desc = 'Add range to opencode', expr = true }) + vim.keymap.set('n', 'goo', function() return require('opencode').operator '@this ' .. '_' end, { desc = 'Add line to opencode', expr = true }) - vim.keymap.set("n", "", function() require("opencode").command("session.half.page.up") end, { desc = "Scroll opencode up" }) - vim.keymap.set("n", "", function() require("opencode").command("session.half.page.down") end, { desc = "Scroll opencode down" }) + vim.keymap.set('n', '', function() require('opencode').command 'session.half.page.up' end, { desc = 'Scroll opencode up' }) + vim.keymap.set('n', '', function() require('opencode').command 'session.half.page.down' end, { desc = 'Scroll opencode down' }) -- You may want these if you use the opinionated `` and `` keymaps above — otherwise consider `o…` (and remove terminal mode from the `toggle` keymap) - vim.keymap.set("n", "+", "", { desc = "Increment under cursor", noremap = true }) - vim.keymap.set("n", "-", "", { desc = "Decrement under cursor", noremap = true }) + vim.keymap.set('n', '+', '', { desc = 'Increment under cursor', noremap = true }) + vim.keymap.set('n', '-', '', { desc = 'Decrement under cursor', noremap = true }) end, } diff --git a/lua/custom/plugins/toggleterm.lua b/lua/custom/plugins/toggleterm.lua new file mode 100644 index 00000000000..ae94cfb8355 --- /dev/null +++ b/lua/custom/plugins/toggleterm.lua @@ -0,0 +1,19 @@ +---@module 'lazy' +---@type LazySpec +return { + { + 'akinsho/toggleterm.nvim', + version = '*', + cmd = { 'ToggleTerm', 'TermExec' }, + keys = { + { 'tt', 'ToggleTerm', desc = '[T]oggle [T]erminal' }, + }, + opts = { + open_mapping = [[]], + direction = 'float', + float_opts = { + border = 'curved', + }, + }, + }, +} From 69e89bc4a0cfe1ed13a7de2517ae7c58b9f8cde8 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 30 Mar 2026 14:23:02 +0800 Subject: [PATCH 11/24] refactor --- init.lua | 19 ++++-------- lazy-lock.json | 2 ++ lua/custom/beancount.lua | 11 +++++++ lua/custom/plugins/neotree.lua | 53 +++++++++++++++++++++++++++++----- 4 files changed, 64 insertions(+), 21 deletions(-) create mode 100644 lua/custom/beancount.lua diff --git a/init.lua b/init.lua index 71052a91357..525b8138ead 100644 --- a/init.lua +++ b/init.lua @@ -91,7 +91,7 @@ vim.g.mapleader = ' ' vim.g.maplocalleader = ' ' -- Set to true if you have a Nerd Font installed and selected in the terminal -vim.g.have_nerd_font = false +vim.g.have_nerd_font = true -- [[ Setting options ]] -- See `:help vim.o` @@ -232,16 +232,7 @@ vim.api.nvim_create_autocmd('TextYankPost', { callback = function() vim.hl.on_yank() end, }) -local warned_missing_bean_format = false -vim.api.nvim_create_autocmd('FileType', { - pattern = 'beancount', - group = vim.api.nvim_create_augroup('beancount-format-check', { clear = true }), - callback = function() - if warned_missing_bean_format or vim.fn.executable 'bean-format' == 1 then return end - warned_missing_bean_format = true - vim.notify('bean-format not found. Install it with: uv tool install beancount', vim.log.levels.WARN, { title = 'conform.nvim' }) - end, -}) +require 'custom.beancount' -- [[ Install `lazy.nvim` plugin manager ]] -- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info @@ -948,10 +939,10 @@ require('lazy').setup({ -- -- require 'kickstart.plugins.debug', -- require 'kickstart.plugins.indent_line', - -- require 'kickstart.plugins.lint', + require 'kickstart.plugins.lint', -- require 'kickstart.plugins.autopairs', - -- require 'kickstart.plugins.neo-tree', - -- require 'kickstart.plugins.gitsigns', -- adds gitsigns recommended keymaps + require 'kickstart.plugins.neo-tree', + require 'kickstart.plugins.gitsigns', -- adds gitsigns recommended keymaps -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` -- This is the easiest way to modularize your config. diff --git a/lazy-lock.json b/lazy-lock.json index 92d1ba41833..83c36af8b46 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -13,8 +13,10 @@ "mini.nvim": { "branch": "main", "commit": "9990c41f10f54f29a888d13024c9f765037bde23" }, "neo-tree.nvim": { "branch": "v3.x", "commit": "9d6826582a3e8c84787bd7355df22a2812a1ad59" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-lint": { "branch": "master", "commit": "4b03656c09c1561f89b6aa0665c15d292ba9499d" }, "nvim-lspconfig": { "branch": "master", "commit": "dd261ad5266ab5bbec249d21efeceda98ff3e1a6" }, "nvim-treesitter": { "branch": "main", "commit": "2f5d4c3f3c675962242096bcc8e586d76dd72eb2" }, + "nvim-web-devicons": { "branch": "master", "commit": "d7462543c9e366c0d196c7f67a945eaaf5d99414" }, "opencode.nvim": { "branch": "main", "commit": "1088ee70dd997d785a1757d351c07407f0abfc9f" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, diff --git a/lua/custom/beancount.lua b/lua/custom/beancount.lua new file mode 100644 index 00000000000..d91d2acb12c --- /dev/null +++ b/lua/custom/beancount.lua @@ -0,0 +1,11 @@ +local warned_missing_bean_format = false + +vim.api.nvim_create_autocmd('FileType', { + pattern = 'beancount', + group = vim.api.nvim_create_augroup('beancount-format-check', { clear = true }), + callback = function() + if warned_missing_bean_format or vim.fn.executable 'bean-format' == 1 then return end + warned_missing_bean_format = true + vim.notify('bean-format not found. Install it with: uv tool install beancount', vim.log.levels.WARN, { title = 'conform.nvim' }) + end, +}) diff --git a/lua/custom/plugins/neotree.lua b/lua/custom/plugins/neotree.lua index 543003d9631..41fc36f93d5 100644 --- a/lua/custom/plugins/neotree.lua +++ b/lua/custom/plugins/neotree.lua @@ -1,12 +1,51 @@ return { { 'nvim-neo-tree/neo-tree.nvim', - branch = 'v3.x', - dependencies = { - 'nvim-lua/plenary.nvim', - 'MunifTanjim/nui.nvim', - 'nvim-tree/nvim-web-devicons', -- optional, but recommended - }, - lazy = false, -- neo-tree will lazily load itself + opts = function(_, opts) + opts.enable_git_status = true + + opts.default_component_configs = vim.tbl_deep_extend('force', opts.default_component_configs or {}, { + git_status = { + symbols = { + added = 'A', + modified = 'M', + deleted = 'D', + renamed = 'R', + untracked = 'U', + ignored = 'I', + unstaged = '*', + staged = '+', + conflict = '!', + }, + }, + }) + + opts.filesystem = vim.tbl_deep_extend('force', opts.filesystem or {}, { + use_libuv_file_watcher = true, + follow_current_file = { enabled = true }, + window = { + mappings = { + ['R'] = 'refresh', + }, + }, + }) + end, + config = function(_, opts) + require('neo-tree').setup(opts) + + local group = vim.api.nvim_create_augroup('NeoTreeAutoRefresh', { clear = true }) + vim.api.nvim_create_autocmd({ 'BufWritePost', 'FocusGained' }, { + group = group, + callback = function() + for _, win in ipairs(vim.api.nvim_list_wins()) do + local buf = vim.api.nvim_win_get_buf(win) + if vim.bo[buf].filetype == 'neo-tree' then + vim.cmd 'silent! Neotree refresh' + return + end + end + end, + }) + end, }, } From dde33856d1b71fcb36e4844cdbc9a51142cd7ec5 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 30 Mar 2026 15:16:03 +0800 Subject: [PATCH 12/24] Add diffview --- init.lua | 11 ++++++++--- lazy-lock.json | 21 ++++++++++++--------- lua/custom/plugins/diffview.lua | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 lua/custom/plugins/diffview.lua diff --git a/init.lua b/init.lua index 525b8138ead..931ebd0b2ba 100644 --- a/init.lua +++ b/init.lua @@ -625,6 +625,11 @@ require('lazy').setup({ if path ~= vim.fn.stdpath 'config' and (vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc')) then return end end + local config_path = vim.fn.stdpath 'config' + local runtime_files = vim.tbl_filter(function(file) + return file ~= config_path and file ~= (config_path .. '/after') + end, vim.api.nvim_get_runtime_file('', true)) + client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { runtime = { version = 'LuaJIT', @@ -634,7 +639,7 @@ require('lazy').setup({ checkThirdParty = false, -- NOTE: this is a lot slower and will cause issues when working on your own configuration. -- See https://github.com/neovim/nvim-lspconfig/issues/3189 - library = vim.tbl_extend('force', vim.api.nvim_get_runtime_file('', true), { + library = vim.tbl_extend('force', runtime_files, { '${3rd}/luv/library', '${3rd}/busted/library', }), @@ -938,9 +943,9 @@ require('lazy').setup({ -- Uncomment any of the lines below to enable them (you will need to restart nvim). -- -- require 'kickstart.plugins.debug', - -- require 'kickstart.plugins.indent_line', + require 'kickstart.plugins.indent_line', require 'kickstart.plugins.lint', - -- require 'kickstart.plugins.autopairs', + require 'kickstart.plugins.autopairs', require 'kickstart.plugins.neo-tree', require 'kickstart.plugins.gitsigns', -- adds gitsigns recommended keymaps diff --git a/lazy-lock.json b/lazy-lock.json index 83c36af8b46..23b3275dc42 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -3,27 +3,30 @@ "blink.cmp": { "branch": "main", "commit": "451168851e8e2466bc97ee3e026c3dcb9141ce07" }, "codediff.nvim": { "branch": "main", "commit": "93cd80c56f71af4671388c568a37d4c84c3ddefa" }, "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, + "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, "fidget.nvim": { "branch": "main", "commit": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970" }, - "gitsigns.nvim": { "branch": "main", "commit": "7c4faa3540d0781a28588cafbd4dd187a28ac6e3" }, + "gitsigns.nvim": { "branch": "main", "commit": "50c205548d8b037b7ff6378fca6d21146f0b6161" }, "guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" }, + "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "a676ab7282da8d651e175118bcf54483ca11e46d" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "037398b9ce4a53ba48d5f94765c641a1fd16d906" }, "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, - "mini.nvim": { "branch": "main", "commit": "9990c41f10f54f29a888d13024c9f765037bde23" }, - "neo-tree.nvim": { "branch": "v3.x", "commit": "9d6826582a3e8c84787bd7355df22a2812a1ad59" }, + "mini.nvim": { "branch": "main", "commit": "af5f75c9ce572a4d1f0c77d6fb4ea764d16c1b3c" }, + "neo-tree.nvim": { "branch": "main", "commit": "84c75e7a7e443586f60508d12fc50f90d9aee14e" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, "nvim-lint": { "branch": "master", "commit": "4b03656c09c1561f89b6aa0665c15d292ba9499d" }, - "nvim-lspconfig": { "branch": "master", "commit": "dd261ad5266ab5bbec249d21efeceda98ff3e1a6" }, - "nvim-treesitter": { "branch": "main", "commit": "2f5d4c3f3c675962242096bcc8e586d76dd72eb2" }, + "nvim-lspconfig": { "branch": "master", "commit": "16812abf0e8d8175155f26143a8504e8253e92b0" }, + "nvim-treesitter": { "branch": "main", "commit": "7caec274fd19c12b55902a5b795100d21531391f" }, "nvim-web-devicons": { "branch": "master", "commit": "d7462543c9e366c0d196c7f67a945eaaf5d99414" }, - "opencode.nvim": { "branch": "main", "commit": "1088ee70dd997d785a1757d351c07407f0abfc9f" }, + "opencode.nvim": { "branch": "main", "commit": "df533d6da724109bf08446392db860fdceddbd0c" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, - "telescope.nvim": { "branch": "master", "commit": "5255aa27c422de944791318024167ad5d40aad20" }, + "telescope.nvim": { "branch": "master", "commit": "e6cdb4dc528c5dc4ca8da86e83ef4e3c84b0729c" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, - "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, + "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } } diff --git a/lua/custom/plugins/diffview.lua b/lua/custom/plugins/diffview.lua new file mode 100644 index 00000000000..f118f2a9cd3 --- /dev/null +++ b/lua/custom/plugins/diffview.lua @@ -0,0 +1,17 @@ +return { + 'sindrets/diffview.nvim', + cmd = { + 'DiffviewOpen', + 'DiffviewClose', + 'DiffviewToggleFiles', + 'DiffviewFocusFiles', + }, + keys = { + { 'gd', 'DiffviewOpen', desc = 'Diffview Open' }, + { 'gq', 'DiffviewClose', desc = 'Diffview Close' }, + }, + dependencies = { + 'nvim-lua/plenary.nvim', + 'nvim-tree/nvim-web-devicons', + }, +} From c7a126475ac96e85db36c37f3176b546092ccf61 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 30 Mar 2026 15:44:46 +0800 Subject: [PATCH 13/24] Add blame --- AGENTS.md | 164 +++++++++++++++++++++++++++++++++++ lazy-lock.json | 1 + lua/custom/plugins/blame.lua | 8 ++ 3 files changed, 173 insertions(+) create mode 100644 AGENTS.md create mode 100644 lua/custom/plugins/blame.lua diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..debcb2a2c97 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,164 @@ +# AGENTS.md + +Agent-facing contributor guide for this Neovim config repository. + +## Repository Snapshot + +- Project type: personal/forked `kickstart.nvim` configuration. +- Primary language: Lua. +- Entry point: `init.lua`. +- Additional modules: `lua/custom/**` and `lua/kickstart/**`. +- Plugin manager: `lazy.nvim`. +- Lockfile: `lazy-lock.json` (tracks plugin versions). + +## Sources Used For This Guide + +- `README.md` +- `.stylua.toml` +- `init.lua` +- `lua/custom/**/*.lua` +- `lua/kickstart/**/*.lua` + +## Cursor/Copilot Rules + +- No `.cursorrules` file found. +- No `.cursor/rules/` directory found. +- No `.github/copilot-instructions.md` found. +- Therefore: follow this `AGENTS.md` + existing repository conventions. + +## Environment and Prerequisites + +- Neovim target: latest stable or nightly (README states this explicitly). +- External tools commonly expected: + - `git`, `make`, `unzip`, `rg` (checked by `lua/kickstart/health.lua`). + - Often useful: `fd`, `tree-sitter` CLI. + - Formatters used by config: `stylua`, `prettier`, `bean-format`. +- If tooling is missing, prefer graceful degradation over hard failure. + +## Build / Lint / Test Commands + +This repo is a config repo, so "build" and "test" are mostly lint/health/smoke checks. + +## Quick Command Matrix + +- Full format check: + - `stylua --check .` +- Apply Lua formatting: + - `stylua .` +- Sync/install plugins headlessly: + - `nvim --headless "+Lazy! sync" +qa` +- Run kickstart health checks headlessly: + - `nvim --headless "+checkhealth kickstart" +qa` +- Open once for runtime/plugin errors (manual smoke): + - `nvim` + +## Single-Test Guidance (Important) + +There is no formal unit-test framework (no `busted`, `plenary` test suite, `make test`, etc.). + +Use one of these "single check" equivalents when you need narrow validation: + +- Single file syntax check (if Lua compiler available): + - `luac -p path/to/file.lua` +- Single module load check in Neovim: + - `nvim --headless "+lua require('custom.plugins.opencode')" +qa` + - Replace module path as needed. +- Single feature health check: + - `nvim --headless "+checkhealth kickstart" +qa` + - Read only the section relevant to your change. + +If a task asks for "run one test", use a module-load or syntax check above and report it as a targeted smoke test. + +## Validation Order For Agents + +When making code changes, run checks in this order unless task says otherwise: + +1. `stylua --check .` +2. Targeted module/syntax check for changed file(s). +3. `nvim --headless "+checkhealth kickstart" +qa` for broader sanity. + +If a command is unavailable locally, state it clearly and provide the exact command for humans/CI. +If a command is unavailable locally, state it clearly and provide the exact command for the local machine. + +## Code Style: Formatting + +Formatting rules are authoritative in `.stylua.toml`: + +- Indentation: 2 spaces. +- Max column width: 160. +- Line endings: Unix. +- Quote style: `AutoPreferSingle` (prefer single quotes). +- Call parentheses: `None` where valid (`require 'x'` style). +- Collapse simple statements: always. + +Never hand-format against Stylua output; run Stylua instead. + +## Code Style: Imports and Module Structure + +- Prefer local requires near first use: + - `local builtin = require 'telescope.builtin'` +- For plugin specs, return a Lua table from module root: + - `return { ... }` +- Keep plugin declarations declarative (`opts`) unless imperative setup is necessary (`config = function() ... end`). +- In `init.lua`, follow existing kickstart ordering and comment style. +- Avoid introducing new top-level globals. + +## Code Style: Types and Annotations + +This repo uses LuaLS annotations heavily. Preserve and extend when useful: + +- `---@module 'lazy'` +- `---@type LazySpec` +- Plugin-specific types where available (e.g. `Gitsigns.Config`, `conform.setupOpts`). +- Use `---@diagnostic disable-next-line: ...` only when justified and narrowly scoped. + +Do not remove useful annotations just to reduce lines. + +## Code Style: Naming Conventions + +- Modules/files: + - lower_snake_case for filenames where practical. + - plugin files grouped by feature in `lua/custom/plugins/`. +- Local variables/functions: + - descriptive lower_snake_case. + - short names only for conventional temporary values (`buf`, `opts`, `client`). +- Augroup names: + - stable, descriptive strings (e.g. `'NeoTreeAutoRefresh'`, `'kickstart-lsp-highlight'`). +- Keymap descriptions: + - concise, action-oriented, consistent bracket hints used by which-key. + +## Code Style: Error Handling and Resilience + +- Prefer non-fatal behavior for optional dependencies. + - Example pattern already used: `pcall(require('telescope').load_extension, 'fzf')`. +- Guard external tool usage with `vim.fn.executable(...)` when needed. +- Use `vim.notify(..., vim.log.levels.WARN/ERROR)` for actionable user-facing issues. +- Keep startup robust: avoid hard errors for optional plugin features. + +## Plugin and Dependency Conventions + +- Add plugins through `lazy` specs, keeping structure consistent with existing blocks. +- When adding a new plugin, prefer putting it under `lua/custom/plugins/*.lua` (or other custom modules) instead of editing upstream kickstart blocks in `init.lua`, to minimize merge conflicts with upstream updates. +- Prefer minimal configuration first (`opts = {}`), then extend only if needed. +- Respect platform guards (e.g., `make` checks, Windows conditionals). +- Do not edit lockfile manually; let lazy manage `lazy-lock.json` updates. + +## Editing and Change Scope + +- Keep changes minimal and local to the requested task. +- Do not refactor unrelated sections opportunistically. +- Preserve existing comments unless they become inaccurate. +- Maintain ASCII unless file already relies on Unicode symbols/icons. + +## Change Hygiene For Agents + +- Before finalizing: run formatting + at least one targeted runtime check. +- Mention exactly what you validated and what you could not validate. +- If no formal tests exist, explicitly say "no unit test suite in this repo". +- Include file paths in reports so reviewers can jump directly. + +## When Unsure + +- Follow existing patterns in nearby files first. +- Prefer reversible, low-risk changes. +- Ask for clarification only when ambiguity materially changes behavior. diff --git a/lazy-lock.json b/lazy-lock.json index 23b3275dc42..77d03ee935a 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,5 +1,6 @@ { "LuaSnip": { "branch": "master", "commit": "5a1e39223db9a0498024a77b8441169d260c8c25" }, + "blame.nvim": { "branch": "main", "commit": "179da7aaacce7c52874af636255ede72dd6fe796" }, "blink.cmp": { "branch": "main", "commit": "451168851e8e2466bc97ee3e026c3dcb9141ce07" }, "codediff.nvim": { "branch": "main", "commit": "93cd80c56f71af4671388c568a37d4c84c3ddefa" }, "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, diff --git a/lua/custom/plugins/blame.lua b/lua/custom/plugins/blame.lua new file mode 100644 index 00000000000..05a081c3ee4 --- /dev/null +++ b/lua/custom/plugins/blame.lua @@ -0,0 +1,8 @@ +---@module 'lazy' +---@type LazySpec +return { + { + 'FabijanZulj/blame.nvim', + opts = {}, + }, +} From 0ed7c56204344db255230be41c27e911b9969fca Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 30 Mar 2026 15:57:12 +0800 Subject: [PATCH 14/24] Add keybinding for blame toggle --- lua/custom/plugins/blame.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lua/custom/plugins/blame.lua b/lua/custom/plugins/blame.lua index 05a081c3ee4..91346d02aa8 100644 --- a/lua/custom/plugins/blame.lua +++ b/lua/custom/plugins/blame.lua @@ -4,5 +4,8 @@ return { { 'FabijanZulj/blame.nvim', opts = {}, + keys = { + { 'tl', 'BlameToggle', desc = '[T]oggle B[l]ame side window' }, + }, }, } From dced8c0e0b768b54477a3443bd363c040fa81157 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Mon, 30 Mar 2026 16:27:38 +0800 Subject: [PATCH 15/24] Add markdown lint; neotree hidden --- README.md | 1 + init.lua | 7 ++++--- lua/custom/plugins/lint.lua | 23 +++++++++++++++++++++++ lua/custom/plugins/neotree.lua | 10 ++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 lua/custom/plugins/lint.lua diff --git a/README.md b/README.md index 093e42a6dd9..35113e9069e 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ External Requirements: - Language Setup: - If you want to write Typescript, you need `npm` - If you want to write Golang, you will need `go` + - If you want to lint Markdown, install `markdownlint-cli2` (via `npm i -g markdownlint-cli2` or Mason) - etc. > [!NOTE] diff --git a/init.lua b/init.lua index 931ebd0b2ba..cd70af38fa8 100644 --- a/init.lua +++ b/init.lua @@ -626,9 +626,10 @@ require('lazy').setup({ end local config_path = vim.fn.stdpath 'config' - local runtime_files = vim.tbl_filter(function(file) - return file ~= config_path and file ~= (config_path .. '/after') - end, vim.api.nvim_get_runtime_file('', true)) + local runtime_files = vim.tbl_filter( + function(file) return file ~= config_path and file ~= (config_path .. '/after') end, + vim.api.nvim_get_runtime_file('', true) + ) client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { runtime = { diff --git a/lua/custom/plugins/lint.lua b/lua/custom/plugins/lint.lua new file mode 100644 index 00000000000..9f6f459ca05 --- /dev/null +++ b/lua/custom/plugins/lint.lua @@ -0,0 +1,23 @@ +return { + { + 'mfussenegger/nvim-lint', + ft = { 'markdown' }, + opts = { + linters = { + markdownlint = { + args = { '--disable', 'MD013', '--' }, + }, + ['markdownlint-cli2'] = { + prepend_args = { '--disable', 'MD013', '--' }, + }, + }, + }, + config = function(_, opts) + local lint = require 'lint' + + for linter_name, linter_config in pairs(opts.linters or {}) do + lint.linters[linter_name] = vim.tbl_deep_extend('force', lint.linters[linter_name] or {}, linter_config) + end + end, + }, +} diff --git a/lua/custom/plugins/neotree.lua b/lua/custom/plugins/neotree.lua index 41fc36f93d5..520f47d645c 100644 --- a/lua/custom/plugins/neotree.lua +++ b/lua/custom/plugins/neotree.lua @@ -23,9 +23,19 @@ return { opts.filesystem = vim.tbl_deep_extend('force', opts.filesystem or {}, { use_libuv_file_watcher = true, follow_current_file = { enabled = true }, + filtered_items = { + visible = false, + hide_dotfiles = true, + hide_gitignored = true, + hide_hidden = true, + always_show = { + '.github', + }, + }, window = { mappings = { ['R'] = 'refresh', + ['H'] = 'toggle_hidden', }, }, }) From 12a46ad57bd6c6dcc80e0f7d4ca55d14ba782ed3 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Wed, 1 Apr 2026 13:57:54 +0800 Subject: [PATCH 16/24] Add persistence --- lazy-lock.json | 1 + lua/custom/plugins/opencode.lua | 38 ++++++++++++++++++++++++++++++ lua/custom/plugins/persistence.lua | 15 ++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 lua/custom/plugins/persistence.lua diff --git a/lazy-lock.json b/lazy-lock.json index 77d03ee935a..f4f0461fd5d 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -22,6 +22,7 @@ "nvim-treesitter": { "branch": "main", "commit": "7caec274fd19c12b55902a5b795100d21531391f" }, "nvim-web-devicons": { "branch": "master", "commit": "d7462543c9e366c0d196c7f67a945eaaf5d99414" }, "opencode.nvim": { "branch": "main", "commit": "df533d6da724109bf08446392db860fdceddbd0c" }, + "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, diff --git a/lua/custom/plugins/opencode.lua b/lua/custom/plugins/opencode.lua index 39a1394c9f3..c14e4086624 100644 --- a/lua/custom/plugins/opencode.lua +++ b/lua/custom/plugins/opencode.lua @@ -25,6 +25,28 @@ return { }, }, config = function() + local sidebar_filetypes = { + ['neo-tree'] = true, + ['snacks_layout_box'] = true, + ['snacks_terminal'] = true, + ['toggleterm'] = true, + ['opencode'] = true, + } + + local function focus_main_window() + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local buf = vim.api.nvim_win_get_buf(win) + local ft = vim.bo[buf].filetype + local bt = vim.bo[buf].buftype + if not sidebar_filetypes[ft] and bt == '' then + vim.api.nvim_set_current_win(win) + return true + end + end + + return false + end + ---@type opencode.Opts vim.g.opencode_opts = { server = { @@ -60,5 +82,21 @@ return { -- You may want these if you use the opinionated `` and `` keymaps above — otherwise consider `o…` (and remove terminal mode from the `toggle` keymap) vim.keymap.set('n', '+', '', { desc = 'Increment under cursor', noremap = true }) vim.keymap.set('n', '-', '', { desc = 'Decrement under cursor', noremap = true }) + + vim.api.nvim_create_autocmd('VimEnter', { + callback = function() + if vim.fn.argc() == 1 and vim.fn.isdirectory(vim.fn.argv(0)) == 1 then + vim.schedule(function() + pcall(function() require('persistence').load() end) + + vim.schedule(function() + focus_main_window() + require('opencode').toggle() + focus_main_window() + end) + end) + end + end, + }) end, } diff --git a/lua/custom/plugins/persistence.lua b/lua/custom/plugins/persistence.lua new file mode 100644 index 00000000000..bac8e9a238f --- /dev/null +++ b/lua/custom/plugins/persistence.lua @@ -0,0 +1,15 @@ +return { + { + 'folke/persistence.nvim', + event = 'BufReadPre', + opts = { + need = 1, + }, + keys = { + { 'qs', function() require('persistence').load() end, desc = '[Q]uit: restore [S]ession' }, + { 'qS', function() require('persistence').select() end, desc = '[Q]uit: restore [S]ession (picker)' }, + { 'ql', function() require('persistence').load { last = true } end, desc = '[Q]uit: restore [L]ast session' }, + { 'qd', function() require('persistence').stop() end, desc = '[Q]uit: [D]isable session save' }, + }, + }, +} From 0a6c31b3247d02bb4e8e8fab370a1638f38f1ab7 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Thu, 2 Apr 2026 16:47:55 +0800 Subject: [PATCH 17/24] Update gitsigns --- init.lua | 2 +- lua/kickstart/plugins/gitsigns.lua | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/init.lua b/init.lua index cd70af38fa8..6bb0946e60e 100644 --- a/init.lua +++ b/init.lua @@ -127,7 +127,7 @@ vim.o.ignorecase = true vim.o.smartcase = true -- Keep signcolumn on by default -vim.o.signcolumn = 'yes' +vim.o.signcolumn = 'yes:1' -- Decrease update time vim.o.updatetime = 250 diff --git a/lua/kickstart/plugins/gitsigns.lua b/lua/kickstart/plugins/gitsigns.lua index 1d8c50c37db..98ef39e69ec 100644 --- a/lua/kickstart/plugins/gitsigns.lua +++ b/lua/kickstart/plugins/gitsigns.lua @@ -10,6 +10,9 @@ return { ---@type Gitsigns.Config ---@diagnostic disable-next-line: missing-fields opts = { + watch_gitdir = { follow_files = true }, + attach_to_untracked = true, + update_debounce = 100, on_attach = function(bufnr) local gitsigns = require 'gitsigns' From 1c3c4c11e7b1a7870075a5844eef7879019ed57a Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Fri, 3 Apr 2026 10:43:48 +0800 Subject: [PATCH 18/24] Refactor layout helpers and custom keymap wiring Centralize window-focus/sidebar logic in custom.layout and route custom mappings through custom.keymaps to reduce duplication. Also avoid auto session restore on directory startup to prevent Neo-tree taking the main editing area. --- AGENTS.md | 8 ++++ init.lua | 2 + lua/custom/keymaps.lua | 1 + lua/custom/layout.lua | 83 +++++++++++++++++++++++++++++++++ lua/custom/plugins/opencode.lua | 36 +++----------- 5 files changed, 101 insertions(+), 29 deletions(-) create mode 100644 lua/custom/keymaps.lua create mode 100644 lua/custom/layout.lua diff --git a/AGENTS.md b/AGENTS.md index debcb2a2c97..ceee174db70 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -143,6 +143,14 @@ Do not remove useful annotations just to reduce lines. - Respect platform guards (e.g., `make` checks, Windows conditionals). - Do not edit lockfile manually; let lazy manage `lazy-lock.json` updates. +## Custom Keymap and Layout Conventions + +- Keep **custom** keymaps in `lua/custom/keymaps.lua`. +- Keep upstream kickstart keymaps in `init.lua` unless intentionally overriding behavior. +- If adding a new `` namespace in `lua/custom/keymaps.lua`, also register its group in which-key (`init.lua` `which-key` spec). +- Keep layout/window helper logic centralized in `lua/custom/layout.lua` (for example `focus_main_window()`), and reuse it from plugin modules instead of duplicating sidebar/window filtering logic. +- If a plugin needs startup window choreography, call `require('custom.layout')` helpers rather than re-implementing window focus rules. + ## Editing and Change Scope - Keep changes minimal and local to the requested task. diff --git a/init.lua b/init.lua index 6bb0946e60e..6ca9aec993e 100644 --- a/init.lua +++ b/init.lua @@ -233,6 +233,7 @@ vim.api.nvim_create_autocmd('TextYankPost', { }) require 'custom.beancount' +require 'custom.keymaps' -- [[ Install `lazy.nvim` plugin manager ]] -- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info @@ -322,6 +323,7 @@ require('lazy').setup({ spec = { { 's', group = '[S]earch', mode = { 'n', 'v' } }, { 't', group = '[T]oggle' }, + { 'w', group = '[W]indows' }, { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, -- Enable gitsigns recommended keymaps first { 'gr', group = 'LSP Actions', mode = { 'n' } }, }, diff --git a/lua/custom/keymaps.lua b/lua/custom/keymaps.lua new file mode 100644 index 00000000000..7aea5e9b2f8 --- /dev/null +++ b/lua/custom/keymaps.lua @@ -0,0 +1 @@ +vim.keymap.set('n', 'wr', function() require('custom.layout').reset_ide_layout() end, { desc = '[W]indows: [R]eset IDE layout' }) diff --git a/lua/custom/layout.lua b/lua/custom/layout.lua new file mode 100644 index 00000000000..217f2226538 --- /dev/null +++ b/lua/custom/layout.lua @@ -0,0 +1,83 @@ +local M = {} + +local sidebar_filetypes = { + ['neo-tree'] = true, + ['snacks_layout_box'] = true, + ['snacks_terminal'] = true, + ['toggleterm'] = true, + ['opencode'] = true, +} + +function M.focus_main_window() + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local buf = vim.api.nvim_win_get_buf(win) + local ft = vim.bo[buf].filetype + local bt = vim.bo[buf].buftype + if not sidebar_filetypes[ft] and bt == '' then + vim.api.nvim_set_current_win(win) + return true + end + end + + return false +end + +local function find_window_by_filetype(filetype) + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + local buf = vim.api.nvim_win_get_buf(win) + if vim.bo[buf].filetype == filetype then return win end + end + + return nil +end + +local function ensure_neotree_window() + local neotree_win = find_window_by_filetype 'neo-tree' + if neotree_win then return neotree_win end + + pcall( + function() + require('neo-tree.command').execute { + action = 'show', + source = 'filesystem', + position = 'left', + reveal = true, + } + end + ) + + return find_window_by_filetype 'neo-tree' +end + +local function ensure_opencode_window() + local opencode_win = find_window_by_filetype 'opencode' + if opencode_win then return opencode_win end + + pcall(function() require('opencode').toggle() end) + + vim.wait(1000, function() return find_window_by_filetype 'opencode' ~= nil end, 50) + return find_window_by_filetype 'opencode' +end + +function M.reset_ide_layout() + local neotree_win = ensure_neotree_window() + local opencode_win = ensure_opencode_window() + + local total_columns = vim.o.columns + local left_width = math.max(20, math.floor(total_columns * 0.10)) + local right_width = math.max(40, math.floor(total_columns * 0.25)) + local min_main_width = 40 + + if left_width + right_width + min_main_width > total_columns then + local available_sidebar_width = math.max(total_columns - min_main_width, 0) + left_width = math.floor(available_sidebar_width * (10 / 35)) + right_width = available_sidebar_width - left_width + end + + if neotree_win and vim.api.nvim_win_is_valid(neotree_win) then vim.api.nvim_win_set_width(neotree_win, left_width) end + if opencode_win and vim.api.nvim_win_is_valid(opencode_win) then vim.api.nvim_win_set_width(opencode_win, right_width) end + + M.focus_main_window() +end + +return M diff --git a/lua/custom/plugins/opencode.lua b/lua/custom/plugins/opencode.lua index c14e4086624..d62b4c81328 100644 --- a/lua/custom/plugins/opencode.lua +++ b/lua/custom/plugins/opencode.lua @@ -25,27 +25,7 @@ return { }, }, config = function() - local sidebar_filetypes = { - ['neo-tree'] = true, - ['snacks_layout_box'] = true, - ['snacks_terminal'] = true, - ['toggleterm'] = true, - ['opencode'] = true, - } - - local function focus_main_window() - for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do - local buf = vim.api.nvim_win_get_buf(win) - local ft = vim.bo[buf].filetype - local bt = vim.bo[buf].buftype - if not sidebar_filetypes[ft] and bt == '' then - vim.api.nvim_set_current_win(win) - return true - end - end - - return false - end + local layout = require 'custom.layout' ---@type opencode.Opts vim.g.opencode_opts = { @@ -85,15 +65,13 @@ return { vim.api.nvim_create_autocmd('VimEnter', { callback = function() - if vim.fn.argc() == 1 and vim.fn.isdirectory(vim.fn.argv(0)) == 1 then + local argv = vim.fn.argv() + local first_arg = argv[1] + if vim.fn.argc() == 1 and type(first_arg) == 'string' and vim.fn.isdirectory(first_arg) == 1 then vim.schedule(function() - pcall(function() require('persistence').load() end) - - vim.schedule(function() - focus_main_window() - require('opencode').toggle() - focus_main_window() - end) + layout.focus_main_window() + require('opencode').toggle() + layout.focus_main_window() end) end end, From 18ba123a17d3bc8a74299d8dbffa9a90043a1810 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Fri, 3 Apr 2026 11:13:58 +0800 Subject: [PATCH 19/24] Refactor custom plugin enable/disable layout Adopt nginx-style plugin folders by importing only custom.plugins.enable and moving inactive specs to custom/plugins/disable. This keeps persistence disabled by default and documents the workflow in AGENTS plus local plugin notes. --- AGENTS.md | 5 ++-- init.lua | 4 +-- .../{oil.lua.disable => disable/oil.lua} | 20 +++++-------- .../plugins/{ => disable}/persistence.lua | 0 .../{tree.lua.disable => disable/tree.lua} | 0 lua/custom/plugins/{ => enable}/blame.lua | 0 lua/custom/plugins/{ => enable}/codediff.lua | 0 lua/custom/plugins/{ => enable}/diffview.lua | 0 lua/custom/plugins/{ => enable}/lint.lua | 0 lua/custom/plugins/{ => enable}/neotree.lua | 0 lua/custom/plugins/{ => enable}/opencode.lua | 30 +++++++++---------- .../plugins/{ => enable}/toggleterm.lua | 0 lua/custom/plugins/init.lua | 7 +++-- 13 files changed, 31 insertions(+), 35 deletions(-) rename lua/custom/plugins/{oil.lua.disable => disable/oil.lua} (86%) rename lua/custom/plugins/{ => disable}/persistence.lua (100%) rename lua/custom/plugins/{tree.lua.disable => disable/tree.lua} (100%) rename lua/custom/plugins/{ => enable}/blame.lua (100%) rename lua/custom/plugins/{ => enable}/codediff.lua (100%) rename lua/custom/plugins/{ => enable}/diffview.lua (100%) rename lua/custom/plugins/{ => enable}/lint.lua (100%) rename lua/custom/plugins/{ => enable}/neotree.lua (100%) rename lua/custom/plugins/{ => enable}/opencode.lua (81%) rename lua/custom/plugins/{ => enable}/toggleterm.lua (100%) diff --git a/AGENTS.md b/AGENTS.md index ceee174db70..620486be3dd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -118,7 +118,7 @@ Do not remove useful annotations just to reduce lines. - Modules/files: - lower_snake_case for filenames where practical. - - plugin files grouped by feature in `lua/custom/plugins/`. + - plugin files grouped by feature under `lua/custom/plugins/enable/` (active) and `lua/custom/plugins/disable/` (inactive). - Local variables/functions: - descriptive lower_snake_case. - short names only for conventional temporary values (`buf`, `opts`, `client`). @@ -138,7 +138,8 @@ Do not remove useful annotations just to reduce lines. ## Plugin and Dependency Conventions - Add plugins through `lazy` specs, keeping structure consistent with existing blocks. -- When adding a new plugin, prefer putting it under `lua/custom/plugins/*.lua` (or other custom modules) instead of editing upstream kickstart blocks in `init.lua`, to minimize merge conflicts with upstream updates. +- When adding a new plugin, prefer putting it under `lua/custom/plugins/enable/*.lua` (or other custom modules) instead of editing upstream kickstart blocks in `init.lua`, to minimize merge conflicts with upstream updates. +- To disable a custom plugin without deleting its spec, move it to `lua/custom/plugins/disable/`. - Prefer minimal configuration first (`opts = {}`), then extend only if needed. - Respect platform guards (e.g., `make` checks, Windows conditionals). - Do not edit lockfile manually; let lazy manage `lazy-lock.json` updates. diff --git a/init.lua b/init.lua index 6ca9aec993e..d364463c348 100644 --- a/init.lua +++ b/init.lua @@ -952,11 +952,11 @@ require('lazy').setup({ require 'kickstart.plugins.neo-tree', require 'kickstart.plugins.gitsigns', -- adds gitsigns recommended keymaps - -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` + -- NOTE: The import below automatically loads enabled custom plugins from `lua/custom/plugins/enable/*.lua` -- This is the easiest way to modularize your config. -- -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. - { import = 'custom.plugins' }, + { import = 'custom.plugins.enable' }, -- -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` -- Or use telescope! diff --git a/lua/custom/plugins/oil.lua.disable b/lua/custom/plugins/disable/oil.lua similarity index 86% rename from lua/custom/plugins/oil.lua.disable rename to lua/custom/plugins/disable/oil.lua index 024555303e7..58333f30a60 100644 --- a/lua/custom/plugins/oil.lua.disable +++ b/lua/custom/plugins/disable/oil.lua @@ -7,13 +7,11 @@ return { columns = { 'icon' }, keymaps = { [''] = function() - local oil = require('oil') - local actions = require('oil.actions') + local oil = require 'oil' + local actions = require 'oil.actions' local entry = oil.get_cursor_entry() - if not entry then - return - end + if not entry then return end if entry.type == 'directory' then actions.select.callback() @@ -34,9 +32,7 @@ return { target_win = win else local target_pos = vim.api.nvim_win_get_position(target_win) - if pos[2] < target_pos[2] then - target_win = win - end + if pos[2] < target_pos[2] then target_win = win end end end end @@ -44,15 +40,13 @@ return { end if not target_win then - vim.cmd('vsplit') + vim.cmd 'vsplit' target_win = vim.api.nvim_get_current_win() vim.api.nvim_set_current_win(sidebar_win) end local dir = oil.get_current_dir() - if not dir then - return - end + if not dir then return end local path = vim.fs.joinpath(dir, entry.name) vim.api.nvim_set_current_win(target_win) @@ -73,7 +67,7 @@ return { end local current_win = vim.api.nvim_get_current_win() - vim.cmd('topleft vsplit') + vim.cmd 'topleft vsplit' local sidebar_win = vim.api.nvim_get_current_win() require('oil').open() vim.api.nvim_win_set_width(sidebar_win, 20) diff --git a/lua/custom/plugins/persistence.lua b/lua/custom/plugins/disable/persistence.lua similarity index 100% rename from lua/custom/plugins/persistence.lua rename to lua/custom/plugins/disable/persistence.lua diff --git a/lua/custom/plugins/tree.lua.disable b/lua/custom/plugins/disable/tree.lua similarity index 100% rename from lua/custom/plugins/tree.lua.disable rename to lua/custom/plugins/disable/tree.lua diff --git a/lua/custom/plugins/blame.lua b/lua/custom/plugins/enable/blame.lua similarity index 100% rename from lua/custom/plugins/blame.lua rename to lua/custom/plugins/enable/blame.lua diff --git a/lua/custom/plugins/codediff.lua b/lua/custom/plugins/enable/codediff.lua similarity index 100% rename from lua/custom/plugins/codediff.lua rename to lua/custom/plugins/enable/codediff.lua diff --git a/lua/custom/plugins/diffview.lua b/lua/custom/plugins/enable/diffview.lua similarity index 100% rename from lua/custom/plugins/diffview.lua rename to lua/custom/plugins/enable/diffview.lua diff --git a/lua/custom/plugins/lint.lua b/lua/custom/plugins/enable/lint.lua similarity index 100% rename from lua/custom/plugins/lint.lua rename to lua/custom/plugins/enable/lint.lua diff --git a/lua/custom/plugins/neotree.lua b/lua/custom/plugins/enable/neotree.lua similarity index 100% rename from lua/custom/plugins/neotree.lua rename to lua/custom/plugins/enable/neotree.lua diff --git a/lua/custom/plugins/opencode.lua b/lua/custom/plugins/enable/opencode.lua similarity index 81% rename from lua/custom/plugins/opencode.lua rename to lua/custom/plugins/enable/opencode.lua index d62b4c81328..2b77d4af50e 100644 --- a/lua/custom/plugins/opencode.lua +++ b/lua/custom/plugins/enable/opencode.lua @@ -25,8 +25,6 @@ return { }, }, config = function() - local layout = require 'custom.layout' - ---@type opencode.Opts vim.g.opencode_opts = { server = { @@ -63,18 +61,20 @@ return { vim.keymap.set('n', '+', '', { desc = 'Increment under cursor', noremap = true }) vim.keymap.set('n', '-', '', { desc = 'Decrement under cursor', noremap = true }) - vim.api.nvim_create_autocmd('VimEnter', { - callback = function() - local argv = vim.fn.argv() - local first_arg = argv[1] - if vim.fn.argc() == 1 and type(first_arg) == 'string' and vim.fn.isdirectory(first_arg) == 1 then - vim.schedule(function() - layout.focus_main_window() - require('opencode').toggle() - layout.focus_main_window() - end) - end - end, - }) + -- Disabled: startup session/window orchestration is handled by persistence workflow. + -- vim.api.nvim_create_autocmd('VimEnter', { + -- callback = function() + -- local layout = require 'custom.layout' + -- local argv = vim.fn.argv() + -- local first_arg = argv[1] + -- if vim.fn.argc() == 1 and type(first_arg) == 'string' and vim.fn.isdirectory(first_arg) == 1 then + -- vim.schedule(function() + -- layout.focus_main_window() + -- require('opencode').toggle() + -- layout.focus_main_window() + -- end) + -- end + -- end, + -- }) end, } diff --git a/lua/custom/plugins/toggleterm.lua b/lua/custom/plugins/enable/toggleterm.lua similarity index 100% rename from lua/custom/plugins/toggleterm.lua rename to lua/custom/plugins/enable/toggleterm.lua diff --git a/lua/custom/plugins/init.lua b/lua/custom/plugins/init.lua index b3ddcfdd3aa..eb0f0ba8904 100644 --- a/lua/custom/plugins/init.lua +++ b/lua/custom/plugins/init.lua @@ -1,7 +1,8 @@ --- You can add your own plugins here or in other files in this directory! --- I promise not to create any merge conflicts in this directory :) +-- Custom plugin layout (nginx style): +-- - enable/*.lua : loaded by lazy via `import = 'custom.plugins.enable'` +-- - disable/*.lua: not imported; keep plugin specs here to disable quickly -- --- See the kickstart.nvim README for more information +-- See init.lua import config for details. ---@module 'lazy' ---@type LazySpec From aed9eee722e118284df1099043538c884d7b76a6 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Fri, 3 Apr 2026 11:32:21 +0800 Subject: [PATCH 20/24] Add auto-session with layout-aware focus restore --- lazy-lock.json | 20 ++++----- lua/custom/layout.lua | 52 +++++++++++++++++++--- lua/custom/plugins/enable/auto_session.lua | 45 +++++++++++++++++++ 3 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 lua/custom/plugins/enable/auto_session.lua diff --git a/lazy-lock.json b/lazy-lock.json index f4f0461fd5d..de7d6edbecc 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,32 +1,32 @@ { "LuaSnip": { "branch": "master", "commit": "5a1e39223db9a0498024a77b8441169d260c8c25" }, + "auto-session": { "branch": "main", "commit": "62437532b38495551410b3f377bcf4aaac574ebe" }, "blame.nvim": { "branch": "main", "commit": "179da7aaacce7c52874af636255ede72dd6fe796" }, "blink.cmp": { "branch": "main", "commit": "451168851e8e2466bc97ee3e026c3dcb9141ce07" }, - "codediff.nvim": { "branch": "main", "commit": "93cd80c56f71af4671388c568a37d4c84c3ddefa" }, + "codediff.nvim": { "branch": "main", "commit": "832f1ecc5f8b15a44cf7537e31d3266d657775b1" }, "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, - "fidget.nvim": { "branch": "main", "commit": "7fa433a83118a70fe24c1ce88d5f0bd3453c0970" }, - "gitsigns.nvim": { "branch": "main", "commit": "50c205548d8b037b7ff6378fca6d21146f0b6161" }, + "fidget.nvim": { "branch": "main", "commit": "889e2e96edef4e144965571d46f7a77bcc4d0ddf" }, + "gitsigns.nvim": { "branch": "main", "commit": "e1fb5425c8812214209b3f24eaa582c6c552cf98" }, "guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "037398b9ce4a53ba48d5f94765c641a1fd16d906" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "25f609e7fca78af7cede4f9fa3af8a94b1c4950b" }, "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, - "mini.nvim": { "branch": "main", "commit": "af5f75c9ce572a4d1f0c77d6fb4ea764d16c1b3c" }, + "mini.nvim": { "branch": "main", "commit": "3923662bf3d6ca49a9503f8d7196ea0450983e6a" }, "neo-tree.nvim": { "branch": "main", "commit": "84c75e7a7e443586f60508d12fc50f90d9aee14e" }, "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, "nvim-lint": { "branch": "master", "commit": "4b03656c09c1561f89b6aa0665c15d292ba9499d" }, - "nvim-lspconfig": { "branch": "master", "commit": "16812abf0e8d8175155f26143a8504e8253e92b0" }, - "nvim-treesitter": { "branch": "main", "commit": "7caec274fd19c12b55902a5b795100d21531391f" }, - "nvim-web-devicons": { "branch": "master", "commit": "d7462543c9e366c0d196c7f67a945eaaf5d99414" }, + "nvim-lspconfig": { "branch": "master", "commit": "8e2084bf5e40c79c1f42210a6ef96a0a4793a763" }, + "nvim-treesitter": { "branch": "main", "commit": "539abf6da5ee8702e37b82cc953131dadd570da2" }, + "nvim-web-devicons": { "branch": "master", "commit": "40e9d5a6cc3db11b309e39593fc7ac03bb844e38" }, "opencode.nvim": { "branch": "main", "commit": "df533d6da724109bf08446392db860fdceddbd0c" }, - "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, - "telescope.nvim": { "branch": "master", "commit": "e6cdb4dc528c5dc4ca8da86e83ef4e3c84b0729c" }, + "telescope.nvim": { "branch": "master", "commit": "cfb85dcf7f822b79224e9e6aef9e8c794211b20b" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, "toggleterm.nvim": { "branch": "main", "commit": "50ea089fc548917cc3cc16b46a8211833b9e3c7c" }, "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, diff --git a/lua/custom/layout.lua b/lua/custom/layout.lua index 217f2226538..8a0a785dbfd 100644 --- a/lua/custom/layout.lua +++ b/lua/custom/layout.lua @@ -8,12 +8,18 @@ local sidebar_filetypes = { ['opencode'] = true, } +function M.is_main_window(win) + if not win or not vim.api.nvim_win_is_valid(win) then return false end + + local buf = vim.api.nvim_win_get_buf(win) + local ft = vim.bo[buf].filetype + local bt = vim.bo[buf].buftype + return not sidebar_filetypes[ft] and bt == '' +end + function M.focus_main_window() for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do - local buf = vim.api.nvim_win_get_buf(win) - local ft = vim.bo[buf].filetype - local bt = vim.bo[buf].buftype - if not sidebar_filetypes[ft] and bt == '' then + if M.is_main_window(win) then vim.api.nvim_set_current_win(win) return true end @@ -31,6 +37,38 @@ local function find_window_by_filetype(filetype) return nil end +function M.capture_focus() + local current_win = vim.api.nvim_get_current_win() + if not M.is_main_window(current_win) then return nil end + + local buf = vim.api.nvim_win_get_buf(current_win) + local buf_name = vim.api.nvim_buf_get_name(buf) + if buf_name == '' then return nil end + + return { + buf_name = buf_name, + } +end + +function M.restore_focus(focus) + if type(focus) ~= 'table' then return M.focus_main_window() end + + local target_buf_name = focus.buf_name + if type(target_buf_name) ~= 'string' or target_buf_name == '' then return M.focus_main_window() end + + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if M.is_main_window(win) then + local buf = vim.api.nvim_win_get_buf(win) + if vim.api.nvim_buf_get_name(buf) == target_buf_name then + vim.api.nvim_set_current_win(win) + return true + end + end + end + + return M.focus_main_window() +end + local function ensure_neotree_window() local neotree_win = find_window_by_filetype 'neo-tree' if neotree_win then return neotree_win end @@ -59,7 +97,9 @@ local function ensure_opencode_window() return find_window_by_filetype 'opencode' end -function M.reset_ide_layout() +function M.reset_ide_layout(opts) + opts = opts or {} + local neotree_win = ensure_neotree_window() local opencode_win = ensure_opencode_window() @@ -77,7 +117,7 @@ function M.reset_ide_layout() if neotree_win and vim.api.nvim_win_is_valid(neotree_win) then vim.api.nvim_win_set_width(neotree_win, left_width) end if opencode_win and vim.api.nvim_win_is_valid(opencode_win) then vim.api.nvim_win_set_width(opencode_win, right_width) end - M.focus_main_window() + if opts.focus_main ~= false then M.focus_main_window() end end return M diff --git a/lua/custom/plugins/enable/auto_session.lua b/lua/custom/plugins/enable/auto_session.lua new file mode 100644 index 00000000000..1ba07b141a4 --- /dev/null +++ b/lua/custom/plugins/enable/auto_session.lua @@ -0,0 +1,45 @@ +return { + { + 'rmagatti/auto-session', + lazy = false, + + ---enables autocomplete for opts + ---@module 'auto-session' + ---@type AutoSession.Config + opts = { + suppressed_dirs = { '~/', '~/Downloads', '/' }, + -- Keep sessions even when only a directory/sidebar is open (IDE-style usage). + auto_delete_empty_sessions = false, + save_extra_data = function(_) + local ok, layout = pcall(require, 'custom.layout') + if not ok then return nil end + + local focus = layout.capture_focus() + if not focus then return nil end + + return vim.fn.json_encode { + focus = focus, + } + end, + restore_extra_data = function(_, extra_data) + local ok_json, decoded = pcall(vim.fn.json_decode, extra_data) + if not ok_json or type(decoded) ~= 'table' then return end + + local ok_layout, layout = pcall(require, 'custom.layout') + if not ok_layout then return end + + local focus = decoded.focus + if type(focus) == 'table' then vim.schedule(function() layout.restore_focus(focus) end) end + end, + post_restore_cmds = { + function(_) + local ok_layout, layout = pcall(require, 'custom.layout') + if not ok_layout then return end + + vim.schedule(function() layout.reset_ide_layout { focus_main = false } end) + end, + }, + -- log_level = 'debug', + }, + }, +} From 83d7ea0443b39256314f1c7859522844ebeaed70 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Fri, 3 Apr 2026 15:03:19 +0800 Subject: [PATCH 21/24] Refine window/session keybindings --- lua/custom/keymaps.lua | 2 +- lua/custom/plugins/enable/auto_session.lua | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lua/custom/keymaps.lua b/lua/custom/keymaps.lua index 7aea5e9b2f8..60c62fd0528 100644 --- a/lua/custom/keymaps.lua +++ b/lua/custom/keymaps.lua @@ -1 +1 @@ -vim.keymap.set('n', 'wr', function() require('custom.layout').reset_ide_layout() end, { desc = '[W]indows: [R]eset IDE layout' }) +vim.keymap.set('n', 'wR', function() require('custom.layout').reset_ide_layout() end, { desc = '[W]indows: [R]eset IDE layout' }) diff --git a/lua/custom/plugins/enable/auto_session.lua b/lua/custom/plugins/enable/auto_session.lua index 1ba07b141a4..ecf80d71353 100644 --- a/lua/custom/plugins/enable/auto_session.lua +++ b/lua/custom/plugins/enable/auto_session.lua @@ -2,6 +2,12 @@ return { { 'rmagatti/auto-session', lazy = false, + keys = { + -- Will use Telescope if installed or a vim.ui.select picker otherwise + { 'wr', 'AutoSession search', desc = 'Session search' }, + { 'ws', 'AutoSession save', desc = 'Save session' }, + { 'wa', 'AutoSession toggle', desc = 'Toggle autosave' }, + }, ---enables autocomplete for opts ---@module 'auto-session' From 9d2e376259962c0e7d96b189f26241bbe8e06233 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Sat, 4 Apr 2026 20:03:23 +0800 Subject: [PATCH 22/24] update opencode, load env --- lua/custom/plugins/enable/opencode.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lua/custom/plugins/enable/opencode.lua b/lua/custom/plugins/enable/opencode.lua index 2b77d4af50e..b007fef9584 100644 --- a/lua/custom/plugins/enable/opencode.lua +++ b/lua/custom/plugins/enable/opencode.lua @@ -25,18 +25,20 @@ return { }, }, config = function() + local opencode_cmd = [[zsh -ic 'opencode --port']] + ---@type opencode.Opts vim.g.opencode_opts = { server = { start = function() - require('opencode.terminal').open('opencode --port', { + require('opencode.terminal').open(opencode_cmd, { split = 'right', width = math.max(40, math.floor(vim.o.columns * 0.4)), }) end, stop = function() require('opencode.terminal').close() end, toggle = function() - require('opencode.terminal').toggle('opencode --port', { + require('opencode.terminal').toggle(opencode_cmd, { split = 'right', width = math.max(40, math.floor(vim.o.columns * 0.4)), }) From 4caeebcd1b796a0a81e741101897908e989eaaed Mon Sep 17 00:00:00 2001 From: hlst Date: Tue, 7 Apr 2026 09:57:34 +0800 Subject: [PATCH 23/24] fix layout restore and diagnostic float behavior --- init.lua | 2 +- lazy-lock.json | 2 +- lua/custom/layout.lua | 30 +++++++++++++++++++--- lua/custom/plugins/enable/auto_session.lua | 4 +++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/init.lua b/init.lua index d364463c348..281fd10c3f1 100644 --- a/init.lua +++ b/init.lua @@ -186,7 +186,7 @@ vim.diagnostic.config { virtual_lines = false, -- Text shows up underneath the line, with virtual lines -- Auto open the float, so you can easily read the errors when jumping with `[d` and `]d` - jump = { float = true }, + jump = { on_jump = function() vim.diagnostic.open_float() end }, } vim.keymap.set('n', 'q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) diff --git a/lazy-lock.json b/lazy-lock.json index de7d6edbecc..2ecc8013f54 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -10,7 +10,7 @@ "gitsigns.nvim": { "branch": "main", "commit": "e1fb5425c8812214209b3f24eaa582c6c552cf98" }, "guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" }, "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, - "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "mason-lspconfig.nvim": { "branch": "main", "commit": "25f609e7fca78af7cede4f9fa3af8a94b1c4950b" }, "mason-tool-installer.nvim": { "branch": "main", "commit": "443f1ef8b5e6bf47045cb2217b6f748a223cf7dc" }, "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, diff --git a/lua/custom/layout.lua b/lua/custom/layout.lua index 8a0a785dbfd..4aa858ba4dc 100644 --- a/lua/custom/layout.lua +++ b/lua/custom/layout.lua @@ -37,6 +37,30 @@ local function find_window_by_filetype(filetype) return nil end +local function is_opencode_window(win) + if not win or not vim.api.nvim_win_is_valid(win) then return false end + + local buf = vim.api.nvim_win_get_buf(win) + local ft = vim.bo[buf].filetype + if ft == 'opencode' then return true end + + local bt = vim.bo[buf].buftype + if bt ~= 'terminal' then return false end + + if ft ~= '' and ft ~= 'snacks_terminal' and ft ~= 'toggleterm' then return false end + + local buf_name = string.lower(vim.api.nvim_buf_get_name(buf)) + return buf_name:find('opencode', 1, true) ~= nil +end + +local function find_opencode_window() + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if is_opencode_window(win) then return win end + end + + return nil +end + function M.capture_focus() local current_win = vim.api.nvim_get_current_win() if not M.is_main_window(current_win) then return nil end @@ -88,13 +112,13 @@ local function ensure_neotree_window() end local function ensure_opencode_window() - local opencode_win = find_window_by_filetype 'opencode' + local opencode_win = find_opencode_window() if opencode_win then return opencode_win end pcall(function() require('opencode').toggle() end) - vim.wait(1000, function() return find_window_by_filetype 'opencode' ~= nil end, 50) - return find_window_by_filetype 'opencode' + vim.wait(1000, function() return find_opencode_window() ~= nil end, 50) + return find_opencode_window() end function M.reset_ide_layout(opts) diff --git a/lua/custom/plugins/enable/auto_session.lua b/lua/custom/plugins/enable/auto_session.lua index ecf80d71353..c1f2cd08347 100644 --- a/lua/custom/plugins/enable/auto_session.lua +++ b/lua/custom/plugins/enable/auto_session.lua @@ -2,6 +2,10 @@ return { { 'rmagatti/auto-session', lazy = false, + init = function() + -- Required by auto-session for filetype and highlighting to survive session restore + vim.o.sessionoptions = 'blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal,localoptions' + end, keys = { -- Will use Telescope if installed or a vim.ui.select picker otherwise { 'wr', 'AutoSession search', desc = 'Session search' }, From 66984355bedaccd091f552c86b6c8cfc9b4358d6 Mon Sep 17 00:00:00 2001 From: hlstwizard Date: Tue, 7 Apr 2026 11:50:50 +0800 Subject: [PATCH 24/24] Extract treesitter custom parsers into separate module --- init.lua | 1 + lua/custom/treesitter.lua | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 lua/custom/treesitter.lua diff --git a/init.lua b/init.lua index 281fd10c3f1..c92e8b415ab 100644 --- a/init.lua +++ b/init.lua @@ -234,6 +234,7 @@ vim.api.nvim_create_autocmd('TextYankPost', { require 'custom.beancount' require 'custom.keymaps' +require 'custom.treesitter' -- [[ Install `lazy.nvim` plugin manager ]] -- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info diff --git a/lua/custom/treesitter.lua b/lua/custom/treesitter.lua new file mode 100644 index 00000000000..fecd00b275a --- /dev/null +++ b/lua/custom/treesitter.lua @@ -0,0 +1,11 @@ +local extra_parsers = { 'bicep', 'beancount' } + +vim.api.nvim_create_autocmd('User', { + pattern = 'VeryLazy', + once = true, + callback = function() + local ok, treesitter = pcall(require, 'nvim-treesitter') + if not ok then return end + treesitter.install(extra_parsers) + end, +})