From b3b70bceeba2271575bccedaaa96f808c1c42230 Mon Sep 17 00:00:00 2001 From: Morten Olsen Date: Mon, 26 Jan 2026 23:04:14 +0100 Subject: [PATCH] Improved flow --- check-commands.lua | 96 ++++++ check-git-keys.lua | 104 ++++++ commands-report.md | 158 +++++++++ docs/README.md | 98 ++++++ docs/cheatsheets/database.md | 164 ++++++++++ docs/cheatsheets/git-workflow.md | 142 ++++++++ docs/cheatsheets/keybindings.md | 206 ++++++++++++ docs/cheatsheets/testing.md | 151 +++++++++ docs/guides/ai-assistant.md | 285 ++++++++++++++++ docs/guides/debugging.md | 413 +++++++++++++++++++++++ docs/guides/git-workflow.md | 509 +++++++++++++++++++++++++++++ docs/guides/go-workflow.md | 409 +++++++++++++++++++++++ docs/guides/python-workflow.md | 363 ++++++++++++++++++++ docs/guides/snippets.md | 449 +++++++++++++++++++++++++ docs/guides/typescript-workflow.md | 294 +++++++++++++++++ lazy-lock.json | 5 + lazyvim.json | 2 +- list-commands.lua | 136 ++++++++ lua/config/options.lua | 39 +++ lua/plugins/database.lua | 63 ++++ lua/plugins/general.lua | 41 +++ lua/plugins/git.lua | 89 +++++ lua/plugins/snippets.lua | 39 +++ lua/plugins/testing.lua | 51 ++- snippets/all.lua | 43 +++ snippets/go.lua | 52 +++ snippets/python.lua | 50 +++ snippets/typescript.lua | 48 +++ 28 files changed, 4492 insertions(+), 7 deletions(-) create mode 100644 check-commands.lua create mode 100644 check-git-keys.lua create mode 100644 commands-report.md create mode 100644 docs/README.md create mode 100644 docs/cheatsheets/database.md create mode 100644 docs/cheatsheets/git-workflow.md create mode 100644 docs/cheatsheets/keybindings.md create mode 100644 docs/cheatsheets/testing.md create mode 100644 docs/guides/ai-assistant.md create mode 100644 docs/guides/debugging.md create mode 100644 docs/guides/git-workflow.md create mode 100644 docs/guides/go-workflow.md create mode 100644 docs/guides/python-workflow.md create mode 100644 docs/guides/snippets.md create mode 100644 docs/guides/typescript-workflow.md create mode 100644 list-commands.lua create mode 100644 lua/plugins/database.lua create mode 100644 lua/plugins/git.lua create mode 100644 lua/plugins/snippets.lua create mode 100644 snippets/all.lua create mode 100644 snippets/go.lua create mode 100644 snippets/python.lua create mode 100644 snippets/typescript.lua diff --git a/check-commands.lua b/check-commands.lua new file mode 100644 index 0000000..af1749b --- /dev/null +++ b/check-commands.lua @@ -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 - Find commands by pattern") + +return M diff --git a/check-git-keys.lua b/check-git-keys.lua new file mode 100644 index 0000000..d33184b --- /dev/null +++ b/check-git-keys.lua @@ -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 "" 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 "" 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 "" 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 diff --git a/commands-report.md b/commands-report.md new file mode 100644 index 0000000..ead0ddd --- /dev/null +++ b/commands-report.md @@ -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. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..9cbd0ba --- /dev/null +++ b/docs/README.md @@ -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**: `` +2. **Find files**: `ff` or `` +3. **Find text**: `sg` (grep) or `/` (in buffer) +4. **File explorer**: `e` +5. **Which-key help**: Press `` 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 | +|--------|---------|----------| +| `f` | **Find/Files** | Find files, recent files | +| `s` | **Search** | Search text, symbols, help | +| `g` | **Git** | Git status, diffs, PRs | +| `c` | **Code** | LSP actions, format, rename | +| `t` | **Test** | Run tests, debug tests | +| `d` | **Debug** | DAP debugging | +| `D` | **Database** | DBUI, connections | +| `R` | **REST** | HTTP requests | +| `k` | **AI (opencode)** | AI assistance | +| `h` | **Harpoon** | Quick file navigation | +| `q` | **Session** | Save/restore sessions | +| `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 `` 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 diff --git a/docs/cheatsheets/database.md b/docs/cheatsheets/database.md new file mode 100644 index 0000000..6d72f0e --- /dev/null +++ b/docs/cheatsheets/database.md @@ -0,0 +1,164 @@ +# Database Cheatsheet + +## Quick Reference + +| Key | Action | +|-----|--------| +| `Du` | Toggle DBUI | +| `Da` | Add connection | +| `Df` | Find DB buffer | + +## Opening DBUI + +``` +Du Toggle database UI +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 + +``` + Toggle node / Execute query +o Open node +R Refresh +d Delete +r Rename +S Sort by +H Toggle help +q Close +``` + +## Writing Queries + +1. `Du` - Open DBUI +2. Navigate to database +3. Press `` on "New Query" +4. Write SQL +5. `Rs` or `` to execute + +## Query Execution + +In a `.sql` buffer connected to DBUI: + +``` + Execute query under cursor +Rs Execute query (visual: selected) +``` + +## Table Helpers + +Right-click or press `` 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 + +``` +Df Find DB buffer +Dr Rename DB buffer +Dl Last query info +``` + +## Common Workflows + +### Connect to Database + +1. `Da` - Add connection +2. Enter connection string +3. Give it a name +4. Connection saved for future sessions + +### Explore Schema + +1. `Du` - Open DBUI +2. Expand database node +3. Expand "Tables" node +4. `` on table for helpers + +### Run Ad-hoc Query + +1. `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 `` + +### 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 diff --git a/docs/cheatsheets/git-workflow.md b/docs/cheatsheets/git-workflow.md new file mode 100644 index 0000000..e3d1495 --- /dev/null +++ b/docs/cheatsheets/git-workflow.md @@ -0,0 +1,142 @@ +# Git Workflow Cheatsheet + +## Quick Reference + +| Key | Action | +|-----|--------| +| `gd` | Open diff view | +| `gD` | Close diff view | +| `gf` | File history | +| `gB` | Toggle blame | +| `gpl` | List PRs | +| `gpc` | Create PR | + +## Viewing Changes + +### Diffview + +``` +gd Open diff view (staged + unstaged) +gD Close diff view +gf Current file history +gF Branch history +gm Compare to origin/main +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 + Open file diff +- Stage/unstage file (must be in file panel) +S Stage all files +U Unstage all files +X Revert file changes + Toggle file panel visibility +e Focus file panel +b Toggle file panel +R Refresh file list +g? Show help +``` + +**Note**: Use `gd` (not `gf`) to open diffview with staging capabilities. File history (`gf`) is read-only. + +## Blame + +``` +gB Toggle inline blame +go Open commit in browser +gy Copy commit URL +``` + +## Staging & Committing (Gitsigns) + +``` +]h Next hunk +[h Previous hunk +ghs Stage hunk +ghr Reset hunk +ghS Stage buffer +ghu Undo stage hunk +ghp Preview hunk +ghb Blame line +``` + +## Pull Requests (Octo) + +### Listing & Navigation + +``` +gpl List PRs +gpo Checkout PR +gpb Open PR in browser +gpd Show PR diff +``` + +### Creating & Managing + +``` +gpc Create PR +gpr Mark PR ready +gpm Merge PR +``` + +### Reviewing + +``` +grs Start review +grr Resume review +grc Submit review +grd Discard review +``` + +### In PR Buffer + +``` +ca Add comment +cd Delete comment +sa Approve +sc Comment +sr Request changes +``` + +## Issues (Octo) + +``` +gil List issues +gic Create issue +gib Open in browser +``` + +## Common Workflows + +### Review a PR + +1. `gpl` - List PRs +2. Select PR and press `` +3. `grs` - Start review +4. Navigate files, add comments +5. `grc` - Submit review + +### Compare Branch to Main + +1. `gm` - Open diff vs main +2. Review changes in split view +3. `gD` - Close when done + +### Investigate File History + +1. `gf` - File history +2. Navigate commits with `j/k` +3. `` to view diff at commit +4. `gD` - Close when done + +### Quick Blame Check + +1. `gB` - Toggle blame +2. Line blame shows inline +3. `go` - Open commit if needed +4. `gB` - Toggle off diff --git a/docs/cheatsheets/keybindings.md b/docs/cheatsheets/keybindings.md new file mode 100644 index 0000000..86c59df --- /dev/null +++ b/docs/cheatsheets/keybindings.md @@ -0,0 +1,206 @@ +# Keybindings Cheatsheet + +Leader key: `` + +## Navigation + +| Key | Description | +|-----|-------------| +| `` | Navigate between splits/tmux panes | +| `ff` | Find files | +| `` | Find files (alt) | +| `fr` | Recent files | +| `fb` | Browse buffers | +| `e` | File explorer | +| `s` | Flash jump (in normal mode) | +| `S` | Flash treesitter | + +## Harpoon (Quick File Access) + +| Key | Description | +|-----|-------------| +| `H` | Add file to harpoon | +| `h` | Toggle harpoon menu | +| `1-9` | Jump to harpoon file 1-9 | + +## Search + +| Key | Description | +|-----|-------------| +| `sg` | Grep (search text) | +| `sw` | Search word under cursor | +| `ss` | Search symbols | +| `sS` | Search symbols (workspace) | +| `/` | Search in buffer | +| `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 | +| `ca` | Code actions | +| `cr` | Rename symbol | +| `cf` | Format document | +| `cd` | Line diagnostics | +| `cS` | Reload snippets | +| `]d` / `[d` | Next/prev diagnostic | +| `]e` / `[e` | Next/prev error | +| `]w` / `[w` | Next/prev warning | + +## Git + +| Key | Description | +|-----|-------------| +| `gg` | Lazygit (if installed) | +| `gd` | Diffview: Open | +| `gD` | Diffview: Close | +| `gf` | Diffview: File history | +| `gF` | Diffview: Branch history | +| `gm` | Diffview: Compare to main | +| `gB` | Toggle git blame | +| `go` | Open commit in browser | +| `gy` | Copy commit URL | + +### GitHub (Octo) + +| Key | Description | +|-----|-------------| +| `gpl` | List PRs | +| `gpc` | Create PR | +| `gpo` | Checkout PR | +| `gpb` | Open PR in browser | +| `gpm` | Merge PR | +| `gil` | List issues | +| `gic` | Create issue | +| `grs` | Start review | +| `grr` | Resume review | +| `grc` | Submit review | + +## Testing + +| Key | Description | +|-----|-------------| +| `tt` | Run nearest test | +| `tf` | Run file tests | +| `ta` | Run all tests | +| `tl` | Run last test | +| `tS` | Stop tests | +| `td` | Debug nearest test | +| `tD` | Debug file tests | +| `tw` | Toggle watch (file) | +| `ts` | Toggle summary | +| `to` | Show output | +| `tO` | Toggle output panel | +| `]t` / `[t` | Next/prev failed test | + +## Debugging (DAP) + +| Key | Description | +|-----|-------------| +| `db` | Toggle breakpoint | +| `dB` | Breakpoint with condition | +| `dc` | Continue | +| `dC` | Run to cursor | +| `di` | Step into | +| `do` | Step over | +| `dO` | Step out | +| `dp` | Pause | +| `dt` | Terminate | +| `du` | Toggle DAP UI | +| `de` | Evaluate expression | + +## Database + +| Key | Description | +|-----|-------------| +| `Du` | Toggle DBUI | +| `Da` | Add DB connection | +| `Df` | Find DB buffer | +| `Dr` | Rename DB buffer | +| `Dl` | Last query info | + +## REST Client + +| Key | Description | +|-----|-------------| +| `Rs` | Send request | +| `Ra` | Send all requests | +| `Rr` | Replay last request | +| `Ri` | Inspect request | +| `Rt` | Toggle headers/body | +| `Rc` | Copy as cURL | +| `Re` | Select environment | +| `]r` / `[r` | Next/prev request | + +## AI Assistant (opencode.nvim) + +| Key | Description | +|-----|-------------| +| `kk` | Toggle opencode | +| `ka` | Ask opencode | +| `kA` | Ask about current file | +| `kn` | New session | +| `ke` | Explain code near cursor | +| `kE` | Explain selection (visual) | +| `kr` | Review file | +| `kg` | Review git diff | +| `kf` | Fix diagnostics | +| `ko` | Optimize selection (visual) | +| `kR` | Refactor selection (visual) | +| `kd` | Document selection (visual) | +| `kt` | Test selection (visual) | +| `kh` | Ask about harpooned files | + +## Session Management + +| Key | Description | +|-----|-------------| +| `qs` | Restore session | +| `ql` | Restore last session | +| `qd` | Don't save session | +| `qS` | Select session | + +## Background Tasks (Executor) + +| Key | Description | +|-----|-------------| +| `Brr` | Run task | +| `Brs` | Set command | +| `Bll` | Show last task | + +## Window Management + +| Key | Description | +|-----|-------------| +| `ww` | Other window | +| `wd` | Delete window | +| `w-` | Split below | +| `w\|` | Split right | +| `wm` | Maximize window | + +## Buffers + +| Key | Description | +|-----|-------------| +| `` | Previous buffer | +| `` | Next buffer | +| `bd` | Delete buffer | +| `bo` | Delete other buffers | + +## Misc + +| Key | Description | +|-----|-------------| +| `l` | Lazy (plugin manager) | +| `L` | Lazy extras | +| `fn` | New file | +| `xl` | Location list | +| `xq` | Quickfix list | +| `xt` | Todo list | +| `uz` | Toggle zen mode | diff --git a/docs/cheatsheets/testing.md b/docs/cheatsheets/testing.md new file mode 100644 index 0000000..10e5579 --- /dev/null +++ b/docs/cheatsheets/testing.md @@ -0,0 +1,151 @@ +# Testing Cheatsheet + +## Quick Reference + +| Key | Action | +|-----|--------| +| `tt` | Run nearest test | +| `tf` | Run file tests | +| `ta` | Run all tests | +| `td` | Debug test | +| `ts` | Toggle summary | + +## Running Tests + +``` +tt Run nearest test (cursor position) +tf Run all tests in current file +ta Run all tests in project +tl Re-run last test +tS Stop running tests +``` + +## Debugging Tests + +``` +td Debug nearest test (with DAP) +tD Debug all tests in file +``` + +## Watch Mode + +``` +tw Toggle watch mode (file) +tW Toggle watch mode (nearest) +``` + +Tests auto-run when file changes. + +## Output & Results + +``` +ts Toggle test summary panel +to Show output for nearest test +tO Toggle output panel +``` + +## Navigation + +``` +]t Jump to next failed test +[t Jump to previous failed test +``` + +## Test Summary Panel + +When summary is open (`ts`): + +``` + 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, tt runs this test + }) +}) +``` + +### Pytest (Python) + +Files detected: `test_*.py`, `*_test.py` + +```python +# Test file example +def test_something(): + # cursor here, 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, tt runs this test +} +``` + +## Common Workflows + +### TDD Workflow + +1. Write failing test +2. `tw` - Enable watch mode +3. Write implementation +4. Test auto-runs on save +5. `tw` - Disable when done + +### Debug Failing Test + +1. `]t` - Jump to failed test +2. `to` - View output +3. Set breakpoint if needed (`db`) +4. `td` - Debug test +5. Step through with DAP controls + +### Run Specific Tests + +1. `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 + +- `tO` to toggle output panel +- Check if test actually ran diff --git a/docs/guides/ai-assistant.md b/docs/guides/ai-assistant.md new file mode 100644 index 0000000..d77f2d4 --- /dev/null +++ b/docs/guides/ai-assistant.md @@ -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 + +``` +kk Toggle opencode panel +``` + +The panel opens on the right side (40% width). + +### Ask a Question + +``` +ka Ask opencode (prompts for input) +``` + +Or with file context: +``` +kA Ask about current file +``` + +## Key Bindings + +### General + +| Key | Mode | Action | +|-----|------|--------| +| `kk` | n | Toggle opencode panel | +| `ka` | n, v | Ask opencode | +| `kA` | n, v | Ask about current file | +| `kn` | n | New session | + +### Code Understanding + +| Key | Mode | Action | +|-----|------|--------| +| `ke` | n | Explain code near cursor | +| `kE` | v | Explain selection | + +### Code Review + +| Key | Mode | Action | +|-----|------|--------| +| `kr` | n | Review current file | +| `kg` | n | Review git diff | +| `kf` | n | Fix diagnostics/errors | +| `kq` | n | Fix quickfix items | + +### Code Generation + +| Key | Mode | Action | +|-----|------|--------| +| `ko` | v | Optimize selection | +| `kR` | v | Refactor selection | +| `kd` | v | Document selection | +| `kt` | v | Generate tests for selection | + +### Harpoon Integration + +| Key | Mode | Action | +|-----|------|--------| +| `kh` | n | Ask about harpooned files | +| `kH` | n | Analyze harpooned files | + +## Common Workflows + +### Understanding Code + +1. Place cursor on complex code +2. `ke` - Explain code near cursor + +Or for larger sections: +1. Select code in visual mode (`V`) +2. `kE` - Explain selection + +### Fixing Bugs + +1. See error in diagnostics +2. `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. `kt` - Generate tests +3. Review generated tests +4. Adjust assertions as needed + +### Refactoring + +1. Select code to refactor (`V`) +2. `kR` - Request refactoring +3. Describe what you want (or let AI decide) +4. Review and apply + +### Code Review + +Before committing: +``` +kg Review git diff +``` + +AI will analyze your changes and suggest improvements. + +### Documenting Code + +1. Select function/class (`V`) +2. `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: `H` on each file +2. `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 + +``` +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 + +``` +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. `ke` - Understand any complex parts +3. `kt` - Generate tests +4. `ko` - Optimize if needed + +### During Code Review + +1. `gd` - Open diffview +2. `kg` - AI review of changes +3. Address suggestions +4. Create PR + +### While Debugging + +1. Hit an error +2. `kf` - Ask AI to fix +3. Or `ke` - Understand the error first +4. Apply fix + +## Tips + +### Quick Explanations + +`K` (hover) shows LSP docs, but for deeper understanding: +``` +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. `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. `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. `kh` - Include them in question diff --git a/docs/guides/debugging.md b/docs/guides/debugging.md new file mode 100644 index 0000000..bc91a68 --- /dev/null +++ b/docs/guides/debugging.md @@ -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**: `db` +2. **Start debugger**: `dc` +3. **Step through**: `di` (into), `do` (over) +4. **Inspect**: `du` (toggle UI) +5. **Stop**: `dt` + +## Key Bindings + +### Breakpoints + +| Key | Action | +|-----|--------| +| `db` | Toggle breakpoint | +| `dB` | Conditional breakpoint | +| `dl` | Log point (print without stopping) | + +### Execution Control + +| Key | Action | +|-----|--------| +| `dc` | Continue (or start) | +| `di` | Step into | +| `do` | Step over | +| `dO` | Step out | +| `dC` | Run to cursor | +| `dp` | Pause | +| `dt` | Terminate | +| `dr` | Toggle REPL | + +### UI & Inspection + +| Key | Action | +|-----|--------| +| `du` | Toggle DAP UI | +| `de` | Evaluate expression | +| `dw` | Add to watch | +| `ds` | View scopes | + +## DAP UI Layout + +When you press `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 `` + +### 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: +- `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. `db` - Set breakpoint +3. `dc` - Start debugging +4. Select "Node.js: Launch" or similar + +#### Debug Tests + +``` +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. `db` - Set breakpoint +3. `dc` - Start debugging +4. Select "Python: Current File" + +#### Debug Tests + +``` +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. `db` - Set breakpoint +3. `dc` - Start debugging +4. Select "Go: Debug Package" + +#### Debug Tests + +``` +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: +``` +db Toggle on current line +``` + +### Conditional Breakpoint + +Only stops when condition is true: +``` +dB Prompts for condition +``` + +Example conditions: +- `x > 10` +- `user.name == "test"` +- `items.length > 0` + +### Log Point + +Prints message without stopping: +``` +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): +``` +dB Enter: hitCount > 5 +``` + +## Debugging Strategies + +### Step Through Unknown Code + +1. Set breakpoint at entry point +2. `dc` - Start +3. `di` - Step into functions to understand them +4. `do` - Step over when you understand +5. `dO` - Step out when done with function + +### Find Where Value Changes + +1. Set breakpoint where value is used +2. `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. `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. `dc` - Start with a test case +3. `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. `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 + +`dr` opens REPL where you can: +- Evaluate expressions +- Call functions +- Modify variables (sometimes) + +### Restart Debugging + +If you need to start over: +``` +dt Terminate +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: `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 diff --git a/docs/guides/git-workflow.md b/docs/guides/git-workflow.md new file mode 100644 index 0000000..9c7bcbb --- /dev/null +++ b/docs/guides/git-workflow.md @@ -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: + +``` +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 +ghs Stage hunk under cursor (in normal or visual mode) +ghr Reset hunk (undo changes) +ghS Stage entire buffer +ghu Undo stage hunk +ghp Preview hunk inline +``` + +**Note**: The `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 `gd` (this shows the file panel on the left) +2. Focus the file panel (press `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 + Open diff for selected file + Toggle file panel +``` + +**Note**: If you see a telescope-like picker, you're in file history mode. Use `gd` (without arguments) to open the main diffview with staging capabilities. + +### 3. Review Before Commit + +``` +gd Open diffview +``` + +Navigate files in left panel, review diffs on right. + +### 4. Commit + +Close diffview first (`gD`), then: + +``` +:Git commit Open commit message editor +``` + +Or use terminal/lazygit: + +``` +gg Open lazygit (if installed) +``` + +## Viewing History + +### File History + +See all commits that changed current file: + +``` +gf File history for current file +``` + +In history view: + +- `j/k` - Navigate commits +- `` - View diff at that commit +- `` - Toggle file panel + +### Branch History + +See all commits on current branch: + +``` +gF Full branch history +``` + +### Compare to Main + +See what's different from main branch: + +``` +gm Compare to origin/main +gM Compare to origin/master +``` + +## Git Blame + +### Toggle Inline Blame + +``` +gB Toggle blame annotations +``` + +Shows author and commit info at end of each line. + +### Investigate a Commit + +When blame is on: + +``` +go Open commit in browser (GitHub) +gy Copy commit URL +``` + +## Working with PRs (Octo) + +### List PRs + +``` +gpl List all PRs +``` + +Navigate and press `` to open. + +### Create PR + +``` +gpc Create new PR +``` + +This opens a buffer to write PR title and description. + +### Checkout PR + +``` +gpo Checkout a PR locally +``` + +Select from list of PRs. + +### Review PR + +#### Start Review + +``` +grs Start review +``` + +#### Add Comments + +In PR file: + +``` +ca Add comment at cursor +``` + +#### Submit Review + +``` +grc Submit review +``` + +Choose: Approve, Comment, or Request Changes. + +#### Other Review Actions + +``` +grr Resume review (if interrupted) +grd Discard review +``` + +### Merge PR + +``` +gpm Merge PR +``` + +### View in Browser + +``` +gpb Open PR in browser +``` + +## Working with Issues (Octo) + +### List Issues + +``` +gil List issues +``` + +### Create Issue + +``` +gic Create new issue +``` + +### Open in Browser + +``` +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: + +``` +co Choose ours +ct Choose theirs +cb Choose both +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 `gd`): + +``` +j/k Navigate files + Open diff for selected file +- Toggle stage/unstage file +S Stage all files +U Unstage all files +X Revert file changes + Toggle file panel visibility +e Focus file panel +b Toggle file panel +R Refresh file list +L Show commit log +g? Show help +``` + +**In the Diff View** (right side): + +``` + Navigate to next file +e Focus file panel +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 `e` to focus it). + +## Common Workflows + +### Feature Development + +1. Create branch (terminal): + + ```bash + git checkout -b feature/my-feature + ``` + +2. Make changes, stage hunks: + + ``` + ghs Stage hunk + ``` + +3. Review all changes: + + ``` + gd Open diffview + ``` + +4. Commit (in terminal or lazygit) + +5. Compare to main before PR: + + ``` + gm Compare to main + ``` + +6. Create PR: + + ``` + gpc Create PR + ``` + +### Code Review + +1. List PRs: + + ``` + gpl + ``` + +2. Select and open PR + +3. Start review: + + ``` + grs + ``` + +4. Navigate files, add comments + +5. Submit: + + ``` + grc + ``` + +### Investigating a Bug + +1. Find when bug was introduced: + + ``` + gf File history + ``` + +2. Navigate commits to find the change + +3. Check blame for context: + + ``` + gB Toggle blame + ``` + +4. Open commit in browser: + + ``` + 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: + +``` +ghp Preview hunk inline (shows diff in floating window) +``` + +### Understanding Diffview Modes + +Diffview has different modes: + +1. **Main Diffview** (`gd`): Shows file panel + diff view. Use this for staging/unstaging files. +2. **File History** (`gf`): Shows a picker to select commits. This is read-only. +3. **Branch History** (`gF`): Shows all commits on current branch. This is read-only. + +For staging/unstaging, always use `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 `gd` shows a picker instead of the file panel: + +1. Make sure you're using `gd` (not `gf` or `gF`) +2. `gf` opens file history (picker mode) - this is read-only +3. `gd` opens main diffview with file panel - use this for staging +4. If file panel isn't visible, press `` or `b` to toggle it +5. Press `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 `e` to focus the file panel first +3. Make sure you opened diffview with `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`. diff --git a/docs/guides/go-workflow.md b/docs/guides/go-workflow.md new file mode 100644 index 0000000..dd95617 --- /dev/null +++ b/docs/guides/go-workflow.md @@ -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 | +|-----|--------| +| `ca` | Code actions | +| `cr` | Rename symbol | +| `cf` | Format (gofmt) | + +### Go-Specific Actions + +Press `ca` for: +- Add import +- Organize imports +- Extract function +- Extract variable +- Generate interface stubs +- Add struct tags +- Fill struct + +### Diagnostics + +| Key | Action | +|-----|--------| +| `cd` | Line diagnostics | +| `]d` / `[d` | Next/prev diagnostic | +| `xx` | Toggle trouble | + +## Testing + +### Running Tests + +| Key | Action | +|-----|--------| +| `tt` | Run test at cursor | +| `tf` | Run file tests | +| `ta` | Run all tests | +| `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 + +``` +ts Toggle test summary +to Show test output +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) { + // 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 + +``` +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 | +|-----|--------| +| `db` | Toggle breakpoint | +| `dB` | Conditional breakpoint | + +### Running Debugger + +| Key | Action | +|-----|--------| +| `dc` | Continue/Start | +| `di` | Step into | +| `do` | Step over | +| `dO` | Step out | +| `dt` | Terminate | + +### DAP UI + +``` +du Toggle DAP UI +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: +``` +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: +``` +xx Toggle trouble (all diagnostics) +``` + +### Struct Tags + +Generate/modify struct tags via code actions: + +```go +type User struct { + Name string // ca → "Add json tag" + Email string +} +``` + +Result: +```go +type User struct { + Name string `json:"name"` + Email string `json:"email"` +} +``` + +## AI Assistance + +| Key | Action | +|-----|--------| +| `ka` | Ask opencode | +| `ke` | Explain code | +| `kR` | Refactor selection | +| `kt` | Generate tests | +| `kd` | Generate comments | + +### Generate Tests + +1. Select function in visual mode +2. `kt` +3. Review generated table-driven tests + +## Common Workflows + +### Starting New Feature + +1. Create/open `.go` file +2. `H` - Mark with harpoon +3. Write code, LSP handles imports +4. `tt` - Test as you go + +### Implementing Interface + +1. Write struct +2. `ca` → "Generate interface stubs" +3. Select interface to implement +4. Fill in method bodies + +### Debugging + +1. `db` - Set breakpoint +2. `dc` - Start debugger +3. Use step commands to navigate +4. `de` - Evaluate expressions +5. `dt` - Terminate when done + +### Error Handling + +Common Go pattern - AI can help: + +1. Write function that returns error +2. `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: +``` +Brs Set command: go run . +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"] + } + ``` diff --git a/docs/guides/python-workflow.md b/docs/guides/python-workflow.md new file mode 100644 index 0000000..bdb5d65 --- /dev/null +++ b/docs/guides/python-workflow.md @@ -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: + ``` + cv Open venv selector + ``` + +3. The LSP will restart with the selected venv. + +## Virtual Environment Management + +### Selecting a Virtual Environment + +``` +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 ft (float term) +python -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +``` + +Then `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 | +|-----|--------| +| `ca` | Code actions | +| `cr` | Rename symbol | +| `cf` | Format document | + +### Diagnostics + +| Key | Action | +|-----|--------| +| `cd` | Line diagnostics | +| `]d` / `[d` | Next/prev diagnostic | +| `xx` | Toggle trouble | + +## Testing with pytest + +### Running Tests + +| Key | Action | +|-----|--------| +| `tt` | Run test at cursor | +| `tf` | Run file tests | +| `ta` | Run all tests | +| `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 + +``` +ts Toggle test summary +to Show test output +tO Toggle output panel +]t / [t Jump to next/prev failed test +``` + +### Debugging Tests + +``` +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 | +|-----|--------| +| `db` | Toggle breakpoint | +| `dB` | Conditional breakpoint | + +### Running Debugger + +| Key | Action | +|-----|--------| +| `dc` | Continue/Start | +| `di` | Step into | +| `do` | Step over | +| `dO` | Step out | +| `dt` | Terminate | + +### DAP UI + +``` +du Toggle DAP UI +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 + +``` +cf Format with black/ruff +``` + +### Import Sorting + +If using isort or ruff: +``` +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 | +|-----|--------| +| `ka` | Ask opencode | +| `ke` | Explain code | +| `kR` | Refactor selection | +| `kt` | Generate tests | +| `kd` | Generate docstrings | + +### Generate Docstrings + +1. Place cursor on function +2. `kd` (or use neogen: `cn`) +3. Review and adjust + +## Common Workflows + +### Starting New Feature + +1. `cv` - Ensure correct venv +2. Create/open file +3. `H` - Mark with harpoon +4. Write code with LSP assistance +5. `tt` - Test as you go + +### Debugging an Issue + +1. `xx` - View all diagnostics +2. Navigate to issue +3. `db` - Set breakpoint +4. `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. `tt` - Run test +4. `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 + +``` +ft Open floating terminal +python Start Python REPL +``` + +### Run Current File + +``` +:!python % Run current file +``` + +Or use executor: +``` +Brs Set command: python % +Brr Run it +``` + +### Documentation + +- `K` on any symbol shows docstring +- Works with standard library and packages + +### Find TODOs + +``` +xt Show all TODO/FIXME comments +``` + +## Troubleshooting + +### LSP Not Finding Imports + +1. Check venv is selected: `cv` +2. `:LspInfo` - Verify pyright is attached +3. Check `pyrightconfig.json` or `pyproject.toml` + +### Wrong Python Version + +1. `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 diff --git a/docs/guides/snippets.md b/docs/guides/snippets.md new file mode 100644 index 0000000..43d1ac7 --- /dev/null +++ b/docs/guides/snippets.md @@ -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 ``. 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 + +``` +cS Reload all snippets +``` + +### 4. Use Snippet + +Type `cl` and press `` 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 `` / `` 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 ( +
+ {} +
+ ) +}} +]], { 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. `cS` - Reload +3. Open file of that type +4. Type trigger + `` + +### Debugging Snippets + +If snippet doesn't work: +1. Check Lua syntax (`:luafile %`) +2. Verify filetype matches +3. Check trigger isn't conflicting + +## Reloading + +``` +cS Reload all custom snippets +``` + +Changes take effect immediately after reload. diff --git a/docs/guides/typescript-workflow.md b/docs/guides/typescript-workflow.md new file mode 100644 index 0000000..de933a8 --- /dev/null +++ b/docs/guides/typescript-workflow.md @@ -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: + ``` + qs Restore session for this directory + ``` + +3. Mark important files with Harpoon: + ``` + H Add current file to harpoon + 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 | +|-----|--------| +| `ca` | Code actions (imports, fixes, refactors) | +| `cr` | Rename symbol (project-wide) | +| `cf` | Format document | + +### Common Code Actions + +When you press `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 | +|-----|--------| +| `cd` | Show line diagnostics | +| `]d` / `[d` | Next/prev diagnostic | +| `]e` / `[e` | Next/prev error | +| `xx` | Toggle trouble (diagnostics list) | + +## Testing with Vitest + +### Running Tests + +| Key | Action | +|-----|--------| +| `tt` | Run test at cursor | +| `tf` | Run all tests in file | +| `ta` | Run all tests in project | +| `tl` | Re-run last test | + +### Test Output + +| Key | Action | +|-----|--------| +| `ts` | Toggle test summary panel | +| `to` | Show test output | +| `tO` | Toggle output panel | + +### Watch Mode + +``` +tw Toggle watch mode for current file +``` + +Tests will auto-run when file changes - great for TDD! + +### Debugging Tests + +``` +td Debug test at cursor (starts DAP) +``` + +## Debugging + +### Setting Breakpoints + +| Key | Action | +|-----|--------| +| `db` | Toggle breakpoint | +| `dB` | Conditional breakpoint | +| `dl` | Log point | + +### Running Debugger + +| Key | Action | +|-----|--------| +| `dc` | Continue/Start debugging | +| `di` | Step into | +| `do` | Step over | +| `dO` | Step out | +| `dt` | Terminate | + +### DAP UI + +``` +du Toggle DAP UI (shows variables, call stack, etc.) +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 + +``` +ca Then select "Fix all ESLint problems" +``` + +Or format the file which may also run ESLint fixes: +``` +cf Format document +``` + +## Code Generation with AI + +Use opencode.nvim for AI-assisted coding: + +| Key | Action | +|-----|--------| +| `ka` | Ask opencode (general) | +| `ke` | Explain code at cursor | +| `kR` | Refactor selection (visual) | +| `kt` | Generate tests for selection | +| `kd` | Document selection | + +### Example: Generate Tests + +1. Select a function in visual mode (`V` to select lines) +2. `kt` - Generate tests +3. Review and accept generated tests + +## Common Workflows + +### Starting a New Feature + +1. `ff` - Find/create feature file +2. `H` - Mark it with harpoon +3. Write code with LSP assistance +4. `ca` - Add imports as needed +5. `tt` - Run tests as you go + +### Fixing a Bug + +1. `xx` - Open trouble to see all errors +2. Navigate to error location +3. `K` - Read documentation +4. `gd` - Go to definition if needed +5. `db` - Set breakpoint +6. `td` - Debug the test + +### Refactoring + +1. `gr` - Find all references +2. `cr` - Rename symbol +3. `ca` - Apply refactoring code actions +4. `kR` - Use AI for complex refactors + +### Code Review Prep + +1. `gm` - Compare to main branch +2. Review your changes +3. `kg` - AI review of git diff +4. Fix any issues +5. `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 + +- `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 + +``` +xt Open todo list (via todo-comments) +``` + +### Symbol Search + +``` +ss Search symbols in file +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 diff --git a/lazy-lock.json b/lazy-lock.json index 5f53f0f..d14448e 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -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" } diff --git a/lazyvim.json b/lazyvim.json index 27c3533..acad360 100644 --- a/lazyvim.json +++ b/lazyvim.json @@ -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", diff --git a/list-commands.lua b/list-commands.lua new file mode 100644 index 0000000..e0975b9 --- /dev/null +++ b/list-commands.lua @@ -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 diff --git a/lua/config/options.lua b/lua/config/options.lua index 244ebbd..2325150 100644 --- a/lua/config/options.lua +++ b/lua/config/options.lua @@ -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" diff --git a/lua/plugins/database.lua b/lua/plugins/database.lua new file mode 100644 index 0000000..358117f --- /dev/null +++ b/lua/plugins/database.lua @@ -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 = { + { "Du", "DBUIToggle", desc = "Toggle DBUI" }, + { "Da", "DBUIAddConnection", desc = "Add DB Connection" }, + { "Df", "DBUIFindBuffer", desc = "Find DB Buffer" }, + { "Dr", "DBUIRenameBuffer", desc = "Rename DB Buffer" }, + { "Dl", "DBUILastQueryInfo", 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 = { + { "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, + }, +} diff --git a/lua/plugins/general.lua b/lua/plugins/general.lua index 9730476..6cc83d6 100644 --- a/lua/plugins/general.lua +++ b/lua/plugins/general.lua @@ -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 = { + { "Rs", function() require("kulala").run() end, desc = "Send Request" }, + { "Ra", function() require("kulala").run_all() end, desc = "Send All Requests" }, + { "Rr", function() require("kulala").replay() end, desc = "Replay Last Request" }, + { "Ri", function() require("kulala").inspect() end, desc = "Inspect Request" }, + { "Rt", function() require("kulala").toggle_view() end, desc = "Toggle Headers/Body" }, + { "Rc", function() require("kulala").copy() end, desc = "Copy as cURL" }, + { "Re", function() require("kulala").set_selected_env() end, desc = "Select Environment" }, + { "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 = { + { "qs", function() require("persistence").load() end, desc = "Restore Session" }, + { "ql", function() require("persistence").load({ last = true }) end, desc = "Restore Last Session" }, + { "qd", function() require("persistence").stop() end, desc = "Don't Save Session" }, + { "qS", function() require("persistence").select() end, desc = "Select Session" }, + }, + }, + + -- Additional which-key groups + { + "folke/which-key.nvim", + opts = { + spec = { + { "R", group = "REST client" }, + { "q", group = "session" }, + }, + }, + }, } diff --git a/lua/plugins/git.lua b/lua/plugins/git.lua new file mode 100644 index 0000000..a926f8e --- /dev/null +++ b/lua/plugins/git.lua @@ -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 = { + { "gd", "DiffviewOpen", desc = "Diffview: Open" }, + { "gD", "DiffviewClose", desc = "Diffview: Close" }, + { "gf", "DiffviewFileHistory %", desc = "Diffview: File History" }, + { "gF", "DiffviewFileHistory", desc = "Diffview: Branch History" }, + { "gm", "DiffviewOpen origin/main...HEAD", desc = "Diffview: Compare to main" }, + { "gM", "DiffviewOpen origin/master...HEAD", 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 gB + date_format = "%r", -- relative time + message_when_not_committed = "Not committed yet", + virtual_text_column = 80, + }, + keys = { + { "gB", "GitBlameToggle", desc = "Toggle Git Blame" }, + { "go", "GitBlameOpenCommitURL", desc = "Open Commit in Browser" }, + { "gy", "GitBlameCopyCommitURL", desc = "Copy Commit URL" }, + }, + }, + + -- Octo.nvim keymaps (plugin already installed via lazyvim.plugins.extras.util.octo) + { + "pwntester/octo.nvim", + keys = { + -- PR operations + { "gpl", "Octo pr list", desc = "List PRs" }, + { "gpc", "Octo pr create", desc = "Create PR" }, + { "gpo", "Octo pr checkout", desc = "Checkout PR" }, + { "gpb", "Octo pr browser", desc = "Open PR in Browser" }, + { "gpr", "Octo pr ready", desc = "Mark PR Ready" }, + { "gpd", "Octo pr diff", desc = "Show PR Diff" }, + { "gpm", "Octo pr merge", desc = "Merge PR" }, + -- Issue operations + { "gil", "Octo issue list", desc = "List Issues" }, + { "gic", "Octo issue create", desc = "Create Issue" }, + { "gib", "Octo issue browser", desc = "Open Issue in Browser" }, + -- Review operations + { "grs", "Octo review start", desc = "Start Review" }, + { "grr", "Octo review resume", desc = "Resume Review" }, + { "grc", "Octo review submit", desc = "Submit Review" }, + { "grd", "Octo review discard", desc = "Discard Review" }, + }, + }, + + -- Which-key group labels for git + { + "folke/which-key.nvim", + opts = { + spec = { + { "gp", group = "pull requests" }, + { "gi", group = "issues" }, + { "gr", group = "review" }, + }, + }, + }, +} diff --git a/lua/plugins/snippets.lua b/lua/plugins/snippets.lua new file mode 100644 index 0000000..d885af2 --- /dev/null +++ b/lua/plugins/snippets.lua @@ -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 = { + { + "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", + }, + }, + }, +} diff --git a/lua/plugins/testing.lua b/lua/plugins/testing.lua index 9ef8b8c..26a370a 100644 --- a/lua/plugins/testing.lua +++ b/lua/plugins/testing.lua @@ -1,11 +1,50 @@ +-- Testing configuration with neotest +-- Supports Vitest (TypeScript), pytest (Python), and go test (Go) return { - "nvim-neotest/neotest", - dependencies = { - "marilari88/neotest-vitest", + { + "nvim-neotest/neotest", + dependencies = { + "marilari88/neotest-vitest", + }, + opts = { + adapters = { + ["neotest-vitest"] = {}, + }, + }, + keys = { + -- Run tests + { "tt", function() require("neotest").run.run() end, desc = "Run Nearest Test" }, + { "tf", function() require("neotest").run.run(vim.fn.expand("%")) end, desc = "Run File Tests" }, + { "ta", function() require("neotest").run.run(vim.uv.cwd()) end, desc = "Run All Tests" }, + { "tl", function() require("neotest").run.run_last() end, desc = "Run Last Test" }, + { "tS", function() require("neotest").run.stop() end, desc = "Stop Tests" }, + + -- Debug tests + { "td", function() require("neotest").run.run({ strategy = "dap" }) end, desc = "Debug Nearest Test" }, + { "tD", function() require("neotest").run.run({ vim.fn.expand("%"), strategy = "dap" }) end, desc = "Debug File Tests" }, + + -- Watch mode + { "tw", function() require("neotest").watch.toggle(vim.fn.expand("%")) end, desc = "Toggle Watch (File)" }, + { "tW", function() require("neotest").watch.toggle() end, desc = "Toggle Watch (Nearest)" }, + + -- Output and summary + { "ts", function() require("neotest").summary.toggle() end, desc = "Toggle Summary" }, + { "to", function() require("neotest").output.open({ enter = true, auto_close = true }) end, desc = "Show Output" }, + { "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" }, + }, }, - opts = { - adapters = { - ["neotest-vitest"] = {}, + + -- Which-key group label + { + "folke/which-key.nvim", + opts = { + spec = { + { "t", group = "test" }, + }, }, }, } diff --git a/snippets/all.lua b/snippets/all.lua new file mode 100644 index 0000000..68b9ba5 --- /dev/null +++ b/snippets/all.lua @@ -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) })), +} diff --git a/snippets/go.lua b/snippets/go.lua new file mode 100644 index 0000000..8eb0a75 --- /dev/null +++ b/snippets/go.lua @@ -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) })), +} diff --git a/snippets/python.lua b/snippets/python.lua new file mode 100644 index 0000000..2f47617 --- /dev/null +++ b/snippets/python.lua @@ -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) })), +} diff --git a/snippets/typescript.lua b/snippets/typescript.lua new file mode 100644 index 0000000..5ffccbf --- /dev/null +++ b/snippets/typescript.lua @@ -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 ( + --
+ -- {} + --
+ -- ) + -- }} + -- ]], { i(1, "Component"), i(2, "props"), i(3, "Props"), i(0) })), +}