;; Plugin specs in Fennel ;; 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) ;; 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" :lazy false :priority 1000 :config (fn [] (let [tokyonight (require :tokyonight)] (tokyonight.setup {:style "night" ; storm, moon, night, or day :transparent false :terminal_colors true})) (vim.cmd.colorscheme "tokyonight"))} ;; Conjure - Interactive REPL for Fennel, Clojure, Lisp, etc. {repo "Olical/conjure" :ft ["fennel" "clojure" "lisp" "scheme" "racket" "lua"] :config (fn [] ;; HUD (set vim.g.conjure#log#hud#enabled true) (set vim.g.conjure#log#hud#width 0.42) (set vim.g.conjure#log#hud#height 0.30) ;; Auto-start lein repl when no .nrepl-port found (set vim.g.conjure#client#clojure#nrepl#connection#auto_repl#enabled true) (set vim.g.conjure#client#clojure#nrepl#connection#auto_repl#cmd "lein repl :headless") ;; Show result inline as virtual text (set vim.g.conjure#eval#result_register "*") (set vim.g.conjure#eval#inline#enabled true) (set vim.g.conjure#eval#inline#prefix "=> ") ;; Open log as vertical split (set vim.g.conjure#log#split#enabled true) (set vim.g.conjure#log#split#direction "vertical") ;; Clojure-specific: strip ANSI from nREPL output (set vim.g.conjure#client#clojure#nrepl#eval#raw_out true) ;; Keymaps (let [km vim.keymap.set] (km :n "lv" (fn [] (vim.cmd "ConjureLogVSplit")) {:desc "Conjure log vertical split"}) (km :n "lt" (fn [] (vim.cmd "ConjureLogTab")) {:desc "Conjure log tab"})))} ;; vim-sexp + tpope's mappings - Structural editing for S-expressions ;; Loaded eagerly so VimEnter fires before plugin sources, letting ;; vim-sexp-mappings-for-regular-people register its FileType autocmds. {repo "tpope/vim-sexp-mappings-for-regular-people" :lazy false :dependencies ["tpope/vim-repeat" "guns/vim-sexp"] :config (fn [] (set vim.g.sexp_filetypes "clojure,scheme,lisp,timl,fennel,racket") (set vim.g.sexp_enable_insert_mode_mappings 0))} ;; vim-surround - Add/change/delete surrounding pairs (quotes, brackets, tags) {repo "tpope/vim-surround" :dependencies ["tpope/vim-repeat"] :event "VeryLazy"} ;; Mason - Package manager for LSP servers, DAP servers, linters, formatters {repo "williamboman/mason.nvim" :lazy false :build ":MasonUpdate" :opts {:ui {:border "rounded"} :registries ["github:mason-org/mason-registry" "github:Crashdummyy/mason-registry"]}} ;; Auto-install LSP servers and tools via Mason {repo "WhoIsSethDaniel/mason-tool-installer.nvim" :lazy false :dependencies ["williamboman/mason.nvim"] :opts {:ensure_installed ["clojure-lsp" "clj-kondo" "fennel-ls" "lua-language-server" "rust-analyzer" "roslyn"]}} ;; Hop - EasyMotion-like word jumping {repo "smoka7/hop.nvim" :version "*" :event "VeryLazy" :config (fn [] (let [hop (require :hop)] (hop.setup) (vim.keymap.set :n "gw" (fn [] (hop.hint_words)) {:desc "Hop to word"})))} ;; LispSchool - Interactive structural editing tutorial ;; Source: fnl/lisp-school.fnl (compiled by nfnl) {:name "lisp-school" :dir (vim.fn.stdpath "config") :cmd ["LispSchool" "LispSchoolNext"] :config (fn [] (vim.api.nvim_create_user_command "LispSchool" (fn [] (let [ls (require :lisp-school)] (ls.start))) {:desc "Start LispSchool tutorial"}) (vim.api.nvim_create_user_command "LispSchoolNext" (fn [] (let [ls (require :lisp-school)] (ls.next))) {:desc "Next LispSchool lesson"}))} ;; which-key - Shows keybinding hints ;; lhs constant defined at top - which-key specs use index [1] for the key sequence {repo "folke/which-key.nvim" :event "VeryLazy" :opts {} :config (fn [_ opts] (local wk (require :which-key)) (wk.setup opts) (wk.add [{lhs "f" :group "find"} {lhs "b" :group "buffer"} {lhs "r" :group "refactor"} {lhs "c" :group "code"} {lhs "h" :group "hunk"} {lhs "t" :group "toggle"} {lhs "l" :group "log"} {lhs "a" :group "AI/Claude"}]))} ;; claudecode.nvim - Claude Code AI assistant integration {repo "coder/claudecode.nvim" :dependencies ["folke/snacks.nvim"] :config true :keys [{lhs "a" :desc "AI/Claude Code"} {lhs "ac" rhs "ClaudeCode" :desc "Toggle Claude"} {lhs "af" rhs "ClaudeCodeFocus" :desc "Focus Claude"} {lhs "ar" rhs "ClaudeCode --resume" :desc "Resume Claude"} {lhs "aC" rhs "ClaudeCode --continue" :desc "Continue Claude"} {lhs "am" rhs "ClaudeCodeSelectModel" :desc "Select Claude model"} {lhs "ab" rhs "ClaudeCodeAdd %" :desc "Add current buffer"} {lhs "as" rhs "ClaudeCodeSend" :mode "v" :desc "Send to Claude"} {lhs "as" rhs "ClaudeCodeTreeAdd" :desc "Add file" :ft ["NvimTree" "neo-tree" "oil" "minifiles" "netrw"]} {lhs "aa" rhs "ClaudeCodeDiffAccept" :desc "Accept diff"} {lhs "ad" rhs "ClaudeCodeDiffDeny" :desc "Deny diff"}]} ;; Supermaven - AI code completion {repo "supermaven-inc/supermaven-nvim" :event "InsertEnter" :opts {:disable_inline_completion true}} ;; blink.cmp - Fast completion engine with LSP support {repo "saghen/blink.cmp" :version "*" :event ["InsertEnter" "CmdlineEnter"] :dependencies ["supermaven-inc/supermaven-nvim"] :opts {:keymap {:preset "super-tab" "" [(fn [cmp] (cmp.show {:providers ["supermaven"]})) :fallback] "" [:select_and_accept :snippet_forward :fallback] "" [(fn [cmp] (cmp.cancel) false) :fallback]} :completion {:list {:selection {:preselect true :auto_insert false}} :documentation {:auto_show true}} :sources {:default ["lsp" "path" "buffer"] :providers {:supermaven {:name "Supermaven" :module "supermaven-blink"}}}}} ;; roslyn.nvim - C# and Blazor/Razor LSP via Roslyn language server ;; Must not be ft-gated: plugin/roslyn.lua calls vim.lsp.enable which needs to ;; run before the FileType event fires, or existing .cs buffers won't attach. {repo "seblj/roslyn.nvim" :lazy false :config (fn [] (let [roslyn (require :roslyn)] (roslyn.setup {})))} ;; gitsigns.nvim - Git diff signs in the sign column {repo "lewis6991/gitsigns.nvim" :event ["BufReadPre" "BufNewFile"] :opts {:signs {:add {:text "│"} :change {:text "│"} :delete {:text "_"} :topdelete {:text "‾"} :changedelete {:text "~"} :untracked {:text "┆"}} :sign_priority 6 :update_debounce 100 :max_file_length 40000 :preview_config {:border "single" :style "minimal" :relative "cursor" :row 0 :col 1} :on_attach (fn [bufnr] (local gs (require :gitsigns)) (fn map [mode l r opts] (let [o (or opts {})] (set o.buffer bufnr) (vim.keymap.set mode l r o))) (map :n "]c" (fn [] (if vim.wo.diff "]c" (do (vim.schedule #(gs.next_hunk)) ""))) {:expr true :desc "Next hunk"}) (map :n "[c" (fn [] (if vim.wo.diff "[c" (do (vim.schedule #(gs.prev_hunk)) ""))) {:expr true :desc "Prev hunk"}) (map [:n :v] "hs" ":Gitsigns stage_hunk" {:desc "Stage hunk"}) (map [:n :v] "hr" ":Gitsigns reset_hunk" {:desc "Reset hunk"}) (map :n "hS" gs.stage_buffer {:desc "Stage buffer"}) (map :n "hu" gs.undo_stage_hunk {:desc "Undo stage"}) (map :n "hR" gs.reset_buffer {:desc "Reset buffer"}) (map :n "hp" gs.preview_hunk {:desc "Preview hunk"}) (map :n "hb" #(gs.blame_line {:full true}) {:desc "Blame line"}) (map :n "tb" gs.toggle_current_line_blame {:desc "Toggle blame"}) (map :n "hd" gs.diffthis {:desc "Diff this"}) (map :n "hD" #(gs.diffthis "~") {:desc "Diff this ~"}) (map :n "td" gs.toggle_deleted {:desc "Toggle deleted"}) (map [:o :x] "ih" ":Gitsigns select_hunk" {:desc "Select hunk"}))}}]