feat: reorg initial commit

This commit is contained in:
Anup Sebastian 2025-10-31 14:36:33 -05:00
parent 1f2f8249ec
commit a6ff6da71b
2 changed files with 545 additions and 0 deletions

156
MIGRATION.md Normal file
View File

@ -0,0 +1,156 @@
# Migration Checklist - Neovim Config Refactor
## Current State ✅
- [x] Working Python LSP (pyright)
- [x] Working Flutter LSP (dartls)
- [x] Lazy-loaded language profiles
- [x] Common plugins loaded globally
- [x] ~1200 line init.lua (needs refactoring)
## Phase 1: Understand Your Config (Before Refactoring)
- [ ] Read through entire `init.lua` - understand every line
- [ ] List all plugins you actually use (vs installed)
- [ ] Identify startup bottlenecks: `nvim --startuptime startup.log`
- [ ] Document your most-used keybindings
- [ ] Run `:checkhealth` to verify everything works
## Phase 2: Extract Configuration (Low Risk)
- [ ] Create `lua/config/options.lua` - Move all `vim.opt` settings
- [ ] Create `lua/config/keymaps.lua` - Move global keymaps
- [ ] Create `lua/config/autocmds.lua` - Move global autocmds
- [ ] Update `init.lua` to require these modules
- [ ] Test: Restart nvim, verify everything works
## Phase 3: Reorganize Plugins (Medium Risk)
- [ ] Create `lua/plugins/core/` directory structure
- [ ] Move UI plugins to `core/ui.lua`
- [ ] Move editor plugins to `core/editor.lua`
- [ ] Move git plugins to `core/git.lua`
- [ ] Move completion to `core/completion.lua`
- [ ] Test after EACH move - don't batch them!
## Phase 4: Refactor LSP (High Risk - Do Last!)
- [ ] Create `lua/plugins/lsp/init.lua` for mason setup
- [ ] Create `lua/plugins/lsp/servers.lua` for general servers (lua_ls)
- [ ] Move language-specific LSP to their lang files
- [ ] Create `lua/util/lsp.lua` for shared utilities
- [ ] Test each language: Python, Flutter, Svelte
## Phase 5: Cleanup
- [ ] Remove unused plugins (check with `:Lazy`)
- [ ] Remove duplicate code
- [ ] Add comments explaining WHY, not WHAT
- [ ] Update README.md with your structure
- [ ] Profile startup time - compare before/after
## Testing Checklist (Run After Each Phase)
- [ ] Python: Open .py file, verify pyright loads, test completion
- [ ] Flutter: Open .dart file, verify dartls loads, test completion
- [ ] Svelte: Open .svelte file, verify svelte-ls loads
- [ ] Git: Open a git repo, test gitsigns
- [ ] Telescope: Test fuzzy finding (<leader>sf)
- [ ] LSP: Test go-to-definition, hover, rename
- [ ] Formatting: Test format-on-save
- [ ] Sessions: Test session save/restore
## Rollback Plan
```bash
# Before starting, create a backup branch
cd ~/.config/nvim
git checkout -b refactor-backup
git checkout -b refactor-attempt
# If something breaks:
git checkout refactor-backup
```
## Performance Targets
| Metric | Before | Target | After |
|--------|--------|--------|-------|
| Startup time | ? ms | <100ms | ? ms |
| Plugins loaded on startup | ? | <30 | ? |
| Time to first edit | ? ms | <200ms | ? ms |
Measure with:
```bash
nvim --startuptime startup.log
# Check the last line for total time
```
## When NOT to Refactor
- [ ] You don't understand why your current config works
- [ ] You're in the middle of a project deadline
- [ ] Your startup time is already <50ms
- [ ] You haven't backed up your config
## When TO Refactor
- [x] Your init.lua is >500 lines (yours is 1200!)
- [x] You have duplicate code across files
- [x] You're adding a 4th+ language (you have 3)
- [x] Startup time is >200ms
- [x] You want to understand how Neovim works
## Expected Benefits
- Faster startup (lazy-loading)
- Easier to add new languages (template)
- Easier to debug (modular)
- Easier to share/document
- Better understanding of Neovim
## Expected Challenges
- LSP loading timing issues (we already solved this!)
- Plugin dependency conflicts
- Breaking changes in lazy.nvim API
- Time investment (plan 4-6 hours)
---
## Quick Win: Do This First (30 minutes)
1. **Extract options** (lowest risk, immediate clarity):
```lua
-- lua/config/options.lua
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
vim.g.have_nerd_font = true
vim.opt.number = true
vim.opt.relativenumber = true
-- ... all your vim.opt settings
```
2. **Extract keymaps**:
```lua
-- lua/config/keymaps.lua
-- Escape closes floating windows
vim.keymap.set('n', '<Esc>', function()
-- ... your escape logic
end)
```
3. **Update init.lua**:
```lua
-- NEW init.lua (first 3 lines!)
require('config.options')
require('config.keymaps')
-- ... rest stays the same for now
```
This alone will make your init.lua 200 lines shorter and much clearer!
---
## Resources to Keep Handy
- [Lazy.nvim Spec](https://lazy.folke.io/spec)
- [:help lua-guide](https://neovim.io/doc/user/lua-guide.html)
- [Your ORGANIZATION.md](./ORGANIZATION.md)
- [Kickstart.nvim](https://github.com/nvim-lua/kickstart.nvim) (reference only)
---
**Remember:** Refactoring is optional. Your current setup WORKS. Only refactor if:
1. You want to learn more about Neovim
2. You want to add many more languages
3. Your startup time bothers you
4. You enjoy organizing code
Good luck! 🚀

389
ORGANIZATION.md Normal file
View File

@ -0,0 +1,389 @@
# Neovim Configuration Organization Guide
## Current Structure (What You Have)
```
~/.config/nvim/
├── init.lua # Main entry point (1200 lines - TOO LARGE!)
├── lua/
│ ├── custom/
│ │ └── plugins/
│ │ ├── init.lua # Common plugins (all filetypes)
│ │ ├── flutter.lua # Flutter-specific (lazy-loaded)
│ │ ├── python.lua # Python-specific (lazy-loaded)
│ │ ├── svelte.lua # Svelte-specific (lazy-loaded)
│ │ └── session.lua # Session management
│ └── kickstart/
│ ├── health.lua
│ └── plugins/
│ ├── autopairs.lua
│ ├── debug.lua
│ ├── gitsigns.lua
│ ├── indent_line.lua
│ ├── lint.lua
│ └── neo-tree.lua
```
## Problems with Current Setup
1. **`init.lua` is massive (1200 lines)** - Should be split into modules
2. **LSP setup is duplicated** - Language-specific LSP code is in `init.lua` instead of language files
3. **Unclear separation** - What belongs in `custom/` vs `kickstart/`?
4. **No clear loading strategy** - Which plugins load when?
---
## Recommended Structure (Optimal Organization)
```
~/.config/nvim/
├── init.lua # THIN entry point (~50 lines)
├── lua/
│ ├── config/
│ │ ├── options.lua # Vim options (set, opt)
│ │ ├── keymaps.lua # Global keymaps
│ │ ├── autocmds.lua # Global autocmds
│ │ └── lazy.lua # Lazy.nvim bootstrap
│ │
│ ├── plugins/
│ │ ├── core/
│ │ │ ├── ui.lua # UI plugins (always loaded)
│ │ │ ├── editor.lua # Editor enhancements (always loaded)
│ │ │ ├── git.lua # Git tools (always loaded)
│ │ │ └── completion.lua # Completion engine (always loaded)
│ │ │
│ │ ├── lsp/
│ │ │ ├── init.lua # LSP infrastructure (mason, lspconfig)
│ │ │ ├── servers.lua # General LSP servers (lua_ls, etc.)
│ │ │ └── keymaps.lua # LSP keymaps (shared)
│ │ │
│ │ └── lang/
│ │ ├── python.lua # Python: LSP + formatters + linters
│ │ ├── flutter.lua # Flutter: LSP + debugging + tools
│ │ ├── svelte.lua # Svelte: LSP + formatters
│ │ ├── go.lua # Future: Go support
│ │ └── rust.lua # Future: Rust support
│ │
│ └── util/
│ ├── lsp.lua # Shared LSP utilities
│ └── init.lua # Shared helper functions
```
---
## How This Works: Lazy-Loading Strategy
### 1. **Core Plugins (Always Loaded)**
```lua
-- lua/plugins/core/editor.lua
return {
{ 'echasnovski/mini.pairs' }, -- Autopairs
{ 'folke/which-key.nvim' }, -- Keybinding helper
{ 'nvim-telescope/telescope.nvim' }, -- Fuzzy finder
}
```
### 2. **LSP Infrastructure (Loaded Early)**
```lua
-- lua/plugins/lsp/init.lua
return {
'neovim/nvim-lspconfig',
dependencies = { 'mason.nvim', 'mason-lspconfig.nvim' },
config = function()
-- Setup mason, but don't configure language servers here
require('mason').setup()
require('mason-lspconfig').setup()
end,
}
```
### 3. **Language-Specific (Lazy-Loaded by FileType)**
```lua
-- lua/plugins/lang/python.lua
return {
-- Mason tools
{
'WhoIsSethDaniel/mason-tool-installer.nvim',
ft = 'python',
config = function()
require('mason-tool-installer').setup({
ensure_installed = { 'pyright', 'ruff' }
})
end,
},
-- LSP setup
{
'neovim/nvim-lspconfig',
ft = 'python',
config = function()
-- Start pyright via autocmd
vim.api.nvim_create_autocmd('FileType', {
pattern = 'python',
callback = function(args)
local capabilities = require('blink.cmp').get_lsp_capabilities()
vim.lsp.start({
name = 'pyright',
cmd = { vim.fn.stdpath('data') .. '/mason/bin/pyright-langserver', '--stdio' },
root_dir = vim.fs.root(args.buf, { 'pyproject.toml', 'setup.py', '.git' }),
capabilities = capabilities,
})
end,
})
end,
},
-- Formatters
{
'stevearc/conform.nvim',
ft = 'python',
config = function()
require('conform').formatters_by_ft.python = { 'ruff_format', 'ruff_organize_imports' }
end,
},
}
```
---
## Migration Plan (Step-by-Step)
### Phase 1: Extract Configuration from init.lua
```lua
-- NEW init.lua (50 lines instead of 1200!)
require('config.options') -- Vim settings
require('config.keymaps') -- Global keymaps
require('config.autocmds') -- Global autocmds
require('config.lazy') -- Bootstrap lazy.nvim and load plugins
```
### Phase 2: Organize Plugins by Loading Strategy
**Always Loaded (Core):**
- `lua/plugins/core/ui.lua` - colorscheme, statusline, bufferline
- `lua/plugins/core/editor.lua` - telescope, which-key, autopairs, neo-tree
- `lua/plugins/core/git.lua` - gitsigns, fugitive
- `lua/plugins/core/completion.lua` - blink.cmp
**Lazy-Loaded by FileType:**
- `lua/plugins/lang/python.lua` - ft = 'python'
- `lua/plugins/lang/flutter.lua` - ft = { 'dart', 'flutter' }
- `lua/plugins/lang/svelte.lua` - ft = 'svelte'
**Lazy-Loaded by Command:**
- Debugging tools - cmd = { 'DapContinue', 'DapToggleBreakpoint' }
- Session management - cmd = { 'SessionSave', 'SessionLoad' }
### Phase 3: Fix LSP Loading Issue
**Problem:** You discovered that language-specific LSP configs in lazy-loaded files don't work because `nvim-lspconfig` is already loaded by `init.lua`.
**Solution:** Two approaches:
#### Option A: Centralized LSP Setup (Simpler)
```lua
-- lua/plugins/lsp/servers.lua
local M = {}
M.setup_python = function()
-- Python LSP setup
end
M.setup_flutter = function()
-- Flutter LSP setup
end
-- Autocmds to trigger setup
vim.api.nvim_create_autocmd('FileType', {
pattern = 'python',
once = true,
callback = M.setup_python,
})
```
#### Option B: Per-Language Setup (Cleaner but Complex)
```lua
-- lua/plugins/lang/python.lua
return {
{
'WhoIsSethDaniel/mason-tool-installer.nvim',
ft = 'python',
config = function()
-- Install tools
require('mason-tool-installer').setup({ ensure_installed = { 'pyright', 'ruff' }})
-- Setup LSP via autocmd (since lspconfig is already loaded)
vim.api.nvim_create_autocmd('FileType', {
pattern = 'python',
callback = function(args)
require('util.lsp').start_server('pyright', args.buf, {
settings = { python = { analysis = { typeCheckingMode = 'basic' }}}
})
end,
})
end,
},
}
-- lua/util/lsp.lua (shared utility)
local M = {}
M.start_server = function(name, bufnr, opts)
local clients = vim.lsp.get_clients({ bufnr = bufnr, name = name })
if #clients > 0 then return end
local capabilities = require('blink.cmp').get_lsp_capabilities()
vim.lsp.start(vim.tbl_deep_extend('force', {
name = name,
capabilities = capabilities,
}, opts))
end
return M
```
---
## Loading Performance Best Practices
### 1. Use Lazy-Loading Triggers
```lua
-- ❌ BAD: Loads immediately on startup
{ 'some/plugin' }
-- ✅ GOOD: Loads only when needed
{ 'some/plugin', ft = 'python' } -- When opening .py files
{ 'some/plugin', cmd = 'SomeCommand' } -- When running :SomeCommand
{ 'some/plugin', keys = '<leader>x' } -- When pressing <leader>x
{ 'some/plugin', event = 'VeryLazy' } -- After startup (low priority)
```
### 2. Profile Your Startup Time
```bash
# Measure startup time
nvim --startuptime startup.log
# Find slow plugins
grep "sourcing" startup.log | sort -k2 -n
```
### 3. Use `:Lazy` to Monitor Loading
- Green plugins = loaded
- Gray plugins = not loaded yet (lazy)
- See what triggered loading
---
## Recommended Final Structure
```
~/.config/nvim/
├── init.lua # ~50 lines: require config modules
├── lua/
│ ├── config/
│ │ ├── options.lua # set.number, opt.clipboard, etc.
│ │ ├── keymaps.lua # Global keymaps only
│ │ ├── autocmds.lua # Global autocmds only
│ │ └── lazy.lua # Bootstrap lazy.nvim
│ │
│ ├── plugins/
│ │ ├── core/
│ │ │ ├── ui.lua # Colorscheme, statusline, etc.
│ │ │ ├── editor.lua # Telescope, which-key, autopairs
│ │ │ ├── git.lua # Gitsigns, fugitive
│ │ │ └── completion.lua # blink.cmp
│ │ │
│ │ ├── lsp/
│ │ │ ├── init.lua # Mason, lspconfig setup
│ │ │ ├── servers.lua # lua_ls and other general servers
│ │ │ └── keymaps.lua # LSP keymaps (on_attach)
│ │ │
│ │ └── lang/
│ │ ├── python.lua # ft = 'python'
│ │ ├── flutter.lua # ft = 'dart'
│ │ └── svelte.lua # ft = 'svelte'
│ │
│ └── util/
│ ├── lsp.lua # Shared LSP helpers
│ └── init.lua # Shared utility functions
├── ORGANIZATION.md # This file
├── MIGRATION.md # Step-by-step migration guide
└── README.md # Your custom README
```
---
## Key Principles
1. **Thin `init.lua`** - Just require modules, no logic
2. **Separate concerns** - Options, keymaps, autocmds, plugins
3. **Lazy-load everything possible** - Use `ft`, `cmd`, `keys`, `event`
4. **Language files are independent** - Each lang/ file is self-contained
5. **Share common code** - Use `util/` for helpers
6. **Profile regularly** - Use `:Lazy profile` and `--startuptime`
---
## Learning Resources
### Understanding Neovim Configuration
- `:help lua-guide` - Official Lua guide
- `:help options` - All vim options
- `:help api` - Lua API reference
### Lazy-Loading
- `:help lazy.nvim` - Lazy.nvim documentation
- `:Lazy profile` - See what's slow
- `:Lazy` - Interactive plugin manager
### LSP
- `:help lsp` - LSP overview
- `:help vim.lsp.start()` - Start LSP servers
- `:LspInfo` - See active LSP clients
### Performance
- `nvim --startuptime startup.log` - Measure startup
- `:profile start profile.log | profile func * | profile file *` - Profile runtime
---
## Next Steps
1. **Commit current working state** ✅ (You're doing this now)
2. **Read through this guide** to understand the concepts
3. **Try the migration in a branch** (don't break your working config!)
4. **Migrate incrementally**:
- Step 1: Extract options/keymaps from init.lua
- Step 2: Move plugins to core/ structure
- Step 3: Refactor language-specific configs
5. **Test after each step** - Make sure everything still works
6. **Profile before and after** - Measure improvements
---
## Questions to Consider
1. **Do you need kickstart/ folder anymore?**
- If you understand the code, merge it into your own structure
2. **How many languages will you support?**
- 3-5 languages: Current structure is fine
- 10+ languages: Consider more sophisticated loading
3. **Do you want to share your config?**
- Yes: Document everything, make it modular
- No: Optimize for your own workflow
4. **How often will you add new languages?**
- Frequently: Build a template system
- Rarely: Current per-file approach works
---
**Remember:** This is YOUR config. Start with what works, refactor when you understand WHY you're refactoring. Don't cargo-cult someone else's structure!