diff --git a/.agents/skills/review-plan/SKILL.md b/.agents/skills/review-plan/SKILL.md
index 2a4768ec..bd27f7ce 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/.agents/skills/summarize/SKILL.md b/.agents/skills/summarize/SKILL.md
new file mode 100644
index 00000000..da6dddd8
--- /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
+```
diff --git a/.gitignore b/.gitignore
index e8247e29..1cb0ece7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
.pytest_cache
.python-version
.testmondata
+.venv/**
.venv
Music
NVIDIA*
diff --git a/Makefile b/Makefile
index 26c9250d..fb101b88 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 e787ebe7..3cc90a33 100644
--- a/README.md
+++ b/README.md
@@ -103,81 +103,60 @@ 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.
-### `s`
+- `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
-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.
+Important keymaps:
-### Aliases
+- `gl`
+- `gll`
+- `zt`
+- `zz`
+- `zb`
-Lot's of aliases - see `./scripts/aliases.sh`. Some small interactive shell helper functions in `./scripts/funcs.sh`.
+### Gitignore
-## AI Configuration
+There is one global ignore file, `./dotfiles/.gitignore`, stowed to `~/.gitignore`. It is wired in by `core.excludesfile` in `./dotfiles/.gitconfig`:
-Two AGENTS.md:
+```
+[core]
+ excludesfile = ~/dotfiles/dotfiles/.gitignore
+```
-- `./AGENTS.md` for this repo
-- `./pi/config/pi/agent/AGENTS.md` for Pi & Claude Code
+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.
-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.
+Two consequences worth knowing:
-CLAUDE.md at the repo root serves the same purpose for Claude Code, but is symlinked to `AGENTS.md`.
+- 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.
-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
-```
+### `s`
-## Agent Configuration
+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.
-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.
+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.
-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
-```
+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
+
+Lot's of aliases - see `./scripts/aliases.sh`. Some small interactive shell helper functions in `./scripts/funcs.sh`.
-## Agent Configuration
+## AI Configuration
+
+Agents are configured twice using two AGENTS.md:
+
+- `./AGENTS.md` for this repo
+- `./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.
+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` (for Pi) and `~/.claude/skills` (for Claude Code).
+Skills are defined once in agents/skills/ and symlinked by make dotfiles to both ~/.agents/skills (pi) and ~/.claude/skills (Claude Code).
diff --git a/config/brew/Brewfile b/config/brew/Brewfile
index 936b183c..f65cb7e2 100644
--- a/config/brew/Brewfile
+++ b/config/brew/Brewfile
@@ -127,4 +127,7 @@ tap "databricks/tap"
brew "databricks"
brew "marp-cli"
brew "btop"
-brew "gum"
\ No newline at end of file
+brew "gum"
+brew "ov" # csv viewer
+
+brew "aspell"
diff --git a/config/lsd/config.yaml b/config/lsd/config.yaml
index b390f3af..6f552894 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/nvim/lazy-lock.json b/config/nvim/lazy-lock.json
index ed5e857b..34ee71d3 100644
--- a/config/nvim/lazy-lock.json
+++ b/config/nvim/lazy-lock.json
@@ -1,52 +1,53 @@
{
"CopilotChat.nvim": { "branch": "main", "commit": "f0c2a23ab79dc295f5e0eef0d8b587a39020c852" },
"Vim-Jinja2-Syntax": { "branch": "master", "commit": "2c17843b074b06a835f88587e1023ceff7e2c7d1" },
- "barbar.nvim": { "branch": "master", "commit": "539d73def39c9172b4d4d769f14090e08f37b29d" },
+ "barbar.nvim": { "branch": "master", "commit": "a4bef5b4fc1f064f2f673172252028eae18191c9" },
"blink-cmp-copilot": { "branch": "main", "commit": "439cff78780c033aa23cf061d7315314b347e3c1" },
- "blink-cmp-dictionary": { "branch": "master", "commit": "35142bba869b869715e91a99d2f46bcf93fca4ae" },
- "blink-cmp-env": { "branch": "main", "commit": "99af62c1f9aa46005e8f50ad4ccee581946546ca" },
+ "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": "d84a20e765fdc9cc8c0775708e083e7185654527" },
+ "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" },
- "codecompanion.nvim": { "branch": "main", "commit": "680c445eb357c72129d175ea5d481aa9e92ae6a5" },
- "conform.nvim": { "branch": "master", "commit": "086a40dc7ed8242c03be9f47fbcee68699cc2395" },
- "copilot.lua": { "branch": "master", "commit": "adff470bca742b7658228ed144589250ecb3dc0a" },
+ "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": "6d808f99bd63303646794406e270bd553ad7792e" },
+ "gitsigns.nvim": { "branch": "main", "commit": "dd3f588bacbeb041be6facf1742e42097f62165d" },
"indent-blankline.nvim": { "branch": "master", "commit": "d28a3f70721c79e3c5f6693057ae929f3d9c0a03" },
- "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
- "lualine.nvim": { "branch": "master", "commit": "a905eeebc4e63fdc48b5135d3bf8aea5618fb21c" },
+ "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" },
+ "lualine.nvim": { "branch": "master", "commit": "131a558e13f9f28b15cd235557150ccb23f89286" },
"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" },
+ "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" },
- "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-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": "c72328a5494b4502947a022fe69c0c47e53b6aa6" },
+ "nvim-web-devicons": { "branch": "master", "commit": "0d7d35fa946837b8738b17c18d1faa1ac351e7f9" },
"obsidian.nvim": { "branch": "main", "commit": "ae1f76a75c7ce36866e1d9342a8f6f5b9c2caf9b" },
- "oil.nvim": { "branch": "master", "commit": "0fcc83805ad11cf714a949c98c605ed717e0b83e" },
+ "oil.nvim": { "branch": "master", "commit": "21c669e7bfeb1546ae988b52813138e4d674bbf5" },
"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" },
+ "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": "506338434fec5ad19cb1f8d45bf92d66c4917393" },
+ "telescope.nvim": { "branch": "master", "commit": "7d324792b7943e4aa16ad007212e6acc6f9fe335" },
"trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" },
"undotree": { "branch": "master", "commit": "6fa6b57cda8459e1e4b2ca34df702f55242f4e4d" },
- "vim": { "branch": "master", "commit": "07b144414730cc4cf4405ab840bf46c5fa12704b" },
+ "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/command.lua b/config/nvim/lua/config/command.lua
index ecb72563..adf20816 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/config/keymap.lua b/config/nvim/lua/config/keymap.lua
index 89aaf9bd..eaa73641 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)
@@ -78,8 +78,17 @@ 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)
-- Telescope
-- Search diagnostics
@@ -99,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()
@@ -114,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(""),
@@ -126,10 +132,21 @@ 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)" })
+-- 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 c9ca6610..69cfd65f 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 da14db1a..5ad18ea7 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/autopairs.lua b/config/nvim/lua/plugins/autopairs.lua
index fba60b3b..dcab1179 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/copilot.lua b/config/nvim/lua/plugins/copilot.lua
index 5c1f8918..7f25be59 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
@@ -59,11 +69,10 @@ 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,
- insert_at_end = true,
auto_follow_cursor = false,
history_path = vim.fn.stdpath("data") .. "/copilotchat_history",
},
diff --git a/config/nvim/lua/plugins/criticmarkup.lua b/config/nvim/lua/plugins/criticmarkup.lua
new file mode 100644
index 00000000..62024f6c
--- /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 04da5d69..c007f581 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)
@@ -131,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 8a3aa95f..ea5f8b40 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 00000000..5353163e
--- /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/semshi.lua b/config/nvim/lua/plugins/semshi.lua
deleted file mode 100644
index a5647075..00000000
--- a/config/nvim/lua/plugins/semshi.lua
+++ /dev/null
@@ -1 +0,0 @@
-return {}
diff --git a/config/nvim/lua/plugins/snacks.lua b/config/nvim/lua/plugins/snacks.lua
new file mode 100644
index 00000000..68908d8d
--- /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 },
+ },
+}
diff --git a/config/nvim/lua/plugins/telescope.lua b/config/nvim/lua/plugins/telescope.lua
index 715bc2a3..fea410a7 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/nvim/lua/plugins/trouble.lua b/config/nvim/lua/plugins/trouble.lua
index 4b11d965..52facb5c 100644
--- a/config/nvim/lua/plugins/trouble.lua
+++ b/config/nvim/lua/plugins/trouble.lua
@@ -2,8 +2,9 @@ return {
{
"folke/trouble.nvim",
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 91cb8101..45f3c127 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 a079e0cf..2456d482 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.
@@ -91,6 +112,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,4 +133,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 review & change
+- Clean low friction interfaces with high information density
diff --git a/dotfiles/.gitconfig b/dotfiles/.gitconfig
index d6697339..310cff5e 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/dotfiles/.gitignore b/dotfiles/.gitignore
index a4916016..9b3a669b 100644
--- a/dotfiles/.gitignore
+++ b/dotfiles/.gitignore
@@ -21,6 +21,7 @@
.python-version
.testmondata
.venv
+.wrangler
Music
NVIDIA*
__pycache__
diff --git a/scripts/aliases.sh b/scripts/aliases.sh
index dd1fe6c5..c77a07e4 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'
@@ -51,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'
@@ -171,3 +173,8 @@ alias ai='claude'
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'
+
+alias dr='bash $PERSONAL_PATH/area/scripts/show-drafts.sh'
diff --git a/scripts/funcs.sh b/scripts/funcs.sh
index f10701e8..68fa19a5 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
diff --git a/scripts/search.sh b/scripts/search.sh
index a80dac16..29f89ac4 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
diff --git a/scripts/todo/todo.go b/scripts/todo/todo.go
index 3dce1554..c3020776 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 {