From 2ecc41e7068ad9d85d5387f78dc88d82ffbe020d Mon Sep 17 00:00:00 2001 From: Dan Kingswell Date: Fri, 28 Aug 2026 15:48:29 +0100 Subject: [PATCH 1/2] feat: editor experience improvements - Add fd to Brewfile (explorer search fix + faster file finding) - Ghostty: font-size 15, unbind super+j and shift+arrow_left/right - Cmd+J hover documentation, Shift+Left/Right selection, f->search - Leader+b+a to delete all other buffers - Explorer: fixed-width central layout, auto-close on file pick --- Brewfile | 1 + configs/ghostty/config | 7 +++++++ configs/nvim/lua/config/keymaps.lua | 22 ++++++++++++++++++++++ configs/nvim/lua/plugins/snacks.lua | 17 +++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/Brewfile b/Brewfile index 9c74888..5858e91 100644 --- a/Brewfile +++ b/Brewfile @@ -1,4 +1,5 @@ brew "neovim" +brew "fd" cask "ghostty" cask "hammerspoon" diff --git a/configs/ghostty/config b/configs/ghostty/config index a27654c..dfb870f 100644 --- a/configs/ghostty/config +++ b/configs/ghostty/config @@ -1,6 +1,9 @@ # Treat Option as Alt so Neovim receives key events properly macos-option-as-alt = true +# Editor text size +font-size = 15 + # Unbind Cmd keys so they pass through to Neovim via the kitty keyboard # protocol. Neovim 0.11+ and Ghostty both support this protocol, so # Neovim will receive these as , , etc. natively. @@ -20,6 +23,10 @@ keybind = super+e=unbind keybind = super+l=unbind keybind = super+g=unbind keybind = super+shift+g=unbind +keybind = super+j=unbind +keybind = super+shift+j=unbind +keybind = shift+arrow_left=unbind +keybind = shift+arrow_right=unbind # Cmd+Shift+Arrow: split terminal in that direction keybind = super+shift+arrow_down=new_split:down diff --git a/configs/nvim/lua/config/keymaps.lua b/configs/nvim/lua/config/keymaps.lua index c4f3019..b649bdf 100644 --- a/configs/nvim/lua/config/keymaps.lua +++ b/configs/nvim/lua/config/keymaps.lua @@ -188,6 +188,9 @@ map({ "n", "i", "v" }, "", vim.lsp.buf.code_action, { desc = "Code actions" -- Cmd+G: go to definition (matching Zed's Cmd+G behavior) map({ "n", "i", "v" }, "", vim.lsp.buf.definition, { desc = "Go to definition" }) +-- Cmd+J: hover documentation (function params, types, etc) +map({ "n", "i", "v" }, "", vim.lsp.buf.hover, { desc = "Hover documentation" }) + -- Cmd+S: save current file map({ "n", "i", "v" }, "", function() if vim.api.nvim_get_mode().mode ~= "n" then @@ -243,6 +246,12 @@ map("n", "", "v", { desc = "Select next line" }) map("v", "", "", { desc = "Extend selection up" }) map("v", "", "", { desc = "Extend selection down" }) +-- Shift+Left/Right: highlight/select text horizontally (like Zed) +map("n", "", "v", { desc = "Select previous character" }) +map("n", "", "v", { desc = "Select next character" }) +map("v", "", "", { desc = "Extend selection left" }) +map("v", "", "", { desc = "Extend selection right" }) + -- Alt+Up/Down: move line (or visual selection) up/down map("n", "", "execute 'move .+' . v:count1==", { desc = "Move Line Down" }) map("n", "", "execute 'move .-' . (v:count1 + 1)==", { desc = "Move Line Up" }) @@ -257,4 +266,17 @@ map("v", "", "y'ba", function() + -- skip the current buffer so the window stays open + local current = vim.api.nvim_get_current_buf() + for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do + if bufnr ~= current and vim.api.nvim_buf_is_loaded(bufnr) and vim.bo[bufnr].buflisted then + pcall(vim.api.nvim_buf_delete, bufnr, { force = true }) + end + end + vim.notify("Deleted all other buffers") +end, { desc = "Delete All Other Buffers" }) diff --git a/configs/nvim/lua/plugins/snacks.lua b/configs/nvim/lua/plugins/snacks.lua index b038f7f..3137c40 100644 --- a/configs/nvim/lua/plugins/snacks.lua +++ b/configs/nvim/lua/plugins/snacks.lua @@ -37,6 +37,23 @@ return { hidden = true, ignored = true, exclude = { "node_modules" }, + jump = { close = true }, + layout = { + layout = { + box = "horizontal", + width = 90, + min_width = 90, + height = 0.8, + { + box = "vertical", + border = true, + title = "{title} {live} {flags}", + { win = "input", height = 1, border = "bottom" }, + { win = "list", border = "none" }, + }, + { win = "preview", title = "{preview}", border = true, width = 0.5 }, + }, + }, }, }, }, From b4b476bb3fcd78cb52a0d55d9bffe6ca6efa5ac4 Mon Sep 17 00:00:00 2001 From: Dan Kingswell Date: Mon, 31 Aug 2026 20:32:16 +0100 Subject: [PATCH 2/2] feat: multi-cursor, buffer close, SQL/lsp fixes, bruno+go+test plugins - Multicursor: add M-C-Down/Up cursors, free up C-Down/C-Up - Keymaps: Shift+Up/Down selection in insert mode, Cmd+B close buffer, word-substitute via 's' - Ghostty: unbind Cmd+B to pass through to Neovim for buffer close - SQL: disable sqlls LSP, disable built-in sqlcomplete omnifunc (drill errors) - New plugins: bruno (API runner), go + neotest (test core & lang) - Update lazy-lock.json pins - Snacks explorer: f key closes all explorers --- configs/ghostty/config | 3 ++ configs/nvim/after/ftplugin/sql.vim | 2 ++ configs/nvim/lazy-lock.json | 40 +++++++++++++----------- configs/nvim/lua/config/keymaps.lua | 8 +++++ configs/nvim/lua/plugins/bruno.lua | 35 +++++++++++++++++++++ configs/nvim/lua/plugins/go.lua | 4 +++ configs/nvim/lua/plugins/multicursor.lua | 4 ++- configs/nvim/lua/plugins/snacks.lua | 7 +++++ configs/nvim/lua/plugins/sql.lua | 2 +- configs/nvim/lua/plugins/test.lua | 9 ++++++ 10 files changed, 94 insertions(+), 20 deletions(-) create mode 100644 configs/nvim/after/ftplugin/sql.vim create mode 100644 configs/nvim/lua/plugins/bruno.lua create mode 100644 configs/nvim/lua/plugins/go.lua create mode 100644 configs/nvim/lua/plugins/test.lua diff --git a/configs/ghostty/config b/configs/ghostty/config index dfb870f..2a5ae1d 100644 --- a/configs/ghostty/config +++ b/configs/ghostty/config @@ -63,3 +63,6 @@ keybind = super+/=unbind # Cmd+A: send Escape to Neovim keybind = super+a=esc: + +# Cmd+B: pass through to Neovim to close buffer +keybind = super+b=unbind diff --git a/configs/nvim/after/ftplugin/sql.vim b/configs/nvim/after/ftplugin/sql.vim new file mode 100644 index 0000000..75e4326 --- /dev/null +++ b/configs/nvim/after/ftplugin/sql.vim @@ -0,0 +1,2 @@ +" Disable nvim's built-in sqlcomplete omni completion (drill errors) +setlocal omnifunc= \ No newline at end of file diff --git a/configs/nvim/lazy-lock.json b/configs/nvim/lazy-lock.json index d54dff4..25e5382 100644 --- a/configs/nvim/lazy-lock.json +++ b/configs/nvim/lazy-lock.json @@ -1,40 +1,44 @@ { "LazyVim": { "branch": "main", "commit": "c10948c50b18fae7f256433afdef09e432410480" }, - "SchemaStore.nvim": { "branch": "main", "commit": "304d2286752923e3b0eb1ddcb3d4002a69b855ad" }, + "SchemaStore.nvim": { "branch": "main", "commit": "76c1a2357d4a9da49a90f922e251e5c32d74c99b" }, "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, + "bruno.nvim": { "branch": "main", "commit": "54bdebc62aa6ffc7906464a20d182c0a660be836" }, "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, - "catppuccin": { "branch": "main", "commit": "49a926655a2f5579e9c276470fc300baaa49e524" }, - "conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" }, + "catppuccin": { "branch": "main", "commit": "edefef779ab08ce1a4a404713e3012b0d202bd35" }, + "conform.nvim": { "branch": "master", "commit": "016802de402556da54c36bd7359b441266b01cdd" }, "crates.nvim": { "branch": "main", "commit": "694357861ec9ebf12475ddcdd04ea45a0923c32d" }, - "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, + "flash.nvim": { "branch": "main", "commit": "5f0f270fdc7c5b0c21d903ee85b9cb06f2ac636a" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, - "gitsigns.nvim": { "branch": "main", "commit": "25050e4ed39e628282831d4cbecb1850454ce915" }, - "grug-far.nvim": { "branch": "main", "commit": "c995bbacf8229dc096ec1c3d60f8531059c86c1b" }, + "gitsigns.nvim": { "branch": "main", "commit": "5be654f2232c10ddcad19c1607a67b6b4b78fc29" }, + "grug-far.nvim": { "branch": "main", "commit": "11595bf747edc270bce2069d1020502ad4ae56cf" }, "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" }, "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, - "mason-lspconfig.nvim": { "branch": "main", "commit": "21c5b3ebeaa0412e28096bb0701434c51c1fbf76" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "40276c4df7e6bdce6801d6c035c6227f9115a855" }, "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, - "mini.ai": { "branch": "main", "commit": "4511b3481707c1d021485475d34f2ed2a50bf47b" }, - "mini.icons": { "branch": "main", "commit": "d48ad47359218d2b019034f95f601b3861180885" }, - "mini.pairs": { "branch": "main", "commit": "30cf2f01c4aaa2033db67376b9924fa2442c05d6" }, + "mini.ai": { "branch": "main", "commit": "25248c6aa002391936a6200f12d1466015987133" }, + "mini.icons": { "branch": "main", "commit": "98faae31e9be1cc054ae63485e58ceb185efcad0" }, + "mini.pairs": { "branch": "main", "commit": "b1c5a726921b7a8c9321e9a7a208aa0571de5810" }, + "neotest": { "branch": "master", "commit": "27bf921498043f7ecd821d6db68d05de244bbd02" }, + "neotest-golang": { "branch": "main", "commit": "65b2be63c3de00e6f15c05388ebdc8d603dbd727" }, "noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" }, - "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, - "nvim-lint": { "branch": "master", "commit": "99cbc3ca8a76845fca50e496be7212bebf907dd3" }, - "nvim-lspconfig": { "branch": "master", "commit": "a683e0ddf0cf64c6cd689e18ffb480ade3c162b7" }, - "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, - "nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" }, + "nui.nvim": { "branch": "main", "commit": "10fc361835c856ba4233ef5ea135b919bf3dce97" }, + "nvim-lint": { "branch": "master", "commit": "3d55c8f67c6ae5c15e1042571e107c7a3d5c5f4e" }, + "nvim-lspconfig": { "branch": "master", "commit": "684cb45c2faa24ce463b4fe9aaf011bfe1e0fb26" }, + "nvim-nio": { "branch": "master", "commit": "edcc181a875301dd21840189aa2f2f9ad69fc172" }, + "nvim-treesitter": { "branch": "main", "commit": "857651fce37eba032ebe28f3a206283cdc65c45a" }, + "nvim-treesitter-textobjects": { "branch": "main", "commit": "898ee307df58f854d11cd7edd06472574d48014e" }, "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, - "render-markdown.nvim": { "branch": "main", "commit": "5adf0895310c1904e5abfaad40a2baad7fe44a07" }, - "rustaceanvim": { "branch": "main", "commit": "d2f5271924117588c82bec9086c9807960aafe1e" }, + "render-markdown.nvim": { "branch": "main", "commit": "4663eb3ecd538bd5062628fb6d95bbe6bdca78f6" }, + "rustaceanvim": { "branch": "main", "commit": "e2798fe326bb3efd2d15b9a652ed3872d358c98d" }, "snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" }, "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, "tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" }, "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, - "ts-comments.nvim": { "branch": "main", "commit": "123a9fb12e7229342f807ec9e6de478b1102b041" }, + "ts-comments.nvim": { "branch": "main", "commit": "a59d6092213447450191122c9346f309161504cb" }, "vim-dadbod": { "branch": "master", "commit": "6d1d41da4873a445c5605f2005ad2c68c99d8770" }, "vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" }, "vim-dadbod-ui": { "branch": "master", "commit": "afd07819d8efcefc3317205b855ad4e3513b0011" }, diff --git a/configs/nvim/lua/config/keymaps.lua b/configs/nvim/lua/config/keymaps.lua index b649bdf..4e29c4d 100644 --- a/configs/nvim/lua/config/keymaps.lua +++ b/configs/nvim/lua/config/keymaps.lua @@ -245,6 +245,8 @@ map("n", "", "v", { desc = "Select previous line" }) map("n", "", "v", { desc = "Select next line" }) map("v", "", "", { desc = "Extend selection up" }) map("v", "", "", { desc = "Extend selection down" }) +map("i", "", "v", { desc = "Select previous line" }) +map("i", "", "v", { desc = "Select next line" }) -- Shift+Left/Right: highlight/select text horizontally (like Zed) map("n", "", "v", { desc = "Select previous character" }) @@ -280,3 +282,9 @@ map("n", "ba", function() end vim.notify("Deleted all other buffers") end, { desc = "Delete All Other Buffers" }) + +-- Substitute word under cursor across file +map("n", "s", ":%s///g", { desc = "Substitute word under cursor" }) + +-- Close current buffer +map("n", "", "bdelete", { desc = "Close buffer" }) diff --git a/configs/nvim/lua/plugins/bruno.lua b/configs/nvim/lua/plugins/bruno.lua new file mode 100644 index 0000000..5d5aa55 --- /dev/null +++ b/configs/nvim/lua/plugins/bruno.lua @@ -0,0 +1,35 @@ +return { + { + "romek-codes/bruno.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + { + "folke/snacks.nvim", + opts = { picker = { enabled = true } }, + }, + }, + config = function(_, opts) + require("bruno").setup(opts) + + local map = LazyVim.safe_keymap_set + map("n", "rr", "BrunoRun", { desc = "Bruno: run request" }) + map("n", "rl", "BrunoReplay", { desc = "Bruno: re-run last request" }) + map("n", "re", "BrunoEnv", { desc = "Bruno: switch environment" }) + map("n", "rs", "BrunoSearch", { desc = "Bruno: search requests" }) + map("n", "rc", "BrunoCopy", { desc = "Bruno: copy as curl" }) + map("n", "ri", "BrunoInspect", { desc = "Bruno: inspect last request" }) + map("n", "rt", "BrunoToggleView", { desc = "Bruno: toggle output view" }) + end, + opts = { + collection_paths = { + { name = "web", path = vim.fn.expand("~") .. "/Code/go/web/requests" }, + }, + picker = "snacks", + }, + }, + { + "nvim-treesitter/nvim-treesitter", + optional = true, + opts = { ensure_installed = { "http", "lua" } }, + }, +} diff --git a/configs/nvim/lua/plugins/go.lua b/configs/nvim/lua/plugins/go.lua new file mode 100644 index 0000000..5f74f89 --- /dev/null +++ b/configs/nvim/lua/plugins/go.lua @@ -0,0 +1,4 @@ +return { + { import = "lazyvim.plugins.extras.test.core" }, + { import = "lazyvim.plugins.extras.lang.go" }, +} \ No newline at end of file diff --git a/configs/nvim/lua/plugins/multicursor.lua b/configs/nvim/lua/plugins/multicursor.lua index a6d66f0..aa4d1a5 100644 --- a/configs/nvim/lua/plugins/multicursor.lua +++ b/configs/nvim/lua/plugins/multicursor.lua @@ -4,8 +4,10 @@ return { branch = 'master', init = function() vim.g.VM_maps = { - ['Find Under'] = '', + ['Find Under'] = '', ['Find Subword Under'] = '', + ['Add Cursor Down'] = '', -- free up + ['Add Cursor Up'] = '', -- free up } end, }, diff --git a/configs/nvim/lua/plugins/snacks.lua b/configs/nvim/lua/plugins/snacks.lua index 3137c40..c5ee3a7 100644 --- a/configs/nvim/lua/plugins/snacks.lua +++ b/configs/nvim/lua/plugins/snacks.lua @@ -37,6 +37,13 @@ return { hidden = true, ignored = true, exclude = { "node_modules" }, + win = { + list = { + keys = { + ["f"] = "explorer_close_all", + }, + }, + }, jump = { close = true }, layout = { layout = { diff --git a/configs/nvim/lua/plugins/sql.lua b/configs/nvim/lua/plugins/sql.lua index 263e8ee..a1705fb 100644 --- a/configs/nvim/lua/plugins/sql.lua +++ b/configs/nvim/lua/plugins/sql.lua @@ -4,7 +4,7 @@ return { "neovim/nvim-lspconfig", opts = { servers = { - sqlls = {}, + sqlls = false, }, }, }, diff --git a/configs/nvim/lua/plugins/test.lua b/configs/nvim/lua/plugins/test.lua new file mode 100644 index 0000000..e6aa1a9 --- /dev/null +++ b/configs/nvim/lua/plugins/test.lua @@ -0,0 +1,9 @@ +return { + { + "nvim-neotest/neotest", + keys = { + { "tt", function() require("neotest").run.run() end, desc = "Run Nearest Test (Neotest)" }, + { "tf", function() require("neotest").run.run(vim.fn.expand("%")) end, desc = "Run File (Neotest)" }, + }, + }, +} \ No newline at end of file