Convert nvim config to submodule
- Remove individual tracked files from .config/nvim - Add as submodule pointing to git@git.ajet.fyi:ajet/nvim-config.git
This commit is contained in:
Submodule
+1
Submodule .config/nvim added at 9f25569788
@@ -1,5 +0,0 @@
|
||||
undodir
|
||||
|
||||
# Generated Lua files (compiled from Fennel by nfnl)
|
||||
lua/config/
|
||||
lua/plugins/
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -1,78 +0,0 @@
|
||||
# Claude Code Context
|
||||
|
||||
This is a Neovim configuration using Fennel (a Lisp that compiles to Lua) via nfnl.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **nfnl** compiles `.fnl` files to `.lua` on save
|
||||
- **lazy.nvim** is the plugin manager
|
||||
- Bootstrap files are in Lua; user config is in Fennel
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
init.lua - Entry point (Lua, do not convert to Fennel)
|
||||
lua/bootstrap.lua - Core plugins in Lua (nfnl, treesitter, telescope)
|
||||
lua/config/ - AUTO-GENERATED from fnl/config/ - do not edit
|
||||
lua/plugins/ - AUTO-GENERATED from fnl/plugins/ - do not edit
|
||||
fnl/config/ - User config in Fennel (options, keymaps, autocmds)
|
||||
fnl/plugins/ - Plugin specs in Fennel
|
||||
.nfnl.fnl - nfnl configuration
|
||||
```
|
||||
|
||||
## Editing Rules
|
||||
|
||||
1. **Never edit files in `lua/config/` or `lua/plugins/`** - they are auto-generated
|
||||
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:
|
||||
```bash
|
||||
cd ~/.config/nvim && nvim --headless -c "NfnlCompileAllFiles" -c "qa"
|
||||
```
|
||||
|
||||
## Fennel Syntax Quick Reference
|
||||
|
||||
```fennel
|
||||
;; Set vim option
|
||||
(set vim.opt.number true)
|
||||
|
||||
;; Define keymap
|
||||
(vim.keymap.set :n "<leader>x" ":cmd<CR>" {:desc "Description"})
|
||||
|
||||
;; Local variable
|
||||
(local foo (require :foo))
|
||||
|
||||
;; Let binding
|
||||
(let [x 1 y 2] (+ x y))
|
||||
|
||||
;; Function
|
||||
(fn my-func [arg] (print arg))
|
||||
|
||||
;; Lambda
|
||||
(fn [x] (* x 2))
|
||||
|
||||
;; Plugin spec (lazy.nvim format)
|
||||
{:1 "author/plugin"
|
||||
:ft ["fennel" "lua"]
|
||||
:config (fn [] (setup-code))}
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Add a plugin
|
||||
Edit `fnl/plugins/init.fnl`, add spec to the vector, save.
|
||||
|
||||
### Add a keymap
|
||||
Edit `fnl/config/init.fnl`, add `(vim.keymap.set ...)`, save.
|
||||
|
||||
### Add an option
|
||||
Edit `fnl/config/init.fnl`, add `(set vim.opt.foo value)`, save.
|
||||
|
||||
### Force recompile all Fennel
|
||||
Run `:NfnlCompileAllFiles` in Neovim.
|
||||
|
||||
## Leader Keys
|
||||
|
||||
- Leader: `<Space>`
|
||||
- Local leader: `<Space>` (same as leader, used by Conjure and paredit)
|
||||
@@ -1,441 +0,0 @@
|
||||
# Neovim Fennel/Clojure Configuration
|
||||
|
||||
A Neovim configuration optimized for Lisp development (Fennel, Clojure, Scheme, Racket) using [Fennel](https://fennel-lang.org/) as the configuration language.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Neovim 0.11+** (uses built-in LSP configuration)
|
||||
- **Git** (for plugin installation)
|
||||
|
||||
### Optional but Recommended
|
||||
|
||||
Install language servers for full IDE features:
|
||||
|
||||
```bash
|
||||
# Clojure LSP (for Clojure/ClojureScript)
|
||||
brew install clojure-lsp/brew/clojure-lsp
|
||||
|
||||
# Fennel Language Server (for Fennel)
|
||||
cargo install fennel-language-server
|
||||
|
||||
# Lua Language Server (for Lua/Neovim plugin development)
|
||||
brew install lua-language-server
|
||||
```
|
||||
|
||||
Or use Mason inside Neovim: `:MasonInstall clojure-lsp lua-language-server`
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Clone this repo to `~/.config/nvim`
|
||||
2. Open Neovim - plugins install automatically on first launch
|
||||
3. Open a `.fnl` or `.clj` file and start editing
|
||||
|
||||
## Understanding Lisp Editing
|
||||
|
||||
If you're new to Lisp, here are the key concepts that make editing different from other languages.
|
||||
|
||||
### S-Expressions (Sexps)
|
||||
|
||||
All Lisp code is made of nested parenthesized expressions called **s-expressions** or **sexps**:
|
||||
|
||||
```clojure
|
||||
(defn greet [name] ; <- this whole thing is a "form" or "sexp"
|
||||
(str "Hello, " name)) ; <- this is a nested form
|
||||
```
|
||||
|
||||
- **Form**: A complete s-expression (anything in balanced parens/brackets/braces)
|
||||
- **Element**: A single item - either an atom (`name`, `42`, `:keyword`) or a form
|
||||
|
||||
### Structural Editing
|
||||
|
||||
Instead of editing text character-by-character, Lisp programmers edit **structures**. The paredit plugin keeps your parentheses balanced automatically and lets you manipulate code by its structure.
|
||||
|
||||
**Example - Slurping:**
|
||||
```clojure
|
||||
;; Before: cursor inside the (+ 1 2) form
|
||||
(foo (+ 1 2) 3 4)
|
||||
|
||||
;; After pressing >) (slurp forward) - pulls 3 into the form
|
||||
(foo (+ 1 2 3) 4)
|
||||
```
|
||||
|
||||
**Example - Barfing:**
|
||||
```clojure
|
||||
;; Before: cursor inside the (+ 1 2 3) form
|
||||
(foo (+ 1 2 3) 4)
|
||||
|
||||
;; After pressing <) (barf forward) - pushes 3 out of the form
|
||||
(foo (+ 1 2) 3 4)
|
||||
```
|
||||
|
||||
### Interactive Development (REPL)
|
||||
|
||||
Lisp development is **interactive**. You connect to a running program (REPL) and evaluate code as you write it. Conjure handles this - you can evaluate any expression and see results immediately.
|
||||
|
||||
---
|
||||
|
||||
## Keybindings Reference
|
||||
|
||||
**Leader key: `Space`**
|
||||
|
||||
Press `Space` and wait to see available options via which-key.
|
||||
|
||||
### General Navigation
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Ctrl-h/j/k/l` | Move between windows |
|
||||
| `Space f f` | Find files (Telescope) |
|
||||
| `Space f g` | Live grep in project |
|
||||
| `Space f b` | List open buffers |
|
||||
| `Space f h` | Search help tags |
|
||||
| `Space b n` | Next buffer |
|
||||
| `Space b p` | Previous buffer |
|
||||
| `Space b d` | Delete buffer |
|
||||
|
||||
### General Editing
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `jk` | Escape insert mode |
|
||||
| `Space w` | Save file |
|
||||
| `Space f s` | Save all files |
|
||||
| `Space q` | Quit |
|
||||
| `Esc` | Clear search highlight |
|
||||
|
||||
### LSP (Language Server)
|
||||
|
||||
Available when editing files with LSP support (Clojure, Fennel, Lua):
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `gd` | Go to definition |
|
||||
| `gD` | Go to declaration |
|
||||
| `gr` | Find references |
|
||||
| `gi` | Go to implementation |
|
||||
| `K` | Show hover documentation |
|
||||
| `Space r n` | Rename symbol |
|
||||
| `Space c a` | Code actions |
|
||||
| `Space e` | Show diagnostic popup |
|
||||
| `Space F` | Format buffer |
|
||||
| `[d` | Previous diagnostic |
|
||||
| `]d` | Next diagnostic |
|
||||
|
||||
**Commands:** `:LspInfo`, `:LspStart`, `:LspStop`, `:LspRestart`, `:LspLog`
|
||||
|
||||
---
|
||||
|
||||
## Conjure - REPL Integration
|
||||
|
||||
Conjure connects your editor to a running REPL, allowing you to evaluate code interactively.
|
||||
|
||||
### Starting a REPL
|
||||
|
||||
**Clojure:**
|
||||
```bash
|
||||
# In your project directory
|
||||
clj -M:repl # or however your project starts a REPL
|
||||
```
|
||||
|
||||
**Fennel:**
|
||||
```bash
|
||||
fennel --repl
|
||||
```
|
||||
|
||||
Conjure auto-connects when you open a Lisp file and a REPL is running.
|
||||
|
||||
### Evaluation Keybindings
|
||||
|
||||
All Conjure bindings start with `Space` (local leader):
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Space e e` | Evaluate form under cursor |
|
||||
| `Space e r` | Evaluate root (top-level) form |
|
||||
| `Space e b` | Evaluate entire buffer |
|
||||
| `Space e f` | Evaluate file |
|
||||
| `Space e !` | Evaluate form and replace with result |
|
||||
| `Space e w` | Evaluate word under cursor |
|
||||
|
||||
### Log Buffer
|
||||
|
||||
Results appear in a floating HUD window. To interact with the full log:
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Space l v` | Open log in vertical split |
|
||||
| `Space l s` | Open log in horizontal split |
|
||||
| `Space l t` | Open log in new tab |
|
||||
| `Space l q` | Close log windows |
|
||||
| `Space l r` | Reset/clear the log |
|
||||
|
||||
### Documentation
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `K` | Show documentation for symbol under cursor |
|
||||
|
||||
### Tip: Learn Interactively
|
||||
|
||||
Run `:ConjureSchool` for an interactive tutorial inside Neovim.
|
||||
|
||||
---
|
||||
|
||||
## nvim-paredit - Structural Editing
|
||||
|
||||
Paredit keeps parentheses balanced and provides structural editing commands.
|
||||
|
||||
### Navigation
|
||||
|
||||
Move by **elements** (atoms or forms) rather than words:
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `W` | Next element head |
|
||||
| `B` | Previous element head |
|
||||
| `E` | Next element tail |
|
||||
| `gE` | Previous element tail |
|
||||
| `(` | Jump to parent form's opening paren |
|
||||
| `)` | Jump to parent form's closing paren |
|
||||
| `T` | Jump to top-level form's head |
|
||||
|
||||
### Slurp and Barf
|
||||
|
||||
**Slurp**: Pull the next/previous element INTO the current form
|
||||
**Barf**: Push the last/first element OUT OF the current form
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `>)` | Slurp forward (pull next element in) |
|
||||
| `<(` | Slurp backward (pull previous element in) |
|
||||
| `<)` | Barf forward (push last element out) |
|
||||
| `>(` | Barf backward (push first element out) |
|
||||
|
||||
**Visual example - forward operations:**
|
||||
```clojure
|
||||
;; Cursor inside: (+ 1 2)
|
||||
(foo (+ 1 2) 3 4)
|
||||
|
||||
;; >) slurp forward - pull 3 into the form
|
||||
(foo (+ 1 2 3) 4)
|
||||
|
||||
;; >) again - pull 4 in
|
||||
(foo (+ 1 2 3 4))
|
||||
|
||||
;; <) barf forward - push 4 back out
|
||||
(foo (+ 1 2 3) 4)
|
||||
```
|
||||
|
||||
**Visual example - backward operations:**
|
||||
```clojure
|
||||
;; Cursor inside: (+ 1 2)
|
||||
(a b (+ 1 2))
|
||||
|
||||
;; <( slurp backward - pull b into the form
|
||||
(a (b + 1 2))
|
||||
|
||||
;; >( barf backward - push b back out
|
||||
(a b (+ 1 2))
|
||||
```
|
||||
|
||||
### Dragging Elements
|
||||
|
||||
Move elements/forms left and right within their parent:
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `>e` | Drag element right |
|
||||
| `<e` | Drag element left |
|
||||
| `>f` | Drag form right |
|
||||
| `<f` | Drag form left |
|
||||
|
||||
**Example:**
|
||||
```clojure
|
||||
;; Cursor on 'a'
|
||||
(foo a b c)
|
||||
|
||||
;; >e drag element right - swap a and b
|
||||
(foo b a c)
|
||||
```
|
||||
|
||||
### Wrapping
|
||||
|
||||
Wrap an element in delimiters:
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `cse(` or `cse)` | Wrap element in `()` |
|
||||
| `cse[` or `cse]` | Wrap element in `[]` |
|
||||
| `cse{` or `cse}` | Wrap element in `{}` |
|
||||
|
||||
### Splice (Unwrap)
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `dsf` | Splice - delete surrounding form, keeping contents |
|
||||
|
||||
**Example:**
|
||||
```clojure
|
||||
;; Before (cursor inside the when form)
|
||||
(when true (println "hello"))
|
||||
|
||||
;; dsf - splice, removing the surrounding parens
|
||||
when true (println "hello")
|
||||
```
|
||||
|
||||
### Raise
|
||||
|
||||
Replace the parent form with the current form/element:
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Space o` | Raise form (replace parent with current form) |
|
||||
| `Space O` | Raise element (replace parent with current element) |
|
||||
|
||||
**Example:**
|
||||
```clojure
|
||||
;; Before: cursor on (inner value)
|
||||
(outer (inner value))
|
||||
|
||||
;; Space o - raise form, replacing parent with current form
|
||||
(inner value)
|
||||
```
|
||||
|
||||
### Text Objects
|
||||
|
||||
Use with operators like `d`, `c`, `y`, `v`:
|
||||
|
||||
| Text Object | Meaning |
|
||||
|-------------|---------|
|
||||
| `af` | Around form (including parens) |
|
||||
| `if` | Inside form (excluding parens) |
|
||||
| `aF` | Around top-level form |
|
||||
| `iF` | Inside top-level form |
|
||||
| `ae` | Around element |
|
||||
| `ie` | Inside element |
|
||||
|
||||
**Examples:**
|
||||
- `daf` - Delete around form (delete entire form including parens)
|
||||
- `cif` - Change inside form (replace form contents)
|
||||
- `yae` - Yank around element
|
||||
|
||||
---
|
||||
|
||||
## Workflow Examples
|
||||
|
||||
### Editing a Clojure Function
|
||||
|
||||
1. Start your REPL: `clj` in terminal
|
||||
2. Open your `.clj` file
|
||||
3. Write a function:
|
||||
```clojure
|
||||
(defn add [a b]
|
||||
(+ a b))
|
||||
```
|
||||
4. `Space e r` to evaluate the top-level form
|
||||
5. Test it: type `(add 1 2)` and `Space e e` to evaluate
|
||||
6. See `3` appear in the HUD
|
||||
|
||||
### Refactoring with Paredit
|
||||
|
||||
Transform `(if test a b)` to `(when test a)`:
|
||||
|
||||
1. Position cursor on `if`
|
||||
2. `ciw` to change word, type `when`
|
||||
3. Move to `b`, `dae` to delete the element
|
||||
4. Done: `(when test a)`
|
||||
|
||||
### Wrapping Code in a Let
|
||||
|
||||
```clojure
|
||||
;; Start with:
|
||||
(+ x y)
|
||||
|
||||
;; Position on the form, then: cse(
|
||||
((+ x y))
|
||||
|
||||
;; Now you have wrapped parens. Type your let:
|
||||
(let [z 1] (+ x y))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
~/.config/nvim/
|
||||
├── init.lua # Entry point (Lua)
|
||||
├── lua/
|
||||
│ ├── bootstrap.lua # Core plugins (nfnl, treesitter, telescope)
|
||||
│ ├── config/ # AUTO-GENERATED from fnl/config/
|
||||
│ └── plugins/ # AUTO-GENERATED from fnl/plugins/
|
||||
└── fnl/
|
||||
├── config/init.fnl # Your settings, keymaps, LSP config
|
||||
└── plugins/init.fnl # Plugin specifications
|
||||
```
|
||||
|
||||
**Important:** Edit files in `fnl/`, not `lua/config/` or `lua/plugins/` - those are auto-generated.
|
||||
|
||||
---
|
||||
|
||||
## Customization
|
||||
|
||||
### Add a Plugin
|
||||
|
||||
Edit `fnl/plugins/init.fnl`, add a spec to the vector:
|
||||
|
||||
```fennel
|
||||
{:1 "author/plugin-name"
|
||||
:config (fn [] (setup-code-here))}
|
||||
```
|
||||
|
||||
### Add a Keymap
|
||||
|
||||
Edit `fnl/config/init.fnl`:
|
||||
|
||||
```fennel
|
||||
(vim.keymap.set :n "<leader>x" ":SomeCommand<CR>" {:desc "Do something"})
|
||||
```
|
||||
|
||||
### Change the Colorscheme
|
||||
|
||||
Edit the tokyonight config in `fnl/plugins/init.fnl`, or add a different colorscheme plugin.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### LSP not working?
|
||||
|
||||
1. Check if the server is installed: `:LspInfo`
|
||||
2. Check the log: `:LspLog`
|
||||
3. Ensure you're in a project with root markers (`.git`, `deps.edn`, etc.)
|
||||
|
||||
### Conjure not connecting?
|
||||
|
||||
1. Make sure your REPL is running before opening the file
|
||||
2. For Clojure: ensure nREPL is exposed (default port 7888 or `.nrepl-port` file)
|
||||
3. Check `:ConjureLog` for connection errors
|
||||
|
||||
### Paredit feels wrong?
|
||||
|
||||
Structural editing takes practice. Start with just `>)` and `<)` for slurp/barf, then gradually add more commands. The `:help nvim-paredit` documentation is excellent.
|
||||
|
||||
---
|
||||
|
||||
## Learning Resources
|
||||
|
||||
- **Conjure Interactive Tutorial**: `:ConjureSchool`
|
||||
- **Fennel Language**: https://fennel-lang.org/tutorial
|
||||
- **Clojure for the Brave and True**: https://www.braveclojure.com/
|
||||
- **Paredit Guide** (Emacs, but concepts apply): https://www.emacswiki.org/emacs/ParEdit
|
||||
|
||||
---
|
||||
|
||||
## Credits
|
||||
|
||||
- [nfnl](https://github.com/Olical/nfnl) - Fennel to Lua compiler for Neovim
|
||||
- [Conjure](https://github.com/Olical/conjure) - Interactive REPL environment
|
||||
- [nvim-paredit](https://github.com/julienvincent/nvim-paredit) - Structural editing
|
||||
- [lazy.nvim](https://github.com/folke/lazy.nvim) - Plugin manager
|
||||
- [tokyonight.nvim](https://github.com/folke/tokyonight.nvim) - Colorscheme
|
||||
@@ -1,139 +0,0 @@
|
||||
;; 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"})
|
||||
|
||||
{}
|
||||
@@ -1,74 +0,0 @@
|
||||
;; 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"}]))}]
|
||||
@@ -1,26 +0,0 @@
|
||||
-- Set leader keys before lazy loads
|
||||
vim.g.mapleader = " "
|
||||
vim.g.maplocalleader = " "
|
||||
|
||||
-- Bootstrap lazy.nvim
|
||||
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
||||
if not (vim.uv or vim.loop).fs_stat(lazypath) then
|
||||
vim.fn.system({
|
||||
"git",
|
||||
"clone",
|
||||
"--filter=blob:none",
|
||||
"https://github.com/folke/lazy.nvim.git",
|
||||
"--branch=stable",
|
||||
lazypath,
|
||||
})
|
||||
end
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
-- Setup lazy.nvim
|
||||
require("lazy").setup({
|
||||
{ import = "bootstrap" },
|
||||
{ import = "plugins" },
|
||||
})
|
||||
|
||||
-- Load Fennel config (compiled from fnl/config/init.fnl)
|
||||
pcall(require, "config.init")
|
||||
@@ -1,54 +0,0 @@
|
||||
-- Core plugins that must be in Lua (nfnl compiles Fennel, so it can't be in Fennel)
|
||||
return {
|
||||
{
|
||||
"Olical/nfnl",
|
||||
lazy = false,
|
||||
config = function()
|
||||
-- Create global commands that work without opening a fennel file first
|
||||
local api = require("nfnl.api")
|
||||
vim.api.nvim_create_user_command("NfnlCompileAllFiles", function(opts)
|
||||
api["compile-all-files"](opts.args ~= "" and opts.args or nil)
|
||||
end, { desc = "Compile all Fennel files", nargs = "?", complete = "dir" })
|
||||
vim.api.nvim_create_user_command("NfnlCompileFile", function(opts)
|
||||
api["compile-file"]({ path = opts.args ~= "" and opts.args or nil })
|
||||
end, { desc = "Compile current or specified Fennel file", nargs = "?", complete = "file" })
|
||||
end,
|
||||
},
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
build = ":TSUpdate",
|
||||
config = function()
|
||||
local langs = { "clojure", "fennel", "lua", "vim", "vimdoc", "query" }
|
||||
|
||||
-- Install parsers asynchronously on first load
|
||||
vim.schedule(function()
|
||||
local installed = require("nvim-treesitter").get_installed()
|
||||
for _, lang in ipairs(langs) do
|
||||
if not vim.list_contains(installed, lang) then
|
||||
require("nvim-treesitter").install(lang)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Enable treesitter highlighting for supported filetypes
|
||||
-- This is required for nvim-paredit to work (needs vim.treesitter.get_node())
|
||||
vim.api.nvim_create_autocmd("FileType", {
|
||||
pattern = { "clojure", "fennel", "lua", "vim", "query", "scheme", "lisp" },
|
||||
callback = function()
|
||||
pcall(vim.treesitter.start)
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
{
|
||||
"nvim-telescope/telescope.nvim",
|
||||
tag = "0.1.8",
|
||||
dependencies = { "nvim-lua/plenary.nvim" },
|
||||
keys = {
|
||||
{ "<leader>ff", "<cmd>Telescope find_files<cr>", desc = "Find files" },
|
||||
{ "<leader>fg", "<cmd>Telescope live_grep<cr>", desc = "Live grep" },
|
||||
{ "<leader>fb", "<cmd>Telescope buffers<cr>", desc = "Buffers" },
|
||||
{ "<leader>fh", "<cmd>Telescope help_tags<cr>", desc = "Help tags" },
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
[submodule ".config/nvim"]
|
||||
path = .config/nvim
|
||||
url = git@git.ajet.fyi:ajet/nvim-config.git
|
||||
branch = main
|
||||
Reference in New Issue
Block a user