Initial commit: Neovim config with Fennel via nfnl

This commit is contained in:
2026-01-29 15:05:35 -05:00
commit 9f25569788
8 changed files with 838 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
;; Main Fennel configuration
;; This file is compiled to lua/config/init.lua by nfnl
;; Options
(set vim.opt.number true)
(set vim.opt.relativenumber true)
(set vim.opt.tabstop 2)
(set vim.opt.shiftwidth 2)
(set vim.opt.expandtab true)
(set vim.opt.smartindent true)
(set vim.opt.wrap false)
(set vim.opt.ignorecase true)
(set vim.opt.smartcase true)
(set vim.opt.termguicolors true)
(set vim.opt.signcolumn "yes")
(set vim.opt.updatetime 250)
(set vim.opt.undofile true)
(set vim.opt.clipboard "unnamedplus")
;; Keymaps
(local keymap vim.keymap.set)
;; Window navigation
(keymap :n "<C-h>" "<C-w>h" {:desc "Move to left window"
:silent true})
(keymap :n "<C-j>" "<C-w>j" {:desc "Move to lower window"
:silent true})
(keymap :n "<C-k>" "<C-w>k" {:desc "Move to upper window"
:silent true})
(keymap :n "<C-l>" "<C-w>l" {:desc "Move to right window"
:silent true})
;; Buffer navigation
(keymap :n "<leader>bn" ":bnext<CR>" {:desc "Next buffer"})
(keymap :n "<leader>bp" ":bprevious<CR>" {:desc "Previous buffer"})
(keymap :n "<leader>bd" ":bdelete<CR>" {:desc "Delete buffer"})
;; Clear search highlight
(keymap :n "<Esc>" ":noh<CR>" {:desc "Clear search highlight"})
;; Better escape
(keymap :i "jk" "<Esc>" {:desc "Escape insert mode"})
;; Save file
(keymap :n "<leader>w" ":w<CR>" {:desc "Save file"})
(keymap :n "<leader>fs" ":wa<CR>" {:desc "Save all files" :silent true})
;; Quit
(keymap :n "<leader>q" ":q<CR>" {:desc "Quit"})
;; Autocommands
(local augroup vim.api.nvim_create_augroup)
(local autocmd vim.api.nvim_create_autocmd)
;; Highlight on yank
(let [yank-group (augroup "YankHighlight" {:clear true})]
(autocmd "TextYankPost" {:group yank-group
:callback (fn [] (vim.highlight.on_yank))}))
;; Remove trailing whitespace on save
(let [whitespace-group (augroup "TrimWhitespace" {:clear true})]
(autocmd "BufWritePre" {:group whitespace-group
:pattern "*"
:command "%s/\\s\\+$//e"}))
;; LSP Configuration (Neovim 0.11+ built-in)
;; Configure servers using vim.lsp.config
(vim.lsp.config :clojure_lsp
{:cmd [:clojure-lsp]
:filetypes [:clojure :edn]
:root_markers [:deps.edn :project.clj :build.boot :shadow-cljs.edn :.git]})
(vim.lsp.config :lua_ls
{:cmd [:lua-language-server]
:filetypes [:lua]
:root_markers [:.luarc.json :.luarc.jsonc :.git]
:settings {:Lua {:runtime {:version :LuaJIT}
:workspace {:library (vim.api.nvim_get_runtime_file "" true)}}}})
(vim.lsp.config :fennel_language_server
{:cmd [:fennel-language-server]
:filetypes [:fennel]
:root_markers [:.nfnl.fnl :fnl :.git]
:settings {:fennel {:workspace {:library (vim.api.nvim_get_runtime_file "" true)}
:diagnostics {:globals [:vim]}}}})
;; Enable the configured LSP servers
(vim.lsp.enable [:clojure_lsp :lua_ls :fennel_language_server])
;; LSP keymaps (set on attach)
(autocmd "LspAttach"
{:callback (fn [ev]
(local opts {:buffer ev.buf})
(keymap :n "gd" vim.lsp.buf.definition opts)
(keymap :n "gD" vim.lsp.buf.declaration opts)
(keymap :n "gr" vim.lsp.buf.references opts)
(keymap :n "gi" vim.lsp.buf.implementation opts)
(keymap :n "K" vim.lsp.buf.hover opts)
(keymap :n "<leader>rn" vim.lsp.buf.rename opts)
(keymap :n "<leader>ca" vim.lsp.buf.code_action opts)
(keymap :n "[d" (fn [] (vim.diagnostic.jump {:count -1})) opts)
(keymap :n "]d" (fn [] (vim.diagnostic.jump {:count 1})) opts)
(keymap :n "<leader>e" vim.diagnostic.open_float opts)
(keymap :n "<leader>F" vim.lsp.buf.format opts))})
;; LSP commands (lspconfig-style)
(local usercmd vim.api.nvim_create_user_command)
(usercmd "LspInfo"
(fn [] (vim.cmd "checkhealth vim.lsp"))
{:desc "Show LSP info"})
(usercmd "LspStart"
(fn [opts]
(if (and opts.args (> (length opts.args) 0))
(vim.lsp.enable opts.args)
(vim.lsp.enable [:clojure_lsp :lua_ls :fennel_language_server])))
{:nargs "?"
:complete (fn [] [:clojure_lsp :lua_ls :fennel_language_server])
:desc "Start LSP server"})
(usercmd "LspStop"
(fn []
(each [_ client (ipairs (vim.lsp.get_clients))]
(vim.lsp.stop_client client.id)))
{:desc "Stop all LSP clients"})
(usercmd "LspRestart"
(fn []
(each [_ client (ipairs (vim.lsp.get_clients))]
(vim.lsp.stop_client client.id))
(vim.defer_fn (fn [] (vim.cmd "edit")) 100))
{:desc "Restart LSP clients"})
(usercmd "LspLog"
(fn [] (vim.cmd (.. "edit " (vim.lsp.get_log_path))))
{:desc "Open LSP log file"})
{}
+74
View File
@@ -0,0 +1,74 @@
;; 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) ;; which-key spec index for the key sequence (see which-key below)
[;; 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 []
;; Enable HUD floating window
(set vim.g.conjure#log#hud#enabled true))}
;; nvim-paredit - Structural editing for Lisp
;; Default keybindings: >)/<) slurp/barf forward, <(/>( slurp/barf backward
;; >e/<e drag element, >f/<f drag form, E/W/B element motions
{repo "julienvincent/nvim-paredit"
:ft ["fennel" "clojure" "lisp" "scheme" "racket"]
:config (fn []
(local paredit (require :nvim-paredit))
;; Use default keybindings (>), <), <(, >(, etc.)
(paredit.setup {})
;; Additional vim-sexp compatible bindings
(local keymap vim.keymap.set)
(local api paredit.api)
;; dsf - Splice (delete surrounding form)
(keymap :n "dsf" api.unwrap_form_under_cursor {:desc "Splice (delete surrounding form)"})
;; cse( cse) - Wrap in parens
(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 {}"}))}
;; Mason - Package manager for LSP servers, DAP servers, linters, formatters
;; Run :MasonInstall clojure_lsp lua_ls to install servers
{repo "williamboman/mason.nvim"
:cmd ["Mason" "MasonInstall" "MasonUpdate"]
:build ":MasonUpdate"
:opts {:ui {:border "rounded"}}}
;; 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 "<leader>f" :group "find"}
{lhs "<leader>b" :group "buffer"}
{lhs "<leader>r" :group "refactor"}
{lhs "<leader>c" :group "code"}]))}]