From 9155782815143e08a6ac631243c79c36f99e7a75 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Mon, 10 Aug 2026 01:55:20 +1200 Subject: [PATCH 01/13] feat --- config/nvim/lua/plugins/copilot.lua | 1 - config/nvim/lua/plugins/trouble.lua | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/config/nvim/lua/plugins/copilot.lua b/config/nvim/lua/plugins/copilot.lua index 5c1f891..04fe78d 100644 --- a/config/nvim/lua/plugins/copilot.lua +++ b/config/nvim/lua/plugins/copilot.lua @@ -63,7 +63,6 @@ return { trusted_tools = { "file", "glob", "grep", "buffer", "gitdiff", "selection" }, auto_fold = false, auto_insert_mode = true, - insert_at_end = true, auto_follow_cursor = false, history_path = vim.fn.stdpath("data") .. "/copilotchat_history", }, diff --git a/config/nvim/lua/plugins/trouble.lua b/config/nvim/lua/plugins/trouble.lua index 4b11d96..40b33c2 100644 --- a/config/nvim/lua/plugins/trouble.lua +++ b/config/nvim/lua/plugins/trouble.lua @@ -2,6 +2,7 @@ return { { "folke/trouble.nvim", dependencies = "nvim-tree/nvim-web-devicons", + cmd = "Trouble", keys = { { "gt", "Trouble diagnostics toggle", desc = "Diagnostics (Trouble)" }, }, From 16f20bebc5fb2fa77ed650dea778b8eb3a8182c0 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sat, 15 Aug 2026 22:44:59 +1200 Subject: [PATCH 02/13] feat --- scripts/aliases.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/aliases.sh b/scripts/aliases.sh index dd1fe6c..95a11ae 100755 --- a/scripts/aliases.sh +++ b/scripts/aliases.sh @@ -171,3 +171,5 @@ alias ai='claude' alias ai-talk='claude converse' alias godot='godot-mono' + +alias prjct='$EDITOR $PERSONAL_PATH/project/project.md' From 79a33893d80ea18235a0d9fd15f06d9298026735 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sat, 22 Aug 2026 02:14:56 +1200 Subject: [PATCH 03/13] feat --- config/nvim/lua/config/keymap.lua | 21 +++++++++++++++++++++ config/nvim/lua/config/lazy.lua | 1 - config/nvim/lua/config/option.lua | 12 ++++++++++++ config/nvim/lua/plugins/semshi.lua | 1 - dotfiles/.gitconfig | 14 +++++++++----- scripts/todo/todo.go | 2 +- 6 files changed, 43 insertions(+), 8 deletions(-) delete mode 100644 config/nvim/lua/plugins/semshi.lua diff --git a/config/nvim/lua/config/keymap.lua b/config/nvim/lua/config/keymap.lua index 559bb98..9fc083c 100644 --- a/config/nvim/lua/config/keymap.lua +++ b/config/nvim/lua/config/keymap.lua @@ -78,6 +78,16 @@ end, { desc = "Surround help" }) km("n", "a", ":ArgWrap", opts) vim.keymap.set("n", "t", vim.cmd.UndotreeToggle) + +-- Diffview toggle +vim.keymap.set("n", "dd", function() + if next(require("diffview.lib").views) == nil then + vim.cmd("DiffviewOpen") + else + vim.cmd("DiffviewClose") + end +end, { desc = "Toggle Diffview" }) + km("n", "w", ":WinResizerStartResize", opts) km("v", "ll", ":Noice dismiss", opts) @@ -125,6 +135,17 @@ vim.keymap.set("n", "sc", function() require("CopilotChat").toggle({ window = { layout = "horizontal" } }) end, { desc = "Toggle Copilot Chat (horizontal)" }) +-- Toggle ignoring whitespace in diffs +vim.keymap.set("n", "dw", function() + if vim.opt.diffopt:get()["iwhite"] then + vim.opt.diffopt:remove("iwhite") + vim.notify("diffopt: iwhite off") + else + vim.opt.diffopt:append("iwhite") + vim.notify("diffopt: iwhite on") + end +end, { desc = "Toggle diff ignore whitespace" }) + -- ZenMode vim.keymap.set("n", "z", ":ZenMode") diff --git a/config/nvim/lua/config/lazy.lua b/config/nvim/lua/config/lazy.lua index c9ca661..69cfd65 100644 --- a/config/nvim/lua/config/lazy.lua +++ b/config/nvim/lua/config/lazy.lua @@ -12,7 +12,6 @@ if not (vim.uv or vim.loop).fs_stat(lazypath) then }) end vim.opt.rtp:prepend(lazypath) -vim.print(lazypath) local opts = { root = vim.fn.stdpath("data") .. "/lazy", -- directory where plugins will be installed diff --git a/config/nvim/lua/config/option.lua b/config/nvim/lua/config/option.lua index da14db1..5ad18ea 100644 --- a/config/nvim/lua/config/option.lua +++ b/config/nvim/lua/config/option.lua @@ -151,6 +151,18 @@ vim.opt.wildignore:append("*.egg-info/**") vim.opt.wildmenu = true vim.opt.wildmode = "longest:full,full" +-- Diff options +vim.opt.diffopt = { + "internal", + "filler", + "closeoff", + "context:12", + "algorithm:histogram", + "linematch:200", + "indent-heuristic", + "iwhite", +} + --- Folding Config vim.opt.foldmethod = "expr" vim.opt.foldexpr = "v:lua.vim.treesitter.foldexpr()" diff --git a/config/nvim/lua/plugins/semshi.lua b/config/nvim/lua/plugins/semshi.lua deleted file mode 100644 index a564707..0000000 --- a/config/nvim/lua/plugins/semshi.lua +++ /dev/null @@ -1 +0,0 @@ -return {} diff --git a/dotfiles/.gitconfig b/dotfiles/.gitconfig index d669733..310cff5 100644 --- a/dotfiles/.gitconfig +++ b/dotfiles/.gitconfig @@ -27,11 +27,15 @@ renames = true [delta] - navigate = true - light = false - side-by-side = true - line-numbers = true - hyperlinks = true + navigate = true + dark = true + side-by-side = true + line-numbers = true + hyperlinks = true + file-style = bold yellow + file-decoration-style = yellow ul + hunk-header-style = file line-number syntax + hunk-header-decoration-style = cyan box [interactive] diffFilter = delta --color-only diff --git a/scripts/todo/todo.go b/scripts/todo/todo.go index 3dce155..c302077 100644 --- a/scripts/todo/todo.go +++ b/scripts/todo/todo.go @@ -23,7 +23,7 @@ func main() { func Resolve(project string) string { // this is one way to have default args // works, but I don't like it! - return ResolveToHome(project, "~/personal/project/") + return ResolveToHome(project, "~/personal/project") } func ResolveToHome(project string, home string) string { From 4f35952b069497faaac2e1fdcc540bccd3268fc8 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sun, 30 Aug 2026 21:57:19 +1200 Subject: [PATCH 04/13] feat --- config/brew/Brewfile | 1 + config/lsd/config.yaml | 13 ++++++++----- config/pi/AGENTS.md | 1 + scripts/aliases.sh | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/config/brew/Brewfile b/config/brew/Brewfile index 89cc7f5..c307fa8 100644 --- a/config/brew/Brewfile +++ b/config/brew/Brewfile @@ -129,3 +129,4 @@ brew "marp-cli" brew "btop" brew "gum" +brew "ov" # csv viewer diff --git a/config/lsd/config.yaml b/config/lsd/config.yaml index b390f3a..6f55289 100644 --- a/config/lsd/config.yaml +++ b/config/lsd/config.yaml @@ -11,7 +11,7 @@ classic: false # Possible values: permission, user, group, context, size, date, name, inode, links, git blocks: # - permission - - user + # - user # - group - size - date @@ -34,7 +34,7 @@ color: # When "classic" is set, this is set to "date". # Possible values: date, relative, '+' # `date_format` will be a `strftime` formatted value. e.g. `date: '+%d %b %y %X'` will give you a date like this: 17 Jun 21 20:14:55 -date: date +date: relative # == Dereference == # Whether to dereference symbolic links. @@ -60,6 +60,9 @@ icons: ignore-globs: - .git - "*pycache*" + - .DS_Store + - node_modules + - .venv # == Indicators == # Whether to add indicator characters to certain listed files. @@ -82,7 +85,7 @@ recursion: # == Size == # Specifies the format of the size column. # Possible values: default, short, bytes -size: default +size: short # == Permission == # Specify the format of the permission column @@ -99,7 +102,7 @@ sorting: # Whether to group directories together and where. # When "classic" is set, this is set to "none". # Possible values: first, last, none - dir-grouping: none + dir-grouping: first # == No Symlink == # Whether to omit showing symlink targets # Possible values: false, true @@ -113,7 +116,7 @@ total-size: false # == Hyperlink == # Attach hyperlink to filenames # Possible values: always, auto, never -hyperlink: never +hyperlink: auto # == Symlink arrow == # Specifies how the symlink arrow display, chars in both ascii and utf8 diff --git a/config/pi/AGENTS.md b/config/pi/AGENTS.md index c06b0ab..9d13855 100644 --- a/config/pi/AGENTS.md +++ b/config/pi/AGENTS.md @@ -104,3 +104,4 @@ I like: - Simple solutions - Small edits that I can change +- Clean low friction interfaces with high information density diff --git a/scripts/aliases.sh b/scripts/aliases.sh index 95a11ae..c071d0a 100755 --- a/scripts/aliases.sh +++ b/scripts/aliases.sh @@ -25,8 +25,10 @@ alias cls='clear && ls' # alias tree='fd --type f | tree --fromfile' # lsd -alias ll='lsd --almost-all --group-directories-first' -alias ls='lsd --almost-all --long --icon always --git --date relative --group-directories-first -a' +alias ll='lsd --almost-all' +alias ls='lsd --almost-all --long --icon auto --git --total-size' +alias lt='lsd --almost-all --long --git --tree --depth 2' +alias tree='lt' # program customization alias bat='bat --color=always --paging=always' From f9d8c2f7faeea21bf54cb64ce235c855185a9ecc Mon Sep 17 00:00:00 2001 From: Adam Green Date: Thu, 3 Sep 2026 23:28:01 +1200 Subject: [PATCH 05/13] feat --- config/nvim/lua/plugins/copilot.lua | 2 +- scripts/aliases.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config/nvim/lua/plugins/copilot.lua b/config/nvim/lua/plugins/copilot.lua index 04fe78d..124fac9 100644 --- a/config/nvim/lua/plugins/copilot.lua +++ b/config/nvim/lua/plugins/copilot.lua @@ -59,7 +59,7 @@ return { - List tradeoffs, assumptions, and uncertainties explicitly when relevant - Prefer small, targeted edits over large rewrites - Produce directly usable code because responses may be copied into the codebase]], - model = "claude-sonnet-4.6", + -- model = "claude-sonnet-4.6", trusted_tools = { "file", "glob", "grep", "buffer", "gitdiff", "selection" }, auto_fold = false, auto_insert_mode = true, diff --git a/scripts/aliases.sh b/scripts/aliases.sh index c071d0a..e5fe936 100755 --- a/scripts/aliases.sh +++ b/scripts/aliases.sh @@ -174,4 +174,5 @@ alias ai-talk='claude converse' alias godot='godot-mono' +alias prj='$EDITOR $PERSONAL_PATH/project/project.md' alias prjct='$EDITOR $PERSONAL_PATH/project/project.md' From 21a40768dbff2578865e501dda4e3de828aeef84 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Thu, 3 Sep 2026 23:50:58 +1200 Subject: [PATCH 06/13] feat --- .gitignore | 1 + README.md | 22 +++++++++++++++++++++- dotfiles/.gitignore | 1 + scripts/search.sh | 5 +++-- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index e8247e2..1cb0ece 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ .pytest_cache .python-version .testmondata +.venv/** .venv Music NVIDIA* diff --git a/README.md b/README.md index 2ca2e0b..9558a28 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,29 @@ Neovim config is in `./config/nvim`. To use the Neovim setup alone, put the `nvi I use Lazy for package management in Neovim - it will install packages when you first open the editor. +### Gitignore + +There is one global ignore file, `./dotfiles/.gitignore`, stowed to `~/.gitignore`. It is wired in by `core.excludesfile` in `./dotfiles/.gitconfig`: + +``` +[core] + excludesfile = ~/dotfiles/dotfiles/.gitignore +``` + +This is the place to add junk that should never be committed in any repo (`.DS_Store`, `__pycache__`, `.venv`, `.wrangler`, `temp*`). Per-repo `.gitignore` files still apply on top of it, for things specific to one project. + +Two consequences worth knowing: + +- Because `core.excludesfile` is set, git ignores its default fallback location `~/.config/git/ignore`. That file exists on this machine but is dead - entries there have no effect and belong in `./dotfiles/.gitignore` instead. +- The global file is only read by tools that resolve `core.excludesfile`. `git`, `rg` and `fd` all do; plain `find` does not. + ### `s` -The `s` command opens a fuzzy file finder (fzf) to search and open files in `$EDITOR`. Run `s` in any directory, or pass a path like `s ~/projects`. Supports multi-select with Tab. +The `s` command opens a fuzzy file finder (fzf) to search and open files in `$EDITOR`. Run `s` in any directory. Supports multi-select with Tab. + +The file list comes from `fd` (set as `FZF_DEFAULT_COMMAND` in `./scripts/search.sh`), so the results respect the ignore rules above - both the repo's own `.gitignore` and the global `~/.gitignore`. `--no-require-git` makes those rules apply outside git repos too, and `archive/` is excluded explicitly. + +The tradeoff is that gitignored files you sometimes want to open (`.env`, `dist/`, anything matching `temp*`) are not reachable via `s`. Add `--no-ignore-vcs` to that command to get them back. ### Aliases diff --git a/dotfiles/.gitignore b/dotfiles/.gitignore index a491601..9b3a669 100644 --- a/dotfiles/.gitignore +++ b/dotfiles/.gitignore @@ -21,6 +21,7 @@ .python-version .testmondata .venv +.wrangler Music NVIDIA* __pycache__ diff --git a/scripts/search.sh b/scripts/search.sh index a80dac1..29f89ac 100755 --- a/scripts/search.sh +++ b/scripts/search.sh @@ -7,8 +7,9 @@ MIN_HEIGHT=20 target_dir="${1:-.}" cd "$target_dir" || exit -# exclude ./archive from the file list fed to fzf -FZF_DEFAULT_COMMAND='find . -path ./archive -prune -o -type f -print' +# respect local .gitignore and the global one (core.excludesFile), plus exclude ./archive +# --no-require-git applies the gitignore rules outside git repos too +FZF_DEFAULT_COMMAND='fd --type f --hidden --no-require-git --exclude .git --exclude archive' export FZF_DEFAULT_COMMAND if [ "$TERM_HEIGHT" -ge "$MIN_HEIGHT" ]; then From 29ce745d9a824511639a6f1a014b30ad20884c3e Mon Sep 17 00:00:00 2001 From: Adam Green Date: Thu, 10 Sep 2026 14:52:11 +1200 Subject: [PATCH 07/13] feat --- scripts/aliases.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/aliases.sh b/scripts/aliases.sh index e5fe936..1eccd46 100755 --- a/scripts/aliases.sh +++ b/scripts/aliases.sh @@ -176,3 +176,5 @@ alias godot='godot-mono' alias prj='$EDITOR $PERSONAL_PATH/project/project.md' alias prjct='$EDITOR $PERSONAL_PATH/project/project.md' + +alias dr='bash $PERSONAL_PATH/area/scripts/show-drafts.sh' From d63c5ebe3415356c9f9fec22a731ea3c022bcf4c Mon Sep 17 00:00:00 2001 From: Adam Green Date: Thu, 10 Sep 2026 15:18:55 +1200 Subject: [PATCH 08/13] feat --- config/nvim/lazy-lock.json | 58 -------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 config/nvim/lazy-lock.json diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json deleted file mode 100644 index ed5e857..0000000 --- a/config/nvim/lazy-lock.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "CopilotChat.nvim": { "branch": "main", "commit": "f0c2a23ab79dc295f5e0eef0d8b587a39020c852" }, - "Vim-Jinja2-Syntax": { "branch": "master", "commit": "2c17843b074b06a835f88587e1023ceff7e2c7d1" }, - "barbar.nvim": { "branch": "master", "commit": "539d73def39c9172b4d4d769f14090e08f37b29d" }, - "blink-cmp-copilot": { "branch": "main", "commit": "439cff78780c033aa23cf061d7315314b347e3c1" }, - "blink-cmp-dictionary": { "branch": "master", "commit": "35142bba869b869715e91a99d2f46bcf93fca4ae" }, - "blink-cmp-env": { "branch": "main", "commit": "99af62c1f9aa46005e8f50ad4ccee581946546ca" }, - "blink-emoji.nvim": { "branch": "master", "commit": "dff709139ad5389fb55ebab026e75278a12b325a" }, - "blink-ripgrep.nvim": { "branch": "main", "commit": "d84a20e765fdc9cc8c0775708e083e7185654527" }, - "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, - "blink.compat": { "branch": "main", "commit": "2ed6d9a28b07fa6f3bface818470605f8896408c" }, - "bullets.vim": { "branch": "master", "commit": "28c22791153a90bb61a86fbeeae0f812e048ade7" }, - "codecompanion.nvim": { "branch": "main", "commit": "680c445eb357c72129d175ea5d481aa9e92ae6a5" }, - "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" }, - "copilot.lua": { "branch": "master", "commit": "adff470bca742b7658228ed144589250ecb3dc0a" }, - "dbtpal": { "branch": "main", "commit": "981eab51609362712c64e3cf3fb773fe11f859b9" }, - "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, - "emmet-vim": { "branch": "master", "commit": "92ef2f74f4093edc99db5e9e4cf7e40116a85bd6" }, - "gitsigns.nvim": { "branch": "main", "commit": "6d808f99bd63303646794406e270bd553ad7792e" }, - "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, - "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, - "lualine.nvim": { "branch": "master", "commit": "a905eeebc4e63fdc48b5135d3bf8aea5618fb21c" }, - "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, - "mini.icons": { "branch": "main", "commit": "bac6317300e205335df425296570d84322730067" }, - "mini.nvim": { "branch": "main", "commit": "5849ef04c32a6a8e55957b946c0a275801d87530" }, - "nvim-autopairs": { "branch": "master", "commit": "59bce2eef357189c3305e25bc6dd2d138c1683f5" }, - "nvim-bqf": { "branch": "main", "commit": "c282a62bec6c0621a1ef5132aa3f4c9fc4dcc2c7" }, - "nvim-colorizer.lua": { "branch": "master", "commit": "5cfe7fffbd01e17b3c1e14af85d5febdef88bd8c" }, - "nvim-lint": { "branch": "master", "commit": "eab58b48eb11d7745c11c505e0f3057165902461" }, - "nvim-lspconfig": { "branch": "master", "commit": "e146efacbafed3789ac568abcc5a981c5decaa58" }, - "nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" }, - "nvim-treesitter-context": { "branch": "master", "commit": "b0c45cefe2c8f7b55fc46f34e563bc428ef99636" }, - "nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" }, - "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, - "nvim-web-devicons": { "branch": "master", "commit": "c72328a5494b4502947a022fe69c0c47e53b6aa6" }, - "obsidian.nvim": { "branch": "main", "commit": "ae1f76a75c7ce36866e1d9342a8f6f5b9c2caf9b" }, - "oil.nvim": { "branch": "master", "commit": "0fcc83805ad11cf714a949c98c605ed717e0b83e" }, - "peek.nvim": { "branch": "master", "commit": "5820d937d5414baea5f586dc2a3d912a74636e5b" }, - "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, - "render-markdown.nvim": { "branch": "main", "commit": "d67113f11384c0dad96fced2f7b91f1fc811e97f" }, - "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, - "telescope-git-file-history.nvim": { "branch": "master", "commit": "4442114f9257e682e60a8cb6de14cf988e26055c" }, - "telescope-makefile": { "branch": "master", "commit": "f35425d7d53d92a04215c3714a5819811d2842c3" }, - "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, - "telescope.nvim": { "branch": "master", "commit": "506338434fec5ad19cb1f8d45bf92d66c4917393" }, - "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, - "undotree": { "branch": "master", "commit": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d" }, - "vim": { "branch": "master", "commit": "07b144414730cc4cf4405ab840bf46c5fa12704b" }, - "vim-argwrap": { "branch": "master", "commit": "03615d1eed248408567bc8fa6a5a8c94ef3cd170" }, - "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, - "vim-markdown": { "branch": "master", "commit": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397" }, - "vim-markdown-toc": { "branch": "master", "commit": "66026b323379c9a712c6169cd43153216acef090" }, - "vim-one": { "branch": "master", "commit": "187f5c85b682c1933f8780d4d419c55d26a82e24" }, - "vim-python-pep8-indent": { "branch": "master", "commit": "60ba5e11a61618c0344e2db190210145083c91f8" }, - "vim-table-mode": { "branch": "master", "commit": "bb025308a45c67c7c8f0763ba37bc2ee3f534df0" }, - "winresizer": { "branch": "master", "commit": "299076f7f79e2e2f7706b2dfacbb3c074ce53257" }, - "zen-mode.nvim": { "branch": "main", "commit": "8564ce6d29ec7554eb9df578efa882d33b3c23a7" } -} From e3113e62340fe65b18acfca9804821d89081a7c0 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Thu, 10 Sep 2026 15:36:37 +1200 Subject: [PATCH 09/13] docs --- README.md | 62 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index f5e04db..ed83612 100644 --- a/README.md +++ b/README.md @@ -133,71 +133,13 @@ Lot's of aliases - see `./scripts/aliases.sh`. Some small interactive shell hel ## AI Configuration -Two AGENTS.md: +Agents are configured twice using two AGENTS.md: - `./AGENTS.md` for this repo -- `./pi/config/pi/agent/AGENTS.md` for Pi & Claude Code +- `./pi/config/pi/agent/AGENTS.md` for Pi & Claude Code outside this repo PI_CODING_AGENT_DIR in dotfiles/common/env.sh points pi's config to ~/dotfiles/config/pi/, which contains agent/AGENTS.md (agent instructions), settings.json, themes, and sessions. CLAUDE.md at the repo root serves the same purpose for Claude Code, but is symlinked to `AGENTS.md`. Skills are defined once in agents/skills/ and symlinked by make dotfiles to both ~/.agents/skills (pi) and ~/.claude/skills (Claude Code). -<<<<<<< HEAD -||||||| 5f1ddca - - - - - Label - setenv.XDG_CONFIG_HOME - ProgramArguments - - sh - -c - launchctl setenv XDG_CONFIG_HOME $HOME/dotfiles - - RunAtLoad - - - - -$ launchctl load ~/Library/LaunchAgents/setenv.XDG_CONFIG_HOME.plist -``` - -## Agent Configuration - -PI_CODING_AGENT_DIR in dotfiles/common/env.sh points pi's config to ~/dotfiles/config/pi/, which contains agent/AGENTS.md (agent instructions), settings.json, themes, and sessions. - -CLAUDE.md at the repo root serves the same purpose for Claude Code. - -Skills are defined once in `.agents/skills/` and symlinked by `make dotfiles` to both `~/.agents/skills` (for Pi) and `~/.claude/skills` (for Claude Code). -||||||| 25036fb -||||||| 5f1ddca - - - - - Label - setenv.XDG_CONFIG_HOME - ProgramArguments - - sh - -c - launchctl setenv XDG_CONFIG_HOME $HOME/dotfiles - - RunAtLoad - - - - -$ launchctl load ~/Library/LaunchAgents/setenv.XDG_CONFIG_HOME.plist -``` - -## Agent Configuration - -PI_CODING_AGENT_DIR in dotfiles/common/env.sh points pi's config to ~/dotfiles/config/pi/, which contains agent/AGENTS.md (agent instructions), settings.json, themes, and sessions. - -CLAUDE.md at the repo root serves the same purpose for Claude Code. - -Skills are defined once in `.agents/skills/` and symlinked by `make dotfiles` to both `~/.agents/skills` (for Pi) and `~/.claude/skills` (for Claude Code). From 15e140b0ceae766c3fbe4c8664e5c09984b90ac3 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Mon, 21 Sep 2026 01:39:12 +1200 Subject: [PATCH 10/13] feat --- .agents/skills/review-plan/SKILL.md | 33 +++++++++++++++- Makefile | 2 + README.md | 17 ++++++++ config/brew/Brewfile | 2 + config/nvim/lazy-lock.json | 57 +++++++++++++++++++++++++++ config/nvim/lua/config/command.lua | 48 +++++++++++++++++++++- config/nvim/lua/plugins/copilot.lua | 10 +++++ config/nvim/lua/plugins/lsp.lua | 10 +++++ config/nvim/lua/plugins/telescope.lua | 5 ++- config/pi/AGENTS.md | 6 ++- scripts/funcs.sh | 35 ++++++++++++++++ 11 files changed, 218 insertions(+), 7 deletions(-) create mode 100644 config/nvim/lazy-lock.json diff --git a/.agents/skills/review-plan/SKILL.md b/.agents/skills/review-plan/SKILL.md index 2a4768e..bd27f7c 100644 --- a/.agents/skills/review-plan/SKILL.md +++ b/.agents/skills/review-plan/SKILL.md @@ -1,5 +1,34 @@ --- name: review-plan -description: Review a plan. +description: Review, critique and propose improvements to an implementation plan. Read this skill when the user asks to review a plan, critique a plan, or propose improvements to a plan. --- -Review thoroughly, critique and propose improvements to the plan. \ No newline at end of file + +Review thoroughly, critique and propose improvements to the plan. + +Your improvements should be structured as followed: + +""" +## Major Changes + +### 1. First Proposed Change + +This code + +```python +some code +``` + +Should become that code: + +```python +other code +``` + +### 2. Second Issue Found + +## Minor Changes + +### 3. Third Change + +## Other Changes +""" diff --git a/Makefile b/Makefile index 26c9250..fb101b8 100644 --- a/Makefile +++ b/Makefile @@ -61,9 +61,11 @@ clean-nvim: rm -rf ~/.local/share/nvim/site rm -rf ./plugin rm -rf ~/dotfiles/nvim/plugin + rm -rf ~/.config/nvim/pack # clean lazy stuff rm -rf ~/.local/share/nvim/lazy ~/.local/state/nvim/lazy + setup-vim: git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim "vim" +PluginInstall +qall diff --git a/README.md b/README.md index ed83612..3cc90a3 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,23 @@ Neovim config is in `./config/nvim`. To use the Neovim setup alone, put the `nvi I use Lazy for package management in Neovim - it will install packages when you first open the editor. +- `config/nvim/init.lua` for the entrypoint +- `config/nvim/after` for filetype specific overrides +- `config/nvim/lua/config` for general configuration +- `config/nvim/lua/config/keymap.lua` for general configuration +- `config/nvim/lua/config/lazy.lua` for Lazy init (?) +- `config/nvim/lua/plugins` for Lazy managed plugins +- `config/nvim/lua/snippets` for autocompletion snippets +- `config/nvim/spell` for spell checking + +Important keymaps: + +- `gl` +- `gll` +- `zt` +- `zz` +- `zb` + ### Gitignore There is one global ignore file, `./dotfiles/.gitignore`, stowed to `~/.gitignore`. It is wired in by `core.excludesfile` in `./dotfiles/.gitconfig`: diff --git a/config/brew/Brewfile b/config/brew/Brewfile index cd1e15c..f65cb7e 100644 --- a/config/brew/Brewfile +++ b/config/brew/Brewfile @@ -129,3 +129,5 @@ brew "marp-cli" brew "btop" brew "gum" brew "ov" # csv viewer + +brew "aspell" diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json new file mode 100644 index 0000000..2510fff --- /dev/null +++ b/config/nvim/lazy-lock.json @@ -0,0 +1,57 @@ +{ + "CopilotChat.nvim": { "branch": "main", "commit": "f0c2a23ab79dc295f5e0eef0d8b587a39020c852" }, + "Vim-Jinja2-Syntax": { "branch": "master", "commit": "2c17843b074b06a835f88587e1023ceff7e2c7d1" }, + "barbar.nvim": { "branch": "master", "commit": "a4bef5b4fc1f064f2f673172252028eae18191c9" }, + "blink-cmp-copilot": { "branch": "main", "commit": "439cff78780c033aa23cf061d7315314b347e3c1" }, + "blink-cmp-dictionary": { "branch": "master", "commit": "17ea03ba5c296310b9f74587b52fde1b04d84c1a" }, + "blink-cmp-env": { "branch": "main", "commit": "6b147eca6fa5975d29f5508aff24e9a9acb6a1f5" }, + "blink-emoji.nvim": { "branch": "master", "commit": "dff709139ad5389fb55ebab026e75278a12b325a" }, + "blink-ripgrep.nvim": { "branch": "main", "commit": "851610e1689a9b3bbba99fbe9242b098e7b5f40f" }, + "blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" }, + "blink.compat": { "branch": "main", "commit": "2ed6d9a28b07fa6f3bface818470605f8896408c" }, + "bullets.vim": { "branch": "master", "commit": "28c22791153a90bb61a86fbeeae0f812e048ade7" }, + "conform.nvim": { "branch": "master", "commit": "24c70347f6b2128679f47d2eb765156ef34bf9e0" }, + "copilot.lua": { "branch": "master", "commit": "7b89909d0647c89298de880255b287b01b7e5d34" }, + "dbtpal": { "branch": "main", "commit": "981eab51609362712c64e3cf3fb773fe11f859b9" }, + "diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" }, + "emmet-vim": { "branch": "master", "commit": "92ef2f74f4093edc99db5e9e4cf7e40116a85bd6" }, + "gitsigns.nvim": { "branch": "main", "commit": "dd3f588bacbeb041be6facf1742e42097f62165d" }, + "indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lualine.nvim": { "branch": "master", "commit": "131a558e13f9f28b15cd235557150ccb23f89286" }, + "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, + "mini.icons": { "branch": "main", "commit": "520995f1d75da0e4cc901ee95080b1ff2bc46b94" }, + "mini.nvim": { "branch": "main", "commit": "44657837c7338e52727facc85c1d95bec1f6bd7c" }, + "nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" }, + "nvim-bqf": { "branch": "main", "commit": "c282a62bec6c0621a1ef5132aa3f4c9fc4dcc2c7" }, + "nvim-colorizer.lua": { "branch": "master", "commit": "5cfe7fffbd01e17b3c1e14af85d5febdef88bd8c" }, + "nvim-lint": { "branch": "master", "commit": "d48f3a76189d03b2239f6df1b2f7e3fa8353743b" }, + "nvim-lspconfig": { "branch": "master", "commit": "a4ed4e761c400849e8c9f8bda33e5083f890268c" }, + "nvim-treesitter": { "branch": "master", "commit": "cf12346a3414fa1b06af75c79faebe7f76df080a" }, + "nvim-treesitter-context": { "branch": "master", "commit": "b311b30818951d01f7b4bf650521b868b3fece16" }, + "nvim-treesitter-textobjects": { "branch": "master", "commit": "5ca4aaa6efdcc59be46b95a3e876300cfead05ef" }, + "nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" }, + "nvim-web-devicons": { "branch": "master", "commit": "0d7d35fa946837b8738b17c18d1faa1ac351e7f9" }, + "obsidian.nvim": { "branch": "main", "commit": "ae1f76a75c7ce36866e1d9342a8f6f5b9c2caf9b" }, + "oil.nvim": { "branch": "master", "commit": "21c669e7bfeb1546ae988b52813138e4d674bbf5" }, + "peek.nvim": { "branch": "master", "commit": "5820d937d5414baea5f586dc2a3d912a74636e5b" }, + "plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" }, + "snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "b25b749b9db64d375d782094e2b9dce53ad53a40" }, + "telescope-git-file-history.nvim": { "branch": "master", "commit": "4442114f9257e682e60a8cb6de14cf988e26055c" }, + "telescope-makefile": { "branch": "master", "commit": "f35425d7d53d92a04215c3714a5819811d2842c3" }, + "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, + "telescope.nvim": { "branch": "master", "commit": "7d324792b7943e4aa16ad007212e6acc6f9fe335" }, + "trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" }, + "undotree": { "branch": "master", "commit": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d" }, + "vim": { "branch": "master", "commit": "e7b91facff94bdf3a248df9b683119b84672256a" }, + "vim-argwrap": { "branch": "master", "commit": "03615d1eed248408567bc8fa6a5a8c94ef3cd170" }, + "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, + "vim-markdown": { "branch": "master", "commit": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397" }, + "vim-markdown-toc": { "branch": "master", "commit": "66026b323379c9a712c6169cd43153216acef090" }, + "vim-one": { "branch": "master", "commit": "187f5c85b682c1933f8780d4d419c55d26a82e24" }, + "vim-python-pep8-indent": { "branch": "master", "commit": "60ba5e11a61618c0344e2db190210145083c91f8" }, + "vim-table-mode": { "branch": "master", "commit": "bb025308a45c67c7c8f0763ba37bc2ee3f534df0" }, + "winresizer": { "branch": "master", "commit": "299076f7f79e2e2f7706b2dfacbb3c074ce53257" }, + "zen-mode.nvim": { "branch": "main", "commit": "8564ce6d29ec7554eb9df578efa882d33b3c23a7" } +} diff --git a/config/nvim/lua/config/command.lua b/config/nvim/lua/config/command.lua index ecb7256..adf2081 100644 --- a/config/nvim/lua/config/command.lua +++ b/config/nvim/lua/config/command.lua @@ -37,11 +37,57 @@ vim.cmd([[ command S lua searchPersonalNotes() ]]) +-- Fuzzy-find a directory under ~, then find files in it +local function pickDirAndFindFiles() + local home = vim.fn.expand("~") + require("telescope.pickers") + .new(require("telescope.themes").get_ivy({ prompt_title = "" }), { + finder = require("telescope.finders").new_oneshot_job({ + "fd", + "-H", + "-a", + "--type", + "d", + "--max-depth", + "2", + "--exclude", + "node_modules", + "--exclude", + "venv", + "--exclude", + ".git", + ".", + home, + }, {}), + sorter = require("telescope.config").values.file_sorter({}), + attach_mappings = function(prompt_bufnr) + require("telescope.actions").select_default:replace(function() + local entry = require("telescope.actions.state").get_selected_entry() + require("telescope.actions").close(prompt_bufnr) + require("telescope.builtin").find_files({ cwd = entry.value }) + end) + return true + end, + }) + :find() +end + +-- Find files from home, tab-completing or picking the directory +-- :F ~/dot -> complete dir, then find_files there +-- :F -> fuzzy-pick a directory, then find_files there +vim.api.nvim_create_user_command("F", function(opts) + if opts.args ~= "" then + require("telescope.builtin").find_files({ cwd = vim.fn.expand(opts.args) }) + else + pickDirAndFindFiles() + end +end, { nargs = "?", complete = "dir" }) + -- Abbreviations vim.cmd("cabbrev v vsp") vim.cmd("cabbrev s sp") -vim.cmd("cabbrev f Telescope find_files cwd=") vim.cmd("cabbrev t Telescope") +vim.cmd("cabbrev f F") -- Fix typos vim.cmd("command W write") diff --git a/config/nvim/lua/plugins/copilot.lua b/config/nvim/lua/plugins/copilot.lua index 124fac9..7f25be5 100644 --- a/config/nvim/lua/plugins/copilot.lua +++ b/config/nvim/lua/plugins/copilot.lua @@ -38,6 +38,16 @@ return { { "nvim-lua/plenary.nvim", branch = "master" }, }, build = "make tiktoken", + -- blink.cmp maps buffer-locally and wins over CopilotChat's + -- completion; opt out of blink here so resource completion (#file:, #buffer:) works + init = function() + vim.api.nvim_create_autocmd("FileType", { + pattern = "copilot-chat", + callback = function() + vim.b.completion = false + end, + }) + end, opts = { system_prompt = [[You are an expert software engineer and data scientist. - Provide clear, concise explanations - favour less verbose implementations diff --git a/config/nvim/lua/plugins/lsp.lua b/config/nvim/lua/plugins/lsp.lua index 04da5d6..05a83f6 100644 --- a/config/nvim/lua/plugins/lsp.lua +++ b/config/nvim/lua/plugins/lsp.lua @@ -7,6 +7,16 @@ return { -- TODO - should these be elsewhere? local opts = { noremap = true, silent = true } vim.keymap.set("n", "gl", vim.diagnostic.open_float, opts) + -- vim.keymap.set("n", "gll", "Trouble diagnostics toggle filter.buf=0", opts) + -- vim.keymap.set("n", "gll", function() + -- vim.diagnostic.open_float({ scope = "buffer" }) + -- end, opts) + -- vim.keymap.set("n", "gll", function() + -- vim.diagnostic.config({ virtual_text = not vim.diagnostic.config().virtual_text }) + -- end, opts) + vim.keymap.set("n", "gll", function() + vim.diagnostic.config({ virtual_lines = not vim.diagnostic.config().virtual_lines }) + end, opts) vim.keymap.set("n", "[d", vim.diagnostic.goto_prev, opts) vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) vim.keymap.set("n", "q", vim.diagnostic.setloclist, opts) diff --git a/config/nvim/lua/plugins/telescope.lua b/config/nvim/lua/plugins/telescope.lua index 715bc2a..fea410a 100644 --- a/config/nvim/lua/plugins/telescope.lua +++ b/config/nvim/lua/plugins/telescope.lua @@ -45,8 +45,9 @@ return { defaults = { layout_strategy = "flex", layout_config = { width = 0.9 }, - prompt_prefix = " ", - selection_caret = " ", + prompt_prefix = " ", + selection_caret = " ", + entry_prefix = " ", path_display = { "smart" }, file_ignore_patterns = { "node_modules", diff --git a/config/pi/AGENTS.md b/config/pi/AGENTS.md index 8550865..59b765d 100644 --- a/config/pi/AGENTS.md +++ b/config/pi/AGENTS.md @@ -91,6 +91,9 @@ Guidelines: - Never use f-string SQL — always parameterize - Always respect existing conventions in the codebase - Only deploy DABs to `dev_developer` target +- Many functions will have a verb as the first word +- Use consistent verbs in function names - for example `load_daily_data` and `load_monthly_data` rather than `cache_monthly_data` +- Consider these two approaches: 1. code is functional bits with other bits that deal with the concrete (ie side-effect free fu) 2. code is functions that do everything. For mature projects, almost certainly I want the former (functional side-effect functions that I can test). Always consider be consistent in what style occurs in a codebase. ## Git Operations @@ -109,6 +112,5 @@ Never perform git operations (branch creation, commits, pushes, merges, checkout I like: - Simple solutions -- Small edits that I can review -- Small edits that I can change +- Small edits that I can review & change - Clean low friction interfaces with high information density diff --git a/scripts/funcs.sh b/scripts/funcs.sh index f10701e..68fa19a 100644 --- a/scripts/funcs.sh +++ b/scripts/funcs.sh @@ -188,6 +188,41 @@ tn () { } alias t='tn' +# toggle a One Light theme for the current tmux session (default is dracula) +# note: window options are set per-window, so windows created while this is +# active get dracula window tabs - re-run the toggle to fix +onelight() { + if [[ -z "$TMUX" ]]; then + echo "not in tmux" + return 1 + fi + + local w + if [[ -n "$(tmux show -qv @onelight)" ]]; then + tmux set -u status-style \; set -u status-left \; set -u status-left-length \ + \; set -u status-right \; set -u status-right-length \ + \; set -u message-style \; set -u @onelight + for w in $(tmux list-windows -F '#{window_id}'); do + tmux setw -u -t "$w" window-status-format \ + \; setw -u -t "$w" window-status-current-format \ + \; setw -u -t "$w" window-status-separator + done + else + tmux set status-style 'bg=#f0f0f0,fg=#494b53' \ + \; set status-left '#[fg=#4078f2,bold] #S #[default]' \ + \; set status-left-length 40 \ + \; set status-right '#[fg=#a0a1a7]%H:%M ' \ + \; set status-right-length 20 \ + \; set message-style 'bg=#e5e5e6,fg=#494b53' \ + \; set @onelight 1 + for w in $(tmux list-windows -F '#{window_id}'); do + tmux setw -t "$w" window-status-format '#[fg=#696c77] #I #W ' \ + \; setw -t "$w" window-status-current-format '#[fg=#fafafa,bg=#4078f2] #I #W ' \ + \; setw -t "$w" window-status-separator '' + done + fi +} + # docker From 1aa1d3764c3cabc2641281b269f4611f3a73ecfc Mon Sep 17 00:00:00 2001 From: Adam Green Date: Mon, 21 Sep 2026 01:39:23 +1200 Subject: [PATCH 11/13] feat --- config/nvim/lua/plugins/snacks.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 config/nvim/lua/plugins/snacks.lua diff --git a/config/nvim/lua/plugins/snacks.lua b/config/nvim/lua/plugins/snacks.lua new file mode 100644 index 0000000..68908d8 --- /dev/null +++ b/config/nvim/lua/plugins/snacks.lua @@ -0,0 +1,11 @@ +return { + "folke/snacks.nvim", + priority = 1000, + lazy = false, + ---@type snacks.Config + opts = { + image = { enabled = true }, + bigfile = { enabled = true }, + quickfile = { enabled = true }, + }, +} From d99dd78affe89d49e78788e6e888ce63b46a9b15 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Mon, 21 Sep 2026 01:40:40 +1200 Subject: [PATCH 12/13] feat --- .agents/skills/summarize/SKILL.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .agents/skills/summarize/SKILL.md diff --git a/.agents/skills/summarize/SKILL.md b/.agents/skills/summarize/SKILL.md new file mode 100644 index 0000000..da6dddd --- /dev/null +++ b/.agents/skills/summarize/SKILL.md @@ -0,0 +1,22 @@ +--- +id: SKILL +aliases: [] +tags: [] +description: Summarize text into a bulleted list of ideas and arguments for and against them. +name: summarize +--- + +Summarization responses should be put into Markdown code blocks. + +Summarizing should list every idea, and every argument for and against it. You should add your own commentary if appropriate. Link to other ideas not in the text if you can. Each idea should be a single line with bullet points below it. There should be no Markdown bolding (ie **) of the idea or bullet points. + +Example summarization output: + +```md +This is an idea +- something +- something else + +This is another idea +- another thing +``` From f03f50ea30e5ce4c540c41ce9fa52640bed4b160 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Sun, 4 Oct 2026 00:36:21 +1300 Subject: [PATCH 13/13] feat --- config/nvim/lazy-lock.json | 2 + config/nvim/lua/config/keymap.lua | 10 +- config/nvim/lua/plugins/autopairs.lua | 27 ++- config/nvim/lua/plugins/criticmarkup.lua | 209 +++++++++++++++++++++++ config/nvim/lua/plugins/lsp.lua | 8 + config/nvim/lua/plugins/mini.lua | 2 +- config/nvim/lua/plugins/multicursor.lua | 53 ++++++ config/nvim/lua/plugins/trouble.lua | 2 +- config/nvim/snippets/markdown.json | 24 +++ config/pi/AGENTS.md | 21 +++ scripts/aliases.sh | 2 +- 11 files changed, 347 insertions(+), 13 deletions(-) create mode 100644 config/nvim/lua/plugins/criticmarkup.lua create mode 100644 config/nvim/lua/plugins/multicursor.lua diff --git a/config/nvim/lazy-lock.json b/config/nvim/lazy-lock.json index 2510fff..34ee71d 100644 --- a/config/nvim/lazy-lock.json +++ b/config/nvim/lazy-lock.json @@ -22,6 +22,7 @@ "markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" }, "mini.icons": { "branch": "main", "commit": "520995f1d75da0e4cc901ee95080b1ff2bc46b94" }, "mini.nvim": { "branch": "main", "commit": "44657837c7338e52727facc85c1d95bec1f6bd7c" }, + "multicursor.nvim": { "branch": "1.0", "commit": "704b99f10a72cc05d370cfeb294ff83412a8ab55" }, "nvim-autopairs": { "branch": "master", "commit": "7b9923abad60b903ece7c52940e1321d39eccc79" }, "nvim-bqf": { "branch": "main", "commit": "c282a62bec6c0621a1ef5132aa3f4c9fc4dcc2c7" }, "nvim-colorizer.lua": { "branch": "master", "commit": "5cfe7fffbd01e17b3c1e14af85d5febdef88bd8c" }, @@ -46,6 +47,7 @@ "undotree": { "branch": "master", "commit": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d" }, "vim": { "branch": "master", "commit": "e7b91facff94bdf3a248df9b683119b84672256a" }, "vim-argwrap": { "branch": "master", "commit": "03615d1eed248408567bc8fa6a5a8c94ef3cd170" }, + "vim-criticmarkup": { "branch": "master", "commit": "d15dc134eb177a170c79f6377f81eb02a9d20b02" }, "vim-fugitive": { "branch": "master", "commit": "3b753cf8c6a4dcde6edee8827d464ba9b8c4a6f0" }, "vim-markdown": { "branch": "master", "commit": "1bc9d0cd8e1cc3e901b0a49c2b50a843f1c89397" }, "vim-markdown-toc": { "branch": "master", "commit": "66026b323379c9a712c6169cd43153216acef090" }, diff --git a/config/nvim/lua/config/keymap.lua b/config/nvim/lua/config/keymap.lua index 9721b95..eaa7364 100644 --- a/config/nvim/lua/config/keymap.lua +++ b/config/nvim/lua/config/keymap.lua @@ -50,7 +50,7 @@ km("n", "fv", ":vsplit | ObsidianFollowLink", opts) km("n", "h", ":sp ~/.zsh_history", opts) -- Insert current file path -km("n", "r", ":r! echo %:p", opts) +km("n", "R", ":r! echo %:p", opts) -- Rebalance windows km("n", "b", "=", opts) @@ -89,7 +89,6 @@ vim.keymap.set("n", "dd", function() end, { desc = "Toggle Diffview" }) km("n", "w", ":WinResizerStartResize", opts) -km("v", "ll", ":Noice dismiss", opts) -- Telescope -- Search diagnostics @@ -109,11 +108,8 @@ km("n", "'", ":lua require'telescope.builtin'.oldfiles(require('telescop km("n", "ro", ":lua require'telescope.builtin'.oldfiles(require('telescope.themes').get_ivy({}))", opts) km("n", "rr", ":lua require'telescope.builtin'.oldfiles(require('telescope.themes').get_ivy({}))", opts) --- Search for a string --- km("n", "rc", ":lua require'telescope.builtin'.live_grep(require('telescope.themes').get_ivy({}))", opts) -- Search for a string under cursor km("n", "rc", ":lua require'telescope.builtin'.grep_string(require('telescope.themes').get_ivy({}))", opts) -km("n", "rg", ":lua require'telescope.builtin'.grep_string(require('telescope.themes').get_ivy({}))", opts) -- Search for a string under cursor - mapped twice km("n", "g", ":lua require'telescope.builtin'.grep_string(require('telescope.themes').get_ivy({}))", opts) vim.keymap.set("n", ".", function() @@ -124,7 +120,7 @@ end, opts) km("n", "rg", ":lua require'telescope.builtin'.live_grep(require('telescope.themes').get_ivy({}))", opts) -- Search for current word in current buffer -vim.keymap.set("n", "rgg", function() +vim.keymap.set("n", "rb", function() require("telescope.builtin").current_buffer_fuzzy_find(require("telescope.themes").get_ivy({ hidden = true, default_text = vim.fn.expand(""), @@ -136,7 +132,7 @@ vim.keymap.set("n", "o", "split | Oil") -- CopilotChat vim.keymap.set("n", "c", ":CopilotChat") -vim.keymap.set("n", "sc", function() +vim.keymap.set("n", "C", function() require("CopilotChat").toggle({ window = { layout = "horizontal" } }) end, { desc = "Toggle Copilot Chat (horizontal)" }) diff --git a/config/nvim/lua/plugins/autopairs.lua b/config/nvim/lua/plugins/autopairs.lua index fba60b3..dcab117 100644 --- a/config/nvim/lua/plugins/autopairs.lua +++ b/config/nvim/lua/plugins/autopairs.lua @@ -33,9 +33,30 @@ return { }) local Rule = require("nvim-autopairs.rule") - npairs.add_rules({ - Rule("/*", "*/", "sql"), - }) + local rules = { Rule("/*", "*/", "sql") } + + -- CriticMarkup: typing `{++` leaves the cursor inside `{++|++}`. blink can't + -- complete these as snippets because its keyword scanner treats `{` and `+` + -- as non-keyword, so the prefix reads as an empty string. + for _, marker in ipairs({ + { "{++", "++}" }, + { "{--", "--}" }, + { "{==", "==}" }, + { "{>>", "<<}" }, + { "{~~", "~>~~}" }, + }) do + local open, close = marker[1], marker[2] + table.insert( + rules, + Rule(open, close, { "markdown", "pandoc", "text" }):replace_endpair(function(opts) + -- the default { } rule has usually already inserted the closing + -- brace; it is absent when the next char suppressed pairing + return vim.startswith(opts.next_char or "", "}") and close:sub(1, -2) or close + end) + ) + end + + npairs.add_rules(rules) -- Integration with blink.cmp is handled automatically end, diff --git a/config/nvim/lua/plugins/criticmarkup.lua b/config/nvim/lua/plugins/criticmarkup.lua new file mode 100644 index 0000000..62024f6 --- /dev/null +++ b/config/nvim/lua/plugins/criticmarkup.lua @@ -0,0 +1,209 @@ +-- CriticMarkup annotations for prose review: +-- {++added++} {--deleted--} {~~old~>new~~} {>>comment<<} {==highlight==} +-- +-- No keymaps. Write annotations with the `critic-*` snippets in snippets/markdown.json, +-- and resolve them with `:Critic accept` / `:Critic reject` on the cursor annotation. +-- +-- The upstream plugin is deliberately neutered — we clear its augroup, which is the +-- only thing that sources its autoload file. That file is broken for this config: +-- * it declares e{a,d,h,c,s} as `` maps at top level, so they +-- bind to whichever buffer is current when it loads and never apply again +-- * it declares ]m / [m as global `nmap`, clobbering the built-in method motions +-- in every filetype +-- * its Accept()/Reject() detect the annotation kind with synID(), which returns 0 +-- because treesitter.lua sets additional_vim_regex_highlighting = false +-- (ie syntax=off) — so its own :Critic silently does nothing +-- +-- Highlighting uses matchadd() for the same syntax=off reason: the plugin's +-- `syn region` definitions never render. Match highlighting combines over +-- treesitter's extmarks, so it shows without touching the treesitter config. + +local filetypes = { "markdown", "pandoc", "text" } + +-- Lua patterns and the resolvers that turn captures into replacement text. +-- Substitution captures old and new; the rest capture a single body. +local annotations = { + { + pattern = "%{%+%+(.-)%+%+%}", + group = "CriticAddition", + accept = function(text) + return text + end, + reject = function() + return "" + end, + }, + { + pattern = "%{%-%-(.-)%-%-%}", + group = "CriticDeletion", + accept = function() + return "" + end, + reject = function(text) + return text + end, + }, + { + pattern = "%{~~(.-)~>(.-)~~%}", + group = "CriticSubstitution", + accept = function(_, new) + return new + end, + reject = function(old) + return old + end, + }, + { + pattern = "%{==(.-)==%}", + group = "CriticHighlight", + accept = function(text) + return text + end, + reject = function(text) + return text + end, + }, + { + pattern = "%{>>(.-)<<%}", + group = "CriticComment", + accept = function() + return "" + end, + reject = function() + return "" + end, + }, +} + +-- Very-nomagic vim regexes for matchadd(). +local match_patterns = { + CriticAddition = [[\V{++\_.\{-}++}]], + CriticDeletion = [[\V{--\_.\{-}--}]], + CriticSubstitution = [[\V{~~\_.\{-}~~}]], + CriticHighlight = [[\V{==\_.\{-}==}]], + CriticComment = [[\V{>>\_.\{-}<<}]], +} + +local highlight_links = { + CriticAddition = "DiffAdd", + CriticDeletion = "DiffDelete", + CriticSubstitution = "DiffChange", + CriticHighlight = "Search", + CriticComment = "Comment", +} + +local function set_highlights() + for group, link in pairs(highlight_links) do + vim.api.nvim_set_hl(0, group, { link = link, default = true }) + end +end + +--- Byte offset of the cursor in the current buffer, 0-indexed. +local function cursor_offset() + local row, col = unpack(vim.api.nvim_win_get_cursor(0)) + return vim.api.nvim_buf_get_offset(0, row - 1) + col +end + +--- Convert a 0-indexed byte offset to a (row, col) pair for nvim_buf_set_text. +local function offset_to_position(offset) + local row = vim.fn.byte2line(offset + 1) - 1 + return row, offset - vim.api.nvim_buf_get_offset(0, row) +end + +--- Innermost annotation containing the cursor, or nil. +local function find_annotation() + local text = table.concat(vim.api.nvim_buf_get_lines(0, 0, -1, false), "\n") + local offset = cursor_offset() + local found = nil + + for _, annotation in ipairs(annotations) do + local from = 1 + while true do + local start, finish, first, second = text:find(annotation.pattern, from) + if not start then + break + end + -- find() is 1-indexed and inclusive; offset is 0-indexed + local inside = offset >= start - 1 and offset < finish + if inside and (not found or start - 1 > found.start) then + found = { + annotation = annotation, + start = start - 1, + finish = finish, + captures = { first, second }, + } + end + from = start + 1 + end + end + + return found +end + +local function resolve(action) + if action ~= "accept" and action ~= "reject" then + vim.notify("Critic takes 'accept' or 'reject', got " .. vim.inspect(action), vim.log.levels.ERROR) + return + end + + local found = find_annotation() + if not found then + vim.notify("No CriticMarkup annotation under cursor", vim.log.levels.WARN) + return + end + + local replacement = found.annotation[action](unpack(found.captures)) + local start_row, start_col = offset_to_position(found.start) + local end_row, end_col = offset_to_position(found.finish) + vim.api.nvim_buf_set_text(0, start_row, start_col, end_row, end_col, vim.split(replacement, "\n")) +end + +local function attach_matches() + if not vim.tbl_contains(filetypes, vim.bo.filetype) or vim.w.criticmarkup_matches then + return + end + for group, pattern in pairs(match_patterns) do + vim.fn.matchadd(group, pattern, 20) + end + vim.w.criticmarkup_matches = true +end + +local function attach_command(buffer) + vim.api.nvim_buf_create_user_command(buffer, "Critic", function(args) + resolve(args.args) + end, { + nargs = 1, + complete = function() + return { "accept", "reject" } + end, + desc = "Accept or reject the CriticMarkup annotation under the cursor", + }) +end + +return { + "vim-pandoc/vim-criticmarkup", + ft = filetypes, + config = function() + -- Clearing the plugin's own augroup stops it ever sourcing its autoload file, + -- so none of its mappings or syntax regions are installed. + pcall(vim.api.nvim_del_augroup_by_name, "criticmarkup") + + set_highlights() + + local group = vim.api.nvim_create_augroup("criticmarkup_config", { clear = true }) + vim.api.nvim_create_autocmd("ColorScheme", { group = group, callback = set_highlights }) + vim.api.nvim_create_autocmd("FileType", { + group = group, + pattern = filetypes, + callback = function(args) + attach_command(args.buf) + end, + }) + -- matchadd() is window-local, so re-apply whenever a buffer lands in a window. + vim.api.nvim_create_autocmd({ "BufWinEnter", "WinNew" }, { group = group, callback = attach_matches }) + + -- The ft trigger means FileType and BufWinEnter already fired for this buffer. + attach_command(0) + attach_matches() + end, +} diff --git a/config/nvim/lua/plugins/lsp.lua b/config/nvim/lua/plugins/lsp.lua index 05a83f6..c007f58 100644 --- a/config/nvim/lua/plugins/lsp.lua +++ b/config/nvim/lua/plugins/lsp.lua @@ -141,6 +141,14 @@ return { } vim.lsp.enable("html") + -- marksman (markdown) + vim.lsp.config["marksman"] = { + cmd = { "marksman", "server" }, + filetypes = { "markdown" }, + root_markers = { ".marksman.toml", ".git" }, + } + vim.lsp.enable("marksman") + -- LSP keymaps and features on attach vim.api.nvim_create_autocmd("LspAttach", { callback = function(args) diff --git a/config/nvim/lua/plugins/mini.lua b/config/nvim/lua/plugins/mini.lua index 8a3aa95..ea5f8b4 100644 --- a/config/nvim/lua/plugins/mini.lua +++ b/config/nvim/lua/plugins/mini.lua @@ -28,7 +28,7 @@ return { require("mini.operators").setup() -- keymap for zoom - vim.keymap.set("n", "z", require("mini.misc").zoom, { desc = "Zoom current buffer" }) + vim.keymap.set("n", "Z", require("mini.misc").zoom, { desc = "Zoom current buffer" }) -- enhanced text objects require("mini.ai").setup({ diff --git a/config/nvim/lua/plugins/multicursor.lua b/config/nvim/lua/plugins/multicursor.lua new file mode 100644 index 0000000..5353163 --- /dev/null +++ b/config/nvim/lua/plugins/multicursor.lua @@ -0,0 +1,53 @@ +return { + "jake-stewart/multicursor.nvim", + branch = "1.0", + config = function() + local mc = require("multicursor-nvim") + mc.setup() + + local set = vim.keymap.set + + -- add or skip cursor above/below the main cursor + set({ "n", "x" }, "", function() mc.lineAddCursor(-1) end) + set({ "n", "x" }, "", function() mc.lineAddCursor(1) end) + set({ "n", "x" }, "", function() mc.lineSkipCursor(-1) end) + set({ "n", "x" }, "", function() mc.lineSkipCursor(1) end) + + -- add or skip a cursor by matching word/selection + set({ "n", "x" }, "n", function() mc.matchAddCursor(1) end) + set({ "n", "x" }, "s", function() mc.matchSkipCursor(1) end) + set({ "n", "x" }, "N", function() mc.matchAddCursor(-1) end) + set({ "n", "x" }, "S", function() mc.matchSkipCursor(-1) end) + + -- disable and enable cursors + set({ "n", "x" }, "", mc.toggleCursor) + + -- these mappings only apply while multiple cursors exist + mc.addKeymapLayer(function(layerSet) + -- select a different cursor as the main one + layerSet({ "n", "x" }, "", mc.prevCursor) + layerSet({ "n", "x" }, "", mc.nextCursor) + + -- delete the main cursor + layerSet({ "n", "x" }, "x", mc.deleteCursor) + + -- esc clears cursors (or re-enables them if disabled) + layerSet("n", "", function() + if not mc.cursorsEnabled() then + mc.enableCursors() + else + mc.clearCursors() + end + end) + end) + + local hl = vim.api.nvim_set_hl + hl(0, "MultiCursorCursor", { reverse = true }) + hl(0, "MultiCursorVisual", { link = "Visual" }) + hl(0, "MultiCursorSign", { link = "SignColumn" }) + hl(0, "MultiCursorMatchPreview", { link = "Search" }) + hl(0, "MultiCursorDisabledCursor", { reverse = true }) + hl(0, "MultiCursorDisabledVisual", { link = "Visual" }) + hl(0, "MultiCursorDisabledSign", { link = "SignColumn" }) + end, +} diff --git a/config/nvim/lua/plugins/trouble.lua b/config/nvim/lua/plugins/trouble.lua index 40b33c2..52facb5 100644 --- a/config/nvim/lua/plugins/trouble.lua +++ b/config/nvim/lua/plugins/trouble.lua @@ -4,7 +4,7 @@ return { dependencies = "nvim-tree/nvim-web-devicons", cmd = "Trouble", keys = { - { "gt", "Trouble diagnostics toggle", desc = "Diagnostics (Trouble)" }, + { "T", "Trouble diagnostics toggle", desc = "Diagnostics (Trouble)" }, }, opts = { auto_open = false, diff --git a/config/nvim/snippets/markdown.json b/config/nvim/snippets/markdown.json index 91cb810..45f3c12 100644 --- a/config/nvim/snippets/markdown.json +++ b/config/nvim/snippets/markdown.json @@ -22,5 +22,29 @@ "`": { "prefix": "`", "body": ["```$1", "```"] + }, + "critic-add": { + "prefix": "critic-add", + "body": ["{++$1++}"] + }, + "critic-delete": { + "prefix": "critic-delete", + "body": ["{--$1--}"] + }, + "critic-substitute": { + "prefix": "critic-substitute", + "body": ["{~~$1~>$2~~}"] + }, + "critic-comment": { + "prefix": "critic-comment", + "body": ["{>>$1<<}"] + }, + "critic-highlight": { + "prefix": "critic-highlight", + "body": ["{==$1==}"] + }, + "critic-highlight-comment": { + "prefix": "critic-highlight-comment", + "body": ["{==$1==}{>>$2<<}"] } } diff --git a/config/pi/AGENTS.md b/config/pi/AGENTS.md index 59b765d..2456d48 100644 --- a/config/pi/AGENTS.md +++ b/config/pi/AGENTS.md @@ -9,6 +9,25 @@ You are an expert software engineer and data scientist, writing excellent code. - Push back — offer different ideas, approaches, and perspectives - Always create a plan and ask to execute before implementing. No plan is OK for simple change, but always ask before executing or editing - If confused, ask a question rather than spinning +- Consider if ASD-STE100 Simplified Technical English (STE) is appropriate - ask if you are not sure if you should be using it or not. I don't always want STE. + +## Concision + +Default to short. My own drafts run ~80 words where yours run ~450 — assume +mine is the target length, not a trimmed version of yours. This applies to +everything you write: replies to me, code comments, commit messages, +documentation, and anything you draft for me to send onward. It bites hardest +in correspondence, where length reads as anxiety, but the habit is general. + +- Minimize the amount of questions answered - if a question depends on the answer of another, only ask the other. +- Don't argue for the answer you want. Make the point and stop. +- Don't pre-empt objections or add reassurance nobody asked for. +- State the why once, briefly, at the end. Don't open with it. +- Structure has to earn its place. Headings, bold, and Option A/Option B +- Cut the throat-clearing. Start at the first real sentence. +- Use " - " spaced hyphens, not em dashes. Parentheticals as "(ie ...)". + +Exception: plans, notes, and technical docs stay detailed. Concision is about not padding — it is not about withholding substance. If something genuinely needs length, give it length. ## How to Act @@ -27,6 +46,8 @@ Read deeply, in great detail. Note intricacies. Go through everything. Plans should be organized by date - use a string of `YYYY-MM` to group plans. +Use ASD-STE100 Simplified Technical English (STE) always when planning. + Plans go in `./docs/ai/YYYY-MM/plan-$NAME.md`. Always start filename with `plan-`. Old plans may exist in `./ai/plan-$NAME.md` or `./ai/docs/plan-$NAME.md` — if found, stop and ask what to do. diff --git a/scripts/aliases.sh b/scripts/aliases.sh index 1eccd46..c77a07e 100755 --- a/scripts/aliases.sh +++ b/scripts/aliases.sh @@ -53,7 +53,7 @@ alias ipy='ipython' alias pipr='pip install -r requirements.txt' # files -alias cheat='$EDITOR $PERSONAL_PATH/resource/cheat_sheet.md' +alias cheat='$EDITOR $PERSONAL_PATH/area/cheat_sheet.md' alias ideas='$EDITOR $HOME/dss/notes/content/ideas/README.md' alias inbox='$EDITOR $PERSONAL_PATH/area/inbox/inbox.md' alias ibx='inbox'