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