Improved flow

This commit is contained in:
Morten Olsen
2026-01-26 23:04:14 +01:00
parent d9950b3e4d
commit b3b70bceeb
28 changed files with 4492 additions and 7 deletions

96
check-commands.lua Normal file
View File

@@ -0,0 +1,96 @@
-- Quick command checker for Neovim
-- Run with: :luafile check-commands.lua
-- Or add to your config as a command
local M = {}
function M.list_all_commands()
local commands = vim.api.nvim_get_commands({})
local sorted = {}
for name, cmd in pairs(commands) do
table.insert(sorted, name)
end
table.sort(sorted)
print("=" .. string.rep("=", 60))
print("REGISTERED COMMANDS (" .. #sorted .. " total)")
print("=" .. string.rep("=", 60))
for _, name in ipairs(sorted) do
print(name)
end
end
function M.check_conflicts()
local commands = vim.api.nvim_get_commands({})
local seen = {}
local conflicts = {}
for name, cmd in pairs(commands) do
if seen[name] then
if not conflicts[name] then
conflicts[name] = {seen[name], cmd}
else
table.insert(conflicts[name], cmd)
end
else
seen[name] = cmd
end
end
if next(conflicts) then
print("⚠️ CONFLICTS FOUND:")
for name, defs in pairs(conflicts) do
print(" " .. name .. ":")
for i, def in ipairs(defs) do
print(" " .. i .. ". " .. (def.definition or "unknown"))
end
end
else
print("✓ No conflicts detected!")
end
end
function M.find_command(pattern)
local commands = vim.api.nvim_get_commands({})
local matches = {}
for name, cmd in pairs(commands) do
if name:match(pattern) then
table.insert(matches, {name = name, cmd = cmd})
end
end
table.sort(matches, function(a, b) return a.name < b.name end)
if #matches > 0 then
print("Commands matching '" .. pattern .. "':")
for _, item in ipairs(matches) do
print(" " .. item.name)
end
else
print("No commands found matching '" .. pattern .. "'")
end
end
-- Create user commands
vim.api.nvim_create_user_command("ListCommands", function()
M.list_all_commands()
end, { desc = "List all registered commands" })
vim.api.nvim_create_user_command("CheckCommandConflicts", function()
M.check_conflicts()
end, { desc = "Check for command conflicts" })
vim.api.nvim_create_user_command("FindCommand", function(opts)
M.find_command(opts.args)
end, { desc = "Find commands matching pattern", nargs = 1 })
print("Commands registered:")
print(" :ListCommands - List all commands")
print(" :CheckCommandConflicts - Check for conflicts")
print(" :FindCommand <pattern> - Find commands by pattern")
return M

104
check-git-keys.lua Normal file
View File

@@ -0,0 +1,104 @@
-- Check for git-related key conflicts
-- Run with: nvim --headless -c "luafile check-git-keys.lua" -c "qa"
local function get_keymaps()
local keymaps = {}
local modes = { "n", "v", "x", "i", "c", "t", "o" }
for _, mode in ipairs(modes) do
local maps = vim.api.nvim_get_keymap(mode)
for _, map in ipairs(maps) do
if map.lhs and map.lhs:match("g") then
table.insert(keymaps, {
mode = mode,
lhs = map.lhs,
rhs = map.rhs or map.callback or "callback",
desc = map.desc or "",
buffer = map.buffer or 0,
})
end
end
end
return keymaps
end
local keymaps = get_keymaps()
-- Group by key
local by_key = {}
for _, map in ipairs(keymaps) do
local key = map.lhs
if not by_key[key] then
by_key[key] = {}
end
table.insert(by_key[key], map)
end
-- Find conflicts (same key, different actions)
print("=" .. string.rep("=", 70))
print("GIT-RELATED KEYMAPS")
print("=" .. string.rep("=", 70))
print()
local conflicts = {}
for key, maps in pairs(by_key) do
if #maps > 1 then
-- Check if they're actually different
local unique = {}
for _, m in ipairs(maps) do
local rhs_str = type(m.rhs) == "string" and m.rhs or (type(m.rhs) == "function" and "<function>" or tostring(m.rhs))
local sig = m.mode .. ":" .. rhs_str
if not unique[sig] then
unique[sig] = m
end
end
if vim.tbl_count(unique) > 1 then
conflicts[key] = maps
end
end
end
-- Print all git-related keys
local git_keys = {}
for key, maps in pairs(by_key) do
if key:match("leader.*g") or key:match("gh") or key:match("]h") or key:match("%[h") then
for _, map in ipairs(maps) do
table.insert(git_keys, map)
end
end
end
table.sort(git_keys, function(a, b)
if a.lhs ~= b.lhs then
return a.lhs < b.lhs
end
return a.mode < b.mode
end)
print("Git-related keymaps:")
for _, map in ipairs(git_keys) do
local buf_info = map.buffer ~= 0 and (" (buf:" .. map.buffer .. ")") or ""
local rhs_str = type(map.rhs) == "string" and map.rhs or (type(map.rhs) == "function" and "<function>" or tostring(map.rhs))
print(string.format(" %s %-20s -> %-30s %s%s",
map.mode, map.lhs,
rhs_str:sub(1, 30),
map.desc ~= "" and ("(" .. map.desc .. ")") or "",
buf_info))
end
print()
if next(conflicts) then
print("⚠️ POTENTIAL CONFLICTS:")
print("=" .. string.rep("=", 70))
for key, maps in pairs(conflicts) do
print(string.format("Key '%s' has multiple bindings:", key))
for _, map in ipairs(maps) do
local rhs_str = type(map.rhs) == "string" and map.rhs or (type(map.rhs) == "function" and "<function>" or tostring(map.rhs))
print(string.format(" %s: %s (%s)", map.mode, rhs_str, map.desc or "no desc"))
end
print()
end
else
print("✓ No conflicts detected in git-related keys")
end

158
commands-report.md Normal file
View File

@@ -0,0 +1,158 @@
# Neovim Commands Report
Generated on: $(date)
## Summary
- **Total Commands**: 80
- **Conflicts**: None detected
- **Missing Commands**: Some commands defined in config files are not registered
## All Registered Commands (Alphabetical)
### Custom/User Commands
#### Tmux Navigator
- `TmuxNavigateDown` - Navigate down
- `TmuxNavigateLeft` - Navigate left
- `TmuxNavigatePrevious` - Navigate to previous
- `TmuxNavigateRight` - Navigate right
- `TmuxNavigateUp` - Navigate up
- `TmuxNavigatorProcessList` - List tmux processes
#### Database (DBUI)
- `DB` - Database command
- `DBUI` - Database UI
- `DBUIAddConnection` - Add database connection
- `DBUIFindBuffer` - Find database buffer
- `DBUIToggle` - Toggle database UI
#### Git/Diff
- `DiffviewClose` - Close diffview
- `DiffviewFileHistory` - Show file history
- `DiffviewOpen` - Open diffview
- `DiffviewToggleFiles` - Toggle diffview files
#### Executor
- `ExecutorRun` - Run task
- `ExecutorSetCommand` - Set command
- `ExecutorToggleDetail` - Toggle detail view
#### Octo (GitHub)
- `Octo` - GitHub operations
### LazyVim Core Commands
- `Lazy` - Plugin manager
- `LazyDev` - Development mode
### LSP/Debugging
- `DapInstall` - Install DAP adapter
- `DapUninstall` - Uninstall DAP adapter
- `Inspect` - Inspect highlights
- `InspectTree` - Inspect treesitter tree
### File Management
- `Explore` - Netrw explore
- `GrugFar` - Grug far
- `GrugFarWithin` - Grug far within
- `Hexplore` - Horizontal explore
- `Lexplore` - Left explore
- `Nexplore` - Netrw explore
- `Pexplore` - Previous explore
- `Sexplore` - Split explore
- `Texplore` - Tab explore
- `Vexplore` - Vertical explore
### Netrw Commands
- `NetUserPass` - Network user password
- `NetrwClean` - Clean netrw
- `NetrwSettings` - Netrw settings
- `Nread` - Netrw read
- `Nsource` - Netrw source
- `Ntree` - Netrw tree
- `Nwrite` - Netrw write
### Markdown
- `MarkdownPreview` - Preview markdown
- `MarkdownPreviewStop` - Stop preview
- `MarkdownPreviewToggle` - Toggle preview
### Testing/Tasks
- `OverseerBuild` - Build task
- `OverseerClearCache` - Clear cache
- `OverseerClose` - Close overseer
- `OverseerDeleteBundle` - Delete bundle
- `OverseerInfo` - Overseer info
- `OverseerLoadBundle` - Load bundle
- `OverseerOpen` - Open overseer
- `OverseerQuickAction` - Quick action
- `OverseerRun` - Run task
- `OverseerRunCmd` - Run command
- `OverseerSaveBundle` - Save bundle
- `OverseerTaskAction` - Task action
- `OverseerToggle` - Toggle overseer
### Treesitter
- `EditQuery` - Edit treesitter query
- `TSInstall` - Install parser
- `TSLog` - Treesitter log
- `TSUninstall` - Uninstall parser
- `TSUpdate` - Update parsers
### UI/Diagnostics
- `Trouble` - Trouble diagnostics
- `TodoTelescope` - Todo telescope
- `TodoTrouble` - Todo trouble
### Utilities
- `ChezmoiEdit` - Edit chezmoi
- `ConformInfo` - Conform info
- `Man` - Manual pages
- `Mason` - Mason installer
- `Neogen` - Generate annotations
- `Open` - Open with system handler
- `StartupTime` - Show startup time
- `UpdateRemotePlugins` - Update remote plugins
- `VenvSelect` - Select virtual environment
### Matchit
- `DoMatchParen` - Do match paren
- `MatchDebug` - Match debug
- `MatchDisable` - Disable match
- `MatchEnable` - Enable match
- `NoMatchParen` - No match paren
## Commands Defined in Config But Not Registered
These commands are referenced in your config files but are not currently registered:
### Git Blame
- `GitBlameToggle` - Toggle git blame (from `lua/plugins/git.lua`)
- `GitBlameOpenCommitURL` - Open commit URL (from `lua/plugins/git.lua`)
- `GitBlameCopyCommitURL` - Copy commit URL (from `lua/plugins/git.lua`)
**Note**: These commands are likely lazy-loaded and will only be available after the git-blame plugin is loaded.
### DBUI Additional Commands
- `DBUIRenameBuffer` - Rename buffer (from `lua/plugins/database.lua`)
- `DBUILastQueryInfo` - Last query info (from `lua/plugins/database.lua`)
**Note**: These may be available as functions rather than commands, or may be lazy-loaded.
## Potential Issues
1. **Git Blame Commands**: The git-blame plugin commands are not registered. This could mean:
- The plugin isn't loaded yet (lazy loading)
- The plugin uses functions instead of commands
- There's a configuration issue
2. **DBUI Commands**: Some DBUI commands are missing. Check if they're available as functions or require the plugin to be loaded first.
## Recommendations
1. **Check Lazy Loading**: Some commands may only be available after their plugins are loaded. Try using the commands after opening a relevant file type.
2. **Verify Plugin Installation**: Run `:Lazy` to check if all plugins are properly installed.
3. **Test Commands**: Test the missing commands in a real Neovim session to see if they're available after plugin loading.
4. **Command Conflicts**: No conflicts were detected, which is good! All command names are unique.

98
docs/README.md Normal file
View File

@@ -0,0 +1,98 @@
# Neovim Workflow Documentation
This documentation covers workflows and keybindings for this LazyVim-based Neovim configuration, optimized for **TypeScript**, **Python**, and **Go** development.
## Quick Start
1. **Leader key**: `<Space>`
2. **Find files**: `<leader>ff` or `<leader><space>`
3. **Find text**: `<leader>sg` (grep) or `<leader>/` (in buffer)
4. **File explorer**: `<leader>e`
5. **Which-key help**: Press `<leader>` and wait
## Cheatsheets (Quick Reference)
| Cheatsheet | Description |
|------------|-------------|
| [Keybindings](cheatsheets/keybindings.md) | Complete keybinding reference by category |
| [Git Workflow](cheatsheets/git-workflow.md) | Git operations, diffs, PRs, and blame |
| [Testing](cheatsheets/testing.md) | Running and debugging tests |
| [Database](cheatsheets/database.md) | Database connections and queries |
## Detailed Guides
| Guide | Description |
|-------|-------------|
| [TypeScript Workflow](guides/typescript-workflow.md) | Complete TypeScript/JavaScript development guide |
| [Python Workflow](guides/python-workflow.md) | Python development with venv, testing, debugging |
| [Go Workflow](guides/go-workflow.md) | Go development guide |
| [Git Workflow](guides/git-workflow.md) | Detailed git operations and PR review workflow |
| [Debugging](guides/debugging.md) | DAP debugging for all languages |
| [Snippets](guides/snippets.md) | Creating custom code snippets |
| [AI Assistant](guides/ai-assistant.md) | Using opencode.nvim for AI-assisted coding |
## Key Binding Prefixes
| Prefix | Purpose | Examples |
|--------|---------|----------|
| `<leader>f` | **Find/Files** | Find files, recent files |
| `<leader>s` | **Search** | Search text, symbols, help |
| `<leader>g` | **Git** | Git status, diffs, PRs |
| `<leader>c` | **Code** | LSP actions, format, rename |
| `<leader>t` | **Test** | Run tests, debug tests |
| `<leader>d` | **Debug** | DAP debugging |
| `<leader>D` | **Database** | DBUI, connections |
| `<leader>R` | **REST** | HTTP requests |
| `<leader>k` | **AI (opencode)** | AI assistance |
| `<leader>h` | **Harpoon** | Quick file navigation |
| `<leader>q` | **Session** | Save/restore sessions |
| `<leader>1-9` | **Harpoon files** | Jump to marked files |
## Configuration Files
| File | Purpose |
|------|---------|
| `lua/config/options.lua` | Neovim settings |
| `lua/config/keymaps.lua` | Global keymaps |
| `lua/plugins/*.lua` | Plugin configurations |
| `snippets/*.lua` | Custom code snippets |
## Plugin Overview
### Core Plugins
- **LazyVim**: Base distribution with sensible defaults
- **Telescope**: Fuzzy finder for files, text, symbols
- **Treesitter**: Syntax highlighting and text objects
- **LSP**: Language server protocol for IDE features
### Language Support
- **TypeScript**: Full LSP, ESLint, Vitest integration
- **Python**: LSP, venv-selector, pytest, DAP
- **Go**: gopls, golangci-lint, go test, DAP
### Productivity
- **Harpoon**: Quick file switching (marks up to 9 files)
- **Flash.nvim**: Fast navigation with search labels
- **Persistence**: Session management
- **Trouble**: Diagnostics list
### Git
- **Diffview**: Side-by-side diffs and file history
- **Git-blame**: Inline blame annotations
- **Octo**: GitHub PRs and issues in Neovim
- **Gitsigns**: Git gutter signs
### Other
- **Neotest**: Test runner for all languages
- **DAP**: Debug adapter protocol
- **Dadbod**: Database client
- **Kulala**: REST client
- **Opencode**: AI assistant
## Getting Help
- Press `<leader>` and wait for which-key popup
- `:Telescope keymaps` - Search all keybindings
- `:Telescope help_tags` - Search help documentation
- `:checkhealth` - Check for configuration issues
- `:Lazy` - Manage plugins

View File

@@ -0,0 +1,164 @@
# Database Cheatsheet
## Quick Reference
| Key | Action |
|-----|--------|
| `<leader>Du` | Toggle DBUI |
| `<leader>Da` | Add connection |
| `<leader>Df` | Find DB buffer |
## Opening DBUI
```
<leader>Du Toggle database UI
<leader>Da Add new connection
```
## Connection Strings
### PostgreSQL
```
postgresql://user:password@localhost:5432/dbname
postgres://user:password@localhost/dbname
# With SSL
postgresql://user:password@host:5432/dbname?sslmode=require
```
### SQLite
```
sqlite:path/to/database.db
sqlite:./local.db
sqlite::memory:
```
## DBUI Navigation
```
<cr> Toggle node / Execute query
o Open node
R Refresh
d Delete
r Rename
S Sort by
H Toggle help
q Close
```
## Writing Queries
1. `<leader>Du` - Open DBUI
2. Navigate to database
3. Press `<cr>` on "New Query"
4. Write SQL
5. `<leader>Rs` or `<cr>` to execute
## Query Execution
In a `.sql` buffer connected to DBUI:
```
<cr> Execute query under cursor
<leader>Rs Execute query (visual: selected)
```
## Table Helpers
Right-click or press `<cr>` on a table for quick actions:
### PostgreSQL
- Count: `SELECT COUNT(*) FROM table`
- First10: `SELECT * FROM table LIMIT 10`
- Schema: `\d+ table`
### SQLite
- Count: `SELECT COUNT(*) FROM table`
- First10: `SELECT * FROM table LIMIT 10`
- Schema: `.schema table`
## Buffer Management
```
<leader>Df Find DB buffer
<leader>Dr Rename DB buffer
<leader>Dl Last query info
```
## Common Workflows
### Connect to Database
1. `<leader>Da` - Add connection
2. Enter connection string
3. Give it a name
4. Connection saved for future sessions
### Explore Schema
1. `<leader>Du` - Open DBUI
2. Expand database node
3. Expand "Tables" node
4. `<cr>` on table for helpers
### Run Ad-hoc Query
1. `<leader>Du` - Open DBUI
2. Navigate to database
3. New Query
4. Write SQL:
```sql
SELECT * FROM users WHERE active = true LIMIT 10;
```
5. Execute with `<cr>`
### Export Results
After running query:
1. Results appear in split
2. `:w filename.csv` to save
## Tips
### Multiple Databases
- Add multiple connections
- Switch by selecting in DBUI
- Each buffer tracks its connection
### Environment Variables
Connection strings can use env vars:
```
postgresql://$DB_USER:$DB_PASS@$DB_HOST/$DB_NAME
```
### SSH Tunnels
For remote databases, set up SSH tunnel first:
```bash
ssh -L 5432:localhost:5432 user@server
```
Then connect to `localhost:5432`.
## Troubleshooting
### Connection Failed
- Check credentials
- Verify database is running
- Check firewall/network
### Missing Adapter
Run `:checkhealth` and verify:
- `vim-dadbod` installed
- Database client available (psql, sqlite3)
### Slow Queries
- Add `LIMIT` to large tables
- Use `EXPLAIN` to analyze

View File

@@ -0,0 +1,142 @@
# Git Workflow Cheatsheet
## Quick Reference
| Key | Action |
|-----|--------|
| `<leader>gd` | Open diff view |
| `<leader>gD` | Close diff view |
| `<leader>gf` | File history |
| `<leader>gB` | Toggle blame |
| `<leader>gpl` | List PRs |
| `<leader>gpc` | Create PR |
## Viewing Changes
### Diffview
```
<leader>gd Open diff view (staged + unstaged)
<leader>gD Close diff view
<leader>gf Current file history
<leader>gF Branch history
<leader>gm Compare to origin/main
<leader>gM Compare to origin/master
```
### In Diffview File Panel
**Important**: Staging keys only work when focused on the file panel (left side).
```
j/k Navigate files
<cr> Open file diff
- Stage/unstage file (must be in file panel)
S Stage all files
U Unstage all files
X Revert file changes
<tab> Toggle file panel visibility
<leader>e Focus file panel
<leader>b Toggle file panel
R Refresh file list
g? Show help
```
**Note**: Use `<leader>gd` (not `<leader>gf`) to open diffview with staging capabilities. File history (`<leader>gf`) is read-only.
## Blame
```
<leader>gB Toggle inline blame
<leader>go Open commit in browser
<leader>gy Copy commit URL
```
## Staging & Committing (Gitsigns)
```
]h Next hunk
[h Previous hunk
<leader>ghs Stage hunk
<leader>ghr Reset hunk
<leader>ghS Stage buffer
<leader>ghu Undo stage hunk
<leader>ghp Preview hunk
<leader>ghb Blame line
```
## Pull Requests (Octo)
### Listing & Navigation
```
<leader>gpl List PRs
<leader>gpo Checkout PR
<leader>gpb Open PR in browser
<leader>gpd Show PR diff
```
### Creating & Managing
```
<leader>gpc Create PR
<leader>gpr Mark PR ready
<leader>gpm Merge PR
```
### Reviewing
```
<leader>grs Start review
<leader>grr Resume review
<leader>grc Submit review
<leader>grd Discard review
```
### In PR Buffer
```
<leader>ca Add comment
<leader>cd Delete comment
<leader>sa Approve
<leader>sc Comment
<leader>sr Request changes
```
## Issues (Octo)
```
<leader>gil List issues
<leader>gic Create issue
<leader>gib Open in browser
```
## Common Workflows
### Review a PR
1. `<leader>gpl` - List PRs
2. Select PR and press `<cr>`
3. `<leader>grs` - Start review
4. Navigate files, add comments
5. `<leader>grc` - Submit review
### Compare Branch to Main
1. `<leader>gm` - Open diff vs main
2. Review changes in split view
3. `<leader>gD` - Close when done
### Investigate File History
1. `<leader>gf` - File history
2. Navigate commits with `j/k`
3. `<cr>` to view diff at commit
4. `<leader>gD` - Close when done
### Quick Blame Check
1. `<leader>gB` - Toggle blame
2. Line blame shows inline
3. `<leader>go` - Open commit if needed
4. `<leader>gB` - Toggle off

View File

@@ -0,0 +1,206 @@
# Keybindings Cheatsheet
Leader key: `<Space>`
## Navigation
| Key | Description |
|-----|-------------|
| `<C-h/j/k/l>` | Navigate between splits/tmux panes |
| `<leader>ff` | Find files |
| `<leader><space>` | Find files (alt) |
| `<leader>fr` | Recent files |
| `<leader>fb` | Browse buffers |
| `<leader>e` | File explorer |
| `s` | Flash jump (in normal mode) |
| `S` | Flash treesitter |
## Harpoon (Quick File Access)
| Key | Description |
|-----|-------------|
| `<leader>H` | Add file to harpoon |
| `<leader>h` | Toggle harpoon menu |
| `<leader>1-9` | Jump to harpoon file 1-9 |
## Search
| Key | Description |
|-----|-------------|
| `<leader>sg` | Grep (search text) |
| `<leader>sw` | Search word under cursor |
| `<leader>ss` | Search symbols |
| `<leader>sS` | Search symbols (workspace) |
| `<leader>/` | Search in buffer |
| `<leader>sr` | Search and replace (grug-far) |
## LSP / Code
| Key | Description |
|-----|-------------|
| `gd` | Go to definition |
| `gr` | Go to references |
| `gI` | Go to implementation |
| `gy` | Go to type definition |
| `K` | Hover documentation |
| `gK` | Signature help |
| `<leader>ca` | Code actions |
| `<leader>cr` | Rename symbol |
| `<leader>cf` | Format document |
| `<leader>cd` | Line diagnostics |
| `<leader>cS` | Reload snippets |
| `]d` / `[d` | Next/prev diagnostic |
| `]e` / `[e` | Next/prev error |
| `]w` / `[w` | Next/prev warning |
## Git
| Key | Description |
|-----|-------------|
| `<leader>gg` | Lazygit (if installed) |
| `<leader>gd` | Diffview: Open |
| `<leader>gD` | Diffview: Close |
| `<leader>gf` | Diffview: File history |
| `<leader>gF` | Diffview: Branch history |
| `<leader>gm` | Diffview: Compare to main |
| `<leader>gB` | Toggle git blame |
| `<leader>go` | Open commit in browser |
| `<leader>gy` | Copy commit URL |
### GitHub (Octo)
| Key | Description |
|-----|-------------|
| `<leader>gpl` | List PRs |
| `<leader>gpc` | Create PR |
| `<leader>gpo` | Checkout PR |
| `<leader>gpb` | Open PR in browser |
| `<leader>gpm` | Merge PR |
| `<leader>gil` | List issues |
| `<leader>gic` | Create issue |
| `<leader>grs` | Start review |
| `<leader>grr` | Resume review |
| `<leader>grc` | Submit review |
## Testing
| Key | Description |
|-----|-------------|
| `<leader>tt` | Run nearest test |
| `<leader>tf` | Run file tests |
| `<leader>ta` | Run all tests |
| `<leader>tl` | Run last test |
| `<leader>tS` | Stop tests |
| `<leader>td` | Debug nearest test |
| `<leader>tD` | Debug file tests |
| `<leader>tw` | Toggle watch (file) |
| `<leader>ts` | Toggle summary |
| `<leader>to` | Show output |
| `<leader>tO` | Toggle output panel |
| `]t` / `[t` | Next/prev failed test |
## Debugging (DAP)
| Key | Description |
|-----|-------------|
| `<leader>db` | Toggle breakpoint |
| `<leader>dB` | Breakpoint with condition |
| `<leader>dc` | Continue |
| `<leader>dC` | Run to cursor |
| `<leader>di` | Step into |
| `<leader>do` | Step over |
| `<leader>dO` | Step out |
| `<leader>dp` | Pause |
| `<leader>dt` | Terminate |
| `<leader>du` | Toggle DAP UI |
| `<leader>de` | Evaluate expression |
## Database
| Key | Description |
|-----|-------------|
| `<leader>Du` | Toggle DBUI |
| `<leader>Da` | Add DB connection |
| `<leader>Df` | Find DB buffer |
| `<leader>Dr` | Rename DB buffer |
| `<leader>Dl` | Last query info |
## REST Client
| Key | Description |
|-----|-------------|
| `<leader>Rs` | Send request |
| `<leader>Ra` | Send all requests |
| `<leader>Rr` | Replay last request |
| `<leader>Ri` | Inspect request |
| `<leader>Rt` | Toggle headers/body |
| `<leader>Rc` | Copy as cURL |
| `<leader>Re` | Select environment |
| `]r` / `[r` | Next/prev request |
## AI Assistant (opencode.nvim)
| Key | Description |
|-----|-------------|
| `<leader>kk` | Toggle opencode |
| `<leader>ka` | Ask opencode |
| `<leader>kA` | Ask about current file |
| `<leader>kn` | New session |
| `<leader>ke` | Explain code near cursor |
| `<leader>kE` | Explain selection (visual) |
| `<leader>kr` | Review file |
| `<leader>kg` | Review git diff |
| `<leader>kf` | Fix diagnostics |
| `<leader>ko` | Optimize selection (visual) |
| `<leader>kR` | Refactor selection (visual) |
| `<leader>kd` | Document selection (visual) |
| `<leader>kt` | Test selection (visual) |
| `<leader>kh` | Ask about harpooned files |
## Session Management
| Key | Description |
|-----|-------------|
| `<leader>qs` | Restore session |
| `<leader>ql` | Restore last session |
| `<leader>qd` | Don't save session |
| `<leader>qS` | Select session |
## Background Tasks (Executor)
| Key | Description |
|-----|-------------|
| `<leader>Brr` | Run task |
| `<leader>Brs` | Set command |
| `<leader>Bll` | Show last task |
## Window Management
| Key | Description |
|-----|-------------|
| `<leader>ww` | Other window |
| `<leader>wd` | Delete window |
| `<leader>w-` | Split below |
| `<leader>w\|` | Split right |
| `<leader>wm` | Maximize window |
## Buffers
| Key | Description |
|-----|-------------|
| `<S-h>` | Previous buffer |
| `<S-l>` | Next buffer |
| `<leader>bd` | Delete buffer |
| `<leader>bo` | Delete other buffers |
## Misc
| Key | Description |
|-----|-------------|
| `<leader>l` | Lazy (plugin manager) |
| `<leader>L` | Lazy extras |
| `<leader>fn` | New file |
| `<leader>xl` | Location list |
| `<leader>xq` | Quickfix list |
| `<leader>xt` | Todo list |
| `<leader>uz` | Toggle zen mode |

151
docs/cheatsheets/testing.md Normal file
View File

@@ -0,0 +1,151 @@
# Testing Cheatsheet
## Quick Reference
| Key | Action |
|-----|--------|
| `<leader>tt` | Run nearest test |
| `<leader>tf` | Run file tests |
| `<leader>ta` | Run all tests |
| `<leader>td` | Debug test |
| `<leader>ts` | Toggle summary |
## Running Tests
```
<leader>tt Run nearest test (cursor position)
<leader>tf Run all tests in current file
<leader>ta Run all tests in project
<leader>tl Re-run last test
<leader>tS Stop running tests
```
## Debugging Tests
```
<leader>td Debug nearest test (with DAP)
<leader>tD Debug all tests in file
```
## Watch Mode
```
<leader>tw Toggle watch mode (file)
<leader>tW Toggle watch mode (nearest)
```
Tests auto-run when file changes.
## Output & Results
```
<leader>ts Toggle test summary panel
<leader>to Show output for nearest test
<leader>tO Toggle output panel
```
## Navigation
```
]t Jump to next failed test
[t Jump to previous failed test
```
## Test Summary Panel
When summary is open (`<leader>ts`):
```
<cr> Jump to test
o Show output
i Show short output
O Show full output
m Mark test
M Clear marks
r Run marked/nearest
R Run all in file
d Debug test
```
## Framework-Specific
### Vitest (TypeScript)
Files detected: `*.test.ts`, `*.spec.ts`, `*.test.tsx`, `*.spec.tsx`
```typescript
// Test file example
describe('MyComponent', () => {
it('should render', () => {
// cursor here, <leader>tt runs this test
})
})
```
### Pytest (Python)
Files detected: `test_*.py`, `*_test.py`
```python
# Test file example
def test_something():
# cursor here, <leader>tt runs this test
pass
class TestMyClass:
def test_method(self):
pass
```
### Go Test
Files detected: `*_test.go`
```go
// Test file example
func TestSomething(t *testing.T) {
// cursor here, <leader>tt runs this test
}
```
## Common Workflows
### TDD Workflow
1. Write failing test
2. `<leader>tw` - Enable watch mode
3. Write implementation
4. Test auto-runs on save
5. `<leader>tw` - Disable when done
### Debug Failing Test
1. `]t` - Jump to failed test
2. `<leader>to` - View output
3. Set breakpoint if needed (`<leader>db`)
4. `<leader>td` - Debug test
5. Step through with DAP controls
### Run Specific Tests
1. `<leader>ts` - Open summary
2. `m` on tests to mark them
3. `r` to run marked tests
## Troubleshooting
### Tests Not Found
- Check file naming convention
- Verify neotest adapter is installed
- Run `:checkhealth neotest`
### Wrong Framework Used
- Check `testing.lua` for adapter config
- Ensure correct adapter is listed
### Output Not Showing
- `<leader>tO` to toggle output panel
- Check if test actually ran

285
docs/guides/ai-assistant.md Normal file
View File

@@ -0,0 +1,285 @@
# AI Assistant Guide (opencode.nvim)
This guide covers using opencode.nvim for AI-assisted coding in Neovim.
## Overview
opencode.nvim provides AI assistance directly in Neovim:
- Ask questions about code
- Get explanations
- Generate code and tests
- Refactor and optimize
- Review changes
- Document code
## Quick Start
### Open AI Panel
```
<leader>kk Toggle opencode panel
```
The panel opens on the right side (40% width).
### Ask a Question
```
<leader>ka Ask opencode (prompts for input)
```
Or with file context:
```
<leader>kA Ask about current file
```
## Key Bindings
### General
| Key | Mode | Action |
|-----|------|--------|
| `<leader>kk` | n | Toggle opencode panel |
| `<leader>ka` | n, v | Ask opencode |
| `<leader>kA` | n, v | Ask about current file |
| `<leader>kn` | n | New session |
### Code Understanding
| Key | Mode | Action |
|-----|------|--------|
| `<leader>ke` | n | Explain code near cursor |
| `<leader>kE` | v | Explain selection |
### Code Review
| Key | Mode | Action |
|-----|------|--------|
| `<leader>kr` | n | Review current file |
| `<leader>kg` | n | Review git diff |
| `<leader>kf` | n | Fix diagnostics/errors |
| `<leader>kq` | n | Fix quickfix items |
### Code Generation
| Key | Mode | Action |
|-----|------|--------|
| `<leader>ko` | v | Optimize selection |
| `<leader>kR` | v | Refactor selection |
| `<leader>kd` | v | Document selection |
| `<leader>kt` | v | Generate tests for selection |
### Harpoon Integration
| Key | Mode | Action |
|-----|------|--------|
| `<leader>kh` | n | Ask about harpooned files |
| `<leader>kH` | n | Analyze harpooned files |
## Common Workflows
### Understanding Code
1. Place cursor on complex code
2. `<leader>ke` - Explain code near cursor
Or for larger sections:
1. Select code in visual mode (`V`)
2. `<leader>kE` - Explain selection
### Fixing Bugs
1. See error in diagnostics
2. `<leader>kf` - Ask AI to fix
3. Review suggested fix
4. Apply or modify as needed
### Generating Tests
1. Select function to test (`V` for lines)
2. `<leader>kt` - Generate tests
3. Review generated tests
4. Adjust assertions as needed
### Refactoring
1. Select code to refactor (`V`)
2. `<leader>kR` - Request refactoring
3. Describe what you want (or let AI decide)
4. Review and apply
### Code Review
Before committing:
```
<leader>kg Review git diff
```
AI will analyze your changes and suggest improvements.
### Documenting Code
1. Select function/class (`V`)
2. `<leader>kd` - Generate documentation
3. Review generated docs
4. Integrate into code
## Working with Multiple Files
### Harpoon Context
Mark related files with harpoon, then ask about them together:
1. Mark files: `<leader>H` on each file
2. `<leader>kh` - Ask about all harpooned files
3. AI has context of all marked files
Example question:
> "How does the user service interact with the database layer?"
### Analyze Architecture
```
<leader>kH Analyze harpooned files
```
Good for understanding relationships between files.
## Effective Prompting
### Be Specific
Bad: "Fix this code"
Good: "This function throws an error when the array is empty. Add a guard clause."
### Provide Context
Bad: "Add error handling"
Good: "Add try-catch with proper error logging following our project's error handling pattern"
### Ask for Explanations
- "Explain why this regex works"
- "What are the edge cases here?"
- "Why might this be slow?"
### Request Alternatives
- "Show me 3 ways to implement this"
- "What's a more functional approach?"
- "How would you do this idiomatically in Go?"
## Session Management
### New Session
```
<leader>kn Start fresh session
```
Clears context for a new topic.
### Continuing Conversations
The panel maintains conversation history. Follow up naturally:
1. Ask initial question
2. "Can you also handle the null case?"
3. "Now add tests for this"
## Integration with Workflow
### During Development
1. Write initial implementation
2. `<leader>ke` - Understand any complex parts
3. `<leader>kt` - Generate tests
4. `<leader>ko` - Optimize if needed
### During Code Review
1. `<leader>gd` - Open diffview
2. `<leader>kg` - AI review of changes
3. Address suggestions
4. Create PR
### While Debugging
1. Hit an error
2. `<leader>kf` - Ask AI to fix
3. Or `<leader>ke` - Understand the error first
4. Apply fix
## Tips
### Quick Explanations
`K` (hover) shows LSP docs, but for deeper understanding:
```
<leader>ke AI explanation with context
```
### Iterative Refinement
1. Get initial suggestion
2. "Make it more concise"
3. "Add error handling"
4. "Use async/await instead"
### Learning Patterns
Ask AI to explain patterns:
- "Explain the repository pattern used here"
- "What design pattern would improve this?"
- "Show me the idiomatic way in this language"
### Code Generation Templates
For repetitive tasks:
1. `<leader>ka`
2. "Generate a CRUD API endpoint for User model following the pattern in user.controller.ts"
## Customization
### Panel Position
Configured in `lua/plugins/opencode.lua`:
```lua
opts = {
window = {
position = "right", -- or "left", "top", "bottom"
width = 0.4, -- 40% of screen
},
}
```
### Auto-reload
When AI edits files, they auto-reload:
```lua
auto_reload_buffers_on_edit = true,
```
## Troubleshooting
### Panel Not Opening
1. Check opencode is installed: `:Lazy`
2. Verify configuration in `lua/plugins/opencode.lua`
### Slow Responses
- Large files take longer
- Consider selecting specific sections instead of whole files
### Context Issues
If AI seems confused:
1. `<leader>kn` - New session
2. Provide clearer context
3. Select specific code rather than asking about whole file
### Not Understanding Codebase
Use harpoon to provide multi-file context:
1. Mark relevant files
2. `<leader>kh` - Include them in question

413
docs/guides/debugging.md Normal file
View File

@@ -0,0 +1,413 @@
# Debugging Guide
This guide covers debugging with DAP (Debug Adapter Protocol) for TypeScript, Python, and Go.
## Overview
DAP provides IDE-like debugging:
- Breakpoints (line, conditional, logpoints)
- Step through code (into, over, out)
- Variable inspection
- Call stack navigation
- Expression evaluation
## Quick Start
### Basic Debugging Flow
1. **Set breakpoint**: `<leader>db`
2. **Start debugger**: `<leader>dc`
3. **Step through**: `<leader>di` (into), `<leader>do` (over)
4. **Inspect**: `<leader>du` (toggle UI)
5. **Stop**: `<leader>dt`
## Key Bindings
### Breakpoints
| Key | Action |
|-----|--------|
| `<leader>db` | Toggle breakpoint |
| `<leader>dB` | Conditional breakpoint |
| `<leader>dl` | Log point (print without stopping) |
### Execution Control
| Key | Action |
|-----|--------|
| `<leader>dc` | Continue (or start) |
| `<leader>di` | Step into |
| `<leader>do` | Step over |
| `<leader>dO` | Step out |
| `<leader>dC` | Run to cursor |
| `<leader>dp` | Pause |
| `<leader>dt` | Terminate |
| `<leader>dr` | Toggle REPL |
### UI & Inspection
| Key | Action |
|-----|--------|
| `<leader>du` | Toggle DAP UI |
| `<leader>de` | Evaluate expression |
| `<leader>dw` | Add to watch |
| `<leader>ds` | View scopes |
## DAP UI Layout
When you press `<leader>du`, the UI shows:
```
┌─────────────┬─────────────────────┐
│ Scopes │ │
│ (variables) │ Source Code │
├─────────────┤ (your file) │
│ Breakpoints │ │
├─────────────┤ │
│ Call Stack │ │
├─────────────┼─────────────────────┤
│ Watch │ Console/REPL │
└─────────────┴─────────────────────┘
```
### Scopes Panel
Shows variables in current scope:
- Local variables
- Function arguments
- Global variables
- Expand objects/arrays with `<cr>`
### Call Stack Panel
Shows function call hierarchy:
- Current function at top
- Click to jump to that frame
- See where you came from
### Breakpoints Panel
Lists all breakpoints:
- Toggle enable/disable
- Delete breakpoints
- See conditions
### Watch Panel
Add expressions to monitor:
- `<leader>dw` to add
- Updates as you step
## Debugging by Language
### TypeScript/JavaScript
#### Prerequisites
```bash
npm install -g @vscode/js-debug
```
#### Debug Current File
1. Open your `.ts` or `.js` file
2. `<leader>db` - Set breakpoint
3. `<leader>dc` - Start debugging
4. Select "Node.js: Launch" or similar
#### Debug Tests
```
<leader>td Debug test at cursor
```
This automatically sets up the test runner with debugging.
#### launch.json Example
```json
{
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "Debug Current File",
"program": "${file}",
"cwd": "${workspaceFolder}",
"sourceMaps": true
},
{
"type": "pwa-node",
"request": "launch",
"name": "Debug Server",
"program": "${workspaceFolder}/src/index.ts",
"preLaunchTask": "tsc: build",
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
]
}
```
### Python
#### Prerequisites
```bash
pip install debugpy
```
#### Debug Current File
1. Open your `.py` file
2. `<leader>db` - Set breakpoint
3. `<leader>dc` - Start debugging
4. Select "Python: Current File"
#### Debug Tests
```
<leader>td Debug test at cursor
```
#### launch.json Example
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"args": ["run", "--debug"],
"env": {
"FLASK_APP": "app.py"
}
},
{
"name": "Python: Django",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": ["runserver", "--noreload"]
}
]
}
```
### Go
#### Prerequisites
```bash
go install github.com/go-delve/delve/cmd/dlv@latest
```
#### Debug Current File
1. Open your `.go` file
2. `<leader>db` - Set breakpoint
3. `<leader>dc` - Start debugging
4. Select "Go: Debug Package"
#### Debug Tests
```
<leader>td Debug test at cursor
```
Works with table-driven tests too!
#### launch.json Example
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Package",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${fileDirname}"
},
{
"name": "Debug Main",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/cmd/server"
},
{
"name": "Attach to Process",
"type": "go",
"request": "attach",
"mode": "local",
"processId": "${command:pickProcess}"
}
]
}
```
## Breakpoint Types
### Line Breakpoint
Standard breakpoint - stops when line is reached:
```
<leader>db Toggle on current line
```
### Conditional Breakpoint
Only stops when condition is true:
```
<leader>dB Prompts for condition
```
Example conditions:
- `x > 10`
- `user.name == "test"`
- `items.length > 0`
### Log Point
Prints message without stopping:
```
<leader>dl Prompts for log message
```
Use `{}` for interpolation:
- `Value of x: {x}`
- `User: {user.name}`
### Hit Count Breakpoint
Stop after N hits (set via conditional):
```
<leader>dB Enter: hitCount > 5
```
## Debugging Strategies
### Step Through Unknown Code
1. Set breakpoint at entry point
2. `<leader>dc` - Start
3. `<leader>di` - Step into functions to understand them
4. `<leader>do` - Step over when you understand
5. `<leader>dO` - Step out when done with function
### Find Where Value Changes
1. Set breakpoint where value is used
2. `<leader>dw` - Add variable to watch
3. Step through, watching for changes
4. Or use conditional breakpoint: `x != expectedValue`
### Debug Loops
1. Set conditional breakpoint: `i == problematicIndex`
2. Or use hit count: stop after N iterations
3. Check variables at specific iteration
### Remote Debugging
For processes running elsewhere:
1. Start process with debug flag
2. Use "attach" configuration
3. Connect to debug port
## Common Workflows
### Finding a Bug
1. Reproduce the bug path
2. Set breakpoint before bug occurs
3. `<leader>dc` - Start debugging
4. Step through, inspecting variables
5. Find where actual != expected
6. Fix and re-test
### Understanding New Code
1. Set breakpoint at function entry
2. `<leader>dc` - Start with a test case
3. `<leader>di` - Step into each function
4. Use watch to track key variables
5. Build mental model of flow
### Performance Investigation
Use log points to trace without stopping:
1. `<leader>dl` at key points
2. Log timing: `Start: {Date.now()}`
3. Run normally
4. Check console for timing
## Tips
### Quick Variable Inspection
Hover over variable with cursor - shows value in float.
### REPL Usage
`<leader>dr` opens REPL where you can:
- Evaluate expressions
- Call functions
- Modify variables (sometimes)
### Restart Debugging
If you need to start over:
```
<leader>dt Terminate
<leader>dc Start again
```
### Breakpoint Persistence
Breakpoints are saved per session. They'll be there when you reopen the file.
## Troubleshooting
### Debugger Won't Start
1. Check adapter is installed
2. `:DapShowLog` for errors
3. Verify launch configuration
### Breakpoints Not Hit
1. Verify file paths match
2. Check source maps (TypeScript)
3. Ensure code is actually executed
### Variables Not Showing
1. Might be optimized out (Go)
2. Check scope (local vs global)
3. Try evaluating directly: `<leader>de`
### Source Maps Issues (TypeScript)
1. Ensure `sourceMaps: true` in launch.json
2. Check tsconfig has `sourceMap: true`
3. Verify outFiles pattern matches
### Slow Debugging
1. Reduce number of breakpoints
2. Use conditional breakpoints
3. Disable logging breakpoints when not needed

