;; 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"})))} ;; nvim-parinfer - Automatic parenthesis balancing ;; See fnl/config/parinfer.fnl for default-enabled flag and toggle logic {repo "gpanders/nvim-parinfer" :ft ["fennel" "clojure" "lisp" "scheme" "racket" "carp" "timl"] :init (fn [] (let [par (require :config.parinfer)] (set vim.g.parinfer_enabled par.default-enabled))) :keys [{lhs "tpi" rhs (fn [] (let [par (require :config.parinfer)] (par.toggle))) :desc "Toggle Parinfer"}]} ;; vim-sexp - Structural editing for S-expressions ;; with tpope's vim-sexp-mappings-for-regular-people {repo "guns/vim-sexp" :ft ["fennel" "clojure" "lisp" "scheme" "racket"] :dependencies ["tpope/vim-repeat" "tpope/vim-sexp-mappings-for-regular-people"] :init (fn [] (set vim.g.sexp_filetypes "clojure,scheme,lisp,timl,fennel,racket") ;; Sync sexp auto-insert with parinfer default (let [par (require :config.parinfer)] (set vim.g.sexp_enable_insert_mode_mappings (if par.default-enabled 0 1)))) :config (fn [] ;; vim-sexp-mappings-for-regular-people's setup is VimEnter-gated. ;; Under lazy.nvim :ft loading, VimEnter has already fired by the ;; time the plugin sources, so its FileType autocmd never registers ;; and the slurp/barf/swap mappings never attach. Register our own ;; FileType autocmd that maps the s directly. (let [fts (or vim.g.sexp_filetypes "clojure,scheme,lisp,timl,fennel,racket") attach (fn [] (let [m (fn [lhs rhs] (vim.keymap.set :n lhs rhs {:buffer 0 :silent true :remap true}))] (m "(sexp_insert_at_list_head)") (m ">I" "(sexp_insert_at_list_tail)") (m "(sexp_swap_list_backward)") (m ">f" "(sexp_swap_list_forward)") (m "(sexp_swap_element_backward)") (m ">e" "(sexp_swap_element_forward)") (m ">(" "(sexp_emit_head_element)") (m "<)" "(sexp_emit_tail_element)") (m "<(" "(sexp_capture_prev_element)") (m ">)" "(sexp_capture_next_element)") (m "dsf" "(sexp_splice_list)")))] (vim.api.nvim_create_augroup "sexp_regular_people_fix" {:clear true}) (vim.api.nvim_create_autocmd "FileType" {:group "sexp_regular_people_fix" :pattern (vim.split fts ",") :callback attach}) ;; Attach to current buffer (the FileType that triggered lazy load ;; already fired before this autocmd was registered). (when (vim.tbl_contains (vim.split fts ",") vim.bo.filetype) (attach))))} ;; Mason - Package manager for LSP servers, DAP servers, linters, formatters {repo "williamboman/mason.nvim" :lazy false :build ":MasonUpdate" :opts {:ui {:border "rounded"}}} ;; 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-language-server" "lua-language-server"]}} ;; 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 "t" :group "toggle"} {lhs "l" :group "log"}]))}]