diff --git a/CLAUDE.md b/CLAUDE.md index 1e4d331..9368c80 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,11 +26,26 @@ fnl/plugins/ - Plugin specs in Fennel 2. **Edit Fennel files in `fnl/`** - they compile to `lua/` on save 3. **`init.lua` and `lua/bootstrap.lua` stay as Lua** - they bootstrap nfnl -**IMPORTANT FOR CLAUDE:** After editing any `.fnl` file, compile all Fennel files to Lua: +## Compiling Fennel (MANDATORY) + +**After editing ANY `.fnl` file, you MUST compile it to Lua:** + ```bash cd ~/.config/nvim && nvim --headless -c "NfnlCompileAllFiles" -c "qa" ``` +If compilation says "destination-exists", delete the lua file first to force recompile: +```bash +cd ~/.config/nvim && rm lua/plugins/init.lua && nvim --headless -c "NfnlCompileAllFiles" -c "qa" +``` + +### Trust Issue Fix + +If you see ".nfnl.fnl is not trusted", add it to nvim's trust database: +```bash +sha256sum ~/.config/nvim/.nfnl.fnl | awk '{print $1 " /home/ajet/.config/nvim/.nfnl.fnl"}' >> ~/.local/state/nvim/trust +``` + ## Fennel Syntax Quick Reference ```fennel diff --git a/fnl/plugins/init.fnl b/fnl/plugins/init.fnl index 5377e2e..1c67b0d 100644 --- a/fnl/plugins/init.fnl +++ b/fnl/plugins/init.fnl @@ -2,7 +2,8 @@ ;; This file is compiled to lua/plugins/init.lua by nfnl (local repo 1) ;; lazy.nvim spec index for the git repo (e.g., "folke/plugin") -(local lhs 1) ;; which-key spec index for the key sequence (see which-key below) +(local lhs 1) ;; lazy.nvim/which-key spec index for key sequence +(local rhs 2) ;; lazy.nvim keys spec index for command/action [;; Tokyonight - Colorscheme {repo "folke/tokyonight.nvim" @@ -23,34 +24,192 @@ ;; Enable HUD floating window (set vim.g.conjure#log#hud#enabled true))} + ;; nvim-parinfer - Automatic parenthesis balancing + ;; Works alongside paredit: parinfer handles passive balancing, + ;; paredit provides explicit structural commands + {repo "gpanders/nvim-parinfer" + :ft ["fennel" "clojure" "lisp" "scheme" "racket" "carp" "timl"] + :keys [{lhs "tpi" + rhs "ParinferToggle" + :desc "Toggle Parinfer"}]} + ;; nvim-paredit - Structural editing for Lisp - ;; Default keybindings: >)/<) slurp/barf forward, <(/>( slurp/barf backward - ;; >e/f/)/<) slurp/barf forwards <(/>( slurp/barf backwards + ;; >e/f/p/