509
docs/guides/git-workflow.md Normal file
View File

@@ -0,0 +1,509 @@
# Git Workflow Guide
This guide covers the complete git workflow in Neovim, from making changes to creating pull requests.
## Overview
Your config includes:
- **Diffview**: Side-by-side diffs, file history, merge resolution
- **Git-blame**: Inline blame annotations
- **Gitsigns**: Gutter signs, hunk staging
- **Octo**: GitHub PRs and issues in Neovim
- **Lazygit**: Full TUI git client (optional)
## Daily Git Workflow
### 1. Check Status
See what's changed:
```
<leader>gd Open diffview (all changes)
```
Or use gitsigns to see hunks in current file:
```
]h Jump to next hunk
[h Jump to previous hunk
```
### 2. Stage Changes
#### Stage Hunks (Gitsigns)
Gitsigns provides inline staging in the current buffer:
```
]h Jump to next hunk
[h Jump to previous hunk
<leader>ghs Stage hunk under cursor (in normal or visual mode)
<leader>ghr Reset hunk (undo changes)
<leader>ghS Stage entire buffer
<leader>ghu Undo stage hunk
<leader>ghp Preview hunk inline
```
**Note**: The `<leader>ghs` command works in both normal and visual mode. In visual mode, it stages the selected lines.
#### Stage in Diffview
**Important**: To stage/unstage files in diffview, you need to open the main diffview (not file history):
1. Open diffview with `<leader>gd` (this shows the file panel on the left)
2. Focus the file panel (press `<leader>e` if needed)
3. Use these keys in the file panel:
```
- Toggle stage/unstage file (under cursor)
S Stage all files
U Unstage all files
X Revert file changes
<cr> Open diff for selected file
<tab> Toggle file panel
```
**Note**: If you see a telescope-like picker, you're in file history mode. Use `<leader>gd` (without arguments) to open the main diffview with staging capabilities.
### 3. Review Before Commit
```
<leader>gd Open diffview
```
Navigate files in left panel, review diffs on right.
### 4. Commit
Close diffview first (`<leader>gD`), then:
```
:Git commit Open commit message editor
```
Or use terminal/lazygit:
```
<leader>gg Open lazygit (if installed)
```
## Viewing History
### File History
See all commits that changed current file:
```
<leader>gf File history for current file
```
In history view:
- `j/k` - Navigate commits
- `<cr>` - View diff at that commit
- `<tab>` - Toggle file panel
### Branch History
See all commits on current branch:
```
<leader>gF Full branch history
```
### Compare to Main
See what's different from main branch:
```
<leader>gm Compare to origin/main
<leader>gM Compare to origin/master
```
## Git Blame
### Toggle Inline Blame
```
<leader>gB Toggle blame annotations
```
Shows author and commit info at end of each line.
### Investigate a Commit
When blame is on:
```
<leader>go Open commit in browser (GitHub)
<leader>gy Copy commit URL
```
## Working with PRs (Octo)
### List PRs
```
<leader>gpl List all PRs
```
Navigate and press `<cr>` to open.
### Create PR
```
<leader>gpc Create new PR
```
This opens a buffer to write PR title and description.
### Checkout PR
```
<leader>gpo Checkout a PR locally
```
Select from list of PRs.
### Review PR
#### Start Review
```
<leader>grs Start review
```
#### Add Comments
In PR file:
```
<leader>ca Add comment at cursor
```
#### Submit Review
```
<leader>grc Submit review
```
Choose: Approve, Comment, or Request Changes.
#### Other Review Actions
```
<leader>grr Resume review (if interrupted)
<leader>grd Discard review
```
### Merge PR
```
<leader>gpm Merge PR
```
### View in Browser
```
<leader>gpb Open PR in browser
```
## Working with Issues (Octo)
### List Issues
```
<leader>gil List issues
```
### Create Issue
```
<leader>gic Create new issue
```
### Open in Browser
```
<leader>gib Open issue in browser
```
## Merge Conflicts
### Open Merge Tool
When you have conflicts:
```
:DiffviewOpen
```
Diffview detects conflicts and shows 3-way merge view.
### Resolve Conflicts
In merge view:
- Left: Ours (current branch)
- Center: Result (what you're building)
- Right: Theirs (incoming changes)
Navigate conflicts:
```
]x Next conflict
[x Previous conflict
```
Choose resolution:
```
<leader>co Choose ours
<leader>ct Choose theirs
<leader>cb Choose both
<leader>c0 Choose none
```
### Complete Merge
After resolving all conflicts:
```
:DiffviewClose
:Git add .
:Git commit
```
## Advanced Diffview
### Custom Comparisons
Compare any refs:
```
:DiffviewOpen origin/main...HEAD
:DiffviewOpen HEAD~5
:DiffviewOpen branch1..branch2
```
### Diffview Panel Keys
**In the File Panel** (left side when open with `<leader>gd`):
```
j/k Navigate files
<cr> Open diff for selected file
- Toggle stage/unstage file
S Stage all files
U Unstage all files
X Revert file changes
<tab> Toggle file panel visibility
<leader>e Focus file panel
<leader>b Toggle file panel
R Refresh file list
L Show commit log
g? Show help
```
**In the Diff View** (right side):
```
<tab> Navigate to next file
<leader>e Focus file panel
<leader>b Toggle file panel
g? Show help
```
**Important**: The staging keys (`-`, `S`, `U`) only work in the **file panel**, not in the diff view itself. Make sure you're focused on the left panel (press `<leader>e` to focus it).
## Common Workflows
### Feature Development
1. Create branch (terminal):
```bash
git checkout -b feature/my-feature
```
2. Make changes, stage hunks:
```
<leader>ghs Stage hunk
```
3. Review all changes:
```
<leader>gd Open diffview
```
4. Commit (in terminal or lazygit)
5. Compare to main before PR:
```
<leader>gm Compare to main
```
6. Create PR:
```
<leader>gpc Create PR
```
### Code Review
1. List PRs:
```
<leader>gpl
```
2. Select and open PR
3. Start review:
```
<leader>grs
```
4. Navigate files, add comments
5. Submit:
```
<leader>grc
```
### Investigating a Bug
1. Find when bug was introduced:
```
<leader>gf File history
```
2. Navigate commits to find the change
3. Check blame for context:
```
<leader>gB Toggle blame
```
4. Open commit in browser:
```
<leader>go
```
### Resolving Merge Conflicts
1. After `git merge` with conflicts:
```
:DiffviewOpen
```
2. For each conflicting file:
- Navigate to conflict
- Choose resolution
- Move to next
3. When done:
```
:DiffviewClose
git add . && git commit
```
## Tips
### Quick Hunk Preview
Without opening diffview, you can preview hunks inline:
```
<leader>ghp Preview hunk inline (shows diff in floating window)
```
### Understanding Diffview Modes
Diffview has different modes:
1. **Main Diffview** (`<leader>gd`): Shows file panel + diff view. Use this for staging/unstaging files.
2. **File History** (`<leader>gf`): Shows a picker to select commits. This is read-only.
3. **Branch History** (`<leader>gF`): Shows all commits on current branch. This is read-only.
For staging/unstaging, always use `<leader>gd` (main diffview).
### Blame with Commit Message
The inline blame shows:
- Author
- Relative time
- Short commit message
### Stashing
Use terminal or lazygit:
```
git stash
git stash pop
```
### Interactive Rebase
Use terminal (not supported in Neovim):
```bash
git rebase -i HEAD~5
```
## Troubleshooting
### Octo Not Working
1. Ensure `gh` CLI is installed
2. Authenticate: `gh auth login`
3. Check `:Octo` commands are available
### Diffview Slow
For large repos:
- Limit file count in view
- Use specific file paths
### Gitsigns Not Showing
1. Verify file is in git repo
2. `:Gitsigns debug_messages`
3. Check file isn't ignored
4. Ensure `lazyvim.plugins.extras.lang.git` is enabled in `lazyvim.json`
### Diffview Shows Telescope Picker Instead of File Panel
If `<leader>gd` shows a picker instead of the file panel:
1. Make sure you're using `<leader>gd` (not `<leader>gf` or `<leader>gF`)
2. `<leader>gf` opens file history (picker mode) - this is read-only
3. `<leader>gd` opens main diffview with file panel - use this for staging
4. If file panel isn't visible, press `<tab>` or `<leader>b` to toggle it
5. Press `<leader>e` to focus the file panel before using staging keys
### Staging Keys Don't Work in Diffview
The staging keys (`-`, `S`, `U`) are built into diffview.nvim and should work by default. If they don't:
1. Make sure you're in the **file panel** (left side), not the diff view (right side)
2. Press `<leader>e` to focus the file panel first
3. Make sure you opened diffview with `<leader>gd` (not file history)
4. Check if there's a key conflict: run `:checkhealth diffview` or `:Telescope keymaps` and search for `-`
5. If `-` is mapped elsewhere, it might conflict - diffview keymaps are buffer-local, so conflicts are rare
**Note**: Diffview's keymaps are set automatically when the file panel is active. If they're not working, there might be a plugin loading issue. Try restarting Neovim or running `:Lazy sync`.

409
docs/guides/go-workflow.md Normal file
View File

@@ -0,0 +1,409 @@
# Go Development Workflow
This guide covers Go development in Neovim with gopls, testing, and debugging.
## Overview
Your config includes:
- **LSP**: gopls (via LazyVim go extra)
- **Linting**: golangci-lint
- **Testing**: go test via neotest
- **Debugging**: delve via DAP
- **Formatting**: gofmt/goimports
## Getting Started
### Project Setup
1. Ensure Go is installed and `GOPATH` is set
2. Open your Go project:
```bash
nvim /path/to/project
```
3. gopls will auto-start when you open a `.go` file
### Module Initialization
If starting fresh:
```bash
go mod init myproject
```
## LSP Features
### Navigation
| Key | Action |
|-----|--------|
| `gd` | Go to definition |
| `gr` | Go to references |
| `gI` | Go to implementation |
| `gy` | Go to type definition |
| `K` | Hover documentation |
### Code Actions
| Key | Action |
|-----|--------|
| `<leader>ca` | Code actions |
| `<leader>cr` | Rename symbol |
| `<leader>cf` | Format (gofmt) |
### Go-Specific Actions
Press `<leader>ca` for:
- Add import
- Organize imports
- Extract function
- Extract variable
- Generate interface stubs
- Add struct tags
- Fill struct
### Diagnostics
| Key | Action |
|-----|--------|
| `<leader>cd` | Line diagnostics |
| `]d` / `[d` | Next/prev diagnostic |
| `<leader>xx` | Toggle trouble |
## Testing
### Running Tests
| Key | Action |
|-----|--------|
| `<leader>tt` | Run test at cursor |
| `<leader>tf` | Run file tests |
| `<leader>ta` | Run all tests |
| `<leader>tl` | Re-run last test |
### Test File Convention
Go tests live in `*_test.go` files:
```go
// math_test.go
package math
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("expected 5, got %d", result)
}
}
```
### Test Output
```
<leader>ts Toggle test summary
<leader>to Show test output
<leader>tO Toggle output panel
]t / [t Jump to failed tests
```
### Table-Driven Tests
Common Go pattern - cursor on any test case runs it:
```go
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, -1, -2},
{"zero", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// <leader>tt here runs this specific case
if got := Add(tt.a, tt.b); got != tt.expected {
t.Errorf("got %d, want %d", got, tt.expected)
}
})
}
}
```
### Debugging Tests
```
<leader>td Debug test at cursor
```
## Debugging with Delve
### Prerequisites
Install delve:
```bash
go install github.com/go-delve/delve/cmd/dlv@latest
```
### Setting Breakpoints
| Key | Action |
|-----|--------|
| `<leader>db` | Toggle breakpoint |
| `<leader>dB` | Conditional breakpoint |
### Running Debugger
| Key | Action |
|-----|--------|
| `<leader>dc` | Continue/Start |
| `<leader>di` | Step into |
| `<leader>do` | Step over |
| `<leader>dO` | Step out |
| `<leader>dt` | Terminate |
### DAP UI
```
<leader>du Toggle DAP UI
<leader>de Evaluate expression
```
### launch.json
For custom debug configs, create `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Package",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${fileDirname}"
},
{
"name": "Debug Main",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/cmd/myapp"
},
{
"name": "Attach to Process",
"type": "go",
"request": "attach",
"mode": "local",
"processId": 0
}
]
}
```
## Code Quality
### Formatting
Go code is auto-formatted on save. Manual format:
```
<leader>cf Format with gofmt
```
### Imports
goimports manages imports automatically:
- Adds missing imports on save
- Removes unused imports
- Sorts imports
### Linting
golangci-lint runs automatically. View issues:
```
<leader>xx Toggle trouble (all diagnostics)
```
### Struct Tags
Generate/modify struct tags via code actions:
```go
type User struct {
Name string // <leader>ca → "Add json tag"
Email string
}
```
Result:
```go
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
```
## AI Assistance
| Key | Action |
|-----|--------|
| `<leader>ka` | Ask opencode |
| `<leader>ke` | Explain code |
| `<leader>kR` | Refactor selection |
| `<leader>kt` | Generate tests |
| `<leader>kd` | Generate comments |
### Generate Tests
1. Select function in visual mode
2. `<leader>kt`
3. Review generated table-driven tests
## Common Workflows
### Starting New Feature
1. Create/open `.go` file
2. `<leader>H` - Mark with harpoon
3. Write code, LSP handles imports
4. `<leader>tt` - Test as you go
### Implementing Interface
1. Write struct
2. `<leader>ca` → "Generate interface stubs"
3. Select interface to implement
4. Fill in method bodies
### Debugging
1. `<leader>db` - Set breakpoint
2. `<leader>dc` - Start debugger
3. Use step commands to navigate
4. `<leader>de` - Evaluate expressions
5. `<leader>dt` - Terminate when done
### Error Handling
Common Go pattern - AI can help:
1. Write function that returns error
2. `<leader>ka` - "Add proper error handling"
3. Or use snippet (if configured):
```go
if err != nil {
return err
}
```
## Project Structure
### Standard Layout
```
myproject/
├── cmd/
│ └── myapp/
│ └── main.go
├── internal/
│ └── pkg/
├── pkg/
│ └── public/
├── go.mod
└── go.sum
```
### go.mod
```go
module github.com/user/myproject
go 1.21
require (
github.com/some/dependency v1.0.0
)
```
## Tips
### Quick Run
```
:!go run . Run current package
:!go run main.go Run specific file
```
Or use executor:
```
<leader>Brs Set command: go run .
<leader>Brr Run it
```
### Build
```
:!go build . Build current package
```
### Generate
```
:!go generate ./... Run go generate
```
### Module Commands
```
:!go mod tidy Clean up go.mod
:!go mod download Download dependencies
```
### Documentation
- `K` on any symbol shows docs
- Works with standard library
- Shows function signatures
## Troubleshooting
### gopls Not Starting
1. `:LspInfo` - Check status
2. Verify gopls is installed:
```bash
go install golang.org/x/tools/gopls@latest
```
3. Check `go.mod` exists in project root
### Imports Not Working
1. Check gopls is running: `:LspInfo`
2. Verify `goimports` is installed:
```bash
go install golang.org/x/tools/cmd/goimports@latest
```
### Debugger Issues
1. Verify delve is installed:
```bash
go install github.com/go-delve/delve/cmd/dlv@latest
```
2. Check `:DapShowLog` for errors
3. Ensure code is compiled (not just source)
### Slow LSP
1. Check for large generated files
2. Add to `.gopls.json`:
```json
{
"build.directoryFilters": ["-vendor", "-node_modules"]
}
```

View File

@@ -0,0 +1,363 @@
# Python Development Workflow
This guide covers Python development in Neovim with virtual environment support, testing, and debugging.
## Overview
Your config includes:
- **LSP**: Pyright (via LazyVim python extra)
- **Linting**: Ruff or pylint
- **Testing**: pytest via neotest
- **Debugging**: debugpy via DAP
- **Virtual Environments**: venv-selector
## Getting Started
### Project Setup
1. Open your Python project:
```bash
nvim /path/to/project
```
2. Select virtual environment:
```
<leader>cv Open venv selector
```
3. The LSP will restart with the selected venv.
## Virtual Environment Management
### Selecting a Virtual Environment
```
<leader>cv Open venv selector
```
This searches for:
- `.venv/` in project
- `venv/` in project
- Poetry environments
- Conda environments
- pyenv environments
### Creating a Virtual Environment
If you don't have one:
```bash
# In terminal or with <leader>ft (float term)
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
Then `<leader>cv` to select it.
## LSP Features
### Navigation
| Key | Action |
|-----|--------|
| `gd` | Go to definition |
| `gr` | Go to references |
| `gI` | Go to implementation |
| `K` | Hover documentation |
### Code Actions
| Key | Action |
|-----|--------|
| `<leader>ca` | Code actions |
| `<leader>cr` | Rename symbol |
| `<leader>cf` | Format document |
### Diagnostics
| Key | Action |
|-----|--------|
| `<leader>cd` | Line diagnostics |
| `]d` / `[d` | Next/prev diagnostic |
| `<leader>xx` | Toggle trouble |
## Testing with pytest
### Running Tests
| Key | Action |
|-----|--------|
| `<leader>tt` | Run test at cursor |
| `<leader>tf` | Run file tests |
| `<leader>ta` | Run all tests |
| `<leader>tl` | Re-run last test |
### Test Discovery
pytest finds tests in:
- `test_*.py` files
- `*_test.py` files
- Functions named `test_*`
- Classes named `Test*`
### Test Output
```
<leader>ts Toggle test summary
<leader>to Show test output
<leader>tO Toggle output panel
]t / [t Jump to next/prev failed test
```
### Debugging Tests
```
<leader>td Debug test at cursor
```
This starts debugpy and allows stepping through test code.
## Debugging
### Setup
debugpy should be installed in your virtual environment:
```bash
pip install debugpy
```
### Setting Breakpoints
| Key | Action |
|-----|--------|
| `<leader>db` | Toggle breakpoint |
| `<leader>dB` | Conditional breakpoint |
### Running Debugger
| Key | Action |
|-----|--------|
| `<leader>dc` | Continue/Start |
| `<leader>di` | Step into |
| `<leader>do` | Step over |
| `<leader>dO` | Step out |
| `<leader>dt` | Terminate |
### DAP UI
```
<leader>du Toggle DAP UI
<leader>de Evaluate expression
```
### launch.json
For custom configurations, create `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Python: Flask",
"type": "python",
"request": "launch",
"module": "flask",
"args": ["run", "--debug"],
"env": {
"FLASK_APP": "app.py"
}
},
{
"name": "Python: FastAPI",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": ["main:app", "--reload"]
}
]
}
```
## Code Quality
### Formatting
```
<leader>cf Format with black/ruff
```
### Import Sorting
If using isort or ruff:
```
<leader>ca Code actions → Organize imports
```
### Type Checking
Pyright provides type checking. For strict mode, add `pyrightconfig.json`:
```json
{
"typeCheckingMode": "strict"
}
```
Or in `pyproject.toml`:
```toml
[tool.pyright]
typeCheckingMode = "strict"
```
## AI Assistance
| Key | Action |
|-----|--------|
| `<leader>ka` | Ask opencode |
| `<leader>ke` | Explain code |
| `<leader>kR` | Refactor selection |
| `<leader>kt` | Generate tests |
| `<leader>kd` | Generate docstrings |
### Generate Docstrings
1. Place cursor on function
2. `<leader>kd` (or use neogen: `<leader>cn`)
3. Review and adjust
## Common Workflows
### Starting New Feature
1. `<leader>cv` - Ensure correct venv
2. Create/open file
3. `<leader>H` - Mark with harpoon
4. Write code with LSP assistance
5. `<leader>tt` - Test as you go
### Debugging an Issue
1. `<leader>xx` - View all diagnostics
2. Navigate to issue
3. `<leader>db` - Set breakpoint
4. `<leader>dc` - Start debugger
5. Step through code
### Adding Tests
1. Create `test_*.py` file
2. Write test function:
```python
def test_something():
assert my_function() == expected
```
3. `<leader>tt` - Run test
4. `<leader>to` - View output
## Project Configuration
### pyproject.toml
Modern Python projects use `pyproject.toml`:
```toml
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.11"
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = "test_*.py"
[tool.ruff]
line-length = 88
select = ["E", "F", "I"]
[tool.pyright]
venvPath = "."
venv = ".venv"
```
### pytest.ini
For pytest configuration:
```ini
[pytest]
testpaths = tests
python_files = test_*.py
addopts = -v --tb=short
```
## Tips
### Quick REPL
```
<leader>ft Open floating terminal
python Start Python REPL
```
### Run Current File
```
:!python % Run current file
```
Or use executor:
```
<leader>Brs Set command: python %
<leader>Brr Run it
```
### Documentation
- `K` on any symbol shows docstring
- Works with standard library and packages
### Find TODOs
```
<leader>xt Show all TODO/FIXME comments
```
## Troubleshooting
### LSP Not Finding Imports
1. Check venv is selected: `<leader>cv`
2. `:LspInfo` - Verify pyright is attached
3. Check `pyrightconfig.json` or `pyproject.toml`
### Wrong Python Version
1. `<leader>cv` - Select correct venv
2. Or set explicitly in `pyrightconfig.json`:
```json
{
"pythonVersion": "3.11"
}
```
### Tests Not Found
1. Check file naming: `test_*.py`
2. Check function naming: `test_*`
3. Verify pytest is installed in venv
### Debugger Not Starting
1. Install debugpy: `pip install debugpy`
2. Check `:DapShowLog` for errors
3. Verify venv is active

449
docs/guides/snippets.md Normal file
View File

@@ -0,0 +1,449 @@
# Custom Snippets Guide
This guide explains how to create and use custom code snippets with LuaSnip.
## Overview
Snippets are code templates that expand when you type a trigger and press `<Tab>`. Your config supports:
- **Lua snippets**: Full power of Lua for dynamic snippets
- **VS Code snippets**: JSON format in `snippets/vscode/`
## Snippet Locations
```
~/.config/nvim/snippets/
├── all.lua # Global snippets (all filetypes)
├── typescript.lua # TypeScript/JavaScript
├── python.lua # Python
├── go.lua # Go
└── vscode/ # VS Code format snippets (optional)
```
## Quick Start
### 1. Open Snippet File
```lua
-- For TypeScript snippets:
nvim ~/.config/nvim/snippets/typescript.lua
```
### 2. Add a Simple Snippet
```lua
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
return {
s("cl", { t("console.log("), i(1), t(")") }),
}
```
### 3. Reload Snippets
```
<leader>cS Reload all snippets
```
### 4. Use Snippet
Type `cl` and press `<Tab>` to expand.
## Snippet Anatomy
### Basic Structure
```lua
s(trigger, nodes, opts)
```
- **trigger**: What you type to activate
- **nodes**: The content (text, placeholders, etc.)
- **opts**: Optional settings
### Node Types
| Node | Function | Purpose |
|------|----------|---------|
| `t(text)` | Text node | Static text |
| `i(index, default)` | Insert node | Tab stop/placeholder |
| `c(index, choices)` | Choice node | Multiple options |
| `f(func, args)` | Function node | Dynamic content |
| `d(index, func, args)` | Dynamic node | Complex dynamic content |
| `rep(index)` | Repeat node | Mirror another node |
## Examples by Complexity
### 1. Simple Text Replacement
```lua
-- Expands "todo" to "// TODO: "
s("todo", { t("// TODO: "), i(0) })
```
### 2. Multiple Tab Stops
```lua
-- Arrow function with parameters and body
s("af", {
t("const "),
i(1, "name"),
t(" = ("),
i(2),
t(") => {"),
t({"", " "}),
i(0),
t({"", "}"}),
})
```
Tab order: name → parameters → body
### 3. Using fmt() for Cleaner Syntax
```lua
local fmt = require("luasnip.extras.fmt").fmt
s("fn", fmt([[
function {}({}) {{
{}
}}
]], { i(1, "name"), i(2), i(0) }))
```
Note: `{{` and `}}` escape braces in fmt.
### 4. Choice Node
```lua
-- Choose between const, let, var
s("var", {
c(1, {
t("const"),
t("let"),
t("var"),
}),
t(" "),
i(2, "name"),
t(" = "),
i(0),
})
```
Press `<C-n>` / `<C-p>` to cycle choices.
### 5. Function Node (Dynamic)
```lua
-- Automatically generate return type
s("fn", {
t("function "),
i(1, "name"),
t("("),
i(2),
t("): "),
f(function(args)
-- Generate return type based on function name
local name = args[1][1]
if name:match("^is") then return "boolean" end
if name:match("^get") then return "string" end
return "void"
end, {1}),
t({" {", " "}),
i(0),
t({"", "}"}),
})
```
### 6. Repeat Node
```lua
-- Class with constructor that uses the class name
s("class", {
t("class "),
i(1, "Name"),
t({" {", " constructor("}),
i(2),
t({") {", " "}),
i(0),
t({"", " }", "", "}", ""}),
t("export default "),
rep(1), -- Repeats the class name
t(";"),
})
```
### 7. Dynamic Node
```lua
-- Generate multiple parameters dynamically
s("params", {
t("function("),
d(1, function()
-- Could read from clipboard, analyze code, etc.
return sn(nil, { i(1, "param1"), t(", "), i(2, "param2") })
end),
t(")"),
})
```
## Language-Specific Examples
### TypeScript
```lua
-- snippets/typescript.lua
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local c = ls.choice_node
local fmt = require("luasnip.extras.fmt").fmt
return {
-- Console log
s("cl", { t("console.log("), i(1), t(")") }),
-- Console log with label
s("cll", fmt('console.log("{}: ", {})', { i(1, "label"), rep(1) })),
-- Arrow function
s("af", fmt("const {} = ({}) => {{\n {}\n}}", { i(1, "name"), i(2), i(0) })),
-- React functional component
s("rfc", fmt([[
export function {}({}: {}) {{
return (
<div>
{}
</div>
)
}}
]], { i(1, "Component"), i(2, "props"), i(3, "Props"), i(0) })),
-- useState hook
s("us", fmt("const [{}, set{}] = useState({})", {
i(1, "state"),
f(function(args)
local name = args[1][1]
return name:sub(1,1):upper() .. name:sub(2)
end, {1}),
i(2, "initialValue"),
})),
-- useEffect hook
s("ue", fmt([[
useEffect(() => {{
{}
}}, [{}])
]], { i(1), i(2) })),
-- Try-catch
s("tc", fmt([[
try {{
{}
}} catch (error) {{
{}
}}
]], { i(1), i(2, "console.error(error)") })),
}
```
### Python
```lua
-- snippets/python.lua
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local fmt = require("luasnip.extras.fmt").fmt
return {
-- Main block
s("main", fmt([[
if __name__ == "__main__":
{}
]], { i(0) })),
-- Function with docstring
s("def", fmt([[
def {}({}):
"""{}"""
{}
]], { i(1, "name"), i(2), i(3, "Description"), i(0) })),
-- Class
s("class", fmt([[
class {}:
"""{}"""
def __init__(self, {}):
{}
]], { i(1, "Name"), i(2, "Description"), i(3), i(0) })),
-- Async function
s("adef", fmt([[
async def {}({}):
{}
]], { i(1, "name"), i(2), i(0) })),
-- Try-except
s("try", fmt([[
try:
{}
except {} as e:
{}
]], { i(1), i(2, "Exception"), i(3, "raise") })),
-- Context manager
s("with", fmt([[
with {}({}) as {}:
{}
]], { i(1, "open"), i(2), i(3, "f"), i(0) })),
}
```
### Go
```lua
-- snippets/go.lua
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local c = ls.choice_node
local fmt = require("luasnip.extras.fmt").fmt
return {
-- Error handling
s("iferr", fmt([[
if err != nil {{
return {}
}}
]], { c(1, { t("err"), i(nil, "nil, err") }) })),
-- Function
s("fn", fmt([[
func {}({}) {} {{
{}
}}
]], { i(1, "name"), i(2), i(3, "error"), i(0) })),
-- Method
s("meth", fmt([[
func ({} *{}) {}({}) {} {{
{}
}}
]], { i(1, "r"), i(2, "Receiver"), i(3, "Method"), i(4), i(5, "error"), i(0) })),
-- Struct
s("st", fmt([[
type {} struct {{
{}
}}
]], { i(1, "Name"), i(0) })),
-- Interface
s("iface", fmt([[
type {} interface {{
{}
}}
]], { i(1, "Name"), i(0) })),
-- Test function
s("test", fmt([[
func Test{}(t *testing.T) {{
{}
}}
]], { i(1, "Name"), i(0) })),
-- Table-driven test
s("ttest", fmt([[
func Test{}(t *testing.T) {{
tests := []struct {{
name string
{}
}}{{
{{}},
}}
for _, tt := range tests {{
t.Run(tt.name, func(t *testing.T) {{
{}
}})
}}
}}
]], { i(1, "Name"), i(2, "// fields"), i(0) })),
}
```
## VS Code Format Snippets
You can also use JSON snippets in `snippets/vscode/`:
```json
// snippets/vscode/typescript.json
{
"Console Log": {
"prefix": "cl",
"body": ["console.log($1)"],
"description": "Console log"
},
"Arrow Function": {
"prefix": "af",
"body": [
"const ${1:name} = (${2:params}) => {",
" $0",
"}"
],
"description": "Arrow function"
}
}
```
## Tips
### Trigger Naming
Use short, memorable triggers:
- `cl` → console.log
- `fn` → function
- `iferr` → if err != nil
### Tab Stop Order
- `i(1)` → First tab stop
- `i(2)` → Second tab stop
- `i(0)` → Final cursor position (always last)
### Default Values
```lua
i(1, "default") -- Shows "default", selected for replacement
```
### Testing Snippets
1. Edit snippet file
2. `<leader>cS` - Reload
3. Open file of that type
4. Type trigger + `<Tab>`
### Debugging Snippets
If snippet doesn't work:
1. Check Lua syntax (`:luafile %`)
2. Verify filetype matches
3. Check trigger isn't conflicting
## Reloading
```
<leader>cS Reload all custom snippets
```
Changes take effect immediately after reload.

View File

@@ -0,0 +1,294 @@
# TypeScript Development Workflow
This guide covers the complete TypeScript/JavaScript development workflow in Neovim.
## Overview
Your config includes:
- **LSP**: TypeScript language server (tsserver) via LazyVim extras
- **Linting**: ESLint integration
- **Testing**: Vitest via neotest
- **Debugging**: DAP for Node.js
- **Formatting**: Prettier (via conform.nvim)
## Getting Started
### Project Setup
1. Open your TypeScript project:
```bash
nvim /path/to/project
```
2. Session will auto-restore if you've worked on it before, or:
```
<leader>qs Restore session for this directory
```
3. Mark important files with Harpoon:
```
<leader>H Add current file to harpoon
<leader>1-9 Quick access to marked files
```
## LSP Features
### Navigation
| Key | Action |
|-----|--------|
| `gd` | Go to definition |
| `gr` | Go to references |
| `gI` | Go to implementation |
| `gy` | Go to type definition |
| `K` | Hover documentation |
### Code Actions
| Key | Action |
|-----|--------|
| `<leader>ca` | Code actions (imports, fixes, refactors) |
| `<leader>cr` | Rename symbol (project-wide) |
| `<leader>cf` | Format document |
### Common Code Actions
When you press `<leader>ca`, you'll see options like:
- Add missing imports
- Remove unused imports
- Organize imports
- Convert to arrow function
- Extract to function/variable
- Move to new file
### Diagnostics
| Key | Action |
|-----|--------|
| `<leader>cd` | Show line diagnostics |
| `]d` / `[d` | Next/prev diagnostic |
| `]e` / `[e` | Next/prev error |
| `<leader>xx` | Toggle trouble (diagnostics list) |
## Testing with Vitest
### Running Tests
| Key | Action |
|-----|--------|
| `<leader>tt` | Run test at cursor |
| `<leader>tf` | Run all tests in file |
| `<leader>ta` | Run all tests in project |
| `<leader>tl` | Re-run last test |
### Test Output
| Key | Action |
|-----|--------|
| `<leader>ts` | Toggle test summary panel |
| `<leader>to` | Show test output |
| `<leader>tO` | Toggle output panel |
### Watch Mode
```
<leader>tw Toggle watch mode for current file
```
Tests will auto-run when file changes - great for TDD!
### Debugging Tests
```
<leader>td Debug test at cursor (starts DAP)
```
## Debugging
### Setting Breakpoints
| Key | Action |
|-----|--------|
| `<leader>db` | Toggle breakpoint |
| `<leader>dB` | Conditional breakpoint |
| `<leader>dl` | Log point |
### Running Debugger
| Key | Action |
|-----|--------|
| `<leader>dc` | Continue/Start debugging |
| `<leader>di` | Step into |
| `<leader>do` | Step over |
| `<leader>dO` | Step out |
| `<leader>dt` | Terminate |
### DAP UI
```
<leader>du Toggle DAP UI (shows variables, call stack, etc.)
<leader>de Evaluate expression under cursor
```
### launch.json
For custom debug configurations, create `.vscode/launch.json`:
```json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Current File",
"program": "${file}",
"cwd": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "Debug Tests",
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
"args": ["run", "${relativeFile}"],
"cwd": "${workspaceFolder}"
}
]
}
```
## Linting (ESLint)
ESLint runs automatically and shows diagnostics inline.
### Fix All
```
<leader>ca Then select "Fix all ESLint problems"
```
Or format the file which may also run ESLint fixes:
```
<leader>cf Format document
```
## Code Generation with AI
Use opencode.nvim for AI-assisted coding:
| Key | Action |
|-----|--------|
| `<leader>ka` | Ask opencode (general) |
| `<leader>ke` | Explain code at cursor |
| `<leader>kR` | Refactor selection (visual) |
| `<leader>kt` | Generate tests for selection |
| `<leader>kd` | Document selection |
### Example: Generate Tests
1. Select a function in visual mode (`V` to select lines)
2. `<leader>kt` - Generate tests
3. Review and accept generated tests
## Common Workflows
### Starting a New Feature
1. `<leader>ff` - Find/create feature file
2. `<leader>H` - Mark it with harpoon
3. Write code with LSP assistance
4. `<leader>ca` - Add imports as needed
5. `<leader>tt` - Run tests as you go
### Fixing a Bug
1. `<leader>xx` - Open trouble to see all errors
2. Navigate to error location
3. `K` - Read documentation
4. `gd` - Go to definition if needed
5. `<leader>db` - Set breakpoint
6. `<leader>td` - Debug the test
### Refactoring
1. `gr` - Find all references
2. `<leader>cr` - Rename symbol
3. `<leader>ca` - Apply refactoring code actions
4. `<leader>kR` - Use AI for complex refactors
### Code Review Prep
1. `<leader>gm` - Compare to main branch
2. Review your changes
3. `<leader>kg` - AI review of git diff
4. Fix any issues
5. `<leader>gpc` - Create PR
## Project-Specific Settings
### TypeScript Config
Your `tsconfig.json` is respected by the LSP. Common settings:
```json
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true
}
}
```
### ESLint Config
`.eslintrc.js` or `eslint.config.js` is auto-detected.
### Prettier Config
`.prettierrc` is respected by the formatter.
## Tips
### Import Organization
- `<leader>ca` → "Organize imports" - sorts and removes unused
- Or configure to organize on save
### Quick Type Info
- `K` on any symbol shows type information
- Works on function parameters, variables, etc.
### Find All TODO/FIXME
```
<leader>xt Open todo list (via todo-comments)
```
### Symbol Search
```
<leader>ss Search symbols in file
<leader>sS Search symbols in workspace
```
## Troubleshooting
### LSP Not Working
1. `:LspInfo` - Check LSP status
2. `:Mason` - Verify typescript-language-server installed
3. Check for `tsconfig.json` in project root
### ESLint Not Running
1. `:LspInfo` - Check if eslint is attached
2. Verify `.eslintrc` exists
3. Check `node_modules` for eslint
### Slow Performance
1. Check `tsconfig.json` includes/excludes
2. Exclude `node_modules` from searches
3. Use project-specific `tsconfig` for large monorepos

View File

@@ -14,9 +14,11 @@
"cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" },
"cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" },
"conform.nvim": { "branch": "master", "commit": "c2526f1cde528a66e086ab1668e996d162c75f4f" },
"diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" },
"executor.nvim": { "branch": "main", "commit": "56dfbe6f7fbf4a6ba7e5934df2d95810e0235f64" },
"flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" },
"friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" },
"git-blame.nvim": { "branch": "main", "commit": "5c536e2d4134d064aa3f41575280bc8a2a0e03d7" },
"gitsigns.nvim": { "branch": "main", "commit": "abf82a65f185bd54adc0679f74b7d6e1ada690c9" },
"grug-far.nvim": { "branch": "main", "commit": "1f7a722a9b9f0206a345377c13e62542f484398a" },
"harpoon": { "branch": "harpoon2", "commit": "87b1a3506211538f460786c23f98ec63ad9af4e5" },
@@ -66,6 +68,9 @@
"trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" },
"ts-comments.nvim": { "branch": "main", "commit": "123a9fb12e7229342f807ec9e6de478b1102b041" },
"venv-selector.nvim": { "branch": "main", "commit": "7316a81aa359e7e609c9b47a30ce3f5548d4ddc6" },
"vim-dadbod": { "branch": "master", "commit": "6d1d41da4873a445c5605f2005ad2c68c99d8770" },
"vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" },
"vim-dadbod-ui": { "branch": "master", "commit": "48c4f271da13d380592f4907e2d1d5558044e4e5" },
"vim-startuptime": { "branch": "master", "commit": "b6f0d93f6b8cf6eee0b4c94450198ba2d6a05ff6" },
"vim-tmux-navigator": { "branch": "master", "commit": "e41c431a0c7b7388ae7ba341f01a0d217eb3a432" },
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }

View File

@@ -14,13 +14,13 @@
"lazyvim.plugins.extras.lang.markdown",
"lazyvim.plugins.extras.lang.nix",
"lazyvim.plugins.extras.lang.python",
"lazyvim.plugins.extras.lang.sql",
"lazyvim.plugins.extras.lang.typescript",
"lazyvim.plugins.extras.lang.yaml",
"lazyvim.plugins.extras.linting.eslint",
"lazyvim.plugins.extras.test.core",
"lazyvim.plugins.extras.ui.treesitter-context",
"lazyvim.plugins.extras.util.chezmoi",
"lazyvim.plugins.extras.util.gitui",
"lazyvim.plugins.extras.util.octo",
"lazyvim.plugins.extras.util.project",
"lazyvim.plugins.extras.util.rest",

136
list-commands.lua Normal file
View File

@@ -0,0 +1,136 @@
-- Script to list all registered commands in Neovim
-- Run with: nvim --headless -c "luafile list-commands.lua" -c "qa"
local commands = vim.api.nvim_get_commands({})
-- Sort commands alphabetically
local sorted_commands = {}
for name, cmd in pairs(commands) do
table.insert(sorted_commands, {
name = name,
cmd = cmd
})
end
table.sort(sorted_commands, function(a, b)
return a.name < b.name
end)
-- Group commands by plugin/source (if we can determine it)
local command_groups = {}
local conflicts = {}
-- Check for conflicts (commands with same name but different definitions)
local seen_names = {}
print("=" .. string.rep("=", 78))
print("ALL REGISTERED COMMANDS IN NVIM CONFIG")
print("=" .. string.rep("=", 78))
print()
for _, item in ipairs(sorted_commands) do
local name = item.name
local cmd = item.cmd
-- Check for conflicts
if seen_names[name] then
if not conflicts[name] then
conflicts[name] = {seen_names[name], cmd}
else
table.insert(conflicts[name], cmd)
end
else
seen_names[name] = cmd
end
-- Format command info
local cmd_type = cmd.bang and "!" or ""
local cmd_range = cmd.range and "range" or ""
local cmd_count = cmd.count ~= "" and cmd.count or ""
local flags = {}
if cmd_type ~= "" then table.insert(flags, "bang") end
if cmd_range ~= "" then table.insert(flags, "range") end
if cmd_count ~= "" then table.insert(flags, "count=" .. cmd_count) end
if cmd.nargs ~= "" then table.insert(flags, "nargs=" .. cmd.nargs) end
local flags_str = #flags > 0 and (" [" .. table.concat(flags, ", ") .. "]") or ""
print(string.format("%-30s %s%s", name, cmd.definition or "", flags_str))
end
print()
print("=" .. string.rep("=", 78))
print("SUMMARY")
print("=" .. string.rep("=", 78))
print(string.format("Total commands: %d", #sorted_commands))
if next(conflicts) then
print()
print("⚠️ CONFLICTS DETECTED:")
print("=" .. string.rep("=", 78))
for name, defs in pairs(conflicts) do
print(string.format("Command '%s' has multiple definitions:", name))
for i, def in ipairs(defs) do
print(string.format(" %d. %s", i, def.definition or ""))
end
print()
end
else
print()
print("✓ No conflicts detected!")
end
print()
print("=" .. string.rep("=", 78))
print("COMMANDS BY PLUGIN (from config files)")
print("=" .. string.rep("=", 78))
print()
-- Commands from config files
local config_commands = {
["Tmux Navigator"] = {
"TmuxNavigateLeft",
"TmuxNavigateDown",
"TmuxNavigateUp",
"TmuxNavigateRight",
"TmuxNavigatePrevious",
},
["Executor"] = {
"ExecutorRun",
"ExecutorToggleDetail",
"ExecutorSetCommand",
},
["DBUI"] = {
"DBUI",
"DBUIToggle",
"DBUIAddConnection",
"DBUIFindBuffer",
"DBUIRenameBuffer",
"DBUILastQueryInfo",
},
["Diffview"] = {
"DiffviewOpen",
"DiffviewClose",
"DiffviewFileHistory",
"DiffviewToggleFiles",
},
["Git Blame"] = {
"GitBlameToggle",
"GitBlameOpenCommitURL",
"GitBlameCopyCommitURL",
},
["Octo"] = {
"Octo",
},
}
for plugin, cmds in pairs(config_commands) do
print(string.format("%s:", plugin))
for _, cmd in ipairs(cmds) do
local exists = commands[cmd] ~= nil
local status = exists and "" or ""
print(string.format(" %s %s", status, cmd))
end
print()
end

View File

@@ -2,4 +2,43 @@
-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
-- Add any additional options here
-- Scrolling: Keep cursor centered
vim.opt.scrolloff = 999
-- Line numbers: Use relative numbers for easier navigation
vim.opt.relativenumber = true
-- Text wrapping: Don't wrap lines (useful for code)
vim.opt.wrap = false
-- Indentation: 2 spaces (common for TS/JS, adjustable per project via .editorconfig)
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.expandtab = true
vim.opt.smartindent = true
-- Search: Smart case sensitivity
vim.opt.ignorecase = true
vim.opt.smartcase = true
-- Undo: Persistent undo across sessions
vim.opt.undofile = true
vim.opt.undolevels = 10000
-- Splits: Open new splits in intuitive directions
vim.opt.splitright = true
vim.opt.splitbelow = true
-- Completion: Better completion experience
vim.opt.completeopt = "menu,menuone,noselect"
-- Performance: Faster updates
vim.opt.updatetime = 200
vim.opt.timeoutlen = 300
-- Visual: Show invisible characters
vim.opt.list = true
vim.opt.listchars = { tab = " ", trail = "·", nbsp = "" }
-- Clipboard: Use system clipboard
vim.opt.clipboard = "unnamedplus"

63
lua/plugins/database.lua Normal file
View File

@@ -0,0 +1,63 @@
-- Database client: vim-dadbod with UI for PostgreSQL, SQLite, etc.
return {
-- Dadbod: Database client
{
"kristijanhusak/vim-dadbod-ui",
dependencies = {
{ "tpope/vim-dadbod", lazy = true },
{ "kristijanhusak/vim-dadbod-completion", ft = { "sql", "mysql", "plsql" }, lazy = true },
},
cmd = { "DBUI", "DBUIToggle", "DBUIAddConnection", "DBUIFindBuffer" },
keys = {
{ "<leader>Du", "<cmd>DBUIToggle<cr>", desc = "Toggle DBUI" },
{ "<leader>Da", "<cmd>DBUIAddConnection<cr>", desc = "Add DB Connection" },
{ "<leader>Df", "<cmd>DBUIFindBuffer<cr>", desc = "Find DB Buffer" },
{ "<leader>Dr", "<cmd>DBUIRenameBuffer<cr>", desc = "Rename DB Buffer" },
{ "<leader>Dl", "<cmd>DBUILastQueryInfo<cr>", desc = "Last Query Info" },
},
init = function()
vim.g.db_ui_use_nerd_fonts = 1
vim.g.db_ui_show_database_icon = 1
-- Store connections in a local file (should be gitignored)
vim.g.db_ui_save_location = vim.fn.stdpath("data") .. "/db_ui"
-- Use .dbout extension for query results
vim.g.db_ui_execute_on_save = false
-- Table helpers - useful query templates
vim.g.db_ui_table_helpers = {
postgresql = {
Count = "SELECT COUNT(*) FROM {table}",
First10 = "SELECT * FROM {table} LIMIT 10",
Schema = "\\d+ {table}",
},
sqlite = {
Count = "SELECT COUNT(*) FROM {table}",
First10 = "SELECT * FROM {table} LIMIT 10",
Schema = ".schema {table}",
},
}
end,
},
-- Which-key group labels for database
{
"folke/which-key.nvim",
opts = {
spec = {
{ "<leader>D", group = "database" },
},
},
},
-- Autocomplete for SQL buffers
{
"hrsh7th/nvim-cmp",
optional = true,
dependencies = {
"kristijanhusak/vim-dadbod-completion",
},
opts = function(_, opts)
opts.sources = opts.sources or {}
table.insert(opts.sources, { name = "vim-dadbod-completion" })
end,
},
}

View File

@@ -120,4 +120,45 @@ return {
terminal = {},
},
},
-- REST Client (kulala.nvim) - keymaps for API testing
-- Plugin is installed via lazyvim.plugins.extras.util.rest
{
"mistweaverco/kulala.nvim",
keys = {
{ "<leader>Rs", function() require("kulala").run() end, desc = "Send Request" },
{ "<leader>Ra", function() require("kulala").run_all() end, desc = "Send All Requests" },
{ "<leader>Rr", function() require("kulala").replay() end, desc = "Replay Last Request" },
{ "<leader>Ri", function() require("kulala").inspect() end, desc = "Inspect Request" },
{ "<leader>Rt", function() require("kulala").toggle_view() end, desc = "Toggle Headers/Body" },
{ "<leader>Rc", function() require("kulala").copy() end, desc = "Copy as cURL" },
{ "<leader>Re", function() require("kulala").set_selected_env() end, desc = "Select Environment" },
{ "<leader>Rv", function() require("kulala").show_stats() end, desc = "Show Stats" },
{ "[r", function() require("kulala").jump_prev() end, desc = "Prev Request" },
{ "]r", function() require("kulala").jump_next() end, desc = "Next Request" },
},
ft = { "http", "rest" },
},
-- Session management keymaps (persistence.nvim is installed via LazyVim)
{
"folke/persistence.nvim",
keys = {
{ "<leader>qs", function() require("persistence").load() end, desc = "Restore Session" },
{ "<leader>ql", function() require("persistence").load({ last = true }) end, desc = "Restore Last Session" },
{ "<leader>qd", function() require("persistence").stop() end, desc = "Don't Save Session" },
{ "<leader>qS", function() require("persistence").select() end, desc = "Select Session" },
},
},
-- Additional which-key groups
{
"folke/which-key.nvim",
opts = {
spec = {
{ "<leader>R", group = "REST client" },
{ "<leader>q", group = "session" },
},
},
},
}

89
lua/plugins/git.lua Normal file
View File

@@ -0,0 +1,89 @@
-- Git workflow enhancements: diffview, git-blame, and Octo keymaps
return {
-- Diffview: Side-by-side diffs and file history
{
"sindrets/diffview.nvim",
cmd = { "DiffviewOpen", "DiffviewClose", "DiffviewFileHistory", "DiffviewToggleFiles" },
keys = {
{ "<leader>gd", "<cmd>DiffviewOpen<cr>", desc = "Diffview: Open" },
{ "<leader>gD", "<cmd>DiffviewClose<cr>", desc = "Diffview: Close" },
{ "<leader>gf", "<cmd>DiffviewFileHistory %<cr>", desc = "Diffview: File History" },
{ "<leader>gF", "<cmd>DiffviewFileHistory<cr>", desc = "Diffview: Branch History" },
{ "<leader>gm", "<cmd>DiffviewOpen origin/main...HEAD<cr>", desc = "Diffview: Compare to main" },
{ "<leader>gM", "<cmd>DiffviewOpen origin/master...HEAD<cr>", desc = "Diffview: Compare to master" },
},
opts = {
enhanced_diff_hl = true,
view = {
default = {
layout = "diff2_horizontal",
},
merge_tool = {
layout = "diff3_mixed",
},
file_history = {
layout = "diff2_horizontal",
},
},
file_panel = {
win_config = {
position = "left",
width = 35,
},
},
},
},
-- Git blame: Inline blame annotations
{
"f-person/git-blame.nvim",
event = "BufRead",
opts = {
enabled = false, -- Disabled by default, toggle with <leader>gB
date_format = "%r", -- relative time
message_when_not_committed = "Not committed yet",
virtual_text_column = 80,
},
keys = {
{ "<leader>gB", "<cmd>GitBlameToggle<cr>", desc = "Toggle Git Blame" },
{ "<leader>go", "<cmd>GitBlameOpenCommitURL<cr>", desc = "Open Commit in Browser" },
{ "<leader>gy", "<cmd>GitBlameCopyCommitURL<cr>", desc = "Copy Commit URL" },
},
},
-- Octo.nvim keymaps (plugin already installed via lazyvim.plugins.extras.util.octo)
{
"pwntester/octo.nvim",
keys = {
-- PR operations
{ "<leader>gpl", "<cmd>Octo pr list<cr>", desc = "List PRs" },
{ "<leader>gpc", "<cmd>Octo pr create<cr>", desc = "Create PR" },
{ "<leader>gpo", "<cmd>Octo pr checkout<cr>", desc = "Checkout PR" },
{ "<leader>gpb", "<cmd>Octo pr browser<cr>", desc = "Open PR in Browser" },
{ "<leader>gpr", "<cmd>Octo pr ready<cr>", desc = "Mark PR Ready" },
{ "<leader>gpd", "<cmd>Octo pr diff<cr>", desc = "Show PR Diff" },
{ "<leader>gpm", "<cmd>Octo pr merge<cr>", desc = "Merge PR" },
-- Issue operations
{ "<leader>gil", "<cmd>Octo issue list<cr>", desc = "List Issues" },
{ "<leader>gic", "<cmd>Octo issue create<cr>", desc = "Create Issue" },
{ "<leader>gib", "<cmd>Octo issue browser<cr>", desc = "Open Issue in Browser" },
-- Review operations
{ "<leader>grs", "<cmd>Octo review start<cr>", desc = "Start Review" },
{ "<leader>grr", "<cmd>Octo review resume<cr>", desc = "Resume Review" },
{ "<leader>grc", "<cmd>Octo review submit<cr>", desc = "Submit Review" },
{ "<leader>grd", "<cmd>Octo review discard<cr>", desc = "Discard Review" },
},
},
-- Which-key group labels for git
{
"folke/which-key.nvim",
opts = {
spec = {
{ "<leader>gp", group = "pull requests" },
{ "<leader>gi", group = "issues" },
{ "<leader>gr", group = "review" },
},
},
},
}

39
lua/plugins/snippets.lua Normal file
View File

@@ -0,0 +1,39 @@
-- Custom snippet configuration for LuaSnip
-- Snippets are loaded from ~/.config/nvim/snippets/
return {
{
"L3MON4D3/LuaSnip",
config = function(_, opts)
local luasnip = require("luasnip")
-- Apply any opts from other configs
if opts then
luasnip.setup(opts)
end
-- Load custom snippets from snippets directory
-- Snippets are written in Lua format for maximum flexibility
require("luasnip.loaders.from_lua").lazy_load({
paths = { vim.fn.stdpath("config") .. "/snippets" },
})
-- Also support VS Code style snippets if you have any
require("luasnip.loaders.from_vscode").lazy_load({
paths = { vim.fn.stdpath("config") .. "/snippets/vscode" },
})
end,
keys = {
{
"<leader>cS",
function()
-- Reload all custom snippets
require("luasnip.loaders.from_lua").load({
paths = { vim.fn.stdpath("config") .. "/snippets" },
})
vim.notify("Snippets reloaded!", vim.log.levels.INFO)
end,
desc = "Reload Snippets",
},
},
},
}

View File

@@ -1,4 +1,7 @@
-- Testing configuration with neotest
-- Supports Vitest (TypeScript), pytest (Python), and go test (Go)
return {
{
"nvim-neotest/neotest",
dependencies = {
"marilari88/neotest-vitest",
@@ -8,4 +11,40 @@ return {
["neotest-vitest"] = {},
},
},
keys = {
-- Run tests
{ "<leader>tt", function() require("neotest").run.run() end, desc = "Run Nearest Test" },
{ "<leader>tf", function() require("neotest").run.run(vim.fn.expand("%")) end, desc = "Run File Tests" },
{ "<leader>ta", function() require("neotest").run.run(vim.uv.cwd()) end, desc = "Run All Tests" },
{ "<leader>tl", function() require("neotest").run.run_last() end, desc = "Run Last Test" },
{ "<leader>tS", function() require("neotest").run.stop() end, desc = "Stop Tests" },
-- Debug tests
{ "<leader>td", function() require("neotest").run.run({ strategy = "dap" }) end, desc = "Debug Nearest Test" },
{ "<leader>tD", function() require("neotest").run.run({ vim.fn.expand("%"), strategy = "dap" }) end, desc = "Debug File Tests" },
-- Watch mode
{ "<leader>tw", function() require("neotest").watch.toggle(vim.fn.expand("%")) end, desc = "Toggle Watch (File)" },
{ "<leader>tW", function() require("neotest").watch.toggle() end, desc = "Toggle Watch (Nearest)" },
-- Output and summary
{ "<leader>ts", function() require("neotest").summary.toggle() end, desc = "Toggle Summary" },
{ "<leader>to", function() require("neotest").output.open({ enter = true, auto_close = true }) end, desc = "Show Output" },
{ "<leader>tO", function() require("neotest").output_panel.toggle() end, desc = "Toggle Output Panel" },
-- Navigation
{ "[t", function() require("neotest").jump.prev({ status = "failed" }) end, desc = "Prev Failed Test" },
{ "]t", function() require("neotest").jump.next({ status = "failed" }) end, desc = "Next Failed Test" },
},
},
-- Which-key group label
{
"folke/which-key.nvim",
opts = {
spec = {
{ "<leader>t", group = "test" },
},
},
},
}

43
snippets/all.lua Normal file
View File

@@ -0,0 +1,43 @@
-- Global snippets (available in all filetypes)
-- See docs/guides/snippets.md for how to create snippets
--
-- Quick reference:
-- s(trigger, nodes, opts) - Create a snippet
-- t(text) - Text node
-- i(index, default) - Insert node (tab stop)
-- c(index, choices) - Choice node
-- f(func, args) - Function node
-- d(index, func, args) - Dynamic node
-- rep(index) - Repeat node
--
-- These snippets work in ANY filetype
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local c = ls.choice_node
local f = ls.function_node
local d = ls.dynamic_node
local sn = ls.snippet_node
local rep = require("luasnip.extras").rep
local fmt = require("luasnip.extras.fmt").fmt
-- Helper function to get current date
local function date()
return os.date("%Y-%m-%d")
end
-- Add your global snippets here
return {
-- Example: Uncomment and modify as needed
--
-- Current date
-- s("date", { f(date) }),
--
-- TODO comment
-- s("todo", fmt("TODO({}): {}", { i(1, "author"), i(0) })),
--
-- FIXME comment
-- s("fixme", fmt("FIXME({}): {}", { i(1, "author"), i(0) })),
}

52
snippets/go.lua Normal file
View File

@@ -0,0 +1,52 @@
-- Go snippets
-- See docs/guides/snippets.md for how to create snippets
--
-- Quick reference:
-- s(trigger, nodes, opts) - Create a snippet
-- t(text) - Text node
-- i(index, default) - Insert node (tab stop)
-- c(index, choices) - Choice node
-- f(func, args) - Function node
-- d(index, func, args) - Dynamic node
-- rep(index) - Repeat node
--
-- Example:
-- s("iferr", fmt("if err != nil {{\n\treturn {}\n}}", { i(1, "err") }))
-- Typing "iferr" + expand will give error handling template
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local c = ls.choice_node
local f = ls.function_node
local d = ls.dynamic_node
local sn = ls.snippet_node
local rep = require("luasnip.extras").rep
local fmt = require("luasnip.extras.fmt").fmt
-- Add your Go snippets here
return {
-- Example: Uncomment and modify as needed
--
-- Error handling
-- s("iferr", fmt([[
-- if err != nil {{
-- return {}
-- }}
-- ]], { i(1, "err") })),
--
-- Function
-- s("fn", fmt([[
-- func {}({}) {} {{
-- {}
-- }}
-- ]], { i(1, "name"), i(2), i(3, "error"), i(0) })),
--
-- Struct
-- s("st", fmt([[
-- type {} struct {{
-- {}
-- }}
-- ]], { i(1, "Name"), i(0) })),
}

50
snippets/python.lua Normal file
View File

@@ -0,0 +1,50 @@
-- Python snippets
-- See docs/guides/snippets.md for how to create snippets
--
-- Quick reference:
-- s(trigger, nodes, opts) - Create a snippet
-- t(text) - Text node
-- i(index, default) - Insert node (tab stop)
-- c(index, choices) - Choice node
-- f(func, args) - Function node
-- d(index, func, args) - Dynamic node
-- rep(index) - Repeat node
--
-- Example:
-- s("def", fmt("def {}({}):\n {}", { i(1, "name"), i(2), i(0) }))
-- Typing "def" + expand will give a function template
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local c = ls.choice_node
local f = ls.function_node
local d = ls.dynamic_node
local sn = ls.snippet_node
local rep = require("luasnip.extras").rep
local fmt = require("luasnip.extras.fmt").fmt
-- Add your Python snippets here
return {
-- Example: Uncomment and modify as needed
--
-- Main block
-- s("main", fmt([[
-- if __name__ == "__main__":
-- {}
-- ]], { i(0) })),
--
-- Class with init
-- s("class", fmt([[
-- class {}:
-- def __init__(self, {}):
-- {}
-- ]], { i(1, "ClassName"), i(2), i(0) })),
--
-- Async function
-- s("adef", fmt([[
-- async def {}({}):
-- {}
-- ]], { i(1, "name"), i(2), i(0) })),
}

48
snippets/typescript.lua Normal file
View File

@@ -0,0 +1,48 @@
-- TypeScript/JavaScript snippets
-- See docs/guides/snippets.md for how to create snippets
--
-- Quick reference:
-- s(trigger, nodes, opts) - Create a snippet
-- t(text) - Text node
-- i(index, default) - Insert node (tab stop)
-- c(index, choices) - Choice node
-- f(func, args) - Function node
-- d(index, func, args) - Dynamic node
-- rep(index) - Repeat node
--
-- Example:
-- s("cl", { t("console.log("), i(1), t(")") })
-- Typing "cl" + expand will give: console.log(|)
local ls = require("luasnip")
local s = ls.snippet
local t = ls.text_node
local i = ls.insert_node
local c = ls.choice_node
local f = ls.function_node
local d = ls.dynamic_node
local sn = ls.snippet_node
local rep = require("luasnip.extras").rep
local fmt = require("luasnip.extras.fmt").fmt
-- Add your TypeScript snippets here
return {
-- Example: Uncomment and modify as needed
--
-- Console log
-- s("cl", { t("console.log("), i(1), t(")") }),
--
-- Arrow function
-- s("af", fmt("const {} = ({}) => {{\n {}\n}}", { i(1, "name"), i(2), i(0) })),
--
-- React functional component
-- s("rfc", fmt([[
-- export function {}({}: {}) {{
-- return (
-- <div>
-- {}
-- </div>
-- )
-- }}
-- ]], { i(1, "Component"), i(2, "props"), i(3, "Props"), i(0) })),
}