mirror of
https://github.com/dwinkler1/nvimConfig.git
synced 2026-09-20 06:27:23 -04:00
Moved pyarrow overlay to overlays, cleanup
This commit is contained in:
parent
b630932348
commit
a4bae164c3
14 changed files with 165 additions and 589 deletions
|
|
@ -1,85 +0,0 @@
|
||||||
# CodeCompanion Revamp Plan
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
- Current: CodeCompanion **19.18.0** via nixpkgs `vimPlugins.codecompanion-nvim` (nixpkgs input lastModified ~2026-05-15).
|
|
||||||
- Latest: **19.20.0**. Key changes since 19.18.0:
|
|
||||||
- v19.19.0: `claude-sonnet-5` support, async/dynamic model fetching, copilot `top_p` fixes, inline orphaned-keymap fix, background command deregistration.
|
|
||||||
- v19.20.0: `gemini_interactions` adapter, PDF support for http adapters (`/file` on Anthropic/Copilot/OpenAI/OpenRouter), env vars from files, prompt-library items auto-receive default rule groups, copilot schema options removed.
|
|
||||||
- **Bug in current setup:** config sets `model = "claude-sonnet-5"` but 19.18.0 predates its support; the model name may not resolve. The nixpkgs bump fixes this.
|
|
||||||
- Files involved:
|
|
||||||
- `plugin/24_completion.lua` — `get_codecompanion_config()`, setup, blink integration.
|
|
||||||
- `plugin/10_keymap.lua` — `<leader>a*` keymaps (lines 69–84, contains duplicates/commented cruft).
|
|
||||||
- `overlays/plugins.nix` — codecompanion overlay (nvimSkipModules); likely unchanged.
|
|
||||||
- `modules/module/specs/plugins.nix` — plugin spec; unchanged.
|
|
||||||
|
|
||||||
## Decisions (confirmed with user)
|
|
||||||
|
|
||||||
1. **Version bump:** `nix flake update nixpkgs` (accepts wider plugin bump; do NOT override src).
|
|
||||||
2. **Adopt:** agent-mode keymaps, one workflow prompt, minor slash-command config (`/share` token). **No MCP.**
|
|
||||||
3. **Models:** `claude-sonnet-5` (copilot) for **chat only**; cheaper copilot model for **inline** and **background** (title generation) — use `gpt-5-mini` as placeholder; verify exact model id via `ga` model picker in a chat buffer after the bump and adjust.
|
|
||||||
4. **Codex (ChatGPT Edu) = heavy agent lane.** Copilot stays the default chat adapter; Codex ACP is launched explicitly for heavy autonomous tasks. Auth via ChatGPT login only (no API key) — user's existing `auth_method = "chatgpt"` is correct per the v19.20.0 adapter source (`"openai-api-key"|"codex-api-key"|"chatgpt"`; the docs page comment `"chat-gpt"` is stale).
|
|
||||||
|
|
||||||
## Tasks
|
|
||||||
|
|
||||||
1. **Bump nixpkgs**
|
|
||||||
- Run `nix flake update nixpkgs`.
|
|
||||||
- Verify: `nix eval --raw nixpkgs#vimPlugins.codecompanion-nvim.version` reports ≥ 19.20.0.
|
|
||||||
- Rebuild the wrapped Neovim per this repo's normal build (`nix build` / the repo's usual package target) and smoke-test that the editor starts.
|
|
||||||
|
|
||||||
2. **`plugin/24_completion.lua` — `get_codecompanion_config()`**
|
|
||||||
- Keep `interactions.chat.adapter = { name = "copilot", model = "claude-sonnet-5" }`.
|
|
||||||
- Change `interactions.inline.adapter` to `{ name = "copilot", model = "gpt-5-mini" }` (cheap/fast).
|
|
||||||
- Add a background adapter so title generation doesn't use Sonnet: set the background chat adapter to copilot/`gpt-5-mini` (config lives under `interactions.background.chat`; confirm exact key against `:h codecompanion` / `:checkhealth codecompanion` after the bump — the docs page "Generating Titles" says an adapter must be configured for background interactions).
|
|
||||||
- Keep existing context_management, rules, display, shared keymaps unchanged.
|
|
||||||
- Add `interactions.chat.slash_commands["share"].opts.token = os.getenv("GITHUB_GIST_TOKEN")`.
|
|
||||||
- **Prompt library additions** (keep `expert`, `fixer`, `suggest`):
|
|
||||||
- `["agent"]`: interaction "chat", alias `agent`, first user prompt starts with `@{agent}` plus selected code block, so Copilot/Claude gets the file-editing tool group (read_file, insert_edit_into_file, grep_search, run_command, etc., with approvals).
|
|
||||||
- `["tdd"]` (name flexible): interaction "chat", `opts = { is_workflow = true, alias = "tdd" }` — 3-stage workflow: (1) plan/understand `#buffer`, (2) `@{agent}` implement, (3) `@{run_command}` run the test suite (leverages run_command's test-flag for agentic workflows).
|
|
||||||
|
|
||||||
3. **`plugin/10_keymap.lua` — clean up + add**
|
|
||||||
- Remove duplicated/commented lines (70–71, 77, 81).
|
|
||||||
- Add:
|
|
||||||
- `nmap_leader("aa", "<cmd>CodeCompanionChat<CR>", "Agent chat (use @{agent})")` or directly `<cmd>CodeCompanion /agent<CR>`.
|
|
||||||
- `xmap_leader("aa", "<cmd>CodeCompanion /agent<CR>", "Agent on selection")`.
|
|
||||||
- `nmap_leader("aw", "<cmd>CodeCompanion /tdd<CR>", "Workflow: plan→implement→test")`.
|
|
||||||
- `nmap_leader("aC", "<cmd>CodeCompanion /compact<CR>", "Compact chat")` (verify `<leader>aC` doesn't clash).
|
|
||||||
- Keep existing mappings unchanged.
|
|
||||||
|
|
||||||
4. **No changes** to `overlays/plugins.nix` or `modules/module/specs/plugins.nix` unless the new version introduces new lazy-module load failures (re-run the build's check phase; `doCheck = false` is already set on the spec entry).
|
|
||||||
|
|
||||||
5. **Codex ACP lane (ChatGPT Edu)**
|
|
||||||
- **Resolved prerequisite:** user has installed `codex-acp` at `~/.nix-profile/bin/codex-acp` (verified on PATH 2026-07-24). The preset adapter's default command (`codex-acp`) now works as-is — **no `commands` override in the Lua config**. Fallback only if the binary misbehaves: override with `commands = { default = { "codex", "acp" } }` (requires the codex CLI's built-in `acp` subcommand; verify with `codex acp --help`).
|
|
||||||
- **Config change (small):** none strictly required — the existing `extend("codex", { defaults = { auth_method = "chatgpt" } })` block in `plugin/24_completion.lua` is correct. Keep it.
|
|
||||||
- Auth: prereq is an active `codex login` session with the ChatGPT Edu account (`~/.codex/auth.json` exists — user confirms validity; if expired, re-run `codex login`, browser/ChatGPT-app flow, no API key).
|
|
||||||
- Keep codex on-demand (do NOT make it the default chat adapter):
|
|
||||||
- Keep `<leader>ak` (`:CodeCompanionChat adapter=codex`).
|
|
||||||
- Add comment documenting ACP-only slash commands for this lane: `/resume` (restore past codex session, fresh chat only), `/mode` (switch agent mode), `/command`, `/acp_session_options`, plus `\`-triggered ACP command completion in the chat buffer.
|
|
||||||
- Do not set a default codex model in config; pick per-session via `ga` / `/acp_session_options` (avoids hardcoding model ids that change with the Edu plan).
|
|
||||||
- PATH note: Neovim must inherit a PATH containing `~/.nix-profile/bin` so the spawned `codex-acp` resolves — true when nvim is launched from the user's normal shell; call it out if validation fails with "command not found".
|
|
||||||
|
|
||||||
6. **Docs/habit notes** (add as comment block above the codecompanion setup, no separate docs file): `/compact`, `/fork`, `/symbols`, `/share`, `/resume`+`/mode` (codex ACP), `gm` (btw), `gty` (YOLO), `gba`/`gbd` (buffer sync), `gd` (debug window).
|
|
||||||
|
|
||||||
## Validation
|
|
||||||
|
|
||||||
- `nix flake update nixpkgs` then repo build succeeds.
|
|
||||||
- In Neovim: `:checkhealth codecompanion` clean.
|
|
||||||
- `:CodeCompanionChat`, press `ga` → copilot adapter lists `claude-sonnet-5`; send a trivial message and confirm response + auto title generation.
|
|
||||||
- In chat: type `@` → completion shows `agent`, `files`, `memory`, etc.; run `@{agent}` task on a scratch repo and confirm the approval prompt flow works.
|
|
||||||
- `:CodeCompanion /tdd` starts the workflow stages in order.
|
|
||||||
- Inline: visual-select code, `:CodeCompanion` prompt → confirm diff shows and `ga`/`gr` accept/reject still work on the cheap model.
|
|
||||||
- `:CodeCompanion /share` prompts/errors sensibly if `GITHUB_GIST_TOKEN` unset.
|
|
||||||
- **Codex lane:** `<leader>ak` opens a chat with the codex ACP adapter; the spawned `codex-acp` process initializes without auth errors (ChatGPT method), a trivial prompt gets a response, and `/mode` lists codex session modes. If it fails with command-not-found, check that Neovim inherited `~/.nix-profile/bin` in PATH (`:echo $PATH` inside nvim).
|
|
||||||
|
|
||||||
## Risks
|
|
||||||
|
|
||||||
- `nix flake update nixpkgs` bumps **all** vimPlugins and Neovim itself; other plugins may break. If the blast radius is too large, fall back to overriding codecompanion `src` to tag `v19.20.0` in `overlays/plugins.nix` (fetchFromGitHub, `doCheck = false`).
|
|
||||||
- Model ids (`claude-sonnet-5`, `gpt-5-mini`) must match the copilot adapter's choices post-bump; verify via `ga` picker and adjust literals.
|
|
||||||
- `gpt-5-mini` may not support tool use on copilot — fine, since inline/background don't use tools.
|
|
||||||
- `codex-acp` lives in the user's nix profile (outside this flake). If the profile is rebuilt/removed, the codex lane breaks — long-term consider adding `codex-acp` to this flake's runtime deps so it's pinned with the rest of the setup (optional follow-up, not required now).
|
|
||||||
- ChatGPT Edu accounts authenticate codex via browser/ChatGPT-app login; token expiry will surface as ACP auth errors → re-run `codex login`.
|
|
||||||
|
|
||||||
## Out of scope
|
|
||||||
|
|
||||||
- MCP server integration.
|
|
||||||
- Custom rules parsers, custom tools, extensions (mcphub/history/vectorcode).
|
|
||||||
|
|
@ -1,191 +0,0 @@
|
||||||
# Neovim + Nix setup review
|
|
||||||
|
|
||||||
Scope: `flake.nix`, `overlays/`, `modules/`, `plugin/*.lua`, `lua/*`, `ftplugin/*`, CI/workflows, and cross-check against the pinned versions in `flake.lock` (nixpkgs weekly `241313f4`).
|
|
||||||
|
|
||||||
## Pinned package versions (from current lock)
|
|
||||||
- neovim `0.12.2`
|
|
||||||
- blink-cmp `1.10.2`
|
|
||||||
- codecompanion-nvim `19.13.0`
|
|
||||||
- nvim-treesitter `0.10.0-unstable-2026-04-03` (main-branch rewrite)
|
|
||||||
- nvim-treesitter-textobjects `0-unstable-2026-04-07` (main-branch rewrite)
|
|
||||||
- copilot-lua `2.0.3`
|
|
||||||
- render-markdown-nvim `8.12.0-unstable-2026-05-07`
|
|
||||||
- zk-nvim `0.4.7-unstable-2026-03-13`
|
|
||||||
- mini.nvim `0.17.0-unstable-2026-05-12`
|
|
||||||
- quarto-nvim `2.1.0`
|
|
||||||
- otter-nvim `2.14.5`
|
|
||||||
- lspconfig `2.9.0`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CRITICAL: Treesitter is currently non-functional
|
|
||||||
|
|
||||||
### Finding
|
|
||||||
The nixpkgs `nvim-treesitter` package is the **main-branch rewrite** — there is no `lua/nvim-treesitter/configs.lua`. The whole module in `plugin/20_startup.lua` lines 212-294 is dead code:
|
|
||||||
|
|
||||||
```lua
|
|
||||||
local ok_configs, configs = pcall(require, "nvim-treesitter.configs") -- fails
|
|
||||||
```
|
|
||||||
|
|
||||||
The working tree already removed the fallback `vim.treesitter.start()` FileType autocmd (the "fixed treesitter" commit deleted it). Net result: **no treesitter highlighting, indentexpr, foldexpr, or textobjects are configured**.
|
|
||||||
|
|
||||||
### Impact
|
|
||||||
- Syntax highlighting falls back to Neovim's regex-only engine.
|
|
||||||
- All textobject keymaps (`]a`, `[a`, `]f`, `[f`, `]e`/`[e`, `<leader>x`/`X`, lsp_interop `<leader>lm`) are inert.
|
|
||||||
- `foldexpr`/`indentexpr` based folding does nothing.
|
|
||||||
|
|
||||||
### Fix direction
|
|
||||||
Rewrite `plugin/20_startup.lua` for main-branch API:
|
|
||||||
1. FileType autocmd → `vim.treesitter.start()` (and optionally `indentexpr`/`foldexpr`).
|
|
||||||
2. `require("nvim-treesitter-textobjects").setup({ move = { set_jumps = true } })` + explicit keymaps using `move.goto_next_start(query, "textobjects")` and `swap.swap_next(...)`.
|
|
||||||
3. The non-Nix `ensure_installed` block should set `opts.ensure_installed` BEFORE the filter (line 278 reads it before line 286 defines it).
|
|
||||||
|
|
||||||
Also remove duplicate `vim.treesitter.language.register("markdown", ...)` between `plugin/20_startup.lua` and `plugin/21_datascience.lua`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CodeCompanion version mismatch
|
|
||||||
|
|
||||||
### Finding
|
|
||||||
Config targets features absent in `19.13.0` (present only in `≥19.19.0`/main):
|
|
||||||
|
|
||||||
| Config usage | Present in 19.13? | Present in main (`v19.20.0`) |
|
|
||||||
|---|---|---|
|
|
||||||
| `interactions.chat.opts.context_management.editing` | No (flat `trigger`/`enabled` only) | Yes |
|
|
||||||
| `interactions.chat.opts.context_management.compaction` | No | Yes |
|
|
||||||
| `<leader>aC` requiring `codecompanion.interactions.chat.context_management.compaction` | **RUNTIME ERROR** | Works |
|
|
||||||
| `slash_commands.share` (`opts.token = ...`) | No (absent from defaults) | Yes |
|
|
||||||
| `adapters.acp.codex.defaults.auth_method = "chatgpt"` | Yes | Yes |
|
|
||||||
| `interactions.chat.adapter = { name = ..., model = ... }` table form | Yes | Yes |
|
|
||||||
|
|
||||||
### Risk
|
|
||||||
On today's lock (`19.13.0`): `/share` is inert, compaction-only keymap throws module-not-found, and `editing`/`compaction` tuning is silently ignored. On `≥19.19.0`/main: everything works.
|
|
||||||
|
|
||||||
### Decision needed (BLOCKING)
|
|
||||||
Choose **exactly one**:
|
|
||||||
|
|
||||||
- **A — Upgrade the plugin pin** (`overlays/plugins.nix` fetch to `v19.20.0` or `main`, bump the lock, and keep the current config). Riskiest change but matches what the config is written for.
|
|
||||||
- **B — Downgrade config call sites** to match `19.13.0`: remove `slash_commands.share`, remove `editing`/`compaction` keys (or collapse to flat `trigger: 0.75`), remove or gate `<leader>aC` on "newer" version.
|
|
||||||
- **C — Version-gate the config**: keep current code, read the installed version at startup and skip the new features when < 19.19.
|
|
||||||
|
|
||||||
I recommend A (the config clearly intends to track upstream main-ish behavior; `nix flake update` already bumped it to `19.18.0` in a prior session and you only reverted because the nightly was still too old — `v19.20.0` is now available).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## DEAD / DUPLICATE code
|
|
||||||
|
|
||||||
- `plugin/20_startup.lua` — the entire `configs.setup(opts)` block is dead (see Treesitter finding above).
|
|
||||||
- `plugin/10_keymap.lua`:
|
|
||||||
- `nmap_leader('od', '<Cmd>Neogen<CR>', ...)` — `neogen` plugin is **not shipped** in `specs/plugins.nix`. Mapping errors on press.
|
|
||||||
- `nmap_leader('fp', '<Cmd>Pick projects<CR>', ...)` — `MiniExtra.pickers.projects` doesn't exist in mini.extra; would error.
|
|
||||||
- `nmap_leader('oS', '<Cmd>lua Config.insert_section()<CR>', ...)` — `Config.insert_section` is never defined.
|
|
||||||
- `vim.lsp.buf.definition()` is bound to `grd`; Neovim 0.11+ defaults include `gr` aliases. Cosmetic, but `]d`/`[d` exist on modern LSP config and would be more idiomatic.
|
|
||||||
- `plugin/23_editor.lua`:
|
|
||||||
- `my_styler` formatter (calls `R -s -e styler::...`) is defined but never referenced — dead.
|
|
||||||
- `plugin/24_completion.lua`:
|
|
||||||
- `providers.cmp_r` is defined in the blink source list but never enabled in `default` or `per_filetype`; inert.
|
|
||||||
- `BLINK_VERSION = "v1.4.1"` — only consulted in the non-Nix install path; nixpkgs is `1.10.2`. Pin it to current or drop.
|
|
||||||
- `get_blink_fuzzy_setting().prebuilt_binary = { force_version = BLINK_VERSION }` — singular key is wrong; blink option is `fuzzy.prebuilt_binaries` (plural). Being skipped in-Nix anyway, but still wrong key.
|
|
||||||
- `modules/module/specs/plugins.nix` — `specs.utils-lazy` ships `nvim-dap*` and `nvim-lint` but there is zero config/tooling that references them in this repo.
|
|
||||||
- `ftplugin/quarto.lua`:
|
|
||||||
- Second top-level `require('quarto').setup()` with **no args** runs _after_ `21_datascience.lua`'s setup and **resets** it to defaults (no `lspFeatures`, no `codeRunner`).
|
|
||||||
- Top-level `require('quarto')` at FileType load also crashes if the quarto plugin isn't installed (e.g. cats off and a `.qmd`/`.quarto` file is opened): Neovim detects `quarto` ft natively in 0.10+.
|
|
||||||
- `plugin/00_options.lua`:
|
|
||||||
- Lines 146-163: two back-to-back FileType autocmds that both remove `r`/`o` from `formatoptions`. The second references an undefined `augroup` variable (nil → autocmd is global, happens to still work).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## STALE / WRONG options
|
|
||||||
|
|
||||||
- `plugin/10_keymap.lua` line 174:
|
|
||||||
```lua
|
|
||||||
require("conform").format({ lsp_fallback = true })
|
|
||||||
```
|
|
||||||
`lsp_fallback` is the **deprecated** boolean form of `conform.nvim`; should be `lsp_format = "fallback"` (the form already used in `plugin/23_editor.lua` and `ftplugin/python.lua`). In newer conform this may warn or error.
|
|
||||||
- `ftplugin/quarto.lua`:
|
|
||||||
- Sets `<Plug>RDSendLine` and R-style keymaps on _all_ quarto buffers, including Python/Julia chunks. This collides with quarto-runner mappings set in `21_datascience.lua`. Should gate on `vim.bo.filetype == "r"` (the ftplugin already imports quarto.runner for python, but the R keys leak).
|
|
||||||
- `.github/dependapot.yml` — filename typo. GitHub expects `dependabot.yml`; Dependabot won't run.
|
|
||||||
- `.github/workflows/check.yml`:
|
|
||||||
- `nix develop` without a `-c` command just launches an interactive shell. In CI it does nothing useful (or hangs). Replace with `nix develop -c echo ok` or drop.
|
|
||||||
- Path filter `'modules'` only matches the root directory itself; should be `modules/**` (or `'modules/**'`).
|
|
||||||
- Changing `plugin/`, `lua/`, `overlays/`, `ftplugin/`, etc. does **not** trigger CI.
|
|
||||||
- `flake.nix` / `.envrc` shellHook:
|
|
||||||
```sh
|
|
||||||
export R_LIBS_SITE=$(strings "$(command -v R)" | grep -oP '/nix/store/[^:]+/library' ...)
|
|
||||||
```
|
|
||||||
`grep -oP` (PCRE) is **not available in macOS BSD grep**. On `aarch64-darwin` this silently fails → `R_LIBS_SITE` is empty. Either depend on `ripgrep` regex (`strings ... | rg -o '...'`) or use `gsed` (GNU sed).
|
|
||||||
- `overlays/plugins.nix` — `zk-nvim` skip list contains `zk.pickers.fzf_lua`; current zk-nvim package likely doesn't load that regardless, but harmless.
|
|
||||||
- `modules/module/settings/core.nix` — `config.settings.nvim_lua_env` references `lp.tiktoken_core` but `tiktoken_core` is **not in `catPkgs.general` or anywhere else** in these files. If there's an extra Lua/tiktoken module, fine; otherwise this option is placeholder dead code.
|
|
||||||
- `modules/module/settings/hosts.nix` — host `m` (marimo) is defined with `enable = false` but also configured with `package`, `argv0`, `addFlag`. Dead block.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## PORTABILITY / DARWIN issues
|
|
||||||
|
|
||||||
- Shell hook `grep -oP` (above) fails on macOS.
|
|
||||||
- `mkdir -p "$R_LIBS_USER"` fine; but `command -v R` on macOS returns the wrapper; the wrapper path injection still works.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## DEAD WEIGHT (shipped but unused)
|
|
||||||
|
|
||||||
- `catPkgs.r` includes `pkgs.rnvimserver` — `rnvimserver` is needed by R.nvim only when using the _socket_ transport; `21_datascience.lua` only uses vim-slime. Acceptable, but `rnvimserver` adds to build time. Include if you actually use it? Currently not used.
|
|
||||||
- `specs.utils-lazy` ships `nvim-dap`, `nvim-dap-ui`, `nvim-dap-virtual-text`, `nvim-lint` — none of these are referenced anywhere in `plugin/` or `lua/`. Consider moving them to a devShell-only cat, or drop them.
|
|
||||||
- `.gitignore` `*.R` — prevents tracking any new `.R` files. `tests/test.R` is already committed so it isn't actively harmful, but it's surprising for a repo whose default cats include R.
|
|
||||||
- `.commandcode/` dir is listed in `.gitignore` but is in the worktree; fine, but worth cleaning up if it's an artifact.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## IMPROVEMENTS given updated packages
|
|
||||||
|
|
||||||
- `catPkgs.markdown` — add `marksman` (it's the LSP used by `render-markdown.nvim` wiki links and configured in LSP). Same binary is needed by `render-markdown` for wiki link ISP.
|
|
||||||
- `vim.lsp.enable` servers configured but binaries missing in PATH:
|
|
||||||
- `marksman` (LSP + render-markdown wiki integration).
|
|
||||||
- `r_ls` (new R language server — package name in nixpkgs is likely `r-languageserver` or `r_ls`; current `catPkgs.r` doesn't ship either).
|
|
||||||
- `clangd` — not required for this data-science setup; either drop or add to `external`.
|
|
||||||
- `julials` — require `LanguageServer.jl` in `settings.lang_packages.julia` for it to be useful.
|
|
||||||
- `blink.cmp` is `1.10.2` but config pins `BLINK_VERSION = "v1.4.1"` for the non-Nix path. Either drop the `BLINK_VERSION` constant (let MiniDeps track HEAD or the tag pinned in flake) or update it to `v1.10.2`.
|
|
||||||
- `conform.nvim` already uses `lsp_format = "fallback"` in `23_editor.lua` and `ftplugin/python.lua`, but `10_keymap.lua` still calls the deprecated `lsp_fallback = true`. Align to `lsp_format = "fallback"`.
|
|
||||||
- `.github/workflows/check.yml` — add path filters for `plugin/**`, `lua/**`, `overlays/**`, `ftplugin/**`, `modules/**`.
|
|
||||||
- `tests/init.lua` smoke-test and `tests/test.R` are present but **not wired into `nix flake check`**. Add a trivial check that runs `lua tests/init.lua` via `nix-shell -A ...`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CONFLICTS
|
|
||||||
|
|
||||||
- `<leader>up` (terminal bracketed paste toggle in `10_keymap.lua`) conflicts with `mini.basics.mappings.option_toggle_prefix = "<leader>u"` (paste toggle), which is set up later in `20_startup.lua` via `now()`. Result: the user's `<leader>up` mapping gets overwritten. Portable workaround: remap to `<leader>tp` (terminal namespace) and keep `<leader>tb` as alternative — both already mapped in 10_keymap.
|
|
||||||
- `ftplugin/quarto.lua` resets quarto-nvim config (kills `lspFeatures`/`codeRunner` set in `21_datascience.lua`) and injects R plug mappings into non-R quarto chunks.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## CLEAN summary for implementer
|
|
||||||
|
|
||||||
### Immediate (not version-dependent)
|
|
||||||
1. Restore treesitter highlighting + textobjects in `plugin/20_startup.lua` using main-branch API.
|
|
||||||
2. Remove duplicate `vim.treesitter.language.register` in `21_datascience.lua`.
|
|
||||||
3. Fix `plugin/10_keymap.lua`: remove/resolve `Neogen`, `Pick projects`, `Config.insert_section` dangling mappings.
|
|
||||||
4. Replace deprecated `lsp_fallback = true` with `lsp_format = "fallback"` in `plugin/10_keymap.lua`.
|
|
||||||
5. Gate `ftplugin/quarto.lua` to not reset config and to not leak R keys into non-R chunks; guard against missing `quarto` plugin.
|
|
||||||
6. Remove duplicate `formatoptions` autocmds (or at least dedupe).
|
|
||||||
7. Dedupe `RNVIM_COMPLDIR` / `TMPDIR` setup (do it in one place).
|
|
||||||
8. Rename `.github/dependapot.yml` to `.github/dependabot.yml`.
|
|
||||||
9. Remove or gate dead host `m` in `hosts.nix`.
|
|
||||||
10. Remove unused `rsplit`? no, irrelevant.
|
|
||||||
11. Add `marksman` to `catPkgs.markdown` and remove orphan LSP entries or ship the binaries.
|
|
||||||
12. Remove dead `conform` formatter `my_styler` and dead blink `cmp_r` provider, or wire them up.
|
|
||||||
|
|
||||||
### Version-dependent (BLOCKED)
|
|
||||||
- **Reset the CodeCompanion version decision**: either pin to `v19.20.0` (keep config, fix `slash_commands.share`, drop the `<leader>aC` compatibility shim, keep `editing`/`compaction`) OR downgrade config to match `19.13.0` (remove `share`, collapse `context_management`).
|
|
||||||
|
|
||||||
### CI / packaging
|
|
||||||
- Fix `nix develop` usage and path filters in `.github/workflows/check.yml`.
|
|
||||||
- Replace `grep -oP` in `flake.nix` shellHook with portable `rg -o` or add `gnused` to `catPkgs.always` and use `gsed`.
|
|
||||||
- Wire `tests/init.lua` into `flake check`.
|
|
||||||
|
|
||||||
### Verification
|
|
||||||
- `nix flake check` on both `aarch64-darwin` and `x86_64-linux`.
|
|
||||||
- `nix build .#packages.<system>.default` succeeds (already does).
|
|
||||||
- Start nvim, verify :TSContext works, treesitter highlighting is on, and `]f`/`[f` textobjects move.
|
|
||||||
- Open a `.qmd` file with cats off → no ftplugin crash.
|
|
||||||
- Confirm `<leader>up` still toggles bracketed paste.
|
|
||||||
- Confirm `:Pick projects` and `:Neogen` and `Config.insert_section` no longer error (or are mapped to valid handlers).
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"lastAgent": "agent-local-096f2785-09c8-4487-b71b-f8ac2b81aaaf",
|
|
||||||
"sessionsByServer": {
|
|
||||||
"api.letta.com": {
|
|
||||||
"agentId": "agent-21b21fd6-49e4-4d5c-a1b7-1c6dcd8dacc9",
|
|
||||||
"conversationId": "default"
|
|
||||||
},
|
|
||||||
"local:/Users/daniel/.letta/lc-local-backend": {
|
|
||||||
"agentId": "agent-local-096f2785-09c8-4487-b71b-f8ac2b81aaaf",
|
|
||||||
"conversationId": "default"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lastSession": {
|
|
||||||
"agentId": "agent-local-096f2785-09c8-4487-b71b-f8ac2b81aaaf",
|
|
||||||
"conversationId": "default"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
||||||
// omp custom tool: read this machine's running Neovim buffers over its RPC
|
|
||||||
// socket. Read-only and on-demand — the model calls it when it needs buffer
|
|
||||||
// content; nothing is injected into prompts automatically.
|
|
||||||
//
|
|
||||||
// Install options
|
|
||||||
// 1. Project scope (this project): keep the file in .omp/tools/ — omp picks it
|
|
||||||
// up when a session's cwd is inside this repository.
|
|
||||||
// 2. All projects: mkdir -p ~/.omp/agent/tools
|
|
||||||
// ln -s "$PWD/.omp/tools/nvim_buffers.mjs" ~/.omp/agent/tools/
|
|
||||||
// then restart `omp` (custom tools are loaded at session bootstrap).
|
|
||||||
//
|
|
||||||
// Socket contract (must match lua/nvim_omp/init.lua):
|
|
||||||
// path = $NVIM_OMP_SOCKET or <XDG_STATE_HOME|~/.local/state>/nvim/omp.sock
|
|
||||||
// The nvim instance running this config starts the listener at startup.
|
|
||||||
// Only one instance can own the socket; a second instance never replaces a
|
|
||||||
// live owner. Remove a stale socket manually only after confirming no nvim
|
|
||||||
// process owns it.
|
|
||||||
|
|
||||||
import os from "node:os";
|
|
||||||
import path from "node:path";
|
|
||||||
|
|
||||||
// Safe default cap so a large buffer cannot flood the conversation.
|
|
||||||
const DEFAULT_MAX_LINES = 2000;
|
|
||||||
|
|
||||||
export default function (pi) {
|
|
||||||
// Resolve socket path with the same rule as lua/nvim_omp/init.lua.
|
|
||||||
const socketPath = () => {
|
|
||||||
const env = process.env.NVIM_OMP_SOCKET;
|
|
||||||
if (env) return env;
|
|
||||||
const state =
|
|
||||||
process.env.XDG_STATE_HOME ||
|
|
||||||
path.join(os.homedir(), ".local", "state");
|
|
||||||
return path.join(state, "nvim", "omp.sock");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Evaluate expr in the remote nvim via `nvim --server`; returns parsed JSON.
|
|
||||||
const rpc = async (expr, signal) => {
|
|
||||||
const bin = process.env.NVIM_BIN || "nvim";
|
|
||||||
const { code, stdout, stderr, killed } = await pi.exec(
|
|
||||||
bin,
|
|
||||||
["--server", socketPath(), "--remote-expr", expr],
|
|
||||||
{ signal },
|
|
||||||
);
|
|
||||||
if (killed) throw new Error("cancelled");
|
|
||||||
if (code !== 0) {
|
|
||||||
const why = String(stderr || "").trim();
|
|
||||||
throw new Error(
|
|
||||||
why.includes("E247")
|
|
||||||
? `No Neovim RPC socket at ${socketPath()}. ` +
|
|
||||||
"Start nvim (or vv) first — the 31_nvim_omp.lua plugin binds the socket at startup."
|
|
||||||
: `nvim RPC failed (${code}): ${why}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const text = String(stdout ?? "").trim();
|
|
||||||
if (!text) throw new Error("empty response from nvim RPC");
|
|
||||||
return JSON.parse(text);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Resolve a buffer argument (number, string, or partial path) to a buffer
|
|
||||||
// number. Returns null when nothing matches.
|
|
||||||
const resolveBuf = async (buffer, signal) => {
|
|
||||||
if (buffer === undefined || buffer === null || buffer === "") {
|
|
||||||
return rpc("json_encode(nvim_get_current_buf())", signal);
|
|
||||||
}
|
|
||||||
if (typeof buffer === "number") return buffer;
|
|
||||||
const bufnum = Number(buffer);
|
|
||||||
if (Number.isInteger(bufnum) && bufnum > 0) return bufnum;
|
|
||||||
const list = await rpc(
|
|
||||||
"json_encode(map(nvim_list_bufs(), {i, v -> " +
|
|
||||||
"{'bufnr': v, 'name': nvim_buf_get_name(v)}}))",
|
|
||||||
signal,
|
|
||||||
);
|
|
||||||
const q = String(buffer);
|
|
||||||
const hit =
|
|
||||||
list.find(
|
|
||||||
(b) => b.name === q || b.name.endsWith("/" + q) || b.name.endsWith(q),
|
|
||||||
) ||
|
|
||||||
list.find((b) => b.name.includes(q));
|
|
||||||
return hit ? hit.bufnr : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tools = [];
|
|
||||||
|
|
||||||
// List open buffers -----------------------------------------------
|
|
||||||
tools.push({
|
|
||||||
name: "nvim_buffers",
|
|
||||||
label: "Neovim Buffers",
|
|
||||||
description:
|
|
||||||
"List the buffers currently open in the user's running Neovim " +
|
|
||||||
"(number, name, current/loaded state, modified). Use before " +
|
|
||||||
"nvim_buffer to pick a buffer.",
|
|
||||||
parameters: pi.arktype({}),
|
|
||||||
async execute(_id, _params, _onUpdate, _ctx, _signal) {
|
|
||||||
const list = await rpc(
|
|
||||||
"json_encode(map(nvim_list_bufs(), {i, v -> {'nr': v, " +
|
|
||||||
"'name': nvim_buf_get_name(v), " +
|
|
||||||
"'current': v == nvim_get_current_buf(), " +
|
|
||||||
"'loaded': nvim_buf_is_loaded(v), " +
|
|
||||||
"'modified': getbufvar(v, '&modified')}}))",
|
|
||||||
);
|
|
||||||
if (!list.length) {
|
|
||||||
return { content: [{ type: "text", text: "No buffers open." }] };
|
|
||||||
}
|
|
||||||
const lines = list.map(
|
|
||||||
(b) =>
|
|
||||||
`${b.nr}\t${b.name || "[no name]"}\t` +
|
|
||||||
`${b.current ? "current " : ""}` +
|
|
||||||
`${b.loaded ? "" : "unloaded "}` +
|
|
||||||
`${b.modified ? "modified" : ""}`.trim(),
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
text: `Open buffers (${list.length}):\n` + lines.join("\n"),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Read a single buffer, line-capped -------------------------------
|
|
||||||
tools.push({
|
|
||||||
name: "nvim_buffer",
|
|
||||||
label: "Neovim Buffer",
|
|
||||||
description:
|
|
||||||
"Read lines of a Neovim buffer. `buffer` accepts the current buffer " +
|
|
||||||
"(default), a buffer number from nvim_buffers, or a file name/path " +
|
|
||||||
"open in Neovim. `maxLines` caps the returned lines (default 2000); " +
|
|
||||||
"pass a larger value explicitly to read more of a long buffer.",
|
|
||||||
parameters: pi.arktype({
|
|
||||||
buffer: "string? | number?",
|
|
||||||
maxLines: "number?",
|
|
||||||
}),
|
|
||||||
async execute(_id, params, _onUpdate, _ctx, signal) {
|
|
||||||
const buf = await resolveBuf(params.buffer, signal);
|
|
||||||
if (buf === null) {
|
|
||||||
return {
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
text: `No buffer matches '${params.buffer}'. List open buffers with nvim_buffers.`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const maxLines =
|
|
||||||
Number.isInteger(params.maxLines) && params.maxLines > 0
|
|
||||||
? Math.min(params.maxLines, 100000)
|
|
||||||
: DEFAULT_MAX_LINES;
|
|
||||||
|
|
||||||
const expr =
|
|
||||||
`json_encode({'name': nvim_buf_get_name(${buf}), ` +
|
|
||||||
`'total': nvim_buf_line_count(${buf}), ` +
|
|
||||||
`'lines': nvim_buf_get_lines(${buf}, 0, ${maxLines}, 0)})`;
|
|
||||||
const { name, total, lines } = await rpc(expr, signal);
|
|
||||||
if (!total) {
|
|
||||||
return {
|
|
||||||
content: [
|
|
||||||
{ type: "text", text: `Buffer ${buf} (${name}) is empty.` },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const truncated =
|
|
||||||
total > lines.length
|
|
||||||
? `\n... ${total - lines.length} more lines ` +
|
|
||||||
`(raise maxLines to read them)`
|
|
||||||
: "";
|
|
||||||
const numbered = lines.map((l, i) => `${i + 1}: ${l}`).join("\n");
|
|
||||||
return {
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
text:
|
|
||||||
`Buffer ${buf} (${name}), ${total} lines:\n` +
|
|
||||||
numbered +
|
|
||||||
truncated,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return tools;
|
|
||||||
}
|
|
||||||
24
flake.lock
generated
24
flake.lock
generated
|
|
@ -22,11 +22,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785967620,
|
"lastModified": 1786384358,
|
||||||
"narHash": "sha256-IItrdb7Puk05RqOBWZYFC5X6Wl1sJmCfh5MWVHw5iMM=",
|
"narHash": "sha256-RzPPiWeUtuvymnpuEWsdtzli5w4kjZs49FqEs3/1u+I=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "b7c2ada94fe99c15b0dbcf4d11fd7850b957a436",
|
"rev": "2fcb964de67fcf60b43471c55d5d99e61a9ccb5a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -39,11 +39,11 @@
|
||||||
"plugins-bloocky": {
|
"plugins-bloocky": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1786042339,
|
"lastModified": 1786453931,
|
||||||
"narHash": "sha256-8QcoC1bS8pRcwBkW3mqD2vgP9Mu0aCdIy6umZO6mUGM=",
|
"narHash": "sha256-OpVm/ubj6rxjGFkjluQLhys/qGWqmN3E7dUMiFUYAZw=",
|
||||||
"owner": "atiladefreitas",
|
"owner": "atiladefreitas",
|
||||||
"repo": "bloocky",
|
"repo": "bloocky",
|
||||||
"rev": "a052c3b1a8126e04b194bb3db3c4c6ca641c0e4e",
|
"rev": "64a6de6560c40b3351d29545528ddaed98cd9984",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -71,11 +71,11 @@
|
||||||
"plugins-dooing": {
|
"plugins-dooing": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785971574,
|
"lastModified": 1786125118,
|
||||||
"narHash": "sha256-GtEC5kWcH0DmiYXkzxzNjjfYLfyEb7zpTLQWdi7n3zs=",
|
"narHash": "sha256-Iil8eCCz61T1Hz1y2cij71Hti+QGXbjH49eGCPMqTbA=",
|
||||||
"owner": "atiladefreitas",
|
"owner": "atiladefreitas",
|
||||||
"repo": "dooing",
|
"repo": "dooing",
|
||||||
"rev": "6748316bc6b4601797fb952a83694cc0a5ef6da2",
|
"rev": "2871aaf400c49187aa4216e7cf7abfa37cd32840",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -108,11 +108,11 @@
|
||||||
},
|
},
|
||||||
"rixpkgs": {
|
"rixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1785776890,
|
"lastModified": 1786421894,
|
||||||
"narHash": "sha256-CzzgB1teVbroR/QhGAnsQToUYCDXEZZtFTcISAooASM=",
|
"narHash": "sha256-BQLZ0kJYdZ3FmC2Vq7PJFmx4wnyifoCdz+5CIkdbDxI=",
|
||||||
"owner": "dwinkler1",
|
"owner": "dwinkler1",
|
||||||
"repo": "rixpkgs",
|
"repo": "rixpkgs",
|
||||||
"rev": "a54080a58b57d5785dc85901850b817bef2aaf83",
|
"rev": "9518d16a41413cf08eecde557b337b87f1422e91",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
|
|
@ -171,11 +171,11 @@
|
||||||
modules = [
|
modules = [
|
||||||
{
|
{
|
||||||
cats = {
|
cats = {
|
||||||
r = false;
|
r = true;
|
||||||
python = true;
|
python = true;
|
||||||
};
|
};
|
||||||
settings.lang_packages.python = nixpkgs.lib.mkForce (with pkgs.python3Packages; [
|
settings.lang_packages.python = nixpkgs.lib.mkForce (with pkgs.python3Packages; [
|
||||||
pandas
|
polars
|
||||||
]);
|
]);
|
||||||
catPkgs.nix = nixpkgs.lib.mkForce [
|
catPkgs.nix = nixpkgs.lib.mkForce [
|
||||||
pkgs.alejandra
|
pkgs.alejandra
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,8 @@ nmap_leader('LL', '<Cmd>luafile %<CR><Cmd>echo "Sourced lua"<CR>', 'Source buffe
|
||||||
nmap_leader('Ls', '<Cmd>lua Config.log_print()<CR>', 'Show log')
|
nmap_leader('Ls', '<Cmd>lua Config.log_print()<CR>', 'Show log')
|
||||||
nmap_leader('Lx', '<Cmd>lua Config.execute_lua_line()<CR>', 'Execute `lua` line')
|
nmap_leader('Lx', '<Cmd>lua Config.execute_lua_line()<CR>', 'Execute `lua` line')
|
||||||
|
|
||||||
-- m is free
|
-- m is for 'mark' (checkbox toggling)
|
||||||
|
nmap_leader('mc', '<Cmd>ToggleCheckbox<CR>', 'Toggle checkbox')
|
||||||
|
|
||||||
-- o is for 'other'
|
-- o is for 'other'
|
||||||
local trailspace_toggle_command = '<Cmd>lua vim.b.minitrailspace_disable = not vim.b.minitrailspace_disable<CR>'
|
local trailspace_toggle_command = '<Cmd>lua vim.b.minitrailspace_disable = not vim.b.minitrailspace_disable<CR>'
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,14 @@ in
|
||||||
{
|
{
|
||||||
basePythonPackages = reqPkgs;
|
basePythonPackages = reqPkgs;
|
||||||
python = prev.python3.withPackages reqPkgs;
|
python = prev.python3.withPackages reqPkgs;
|
||||||
}
|
|
||||||
|
# pyarrow's test_timezone_absent reads /usr/share/zoneinfo, which is
|
||||||
|
# blocked by the build sandbox (PermissionError: Operation not permitted).
|
||||||
|
python3Packages = prev.python3Packages // {
|
||||||
|
pyarrow = prev.python3Packages.pyarrow.overridePythonAttrs (old: {
|
||||||
|
disabledTests = (old.disabledTests or [ ]) ++ [
|
||||||
|
"pyarrow/tests/test_orc.py::test_timezone_absent"
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -119,3 +119,69 @@ Config.add = (function(pkg)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Config.now_if_args = vim.fn.argc(-1) > 0 and MiniDeps.now or MiniDeps.later
|
Config.now_if_args = vim.fn.argc(-1) > 0 and MiniDeps.now or MiniDeps.later
|
||||||
|
|
||||||
|
-- Checkbox
|
||||||
|
local checked_character = "x"
|
||||||
|
|
||||||
|
local checked_checkbox = "%[" .. checked_character .. "%]"
|
||||||
|
local unchecked_checkbox = "%[ %]"
|
||||||
|
|
||||||
|
local line_contains_unchecked = function(line)
|
||||||
|
return line:find(unchecked_checkbox)
|
||||||
|
end
|
||||||
|
|
||||||
|
local line_contains_checked = function(line)
|
||||||
|
return line:find(checked_checkbox)
|
||||||
|
end
|
||||||
|
|
||||||
|
local line_with_checkbox = function(line)
|
||||||
|
return line:find("^%s*- " .. checked_checkbox)
|
||||||
|
or line:find("^%s*- " .. unchecked_checkbox)
|
||||||
|
or line:find("^%s*%d%. " .. checked_checkbox)
|
||||||
|
or line:find("^%s*%d%. " .. unchecked_checkbox)
|
||||||
|
end
|
||||||
|
|
||||||
|
local checkbox = {
|
||||||
|
check = function(line)
|
||||||
|
return line:gsub(unchecked_checkbox, checked_checkbox, 1)
|
||||||
|
end,
|
||||||
|
|
||||||
|
uncheck = function(line)
|
||||||
|
return line:gsub(checked_checkbox, unchecked_checkbox, 1)
|
||||||
|
end,
|
||||||
|
|
||||||
|
make_checkbox = function(line)
|
||||||
|
if not line:match("^%s*%-%s") and not line:match("^%s*%d%.%s") then
|
||||||
|
-- "xxx" -> "- [ ] xxx"
|
||||||
|
return line:gsub("(%S+)", "- [ ] %1", 1)
|
||||||
|
else
|
||||||
|
-- "- xxx" -> "- [ ] xxx", "3. xxx" -> "3. [ ] xxx"
|
||||||
|
return line:gsub("(%s*- )(.*)", "%1[ ] %2", 1):gsub("(%s*%d%. )(.*)", "%1[ ] %2", 1)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Config.togglecb = function()
|
||||||
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||||
|
local start_line = cursor[1] - 1
|
||||||
|
local current_line = vim.api.nvim_buf_get_lines(bufnr, start_line, start_line + 1, false)[1] or ""
|
||||||
|
|
||||||
|
-- If the line contains a checked checkbox then uncheck it.
|
||||||
|
-- Otherwise, if it contains an unchecked checkbox, check it.
|
||||||
|
local new_line = ""
|
||||||
|
|
||||||
|
if not line_with_checkbox(current_line) then
|
||||||
|
new_line = checkbox.make_checkbox(current_line)
|
||||||
|
elseif line_contains_unchecked(current_line) then
|
||||||
|
new_line = checkbox.check(current_line)
|
||||||
|
elseif line_contains_checked(current_line) then
|
||||||
|
new_line = checkbox.uncheck(current_line)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, start_line, start_line + 1, false, { new_line })
|
||||||
|
vim.api.nvim_win_set_cursor(0, cursor)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command("ToggleCheckbox", Config.togglecb, {})
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
-- Bloocky: timeblocking calendar (day/week/month views), persisted to JSON.
|
|
||||||
-- Loaded via the `general` cat spec (nix mode) or MiniDeps (non-nix).
|
|
||||||
-- Default global toggle is <leader>tb, which collides with the terminal map
|
|
||||||
-- (toggle bracketed paste), so it is moved to the calendar/tasks group <leader>c.
|
|
||||||
local Config = require('config')
|
|
||||||
|
|
||||||
if not Config.isNixCats then
|
|
||||||
local later = MiniDeps.later
|
|
||||||
later(function()
|
|
||||||
MiniDeps.add({ source = 'atiladefreitas/bloocky' })
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local nix = require('config.nix')
|
|
||||||
local later = MiniDeps.later
|
|
||||||
|
|
||||||
later(function()
|
|
||||||
if not nix.get_cat('general', false) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
require('bloocky').setup({
|
|
||||||
week_start = "monday",
|
|
||||||
window = {
|
|
||||||
-- Width per view: fraction of the editor width (or absolute columns if > 1).
|
|
||||||
-- A single number applies to every view.
|
|
||||||
width = {
|
|
||||||
month = 0.99,
|
|
||||||
week = 0.99,
|
|
||||||
day = 0.8,
|
|
||||||
},
|
|
||||||
border = "rounded",
|
|
||||||
},
|
|
||||||
integrations = {
|
|
||||||
dooing = {
|
|
||||||
enabled = true, -- show Dooing todos on their due date
|
|
||||||
show_done = false, -- also show completed todos
|
|
||||||
},
|
|
||||||
},
|
|
||||||
keymaps = {
|
|
||||||
toggle = '<leader>cb',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
-- Dooing: minimalist todo list manager with a floating window, persisted to JSON.
|
|
||||||
-- Loaded via the `general` cat spec (nix mode) or MiniDeps (non-nix).
|
|
||||||
-- Default globals <leader>td / <leader>tN occupy the terminal group, so the
|
|
||||||
-- todo toggles are moved to the calendar/tasks group <leader>c.
|
|
||||||
local Config = require('config')
|
|
||||||
|
|
||||||
if not Config.isNixCats then
|
|
||||||
local later = MiniDeps.later
|
|
||||||
later(function()
|
|
||||||
MiniDeps.add({ source = 'atiladefreitas/dooing' })
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local nix = require('config.nix')
|
|
||||||
local later = MiniDeps.later
|
|
||||||
local now = MiniDeps.now
|
|
||||||
later(function()
|
|
||||||
if not nix.get_cat('general', false) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local dooing = require('dooing')
|
|
||||||
require("dooing").setup({
|
|
||||||
keymaps = {
|
|
||||||
toggle_window = "<leader>cd",
|
|
||||||
open_project_todo = "<leader>cD",
|
|
||||||
show_due_notification = "<leader>cN",
|
|
||||||
create_nested_task = "<leader>cn", -- Create nested subtask under current todo
|
|
||||||
toggle_priority = "a",
|
|
||||||
},
|
|
||||||
calendar = {
|
|
||||||
week_start_day = "monday",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
-- Remove Dooing's old defaults.
|
|
||||||
vim.keymap.del("n", "<leader>td")
|
|
||||||
vim.keymap.del("n", "<leader>tD")
|
|
||||||
vim.keymap.del("n", "<leader>tN")
|
|
||||||
|
|
||||||
-- Restore mappings overwritten by Dooing.
|
|
||||||
local helpers = require('keymap.helpers')
|
|
||||||
local nmap_leader = helpers.nmap_leader
|
|
||||||
-- t is for 'terminal'
|
|
||||||
nmap_leader("td", '<Cmd>lua Config.terminal.open_duckdb();Config.terminal.toggle_bracket()<CR>', 'Open DuckDB')
|
|
||||||
end)
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
-- omp bridge entrypoint: start the RPC socket as early as possible so the omp
|
|
||||||
-- harness can read this instance's buffers on demand (see lua/nvim_omp/init.lua
|
|
||||||
-- and .omp/tools/nvim_buffers.mjs). Safe to fail silently — the socket is a
|
|
||||||
-- convenience, not a dependency of the editor.
|
|
||||||
local ok, nvim_omp = pcall(require, "nvim_omp")
|
|
||||||
if ok then
|
|
||||||
nvim_omp.start()
|
|
||||||
end
|
|
||||||
71
plugin/32_checkbox.lua
Normal file
71
plugin/32_checkbox.lua
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
-- Minimal Markdown checkbox toggler: `:ToggleCheckbox` (mapped to <leader>mc).
|
||||||
|
-- Toggles `- [ ]`/`- [x]` (and numbered `N. [ ]`/`N. [x]`) on the current line;
|
||||||
|
-- creates a checkbox on lines without one.
|
||||||
|
|
||||||
|
local checked_character = "x"
|
||||||
|
|
||||||
|
local checked_checkbox = "%[" .. checked_character .. "%]"
|
||||||
|
local unchecked_checkbox = "%[ %]"
|
||||||
|
|
||||||
|
local line_contains_unchecked = function(line)
|
||||||
|
return line:find(unchecked_checkbox)
|
||||||
|
end
|
||||||
|
|
||||||
|
local line_contains_checked = function(line)
|
||||||
|
return line:find(checked_checkbox)
|
||||||
|
end
|
||||||
|
|
||||||
|
local line_with_checkbox = function(line)
|
||||||
|
return line:find("^%s*- " .. checked_checkbox)
|
||||||
|
or line:find("^%s*- " .. unchecked_checkbox)
|
||||||
|
or line:find("^%s*%d%. " .. checked_checkbox)
|
||||||
|
or line:find("^%s*%d%. " .. unchecked_checkbox)
|
||||||
|
end
|
||||||
|
|
||||||
|
local checkbox = {
|
||||||
|
check = function(line)
|
||||||
|
return line:gsub(unchecked_checkbox, checked_checkbox, 1)
|
||||||
|
end,
|
||||||
|
|
||||||
|
uncheck = function(line)
|
||||||
|
return line:gsub(checked_checkbox, unchecked_checkbox, 1)
|
||||||
|
end,
|
||||||
|
|
||||||
|
make_checkbox = function(line)
|
||||||
|
if not line:match("^%s*%-%s") and not line:match("^%s*%d%.%s") then
|
||||||
|
-- "xxx" -> "- [ ] xxx"
|
||||||
|
return line:gsub("(%S+)", "- [ ] %1", 1)
|
||||||
|
else
|
||||||
|
-- "- xxx" -> "- [ ] xxx", "3. xxx" -> "3. [ ] xxx"
|
||||||
|
return line:gsub("(%s*- )(.*)", "%1[ ] %2", 1):gsub("(%s*%d%. )(.*)", "%1[ ] %2", 1)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
M.toggle = function()
|
||||||
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||||
|
local start_line = cursor[1] - 1
|
||||||
|
local current_line = vim.api.nvim_buf_get_lines(bufnr, start_line, start_line + 1, false)[1] or ""
|
||||||
|
|
||||||
|
-- If the line contains a checked checkbox then uncheck it.
|
||||||
|
-- Otherwise, if it contains an unchecked checkbox, check it.
|
||||||
|
local new_line = ""
|
||||||
|
|
||||||
|
if not line_with_checkbox(current_line) then
|
||||||
|
new_line = checkbox.make_checkbox(current_line)
|
||||||
|
elseif line_contains_unchecked(current_line) then
|
||||||
|
new_line = checkbox.check(current_line)
|
||||||
|
elseif line_contains_checked(current_line) then
|
||||||
|
new_line = checkbox.uncheck(current_line)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, start_line, start_line + 1, false, { new_line })
|
||||||
|
vim.api.nvim_win_set_cursor(0, cursor)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command("ToggleCheckbox", M.toggle, {})
|
||||||
|
|
||||||
|
return M
|
||||||
1
result
Symbolic link
1
result
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
/nix/store/12g17cxiz4wkn5zy483xhbkybpqwc9k4-neovim-unwrapped-0.12.4
|
||||||
Loading…
Reference in a new issue