From 30effbb4744156855966ed3cc032a54f01dfea9f Mon Sep 17 00:00:00 2001 From: Brad Anderson Date: Thu, 9 Jul 2026 21:15:47 -0700 Subject: [PATCH] Port neovim configs from vimscript to lua --- config/nvim/README.md | 133 +++++++++++++++++++ config/nvim/{init.vim => bkp-init.vim} | 0 config/nvim/ftplugin/python.lua | 2 + config/nvim/ftplugin/vimwiki.lua | 36 ++++++ config/nvim/init.lua | 33 +++++ config/nvim/lazy-lock.json | 45 +++++++ config/nvim/lua/config/autocmds.lua | 34 +++++ config/nvim/lua/config/keymaps.lua | 49 +++++++ config/nvim/lua/config/options.lua | 61 +++++++++ config/nvim/lua/plugins/ai.lua | 53 ++++++++ config/nvim/lua/plugins/completion.lua | 10 ++ config/nvim/lua/plugins/editor.lua | 136 ++++++++++++++++++++ config/nvim/lua/plugins/format.lua | 50 +++++++ config/nvim/lua/plugins/git.lua | 4 + config/nvim/lua/plugins/lsp.lua | 41 ++++++ config/nvim/lua/plugins/misc.lua | 38 ++++++ config/nvim/lua/plugins/rust.lua | 25 ++++ config/nvim/lua/plugins/treesitter.lua | 71 ++++++++++ config/nvim/lua/plugins/ui.lua | 91 +++++++++++++ config/nvim/lua/plugins/vimwiki.lua | 64 +++++++++ config/nvim/lua/util.lua | 28 ++++ config/profile | 2 +- config/tmux.conf | 84 +++++++++++- config/tmux/legacy.conf | 16 +++ config/tmux/{tmux_3.1c.conf => modern.conf} | 35 +---- config/tmux/tmux_1.9_down.conf | 37 ------ config/tmux/tmux_1.9_to_2.1.conf | 2 - config/tmux/tmux_2.1_to_2.5.conf | 48 ------- config/tmux/tmux_2.5_up.conf | 42 ------ config/tmux/tmux_shared.conf | 110 ---------------- config/tmux/verify_tmux_version.sh | 27 ---- 31 files changed, 1108 insertions(+), 299 deletions(-) create mode 100644 config/nvim/README.md rename config/nvim/{init.vim => bkp-init.vim} (100%) create mode 100644 config/nvim/ftplugin/python.lua create mode 100644 config/nvim/ftplugin/vimwiki.lua create mode 100644 config/nvim/init.lua create mode 100644 config/nvim/lazy-lock.json create mode 100644 config/nvim/lua/config/autocmds.lua create mode 100644 config/nvim/lua/config/keymaps.lua create mode 100644 config/nvim/lua/config/options.lua create mode 100644 config/nvim/lua/plugins/ai.lua create mode 100644 config/nvim/lua/plugins/completion.lua create mode 100644 config/nvim/lua/plugins/editor.lua create mode 100644 config/nvim/lua/plugins/format.lua create mode 100644 config/nvim/lua/plugins/git.lua create mode 100644 config/nvim/lua/plugins/lsp.lua create mode 100644 config/nvim/lua/plugins/misc.lua create mode 100644 config/nvim/lua/plugins/rust.lua create mode 100644 config/nvim/lua/plugins/treesitter.lua create mode 100644 config/nvim/lua/plugins/ui.lua create mode 100644 config/nvim/lua/plugins/vimwiki.lua create mode 100644 config/nvim/lua/util.lua create mode 100644 config/tmux/legacy.conf rename config/tmux/{tmux_3.1c.conf => modern.conf} (53%) delete mode 100644 config/tmux/tmux_1.9_down.conf delete mode 100644 config/tmux/tmux_1.9_to_2.1.conf delete mode 100644 config/tmux/tmux_2.1_to_2.5.conf delete mode 100644 config/tmux/tmux_2.5_up.conf delete mode 100644 config/tmux/tmux_shared.conf delete mode 100755 config/tmux/verify_tmux_version.sh diff --git a/config/nvim/README.md b/config/nvim/README.md new file mode 100644 index 0000000..7bbc479 --- /dev/null +++ b/config/nvim/README.md @@ -0,0 +1,133 @@ +# nvim config map + +Lua config managed by [lazy.nvim](https://github.com/folke/lazy.nvim). Leader is `,`, local leader is `\`. + +## Layout + +- `init.lua` — bootstraps lazy.nvim, loads `config/` then `plugins/` +- `lua/config/options.lua` — `vim.opt` settings +- `lua/config/keymaps.lua` — keymaps not tied to a specific plugin +- `lua/config/autocmds.lua` — autocommands +- `lua/plugins/*.lua` — one lazy.nvim spec file per topic (each file returns a plugin spec table; lazy.nvim loads every file in the directory automatically) +- `ftplugin/*.lua` — filetype-specific settings (Python, vimwiki) +- `lua/util.lua` — small helper functions (`ranger()`, `delete_trailing_ws()`) used from keymaps + +## Plugins + +### Navigation & editing (`plugins/editor.lua`) + +- **[neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim)** — file explorer sidebar + - `t` — toggle + - `cd` — cd to current file's directory and open +- **[telescope.nvim](https://github.com/nvim-telescope/telescope.nvim)** — fuzzy finder for files/buffers/grep/LSP symbols + - `.` — jump to symbol + - `;` — jump to buffer + - `be` — jump to buffer, sorted by most recently used + - `ag` — live grep +- **[flash.nvim](https://github.com/folke/flash.nvim)** — jump to any visible location via search-like labels + - `/` — jump + - `s` — search jump + - `s` — treesitter jump + - `f` — forward jump +- **[nvim-surround](https://github.com/kylechui/nvim-surround)** — add/change/delete surrounding pairs (quotes, tags, brackets) + - `ys`, `cs`, `ds` — plugin defaults +- **[nvim-autopairs](https://github.com/windwp/nvim-autopairs)** — auto-close brackets/quotes, automatic +- **[nvim-treesitter-context](https://github.com/nvim-treesitter/nvim-treesitter-context)** — sticky header showing enclosing function/class while scrolling, automatic +- **[mini.align](https://github.com/echasnovski/mini.nvim)** — align text on a character + - `ga=`, `ga:` +- **[mini.bufremove](https://github.com/echasnovski/mini.nvim)** — close a buffer without closing its window/split + - `c` +- **[vim-visual-multi](https://github.com/mg979/vim-visual-multi)** — multiple cursors + - `` — add cursor on word +- **[vim-tmux-navigator](https://github.com/christoomey/vim-tmux-navigator)** — move between nvim splits and tmux panes; also works from inside `:terminal` buffers (e.g. the Claude Code terminal) + - `` — move left/down/up/right +- **[emmet-vim](https://github.com/mattn/emmet-vim)** — Emmet expansion, HTML/CSS files only + +### UI (`plugins/ui.lua`) + +- **[gruvbox.nvim](https://github.com/ellisonleao/gruvbox.nvim)** — colorscheme +- **[lualine.nvim](https://github.com/nvim-lualine/lualine.nvim)** — statusline +- **[bufferline.nvim](https://github.com/akinsho/bufferline.nvim)** — buffer tabs along the top +- **[indent-blankline.nvim](https://github.com/lukas-reineke/indent-blankline.nvim)** — indent guides +- **[rainbow-delimiters.nvim](https://github.com/HiPhish/rainbow-delimiters.nvim)** — rainbow-colored matching brackets +- **[nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons)** — filetype icons (dependency for several plugins above) +- **[alpha-nvim](https://github.com/goolord/alpha-nvim)** — start screen shown on launch, see [Dashboard](#dashboard) below + - `o` — reopen + +### Completion & LSP + +- **[blink.cmp](https://github.com/Saghen/blink.cmp)** — completion engine (LSP, path, buffer sources) — `plugins/completion.lua` +- **[mason.nvim](https://github.com/mason-org/mason.nvim)** / **[mason-lspconfig.nvim](https://github.com/mason-org/mason-lspconfig.nvim)** — installs/manages LSP servers — `plugins/lsp.lua` +- **[nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)** — LSP client config for `ts_ls`, `svelte`, `html`, `cssls`, `basedpyright`, `ruff`, `bashls` — `plugins/lsp.lua` +- **[rustaceanvim](https://github.com/mrcjkb/rustaceanvim)** — Rust LSP setup (`rust_analyzer`), replaces the standard lspconfig flow for Rust — `plugins/rust.lua` + - `rr` — cargo run + +LSP buffer keymaps (set on `LspAttach`, see `plugins/lsp.lua`): + +- `K` — hover +- `gd` — definition +- `gy` — type definition +- `gi` — implementation +- `gr` — references +- `rn` — rename +- `ff` (visual) — format selection + +### Formatting & linting (`plugins/format.lua`) + +- **[conform.nvim](https://github.com/stevearc/conform.nvim)** — format-on-save (prettier, ruff_format, rustfmt, stylua per filetype) +- **[nvim-lint](https://github.com/mfussenegger/nvim-lint)** — async linting on save/insert-leave (eslint_d, shellcheck) + +### Treesitter (`plugins/treesitter.lua`) + +**[nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter)** — syntax highlighting, folding, and indentation for the installed parser list. Uses core Neovim's built-in `vim.treesitter.start()`/foldexpr rather than the old treesitter modules. + +### Git (`plugins/git.lua`) + +- **[gitsigns.nvim](https://github.com/lewis6991/gitsigns.nvim)** — git change signs in the gutter, hunk stage/preview/blame +- **[vim-fugitive](https://github.com/tpope/vim-fugitive)** — Git commands + - `:Git`, `:Gdiffsplit`, `:Gvdiffsplit`, `:Gread`, `:Gwrite`, `:Gclog` + +### AI (`plugins/ai.lua`) + +- **[snacks.nvim](https://github.com/folke/snacks.nvim)** — utility library (terminal provider etc.), dependency for claudecode.nvim +- **[claudecode.nvim](https://github.com/coder/claudecode.nvim)** — Claude Code terminal integration. Diffs render as a single unified (VS Code-style, red/green interleaved) buffer in one new split next to your active pane, and keyboard focus stays in the Claude terminal instead of jumping to the diff. + - `ac` — toggle + - `af` — focus + - `ab` — add current buffer + - `as` (visual) — send selection + - `aa` / `ad` — accept/deny diff + +### Wiki / notes (`plugins/vimwiki.lua`) + +- **[vimwiki](https://github.com/vimwiki/vimwiki)** — personal wiki across 4 notebooks (bradwiki, work, private, shared under `~/synced-notebooks/`) + - `m...` — wiki keymaps (`vim.g.vimwiki_map_prefix`) +- **[vim-zettel](https://github.com/michal-h21/vim-zettel)** — Zettelkasten-style note linking on top of vimwiki +- **[vim-table-mode](https://github.com/dhruvasagar/vim-table-mode)** — markdown/wiki table formatting + - `:TableModeToggle`, or `t...` prefix +- **[markdown-preview.nvim](https://github.com/iamcco/markdown-preview.nvim)** — live browser preview for markdown/vimwiki + - `v` — toggle preview + +### Misc (`plugins/misc.lua`) + +- **[aerial.nvim](https://github.com/stevearc/aerial.nvim)** — code outline/symbol sidebar + - `ct` — toggle +- **[undotree](https://github.com/jiaoshijie/undotree)** — visual undo history tree + - `u` — toggle +- **[persistence.nvim](https://github.com/folke/persistence.nvim)** — session save/restore per project + - restore from the dashboard's `s` button +- **[which-key.nvim](https://github.com/folke/which-key.nvim)** — keybinding cheatsheet, built from every mapping's `desc` + - `?` — browse all keybindings; press a key to drill into a group, `` to go back up, `` to close + +## Dashboard + +The start screen (shown on launch, reopen with `o`) is [alpha-nvim](https://github.com/goolord/alpha-nvim), configured in `plugins/ui.lua`. It shows a random `fortune | cowthink` header plus buttons: + +- `e` — new file +- `f` — find file (Telescope) +- `g` — live grep (Telescope) +- `s` — restore last session (persistence.nvim) +- `q` — quit + +## Buffer navigation + +`be` fuzzy-searches open buffers via Telescope, sorted by most recently used, excluding the current buffer. `;` does the same but in default Telescope order. Both are fuzzy-filterable as you type. diff --git a/config/nvim/init.vim b/config/nvim/bkp-init.vim similarity index 100% rename from config/nvim/init.vim rename to config/nvim/bkp-init.vim diff --git a/config/nvim/ftplugin/python.lua b/config/nvim/ftplugin/python.lua new file mode 100644 index 0000000..3e4e866 --- /dev/null +++ b/config/nvim/ftplugin/python.lua @@ -0,0 +1,2 @@ +vim.bo.textwidth = 79 +vim.bo.fileformat = "unix" diff --git a/config/nvim/ftplugin/vimwiki.lua b/config/nvim/ftplugin/vimwiki.lua new file mode 100644 index 0000000..1b3bc54 --- /dev/null +++ b/config/nvim/ftplugin/vimwiki.lua @@ -0,0 +1,36 @@ +local map = function(mode, lhs, rhs) + vim.keymap.set(mode, lhs, rhs, { buffer = true }) +end + +map("n", "mm", "VimwikiIndex") +map("n", "mw", "VimwikiUISelect") +map("n", "mhelp", ":verbose map ,m") +map("n", "mg", "VimwikiGoto") +map("n", "mf", "VimwikiUISelect1") +map("n", "m", "VimwikiUISelect2") +map("n", "mp", "VimwikiUISelect3") +map("n", "ms", "VimwikiUISelect4") + +map("n", "m-", "VimwikiSplitLink") +map("n", "m", "VimwikiVSplitLink") + +map("n", "mnt", "VimwikiNextTask") +map("n", "mnl", "VimwikiNextLink") +map("n", "mNl", "VimwikiPrevLink") + +map({ "n", "i", "v" }, "", "VimwikiIncreaseLvlSingleItem") +map({ "n", "i", "v" }, "", "VimwikiDecreaseLvlSingleItem") + +map("i", "", "VimwikiToggleListItemA") +map("n", "", "VimwikiRemoveSingleCB") +map("i", "", "VimwikiRemoveSingleCBa") +map("n", "mb", "VimwikiBackLinks") +map("n", "mqtoc", "VimwikiTOC") +map("n", "mqgtl", "VimwikiRebuildTagsVimwikiGenerateTagLinks") + +map("v", "mk", 'c[]Pea()"+P') +map("i", "mk", 'viWea') +map("n", "mk", 'ciw[]Pea()"+P') + +map("n", "mag", ":ZettelOpen") +map("n", "mat", ":ZettelOpentitle:") diff --git a/config/nvim/init.lua b/config/nvim/init.lua new file mode 100644 index 0000000..80b1fad --- /dev/null +++ b/config/nvim/init.lua @@ -0,0 +1,33 @@ +-- Leader keys MUST be set before lazy.setup() so lazy-loaded `keys = {...}` +-- specs resolve correctly when they register their keymaps. +vim.g.mapleader = "," +vim.g.maplocalleader = "\\" + +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not vim.uv.fs_stat(lazypath) then + local out = vim.fn.system({ + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", + lazypath, + }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, + { out, "WarningMsg" }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end +vim.opt.rtp:prepend(lazypath) + +require("config.options") +require("config.keymaps") +require("config.autocmds") + +require("lazy").setup("plugins", { + change_detection = { notify = false }, +}) diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json new file mode 100644 index 0000000..af25d01 --- /dev/null +++ b/config/nvim/lazy-lock.json @@ -0,0 +1,45 @@ +{ + "aerial.nvim": { "branch": "master", "commit": "28fe6e822ae344544c379d60fcb13c9519a1f08a" }, + "alpha-nvim": { "branch": "main", "commit": "6c6a89d5b068b5251c8bdf0dd57bb921bcfeeb09" }, + "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, + "blink.lib": { "branch": "main", "commit": "5876dd95deeb70aadbe9f1c0b7117a135061cdac" }, + "bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" }, + "claudecode.nvim": { "branch": "main", "commit": "2390c6e45c4789072c293ac69de051d169668b29" }, + "conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" }, + "emmet-vim": { "branch": "master", "commit": "92ef2f74f4093edc99db5e9e4cf7e40116a85bd6" }, + "flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" }, + "gitsigns.nvim": { "branch": "main", "commit": "eb60cc7b94c46005237fd34170d76f3a089a90aa" }, + "gruvbox.nvim": { "branch": "main", "commit": "154eb5ff5b96d0641307113fa385eaf0d36d9796" }, + "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" }, + "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "47059d71b42d74b0a1e9f61c1d99d301039c3b5b" }, + "mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" }, + "mini.align": { "branch": "main", "commit": "8cebe89d82f20e6d21b27346bcde4b4b6244a9f1" }, + "mini.bufremove": { "branch": "main", "commit": "4cfbb201b2760da79ca6e1a00e9f67cbc99cbb8f" }, + "neo-tree.nvim": { "branch": "v3.x", "commit": "ebd66767191714e008ce73b769518a763ff31bdc" }, + "nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" }, + "nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" }, + "nvim-lint": { "branch": "master", "commit": "a219b2c9e5b4765e5c845aba119dad55806fcaf1" }, + "nvim-lspconfig": { "branch": "master", "commit": "d224a1920728ba129880efc700d4a0180ac4ecbb" }, + "nvim-surround": { "branch": "main", "commit": "8b47db616ef658b8fc27e61db2896aa2f40134de" }, + "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, + "nvim-treesitter-context": { "branch": "master", "commit": "b311b30818951d01f7b4bf650521b868b3fece16" }, + "nvim-web-devicons": { "branch": "master", "commit": "dad71387de386a946b123079d0e53f23028f3abd" }, + "persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" }, + "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, + "rainbow-delimiters.nvim": { "branch": "master", "commit": "a798325b7f36acc62741d1029930a7b96d4dd4bf" }, + "rustaceanvim": { "branch": "main", "commit": "88575b98bb9937fb9983ddec5e532b67e75ce677" }, + "snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" }, + "telescope.nvim": { "branch": "master", "commit": "427b576c16792edad01a92b89721d923c19ad60f" }, + "undotree": { "branch": "main", "commit": "02b69aed427b848c4dca483fc5e9524b6019c296" }, + "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, + "vim-table-mode": { "branch": "master", "commit": "bb025308a45c67c7c8f0763ba37bc2ee3f534df0" }, + "vim-tmux-navigator": { "branch": "master", "commit": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432" }, + "vim-visual-multi": { "branch": "master", "commit": "a6975e7c1ee157615bbc80fc25e4392f71c344d4" }, + "vim-zettel": { "branch": "master", "commit": "554d16bf65b04ae86b92db08a44b4fbcbc31023f" }, + "vimwiki": { "branch": "dev", "commit": "a54a3002e229c4b43d69ced170ff77663a5b2c40" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/config/nvim/lua/config/autocmds.lua b/config/nvim/lua/config/autocmds.lua new file mode 100644 index 0000000..5dc20dc --- /dev/null +++ b/config/nvim/lua/config/autocmds.lua @@ -0,0 +1,34 @@ +-- autoread (options.lua) only reloads a buffer once Vim checks the file's +-- timestamp, which by default only happens on a handful of internal +-- triggers. Force that check on focus/buffer-switch/idle so external edits +-- (e.g. from claudecode.nvim) show up immediately instead of surfacing the +-- stale-buffer prompt later. +vim.api.nvim_create_autocmd({ "FocusGained", "BufEnter", "CursorHold", "CursorHoldI" }, { + group = vim.api.nvim_create_augroup("CheckTimeOnFocus", { clear = true }), + callback = function() + if vim.fn.getcmdwintype() == "" then + vim.cmd("checktime") + end + end, +}) + +local augroup = vim.api.nvim_create_augroup("EnterBuffer", { clear = true }) + +vim.api.nvim_create_autocmd({ "BufNewFile", "BufReadPre", "FileReadPre", "BufEnter" }, { + group = augroup, + pattern = "Makefile", + callback = function() + vim.bo.expandtab = false + vim.bo.softtabstop = 0 + vim.bo.shiftwidth = 8 + end, +}) + +vim.api.nvim_create_autocmd({ "BufNewFile", "BufReadPre", "FileReadPre", "BufEnter" }, { + group = augroup, + pattern = { "*.asm", "*.S" }, + callback = function() + vim.bo.softtabstop = 8 + vim.bo.shiftwidth = 8 + end, +}) diff --git a/config/nvim/lua/config/keymaps.lua b/config/nvim/lua/config/keymaps.lua new file mode 100644 index 0000000..886bfc9 --- /dev/null +++ b/config/nvim/lua/config/keymaps.lua @@ -0,0 +1,49 @@ +local map = vim.keymap.set + +-- Insert/command-mode escape via ,, +map("i", ",,", "") +map("c", ",,", "") + +-- Move by display line, not physical line +map("n", "j", "gj") +map("n", "k", "gk") + +-- Clear search highlight +map("n", "", ":nohl") + +-- Hex mode +map("n", "\\he", ":%!xxd") +map("n", "\\hd", ":%!xxd -r") + +-- Toggle whitespace display +map("n", "lw", ":set list!") +-- List registers / marks +map("n", "lr", ":reg") +map("n", "lm", ":marks") + +-- Prev/next buffer +map("n", "q", ":bp") +map("n", "w", ":bn") + +-- System clipboard +map({ "n", "v" }, "y", '"+y') +map({ "n", "v" }, "Y", '"+Y') +map({ "n", "v" }, "p", '"+p') +map({ "n", "v" }, "P", '"+P') +map({ "n", "v" }, "x", '"+x') +map("n", "dd", '"+dd') + +-- Make split +map("n", "-", ":sp") +map("n", "", ":vsp") + +-- Open init.lua +map("n", "v", ":e $MYVIMRC") + +-- Low-light / daylight mode +map("n", "ll", ":set background=dark") +map("n", "LL", ":set background=light") + +-- Ranger / trailing whitespace utilities +map("n", "ra", function() require("util").ranger() end) +map("n", "rw", function() require("util").delete_trailing_ws() end) diff --git a/config/nvim/lua/config/options.lua b/config/nvim/lua/config/options.lua new file mode 100644 index 0000000..82a1fe1 --- /dev/null +++ b/config/nvim/lua/config/options.lua @@ -0,0 +1,61 @@ +local opt = vim.opt + +-- Completion / buffers +opt.omnifunc = "syntaxcomplete#Complete" +opt.hidden = true +opt.autoread = true + +-- No swap/backup files +opt.swapfile = false +opt.backup = false + +opt.number = true + +-- matchit is built into Neovim's runtime already; no `runtime macros/matchit.vim` needed + +opt.encoding = "utf-8" +opt.lazyredraw = true +opt.backspace = { "indent", "eol", "start" } +opt.history = 700 +opt.incsearch = true +opt.ignorecase = true +opt.smartcase = true +opt.scrolloff = 15 + +opt.wildmode = { "longest", "list", "full" } +opt.wildmenu = true +opt.wildcharm = vim.api.nvim_replace_termcodes("", true, true, true):byte() + +opt.mouse = "a" + +-- Tabs +opt.tabstop = 4 +opt.softtabstop = 4 +opt.expandtab = true +opt.shiftwidth = 4 + +opt.wrap = true +opt.linebreak = true +opt.list = false + +opt.ruler = true +opt.showmatch = true + +opt.viewoptions:remove("options") + +opt.shortmess:append("I") + +opt.laststatus = 2 +opt.showmode = false + +opt.termguicolors = true +vim.g.enable_bold_font = 1 + +-- Have vrm extend background color to full terminal screen +vim.cmd("set t_ut=") + +opt.splitbelow = true +opt.splitright = true + +opt.updatetime = 300 +opt.shortmess:append("c") diff --git a/config/nvim/lua/plugins/ai.lua b/config/nvim/lua/plugins/ai.lua new file mode 100644 index 0000000..ac1e1ba --- /dev/null +++ b/config/nvim/lua/plugins/ai.lua @@ -0,0 +1,53 @@ +return { + { "folke/snacks.nvim", lazy = false }, + + { + "coder/claudecode.nvim", + dependencies = { "folke/snacks.nvim" }, + opts = { + terminal = { + provider = "snacks", + split_side = "right", + split_width_percentage = 0.30, + }, + diff_opts = { + keep_terminal_focus = true, + -- Unified (single-buffer, VS Code-style) diff instead of side-by-side + -- splits: it only ever opens one new window, so it can't add a second + -- split and squish the rest of the layout the way the side-by-side + -- diff sometimes did. + layout = "unified", + }, + }, + config = function(_, opts) + require("claudecode").setup(opts) + + -- claudecode picks a window for the diff by scanning all windows for the + -- first non-sidebar/non-terminal one, not the one you're actually + -- focused on, so the diff could land away from your active pane. Prefer + -- the current window when it's a normal editing window. + local diff = require("claudecode.diff") + local default_find_main_editor_window = diff._find_main_editor_window + diff._find_main_editor_window = function() + local win = vim.api.nvim_get_current_win() + local buf = vim.api.nvim_win_get_buf(win) + local buftype = vim.api.nvim_buf_get_option(buf, "buftype") + local win_config = vim.api.nvim_win_get_config(win) + local is_floating = win_config.relative and win_config.relative ~= "" + local is_diff_win = vim.api.nvim_win_get_option(win, "diff") + if not is_floating and not is_diff_win and buftype ~= "terminal" and buftype ~= "prompt" then + return win + end + return default_find_main_editor_window() + end + end, + keys = { + { "ac", "ClaudeCode", desc = "Toggle Claude Code" }, + { "af", "ClaudeCodeFocus", desc = "Focus Claude Code" }, + { "ab", "ClaudeCodeAdd %", desc = "Add buffer to Claude Code" }, + { "as", "ClaudeCodeSend", mode = "v", desc = "Send selection to Claude Code" }, + { "aa", "ClaudeCodeDiffAccept", desc = "Accept Claude Code diff" }, + { "ad", "ClaudeCodeDiffDeny", desc = "Deny Claude Code diff" }, + }, + }, +} diff --git a/config/nvim/lua/plugins/completion.lua b/config/nvim/lua/plugins/completion.lua new file mode 100644 index 0000000..b287dbb --- /dev/null +++ b/config/nvim/lua/plugins/completion.lua @@ -0,0 +1,10 @@ +return { + "saghen/blink.cmp", + version = "*", + opts = { + keymap = { preset = "default" }, + appearance = { nerd_font_variant = "mono" }, + completion = { documentation = { auto_show = true } }, + sources = { default = { "lsp", "path", "buffer" } }, + }, +} diff --git a/config/nvim/lua/plugins/editor.lua b/config/nvim/lua/plugins/editor.lua new file mode 100644 index 0000000..53958e5 --- /dev/null +++ b/config/nvim/lua/plugins/editor.lua @@ -0,0 +1,136 @@ +return { + { + "nvim-neo-tree/neo-tree.nvim", + branch = "v3.x", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-tree/nvim-web-devicons", + "MunifTanjim/nui.nvim", + }, + keys = { + { "t", ":Neotree toggle", desc = "Toggle file explorer" }, + { + "cd", + function() + vim.cmd("cd " .. vim.fn.fnameescape(vim.fn.expand("%:p:h"))) + vim.cmd("pwd") + vim.cmd("Neotree dir=" .. vim.fn.fnameescape(vim.fn.getcwd())) + end, + desc = "cd to current file's directory and open explorer", + }, + }, + opts = {}, + }, + + { + "nvim-telescope/telescope.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + { "nvim-telescope/telescope-fzf-native.nvim", build = "make" }, + }, + cmd = "Telescope", + keys = { + { ".", "Telescope lsp_document_symbols", desc = "Jump to symbol" }, + { ";", "Telescope buffers", desc = "Jump to buffer" }, + { + "be", + "Telescope buffers sort_mru=true ignore_current_buffer=true", + desc = "Jump to buffer (MRU)", + }, + { "ag", "Telescope live_grep", desc = "Grep" }, + }, + config = function() + local telescope = require("telescope") + telescope.setup({}) + telescope.load_extension("fzf") + end, + }, + + { + "folke/flash.nvim", + event = "VeryLazy", + opts = {}, + keys = { + { "/", function() require("flash").jump() end, mode = { "n", "x", "o" }, desc = "Flash jump" }, + { "s", function() require("flash").jump({ search = { mode = "search" } }) end, mode = { "n", "x", "o" }, desc = "Flash search jump" }, + { "s", function() require("flash").treesitter() end, mode = { "n", "x", "o" }, desc = "Flash treesitter" }, + { "f", function() require("flash").jump({ search = { forward = true, wrap = false } }) end, mode = { "n", "x", "o" }, desc = "Flash forward" }, + }, + }, + + { "kylechui/nvim-surround", event = { "BufReadPost", "BufNewFile" }, opts = {} }, + { "windwp/nvim-autopairs", event = "InsertEnter", opts = {} }, + + { + "nvim-treesitter/nvim-treesitter-context", + event = { "BufReadPost", "BufNewFile" }, + dependencies = { "nvim-treesitter/nvim-treesitter" }, + opts = {}, + }, + + { + "echasnovski/mini.align", + version = "*", + keys = { + { "ga=", mode = { "n", "x" }, desc = "Align on =" }, + { "ga:", mode = { "n", "x" }, desc = "Align on :" }, + }, + config = function() + require("mini.align").setup({ + mappings = { start = "ga", start_with_preview = "" }, + }) + end, + }, + + { "echasnovski/mini.bufremove", version = "*", keys = { + { "c", function() require("mini.bufremove").delete(0, false) end, desc = "Close buffer" }, + } }, + + { + "mg979/vim-visual-multi", + branch = "master", + keys = { "" }, + init = function() + vim.g.VM_maps = { + ["Find Under"] = "", + ["Find Subword Under"] = "", + } + end, + }, + + { + "christoomey/vim-tmux-navigator", + lazy = false, + -- Plugin's own default mappings rely on a Vim-only terminal escape + -- that Neovim doesn't support, so :terminal buffers (e.g. claudecode.nvim) + -- leak the raw keystrokes to the embedded process. Disable them and + -- define our own, using Neovim's actual terminal-mode escape. + init = function() + vim.g.tmux_navigator_no_mappings = 1 + end, + keys = { + { "", "TmuxNavigateLeft" }, + { "", "TmuxNavigateDown" }, + { "", "TmuxNavigateUp" }, + { "", "TmuxNavigateRight" }, + { "", "TmuxNavigateLeft", mode = "t" }, + { "", "TmuxNavigateDown", mode = "t" }, + { "", "TmuxNavigateUp", mode = "t" }, + { "", "TmuxNavigateRight", mode = "t" }, + }, + }, + + { + "mattn/emmet-vim", + ft = { "html", "css" }, + init = function() + vim.g.user_emmet_install_global = 0 + end, + config = function() + vim.api.nvim_create_autocmd("FileType", { + pattern = { "html", "css" }, + callback = function() vim.fn["emmet#install"]() end, + }) + end, + }, +} diff --git a/config/nvim/lua/plugins/format.lua b/config/nvim/lua/plugins/format.lua new file mode 100644 index 0000000..4a9a888 --- /dev/null +++ b/config/nvim/lua/plugins/format.lua @@ -0,0 +1,50 @@ +return { + { + "stevearc/conform.nvim", + event = { "BufWritePre" }, + cmd = { "ConformInfo" }, + opts = { + formatters_by_ft = { + css = { "prettier" }, + svelte = { "prettier" }, + pcss = { "prettier" }, + html = { "prettier" }, + typescript = { "prettier" }, + typescriptreact = { "prettier" }, + javascript = { "prettier" }, + javascriptreact = { "prettier" }, + json = { "prettier" }, + yaml = { "prettier" }, + markdown = { "prettier" }, + python = { "ruff_format" }, + rust = { "rustfmt" }, + lua = { "stylua" }, + }, + format_on_save = { + lsp_format = "fallback", + timeout_ms = 2000, + }, + }, + }, + + { + "mfussenegger/nvim-lint", + event = { "BufWritePost", "BufReadPost", "InsertLeave" }, + config = function() + require("lint").linters_by_ft = { + javascript = { "eslint_d" }, + typescript = { "eslint_d" }, + javascriptreact = { "eslint_d" }, + typescriptreact = { "eslint_d" }, + svelte = { "eslint_d" }, + sh = { "shellcheck" }, + } + + vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost", "InsertLeave" }, { + callback = function() + require("lint").try_lint() + end, + }) + end, + }, +} diff --git a/config/nvim/lua/plugins/git.lua b/config/nvim/lua/plugins/git.lua new file mode 100644 index 0000000..16a2735 --- /dev/null +++ b/config/nvim/lua/plugins/git.lua @@ -0,0 +1,4 @@ +return { + { "lewis6991/gitsigns.nvim", event = { "BufReadPre", "BufNewFile" }, opts = {} }, + { "tpope/vim-fugitive", cmd = { "Git", "Gdiffsplit", "Gvdiffsplit", "Gread", "Gwrite", "Gclog" } }, +} diff --git a/config/nvim/lua/plugins/lsp.lua b/config/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..4d08f1b --- /dev/null +++ b/config/nvim/lua/plugins/lsp.lua @@ -0,0 +1,41 @@ +local servers = { "ts_ls", "svelte", "html", "cssls", "basedpyright", "ruff", "bashls" } + +return { + { + "mason-org/mason.nvim", + opts = {}, + }, + { + "mason-org/mason-lspconfig.nvim", + dependencies = { "mason-org/mason.nvim" }, + opts = { + ensure_installed = servers, + }, + }, + { + "neovim/nvim-lspconfig", + dependencies = { "mason-org/mason-lspconfig.nvim", "saghen/blink.cmp", "saghen/blink.lib" }, + config = function() + local capabilities = require("blink.cmp").get_lsp_capabilities() + + vim.api.nvim_create_autocmd("LspAttach", { + group = vim.api.nvim_create_augroup("LspKeymaps", { clear = true }), + callback = function(args) + local opts = { buffer = args.buf } + vim.keymap.set("n", "K", vim.lsp.buf.hover, opts) + vim.keymap.set("n", "gd", vim.lsp.buf.definition, opts) + vim.keymap.set("n", "gy", vim.lsp.buf.type_definition, opts) + vim.keymap.set("n", "gi", vim.lsp.buf.implementation, opts) + vim.keymap.set("n", "gr", vim.lsp.buf.references, opts) + vim.keymap.set("n", "rn", vim.lsp.buf.rename, opts) + vim.keymap.set("v", "ff", function() vim.lsp.buf.format({ async = true }) end, opts) + end, + }) + + for _, server in ipairs(servers) do + vim.lsp.config(server, { capabilities = capabilities }) + vim.lsp.enable(server) + end + end, + }, +} diff --git a/config/nvim/lua/plugins/misc.lua b/config/nvim/lua/plugins/misc.lua new file mode 100644 index 0000000..b8bd7a1 --- /dev/null +++ b/config/nvim/lua/plugins/misc.lua @@ -0,0 +1,38 @@ +return { + { + "stevearc/aerial.nvim", + dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" }, + keys = { + { "ct", "AerialToggle", desc = "Toggle symbol outline" }, + }, + opts = {}, + }, + + { + "jiaoshijie/undotree", + dependencies = { "nvim-lua/plenary.nvim" }, + keys = { + { "u", function() require("undotree").toggle() end, desc = "Toggle undo tree" }, + }, + opts = {}, + }, + + { + "folke/persistence.nvim", + event = "BufReadPre", + opts = {}, + }, + + { + "folke/which-key.nvim", + event = "VeryLazy", + opts = {}, + keys = { + { + "?", + function() require("which-key").show({ global = true }) end, + desc = "Keybinding cheatsheet", + }, + }, + }, +} diff --git a/config/nvim/lua/plugins/rust.lua b/config/nvim/lua/plugins/rust.lua new file mode 100644 index 0000000..5a443a7 --- /dev/null +++ b/config/nvim/lua/plugins/rust.lua @@ -0,0 +1,25 @@ +return { + { + "mrcjkb/rustaceanvim", + version = "^6", + lazy = false, + init = function() + vim.g.rustaceanvim = { + tools = {}, + server = { + on_attach = function(_, bufnr) + vim.keymap.set("n", "rr", function() + vim.cmd.RustLsp("run") + end, { buffer = bufnr }) + end, + }, + } + end, + }, + { + "mason-org/mason-lspconfig.nvim", + opts = { + automatic_enable = { exclude = { "rust_analyzer" } }, + }, + }, +} diff --git a/config/nvim/lua/plugins/treesitter.lua b/config/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..a330ce6 --- /dev/null +++ b/config/nvim/lua/plugins/treesitter.lua @@ -0,0 +1,71 @@ +return { + "nvim-treesitter/nvim-treesitter", + lazy = false, + build = ":TSUpdate", + config = function() + local parsers = { + "javascript", + "typescript", + "tsx", + "svelte", + "html", + "css", + "scss", + "json", + "yaml", + "python", + "rust", + "bash", + "lua", + "vim", + "vimdoc", + "query", + "markdown", + "markdown_inline", + "regex", + } + + -- Install parsers + require("nvim-treesitter").install(parsers) + + -- Enable treesitter highlighting, folding, and indentation for + -- filetypes with an installed parser. Note some filetype names differ + -- from their parser names (e.g. "bash" parser -> "sh" filetype). + vim.api.nvim_create_autocmd("FileType", { + pattern = { + "javascript", + "typescript", + "typescriptreact", + "javascriptreact", + "svelte", + "html", + "css", + "scss", + "json", + "yaml", + "python", + "rust", + "sh", + "lua", + "vim", + "help", + "query", + "markdown", + }, + callback = function() + -- Highlighting, provided by Neovim + vim.treesitter.start() + -- Folding, provided by Neovim + vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()" + vim.wo.foldmethod = "expr" + -- Indentation, provided by nvim-treesitter + vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" + end, + }) + + -- General fold display settings (not treesitter-specific) + vim.opt.foldlevel = 2 + vim.opt.foldlevelstart = 2 + vim.opt.foldcolumn = "5" + end, +} diff --git a/config/nvim/lua/plugins/ui.lua b/config/nvim/lua/plugins/ui.lua new file mode 100644 index 0000000..8deae03 --- /dev/null +++ b/config/nvim/lua/plugins/ui.lua @@ -0,0 +1,91 @@ +return { + { + "ellisonleao/gruvbox.nvim", + priority = 1000, + opts = { + italic = { strings = true, comments = true, operators = false, folds = true }, + invert_selection = true, + invert_signs = false, + }, + config = function(_, opts) + require("gruvbox").setup(opts) + vim.o.background = "dark" + local ok = pcall(vim.cmd.colorscheme, "gruvbox") + if not ok then + vim.cmd.colorscheme("desert") + end + end, + }, + + { + "nvim-lualine/lualine.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + event = "VeryLazy", + opts = { + options = { theme = "gruvbox" }, + }, + }, + + { + "akinsho/bufferline.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + event = "VeryLazy", + opts = {}, + }, + + { + "lukas-reineke/indent-blankline.nvim", + main = "ibl", + event = { "BufReadPost", "BufNewFile" }, + opts = {}, + }, + + { + "HiPhish/rainbow-delimiters.nvim", + event = { "BufReadPost", "BufNewFile" }, + }, + + { "nvim-tree/nvim-web-devicons", opts = {} }, + + { + "goolord/alpha-nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + event = "VimEnter", + config = function() + local alpha = require("alpha") + local dashboard = require("alpha.themes.dashboard") + + local function fortune_header() + local cows = vim.fn.systemlist("cowsay -l") + local cow = "default" + if #cows > 1 then + cow = cows[math.random(2, #cows)] + end + local moods = { "b", "d", "g", "p", "s", "t", "w", "y" } + local mood = moods[math.random(#moods)] + local cmd = string.format( + "fortune -a -s | fmt -80 -s | cowthink -%s -f %s -n", + mood, + cow + ) + local ok, lines = pcall(vim.fn.systemlist, cmd) + if not ok or #lines == 0 then + return { "Welcome to Neovim" } + end + return lines + end + + dashboard.section.header.val = fortune_header() + dashboard.section.buttons.val = { + dashboard.button("e", " New file", ":enew"), + dashboard.button("f", " Find file", ":Telescope find_files"), + dashboard.button("g", " Live grep", ":Telescope live_grep"), + dashboard.button("s", " Restore session", ":lua require('persistence').load()"), + dashboard.button("q", " Quit", ":qa"), + } + alpha.setup(dashboard.opts) + + vim.keymap.set("n", "o", ":Alpha") + end, + }, +} diff --git a/config/nvim/lua/plugins/vimwiki.lua b/config/nvim/lua/plugins/vimwiki.lua new file mode 100644 index 0000000..88bae72 --- /dev/null +++ b/config/nvim/lua/plugins/vimwiki.lua @@ -0,0 +1,64 @@ +vim.g.vimwiki_list = { + { + path = "~/synced-notebooks/bradwiki/", + syntax = "markdown", + ext = ".md", + diary_rel_path = "daily_notes/", + diary_index = "index", + diary_header = "Daily Notes", + auto_tags = 1, + auto_diary_index = 1, + auto_generate_links = 1, + auto_generate_tags = 1, + }, + { + path = "~/synced-notebooks/work_notebook/", + syntax = "markdown", + ext = ".md", + diary_rel_path = "daily_notes/", + diary_index = "index", + diary_header = "Daily Notes", + auto_tags = 1, + auto_diary_index = 1, + auto_generate_links = 1, + auto_generate_tags = 1, + }, + { path = "~/synced-notebooks/privatewiki/", syntax = "markdown", ext = ".md" }, + { path = "~/synced-notebooks/sharedwiki/", syntax = "markdown", ext = ".md" }, +} +vim.g.vimwiki_map_prefix = "m" +vim.g.vimwiki_folding = "list" +vim.g.markdown_folding = 1 + +vim.g.zettel_options = { + {}, + { + front_matter = { { "tags", "" }, { "type", "note" } }, + template = "~/work_notebook/templates/daily_note.tpl", + }, +} + +vim.g.table_mode_map_prefix = "t" + +vim.api.nvim_create_autocmd("FileType", { + group = vim.api.nvim_create_augroup("VimwikiFiletype", { clear = true }), + pattern = "vimwiki", + callback = function() + vim.opt_local.breakindent = true + vim.opt_local.breakindentopt = "shift:2" + end, +}) + +return { + { "vimwiki/vimwiki", lazy = false }, + { "michal-h21/vim-zettel", dependencies = { "vimwiki/vimwiki" }, lazy = false }, + { "dhruvasagar/vim-table-mode", cmd = "TableModeToggle" }, + { + "iamcco/markdown-preview.nvim", + build = function() vim.fn["mkdp#util#install"]() end, + ft = { "markdown", "vimwiki" }, + keys = { + { "v", "MarkdownPreviewToggle", ft = { "markdown", "vimwiki" }, desc = "Toggle markdown preview" }, + }, + }, +} diff --git a/config/nvim/lua/util.lua b/config/nvim/lua/util.lua new file mode 100644 index 0000000..46695f3 --- /dev/null +++ b/config/nvim/lua/util.lua @@ -0,0 +1,28 @@ +local M = {} + +-- Open ranger from within nvim; if it writes a chosen path to its return +-- file, open that file. Mirrors the old vimscript Ranger() function. +function M.ranger() + if vim.fn.executable("ranger") == 0 then + vim.notify("ranger is not installed", vim.log.levels.WARN) + return + end + local tmpfile = vim.fn.system("mktemp -u"):gsub("\n", "") + vim.cmd(("silent !RANGER_RETURN_FILE=%s ranger"):format(tmpfile)) + if vim.fn.filereadable(tmpfile) == 1 then + local filetoedit = vim.fn.system("cat " .. tmpfile) + vim.cmd("edit " .. filetoedit) + vim.fn.delete(tmpfile) + end + vim.cmd("redraw!") +end + +-- Delete trailing whitespace on the current buffer, preserving cursor +-- position. Mirrors the old vimscript DeleteTrailingWS() function. +function M.delete_trailing_ws() + local view = vim.fn.winsaveview() + vim.cmd([[silent! %s/\s\+$//ge]]) + vim.fn.winrestview(view) +end + +return M diff --git a/config/profile b/config/profile index 342c22b..1f3e23c 100644 --- a/config/profile +++ b/config/profile @@ -97,7 +97,7 @@ export PATH="$PYENV_ROOT/bin:$PATH" # Make sure ssh-agent is available if [ -n "$LOAD_SSH_KEYS" ] && [ "$LOAD_SSH_KEYS" -eq 1 ]; then - if program_installed ssh-add && [ ! -z "$SSH_AUTH_SOCK" ] && [ -d "$SSH_AUTH_SOCK" ] > /dev/null 2&>1 ; then + if program_installed ssh-add && [ ! -z "$SSH_AUTH_SOCK" ] && [ -d "$SSH_AUTH_SOCK" ] > /dev/null 2>&1 ; then # Add SSH keys to agent if not already added ## Find existing keys, supporting one layer of folder organization public_keys=($(find "$HOME/.ssh/" -maxdepth 2 -name "*.pub")) diff --git a/config/tmux.conf b/config/tmux.conf index 84e7b12..0cb0a49 100644 --- a/config/tmux.conf +++ b/config/tmux.conf @@ -1,2 +1,82 @@ -# run-shell "~/.tmux/verify_tmux_version.sh" -source-file "~/.tmux/tmux_3.1c.conf" +# ---------------------------------------------------------------------------- +# Prefix +# ---------------------------------------------------------------------------- +set -g prefix C-a +unbind C-b +bind C-a send-prefix +bind Tab last-window + +# ---------------------------------------------------------------------------- +# General behavior +# ---------------------------------------------------------------------------- +set-option -g set-titles on +set -g default-terminal "screen-256color" +set -g history-limit 10000 +set -sg escape-time 1 +set-option -g base-index 1 +setw -g pane-base-index 1 +setw -g aggressive-resize on + +# ---------------------------------------------------------------------------- +# Windows and panes +# ---------------------------------------------------------------------------- +bind T swap-window -t 1 +bind | split-window -h -c "#{pane_current_path}" +bind - split-window -v -c "#{pane_current_path}" +bind c new-window -c "#{pane_current_path}" + +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R + +# Smart pane switching with awareness of vim splits +is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?)(diff)?$"' +bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L" +bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D" +bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U" +bind -n C-l if-shell "$is_vim" "send-keys C-l" "select-pane -R" +bind -n 'C-\' if-shell "$is_vim" "send-keys 'C-\\'" "select-pane -l" + +bind -r C-h select-window -t :- +bind -r C-l select-window -t :+ + +bind a setw synchronize-panes + +# ---------------------------------------------------------------------------- +# Copy mode and mouse +# ---------------------------------------------------------------------------- +setw -g mode-keys vi +set-option -g -q mouse on + +bind y run 'tmux save-buffer - | reattach-to-user-namespace pbcopy' +bind C-y run 'tmux save-buffer - | reattach-to-user-namespace pbcopy' + +# tmux renamed the copy-mode key table (vi-copy -> copy-mode-vi) and changed +# bind-key's table flag (-t -> -T) in 2.4. Source the file matching the +# running tmux so old tmux never parses syntax it doesn't understand. +if-shell "tmux -V | awk '{print $2}' | awk -F. '{if ($1*1000+$2 < 2004) exit 0; else exit 1}'" 'source-file ~/.tmux/legacy.conf' 'source-file ~/.tmux/modern.conf' + +# ---------------------------------------------------------------------------- +# Misc bindings +# ---------------------------------------------------------------------------- +bind-key C run-shell "cal $(date +%Y)" +bind r source-file ~/.tmux.conf \; display "Reloaded config" + +# ---------------------------------------------------------------------------- +# Powerline (guarded so machines without it don't error on load) +# ---------------------------------------------------------------------------- +run-shell "command -v powerline-daemon >/dev/null 2>&1 && powerline-daemon -q; true" +run-shell "command -v powerline-config >/dev/null 2>&1 && powerline-config tmux setup; true" + +# ---------------------------------------------------------------------------- +# Plugins (TPM) +# ---------------------------------------------------------------------------- +set -g @plugin 'tmux-plugins/tpm' +set -g @plugin 'tmux-plugins/tmux-sensible' + +# Local overrides +if-shell "[ -f ~/.tmux_local.conf ]" 'source ~/.tmux_local.conf' + +# Initialize TPM (must be the last line) +run '~/.tmux/plugins/tpm/tpm' diff --git a/config/tmux/legacy.conf b/config/tmux/legacy.conf new file mode 100644 index 0000000..796ad2a --- /dev/null +++ b/config/tmux/legacy.conf @@ -0,0 +1,16 @@ +# tmux < 2.4 copy-mode key table (vi-copy, old -t flag) and mouse-wheel/ +# PageUp passthrough. Sourced conditionally from tmux.conf; see +# tmux/modern.conf for tmux >= 2.4. + +bind-key -t vi-copy PPage page-up +bind-key -t vi-copy NPage page-down +bind-key -t vi-copy WheelUpPane halfpage-up +bind-key -t vi-copy WheelDownPane halfpage-down +bind-key -t vi-copy v begin-selection +bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy" +unbind-key -t vi-copy Enter +bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy" + +bind-key -n PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage" +bind-key -n WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M" +bind-key -n WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M" diff --git a/config/tmux/tmux_3.1c.conf b/config/tmux/modern.conf similarity index 53% rename from config/tmux/tmux_3.1c.conf rename to config/tmux/modern.conf index e1f37b6..a188ce8 100644 --- a/config/tmux/tmux_3.1c.conf +++ b/config/tmux/modern.conf @@ -1,42 +1,17 @@ -# PREFIX | splits horizontally and PREFIX - splits vertically -bind | split-window -h -c "#{pane_current_path}" -bind - split-window -v -c "#{pane_current_path}" +# tmux >= 2.4 copy-mode key table and mouse-wheel/PageUp passthrough. +# Sourced conditionally from tmux.conf; see tmux/legacy.conf for older tmux. -# open new window with pwd -bind c new-window -c "#{pane_current_path}" - -# use vim keybindings in copy mode -setw -g mode-keys vi - -# Copy Mode bind-key -T copy-mode-vi PPage send-keys -X page-up bind-key -T copy-mode-vi NPage send-keys -X page-down - -# Mouse Wheel bind-key -T copy-mode-vi WheelUpPane send-keys -X halfpage-up bind-key -T copy-mode-vi WheelDownPane send-keys -X halfpage-down - -# v selection bind-key -T copy-mode-vi v send-keys -X begin-selection bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy" - -# make enter use copy pipe -unbind -T copy-mode-vi Enter +unbind-key -T copy-mode-vi Enter bind-key -T copy-mode-vi Enter send-keys -X copy-pipe "reattach-to-user-namespace pbcopy" -set-option -g -q mouse on -set-option -g -q mouse-resize-pane on -set-option -g -q mouse-select-pane on -set-option -g -q mouse-select-window on - -# Enable middle click in urxvt -set-option -ga terminal-override ',rxvt-uni*:XT:Ms=\E]52;%p1%s;%p2%s\007' - -# Copy Mode +# Let mouse wheel / PageUp pass through to apps using the alternate screen +# (vim, less, etc.) instead of always entering copy-mode bind-key -T root PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage" - -# Mouse Wheel bind-key -T root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M" bind-key -T root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M" - -source ~/.tmux/tmux_shared.conf diff --git a/config/tmux/tmux_1.9_down.conf b/config/tmux/tmux_1.9_down.conf deleted file mode 100644 index 16840c0..0000000 --- a/config/tmux/tmux_1.9_down.conf +++ /dev/null @@ -1,37 +0,0 @@ -# PREFIX | splits horizontally and PREFIX - splits vertically -bind | split-window -h -bind - split-window -v - -# mouse support -set -g mode-mouse on # scrolling -set -g mouse-select-pane on # clicking into panes -set -g mouse-resize-pane on # resizing panes -set -g mouse-select-window on # select windows - -# toggle mouse support -bind m \ - set -g mode-mouse on \;\ - set -g mouse-resize-pane on \;\ - set -g mouse-select-pane on \;\ - set -g mouse-select-window on \;\ - display 'Mouse: ON' - -bind M \ - set -g mode-mouse off \;\ - set -g mouse-resize-pane off \;\ - set -g mouse-select-pane off \;\ - set -g mouse-select-window off \;\ - display 'Mouse: OFF' - -# ---------------------- -# set some pretty colors -# ---------------------- -# set pane colors - hilight the active pane -# set-option -g pane-border-fg colour235 #base02 -# set-option -g pane-active-border-fg colour240 #base01 - -# # colorize messages in the command line -# set-option -g message-bg black #base02 -# set-option -g message-fg brightred #orange - -source "$HOME/.tmux/tmux_shared.conf" diff --git a/config/tmux/tmux_1.9_to_2.1.conf b/config/tmux/tmux_1.9_to_2.1.conf deleted file mode 100644 index c4063c7..0000000 --- a/config/tmux/tmux_1.9_to_2.1.conf +++ /dev/null @@ -1,2 +0,0 @@ - -source "$HOME/.tmux/tmux_shared.conf" diff --git a/config/tmux/tmux_2.1_to_2.5.conf b/config/tmux/tmux_2.1_to_2.5.conf deleted file mode 100644 index 37264ec..0000000 --- a/config/tmux/tmux_2.1_to_2.5.conf +++ /dev/null @@ -1,48 +0,0 @@ -# PREFIX | splits horizontally and PREFIX - splits vertically -bind | split-window -h -c "#{pane_current_path}" -bind - split-window -v -c "#{pane_current_path}" - -# open new window with pwd -bind c new-window -c "#{pane_current_path}" - -# PREFIX T makes current window index 1 -bind T swap-window -t 1 - -# use vim movement for panes -bind h select-pane -L -bind j select-pane -D -bind k select-pane -U -bind l select-pane -R - -# mouse support -set-option -g -q mouse on - -# Copy Mode -bind-key -t root PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage" -bind-key -t vi-copy PPage page-up -bind-key -t vi-copy NPage page-down -# Mouse Wheel -bind-key -t root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M" -bind-key -t root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M" -bind-key -t vi-copy WheelUpPane halfpage-up -bind-key -t vi-copy WheelDownPane halfpage-down - -# Make sure the client is always using the correct environment -# eval $(tmux switch-client \; show-environment -s) - -# Copy/Paste -# -# provide access to clipboard -# set-option -g default-command "reattach-to-user-namespace -l zsh" -# set-window-option -g automatic-rename on - -# use vim keybindings in copy mode -setw -g mode-keys vi - -# v selection -bind-key -t vi-copy v begin-selection -bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy" - -# make enter use copy pipe -unbind -t vi-copy Enter -bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy" diff --git a/config/tmux/tmux_2.5_up.conf b/config/tmux/tmux_2.5_up.conf deleted file mode 100644 index e1f37b6..0000000 --- a/config/tmux/tmux_2.5_up.conf +++ /dev/null @@ -1,42 +0,0 @@ -# PREFIX | splits horizontally and PREFIX - splits vertically -bind | split-window -h -c "#{pane_current_path}" -bind - split-window -v -c "#{pane_current_path}" - -# open new window with pwd -bind c new-window -c "#{pane_current_path}" - -# use vim keybindings in copy mode -setw -g mode-keys vi - -# Copy Mode -bind-key -T copy-mode-vi PPage send-keys -X page-up -bind-key -T copy-mode-vi NPage send-keys -X page-down - -# Mouse Wheel -bind-key -T copy-mode-vi WheelUpPane send-keys -X halfpage-up -bind-key -T copy-mode-vi WheelDownPane send-keys -X halfpage-down - -# v selection -bind-key -T copy-mode-vi v send-keys -X begin-selection -bind-key -T copy-mode-vi y send-keys -X copy-pipe "reattach-to-user-namespace pbcopy" - -# make enter use copy pipe -unbind -T copy-mode-vi Enter -bind-key -T copy-mode-vi Enter send-keys -X copy-pipe "reattach-to-user-namespace pbcopy" - -set-option -g -q mouse on -set-option -g -q mouse-resize-pane on -set-option -g -q mouse-select-pane on -set-option -g -q mouse-select-window on - -# Enable middle click in urxvt -set-option -ga terminal-override ',rxvt-uni*:XT:Ms=\E]52;%p1%s;%p2%s\007' - -# Copy Mode -bind-key -T root PPage if-shell -F "#{alternate_on}" "send-keys PPage" "copy-mode -e; send-keys PPage" - -# Mouse Wheel -bind-key -T root WheelUpPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; copy-mode -e; send-keys -M" -bind-key -T root WheelDownPane if-shell -F -t = "#{alternate_on}" "send-keys -M" "select-pane -t =; send-keys -M" - -source ~/.tmux/tmux_shared.conf diff --git a/config/tmux/tmux_shared.conf b/config/tmux/tmux_shared.conf deleted file mode 100644 index 0ac08f8..0000000 --- a/config/tmux/tmux_shared.conf +++ /dev/null @@ -1,110 +0,0 @@ -# use UTF8 -# set -g utf8 -# set-window-option -g utf8 on - -# 256 color mode -set -g default-terminal "screen-256color" -# set-option -sa terminal-overrides ',screen*:RGB' -# set-option -ga terminal-overrides ',screen*:Tc' -# set-option -sa terminal-overrides ',xterm*:RGB' -# set-option -ga terminal-overrides ',xterm*:Tc' -# set-option -sa terminal-overrides ',tmux*:RGB' -# set-option -ga terminal-overrides ',tmux*:Tc' -# set-option -sa terminal-overrides ',rxvt*:RGB' -# set-option -ga terminal-overrides ',rxvt*:Tc' - -# Properly handle ssh agent forwarding when reconnecting to session -# set-environment -g 'SSH_AUTH_SOCK' ~/.ssh/ssh_auth_sock - -set-option -g set-titles on -# Tmux attach will create a new session if one doesn't exist -# new-session -n $HOST - -# set scrollback history -set -g history-limit 10000 - -# set Ctrl-a as prefix and unbind Ctrl-b -set -g prefix C-a -unbind C-b - -# last active window -# bind-key C-a last-window -bind Tab last-window - -# pass prefix through to application -bind C-a send-prefix - -# don't constrain size unless smaller client looking at window -setw -g aggressive-resize on - -# set command delay -set -sg escape-time 1 - -# set base index to 1 rather than 0 -set-option -g base-index 1 -setw -g pane-base-index 1 - -# use PREFIX-r to reload config -bind r source-file ~/.tmux/tmux_shared.conf \; display "Reloaded config" - -# PREFIX T makes current window index 1 -bind T swap-window -t 1 - -# use vim movement for panes -bind h select-pane -L -bind j select-pane -D -bind k select-pane -U -bind l select-pane -R - -# Smart pane switching with awareness of vim splits -is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?)(diff)?$"' -bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L" -bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D" -bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U" -bind -n C-l if-shell "$is_vim" "send-keys C-l" "select-pane -R" -bind -n 'C-\' if-shell "$is_vim" "send-keys 'C-\\'" "select-pane -l" - -# bind C-h and C-l to cycle through panes -bind -r C-h select-window -t :- -bind -r C-l select-window -t :+ - -# Synchonize keyboard input across panes -bind a setw synchronize-panes - -# open calendar -bind-key C run-shell "cal $(date +%Y)" - -# Make sure the client is always using the correct environment -# eval $(tmux switch-client \; show-environment -s) - -bind y run 'tmux save-buffer - | reattach-to-user-namespace pbcopy ' -bind C-y run 'tmux save-buffer - | reattach-to-user-namespace pbcopy '1 - -# ---------------------- -# set some pretty colors -# ---------------------- -# set pane colors - hilight the active pane -# set-option -g pane-border-fg colour235 #base02 -# set-option -g pane-active-border-fg colour240 #base01 - -# Show active pane -# set-window-option -g window-style 'bg=#181818' -# set-window-option -g window-active-style 'bg=black' -# set-window-option -g pane-active-border-style '' -# set-window-option -g pane-active-border-style 'fg=#181818' - -# colorize messages in the command line -# set-option -g message-bg black #base02 -# set-option -g message-fg brightred #orange - -# Powerline -run-shell "powerline-daemon -q" -run-shell "powerline-config tmux setup" -# source-file $POWERLINE_ROOT/bindings/tmux/powerline.conf - -# Tmux plugins -set -g @plugin 'tmux-plugins/tpm' -set -g @plugin 'tmux-plugins/tmux-sensible' - -# Local overrides -if-shell "[ -f ~/.tmux_local.conf ]" 'source ~/.tmux_local.conf' diff --git a/config/tmux/verify_tmux_version.sh b/config/tmux/verify_tmux_version.sh deleted file mode 100755 index 34fc96b..0000000 --- a/config/tmux/verify_tmux_version.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -verify_tmux_version() { - tmux_home=~/.tmux - tmux_version="$(tmux -V | cut -c 6-)" - - # This is necessary because 3.1c gives a syntax error in bc - # TODO Fix this it will break with the next tmux version - if [[ $tmux_version -eq "3.1c"]] ; then - source-file $tmux_home/tmux_3.1c.conf - exit - if [[ $(echo "$tmux_version >= 2.5" | bc) -eq 1 ]] ; then - source-file $tmux_home/tmux_3.1c.conf - exit - elif [[ $(echo "$tmux_version >= 2.1" | bc) -eq 1 ]] ; then - source-file $tmux_home/tmux_2.1_to_2.5.conf - exit - elif [[ $(echo "$tmux_version >= 1.9" | bc) -eq 1 ]] ; then - source-file $tmux_home/tmux_1.9_to_2.1.conf - exit - else - source-file $tmux_home/tmux_1.9_down.conf - exit - fi -} - -verify_tmux_version