@ splice + ;; o/O raise form/element + ;; + ;; Additional bindings added below for vim-sexp compatibility {repo "julienvincent/nvim-paredit" :ft ["fennel" "clojure" "lisp" "scheme" "racket"] :config (fn [] (local paredit (require :nvim-paredit)) - ;; Use default keybindings (>), <), <(, >(, etc.) + (local api paredit.api) + (local wrap paredit.wrap) + (local cursor paredit.cursor) + (local keymap vim.keymap.set) + + ;; Use default keybindings (paredit.setup {}) - ;; Additional vim-sexp compatible bindings - (local keymap vim.keymap.set) - (local api paredit.api) + ;; ============================================================ + ;; vim-sexp-mappings-for-regular-people (tpope) style bindings + ;; ============================================================ - ;; dsf - Splice (delete surrounding form) + ;; dsf - Splice (delete surrounding form) - alias for @ (keymap :n "dsf" api.unwrap_form_under_cursor {:desc "Splice (delete surrounding form)"}) - ;; cse( cse) - Wrap in parens + ;; cse* - Surround element (no insert mode, surround.vim style) + (keymap :n "cseb" #(api.wrap_element_under_cursor "(" ")") {:desc "Wrap element in ()"}) (keymap :n "cse(" #(api.wrap_element_under_cursor "(" ")") {:desc "Wrap element in ()"}) (keymap :n "cse)" #(api.wrap_element_under_cursor "(" ")") {:desc "Wrap element in ()"}) - - ;; cse[ cse] - Wrap in brackets (keymap :n "cse[" #(api.wrap_element_under_cursor "[" "]") {:desc "Wrap element in []"}) (keymap :n "cse]" #(api.wrap_element_under_cursor "[" "]") {:desc "Wrap element in []"}) - - ;; cse{ cse} - Wrap in braces (keymap :n "cse{" #(api.wrap_element_under_cursor "{" "}") {:desc "Wrap element in {}"}) - (keymap :n "cse}" #(api.wrap_element_under_cursor "{" "}") {:desc "Wrap element in {}"}))} + (keymap :n "cse}" #(api.wrap_element_under_cursor "{" "}") {:desc "Wrap element in {}"}) + + ;; I - Insert at form head/tail (tpope style) + (keymap :n "I" + (fn [] + (api.move_to_parent_form_end) + (vim.cmd "startinsert")) + {:desc "Insert at form tail"}) + + ;; W/B/E/gE - Element-wise motions (override WORD motions) + (each [_ mode (ipairs [:n :x :o])] + (keymap mode "W" api.move_to_next_element_head {:desc "Next element head"}) + (keymap mode "B" api.move_to_prev_element_head {:desc "Previous element head"}) + (keymap mode "E" api.move_to_next_element_tail {:desc "Next element tail"}) + (keymap mode "gE" api.move_to_prev_element_tail {:desc "Previous element tail"})) + + ;; ============================================================ + ;; vim-sexp (guns) style LocalLeader bindings + ;; ============================================================ + + ;; w/W - Wrap element + insert at head/tail + (keymap :n "w" + (fn [] + (cursor.place_cursor + (wrap.wrap_element_under_cursor "( " ")") + {:placement "inner_start" :mode "insert"})) + {:desc "Wrap element, insert head"}) + (keymap :n "W" + (fn [] + (cursor.place_cursor + (wrap.wrap_element_under_cursor "(" ")") + {:placement "inner_end" :mode "insert"})) + {:desc "Wrap element, insert tail"}) + + ;; i/I - Wrap form + insert at head/tail + (keymap :n "i" + (fn [] + (cursor.place_cursor + (wrap.wrap_enclosing_form_under_cursor "( " ")") + {:placement "inner_start" :mode "insert"})) + {:desc "Wrap form, insert head"}) + (keymap :n "I" + (fn [] + (cursor.place_cursor + (wrap.wrap_enclosing_form_under_cursor "(" ")") + {:placement "inner_end" :mode "insert"})) + {:desc "Wrap form, insert tail"}) + + ;; [ ] { } - Wrap form in brackets/braces + insert + (keymap :n "[" + (fn [] + (cursor.place_cursor + (wrap.wrap_enclosing_form_under_cursor "[ " "]") + {:placement "inner_start" :mode "insert"})) + {:desc "Wrap form in [], insert head"}) + (keymap :n "]" + (fn [] + (cursor.place_cursor + (wrap.wrap_enclosing_form_under_cursor "[" "]") + {:placement "inner_end" :mode "insert"})) + {:desc "Wrap form in [], insert tail"}) + (keymap :n "{" + (fn [] + (cursor.place_cursor + (wrap.wrap_enclosing_form_under_cursor "{ " "}") + {:placement "inner_start" :mode "insert"})) + {:desc "Wrap form in {}, insert head"}) + (keymap :n "}" + (fn [] + (cursor.place_cursor + (wrap.wrap_enclosing_form_under_cursor "{" "}") + {:placement "inner_end" :mode "insert"})) + {:desc "Wrap form in {}, insert tail"}) + + ;; e[ e] e{ e} - Wrap element in brackets/braces + insert + (keymap :n "e[" + (fn [] + (cursor.place_cursor + (wrap.wrap_element_under_cursor "[ " "]") + {:placement "inner_start" :mode "insert"})) + {:desc "Wrap element in [], insert head"}) + (keymap :n "e]" + (fn [] + (cursor.place_cursor + (wrap.wrap_element_under_cursor "[" "]") + {:placement "inner_end" :mode "insert"})) + {:desc "Wrap element in [], insert tail"}) + (keymap :n "e{" + (fn [] + (cursor.place_cursor + (wrap.wrap_element_under_cursor "{ " "}") + {:placement "inner_start" :mode "insert"})) + {:desc "Wrap element in {}, insert head"}) + (keymap :n "e}" + (fn [] + (cursor.place_cursor + (wrap.wrap_element_under_cursor "{" "}") + {:placement "inner_end" :mode "insert"})) + {:desc "Wrap element in {}, insert tail"}) + + ;; h/l - Insert at list head/tail (vim-sexp originals) + ;; Same as I but with localleader + (keymap :n "h" + (fn [] + (api.move_to_parent_form_start) + (vim.cmd "normal! l") + (vim.cmd "startinsert")) + {:desc "Insert at list head"}) + (keymap :n "l" + (fn [] + (api.move_to_parent_form_end) + (vim.cmd "startinsert")) + {:desc "Insert at list tail"}) + + ;; [[ / ]] - Move to prev/next top-level form + (each [_ mode (ipairs [:n :x :o])] + (keymap mode "]]" + (fn [] + ;; Go to current top-level, then find next + (api.move_to_parent_form_end) + (api.move_to_next_element_head)) + {:desc "Next top-level form"}) + (keymap mode "[[" + (fn [] + ;; Go to current top-level start, then find prev + (api.move_to_parent_form_start) + (api.move_to_prev_element_head)) + {:desc "Previous top-level form"})))} + + ;; Clojure-Typst - Syntax highlighting for #t"" Typst literals in Clojure + ;; Injects Typst highlighting into tagged literals, ~() switches back to Clojure + {:dir "/home/ajet/repos/clojure-typst/editors/nvim" + :ft ["clojure"]} ;; Mason - Package manager for LSP servers, DAP servers, linters, formatters ;; Run :MasonInstall clojure_lsp lua_ls to install servers @@ -71,4 +230,5 @@ [{lhs "f" :group "find"} {lhs "b" :group "buffer"} {lhs "r" :group "refactor"} - {lhs "c" :group "code"}]))}] + {lhs "c" :group "code"} + {lhs "t" :group "toggle"}]))}] diff --git a/lazy-lock.json b/lazy-lock.json index cceedb0..9f3f7f9 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -4,6 +4,7 @@ "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, "nfnl": { "branch": "main", "commit": "fecf731e02bc51d88372c4f992fe1ef0c19c02ae" }, "nvim-paredit": { "branch": "master", "commit": "b6ba636874a3115d944e35746444724240568aca" }, + "nvim-parinfer": { "branch": "master", "commit": "3968e669d9f02589aa311d33cb475b16b27c5fbb" }, "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "telescope.nvim": { "branch": "master", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" },