75 Commits

Author SHA1 Message Date
847c71a194 Update projects 2025-12-23 22:52:37 +00:00
Chris
78b8bf177c Merge branch 'main' of labs.scarif.space:chris/nvim 2025-12-18 09:18:41 +00:00
Chris
4f8e722f13 Snippets 2025-12-18 09:18:00 +00:00
1f58b9f136 More snippets 2025-12-17 16:52:51 +00:00
Chris
4d3aada204 Remove textobjects 2025-12-10 14:26:27 +00:00
Chris
d53821dbf7 textobjects 2025-12-10 11:47:00 +00:00
e89dbcac87 Cool stuff 2025-12-09 23:07:24 +00:00
5bf1ec232e Super keymaps 2025-12-09 22:49:24 +00:00
aded597ffe Trying stuff 2025-12-09 22:10:16 +00:00
Chris
282301e206 Plugins 2025-12-09 16:24:08 +00:00
9bd219f053 Snippets 2025-12-09 10:35:51 +00:00
0cce7837f2 God of snippets 2025-12-08 20:18:20 +00:00
Chris
f79e89d335 Snippets 2025-12-08 16:33:11 +00:00
Chris
1f5a3d19f2 Migrate map 2025-12-08 09:29:10 +00:00
dc5d2e20ff Snippets 2025-12-08 00:52:01 +00:00
256a5695ed Super keymaps 2025-12-07 18:47:34 +00:00
2a4578e1eb Better typescript 2025-11-21 19:36:05 +00:00
52ae098ac6 Add laravel maps 2025-11-16 10:01:02 +00:00
1c96d03649 Fix some things 2025-11-15 13:55:47 +00:00
Chris
344623eaf6 Hylark settings 2025-11-12 09:21:24 +00:00
f16cb91875 Stuff 2025-11-11 22:58:02 +00:00
8e2d413e0a Yazi plugin 2025-11-11 21:51:41 +00:00
2062c442b2 Fix copilot check 2025-11-10 20:58:07 +00:00
Chris
2255489fd8 Sharing config 2025-11-10 09:19:30 +00:00
a21a1a3386 More changes 2025-11-09 23:03:51 +00:00
529cfa79c8 More project specific stuff 2025-11-07 22:10:53 +00:00
f8f6d8e776 Quicker and project specific settings 2025-11-07 14:27:25 +00:00
5016dd4ee8 Add completion ignore ft 2025-10-29 20:29:38 +00:00
37b4d8a6e4 Ignore buffer 2025-10-25 14:50:02 +01:00
Chris
d44eac696f Remove 2025-10-21 09:52:22 +01:00
Chris
5c08ce032e Rename files 2025-10-21 09:50:49 +01:00
9415b1df07 More on AI 2025-10-19 13:07:29 +01:00
406e5cfe8e AI stuff 2025-10-19 10:01:51 +01:00
Chris
6a0c90bf26 Merge branch 'main' of labs.scarif.space:chris/nvim 2025-09-08 09:22:01 +01:00
Chris
7744e83086 Update snippets 2025-09-08 09:20:42 +01:00
d4ecc5aa67 Improve debugging 2025-09-08 09:19:08 +01:00
Chris
2b1d2ed5be Update snippets 2025-08-26 18:23:17 +01:00
ca6e7089fa Type 2025-08-23 12:16:33 +01:00
4f6f50cd6f Update phpactor 2025-08-13 09:04:55 +01:00
Chris
b4821e8a52 Import with extensions 2025-07-30 16:20:50 +01:00
Chris
dc0fed3735 Cleaning up 2025-07-25 12:32:22 +01:00
Chris
b72760d868 Remove go server 2025-07-24 14:34:27 +01:00
Chris
7ec52ae64a Merge branch 'main' of labs.scarif.space:chris/nvim 2025-07-24 14:31:25 +01:00
Chris
278f31d4ea Fixing lsp 2025-07-24 14:27:38 +01:00
ebb69274ba Update aider and projects 2025-07-19 11:52:57 +01:00
ff00984c4e Reordering 2025-07-01 22:44:17 +01:00
6fb67640ef Improve dashboard 2025-07-01 22:39:59 +01:00
Chris
2dc48b5b4c More aider commands 2025-06-30 09:10:05 +01:00
379f2acd55 Update aider shortcut 2025-06-26 16:46:04 +01:00
ed1f52af11 Comment out vectorcode 2025-06-20 22:16:56 +01:00
Chris
f090b1a43e More settings 2025-05-12 17:09:14 +01:00
Chris
4975f4c459 Improvements to Code companion 2025-05-12 09:04:50 +01:00
Chris
d97fdc798f Lighten line number colors 2025-05-12 09:04:50 +01:00
6f3a5a40e5 Install Aider 2025-05-11 18:22:49 +01:00
Chris
ea9ee8267a Start on insert mode 2025-05-08 07:59:46 +01:00
Chris
b8d7a1c9ab Updating debug 2025-05-07 07:58:00 +01:00
Chris
ed622165b8 Fixing some things 2025-05-06 07:18:21 +01:00
3ba111e55c Fix typo 2025-05-05 07:28:57 +01:00
c084f286a1 Merge branch 'fix-detached' 2025-05-05 07:28:04 +01:00
acccc74130 Fixing the keymap for changing model 2025-05-05 07:27:24 +01:00
c329bab9d6 Adding MCP Hub 2025-05-05 07:25:00 +01:00
Chris
6dfef7bd87 Upgrade config 2025-05-02 20:58:31 +01:00
Chris
17e642dcd3 Adding some snippets and keymaps 2025-04-29 17:22:36 +01:00
767d2595cd Delete chroma.log 2025-04-28 09:20:31 +01:00
cfb3885afd Fix closing logic 2025-04-28 08:38:30 +01:00
Chris
f6c23ab11a Fix merge conflict 2025-04-24 12:02:34 +01:00
Chris
ca3a910401 Snippets 2025-04-24 12:01:48 +01:00
Chris
62b3b156fa More changes 2025-04-24 12:00:18 +01:00
c7d39fe79c Close vim if only non-file windows are open 2025-04-23 22:38:44 +01:00
bf83c416c5 Typo 2025-04-22 16:55:58 +01:00
0940219a08 Only use Wakatime on mac 2025-04-15 21:03:11 +01:00
Chris
eeb4e44367 Improved AI tools 2025-04-15 20:48:35 +01:00
Chris
c3574de9bc First day of development changes 2025-04-14 15:20:54 +01:00
Chris
01164c6d8b More plugin configuration 2025-04-14 11:38:42 +01:00
f2f3b1812a Loads of changes 2025-04-13 22:53:08 +01:00
44 changed files with 3144 additions and 906 deletions

View File

@@ -1 +0,0 @@
AIHUBMIX_API_KEY=

View File

@@ -0,0 +1,114 @@
{
"name": "Neovim Configuration",
"version": "1.0.0",
"system_prompt": "You are an expert Neovim configuration assistant. Help the user understand and modify their Neovim setup. Focus on clear explanations and suggest improvements when appropriate.",
"vars": {
"lua_dir": "lua"
},
"groups": [
{
"name": "Core Configuration",
"system_prompt": "These files define the core Neovim behavior including options, keymaps, and autocommands. When suggesting changes, ensure they align with Neovim best practices.",
"data": [
"core_opt",
"core_keymap",
"core_autocmd",
"core_helpers"
]
},
{
"name": "Plugin Management",
"system_prompt": "This file contains the plugin manager setup. Help the user understand plugin dependencies and installation patterns.",
"data": [
"lazy_init"
]
},
{
"name": "LSP Configuration",
"system_prompt": "These files define the Language Server Protocol setup. Help the user configure language servers, diagnostics, and code actions.",
"data": [
"lsp_config"
]
},
{
"name": "Frequently Used Plugins",
"system_prompt": "These are plugins the user frequently configures. Provide detailed explanations about their options and how they interact with the rest of the configuration.",
"data": [
"plugin_codecompanion",
"plugin_edgy",
"plugin_snacks",
"plugin_mini",
"plugin_telescope"
]
},
{
"name": "UI and Theme",
"system_prompt": "These files define the visual appearance of Neovim. Help the user understand how to customize colors and UI elements.",
"data": [
"plugin_colorscheme"
]
}
],
"data": {
"core_opt": {
"type": "file",
"path": "${lua_dir}/opt.lua",
"description": "Neovim options configuration"
},
"core_keymap": {
"type": "file",
"path": "${lua_dir}/keymap.lua",
"description": "Key mappings configuration"
},
"core_autocmd": {
"type": "file",
"path": "${lua_dir}/autocmd.lua",
"description": "Automatic commands configuration"
},
"core_helpers": {
"type": "file",
"path": "${lua_dir}/helpers.lua",
"description": "Helper functions for Neovim configuration"
},
"lazy_init": {
"type": "file",
"path": "${lua_dir}/lazy_init.lua",
"description": "Lazy plugin manager initialization"
},
"lsp_config": {
"type": "file",
"path": "${lua_dir}/plugins/lsp.lua",
"description": "LSP plugins and configuration"
},
"plugin_codecompanion": {
"type": "file",
"path": "${lua_dir}/plugins/codecompanion.lua",
"description": "CodeCompanion plugin configuration"
},
"plugin_edgy": {
"type": "file",
"path": "${lua_dir}/plugins/edgy.lua",
"description": "Edgy plugin configuration"
},
"plugin_snacks": {
"type": "file",
"path": "${lua_dir}/plugins/snacks.lua",
"description": "Snacks plugin configuration"
},
"plugin_mini": {
"type": "file",
"path": "${lua_dir}/plugins/mini.lua",
"description": "Mini plugins configuration"
},
"plugin_telescope": {
"type": "file",
"path": "${lua_dir}/plugins/telescope.lua",
"description": "Telescope fuzzy finder configuration"
},
"plugin_colorscheme": {
"type": "file",
"path": "${lua_dir}/plugins/color.lua",
"description": "Color scheme and UI appearance configuration"
}
}
}

472
init.lua
View File

@@ -11,456 +11,38 @@ require 'opt'
require 'keymap' require 'keymap'
require 'autocmd' require 'autocmd'
require 'lazy_init' require 'lazy_init'
require 'visuals'
require 'projects'
-- nnoremap <Leader>ev :tabedit $MYVIMRC<CR> require('helpers').edit_cf('v', '/init.lua')
-- The line beneath this is called `modeline`. See `:help modeline` --[[
-- vim: ts=2 sts=2 sw=2 et TODO: Neovim configurations I want to add:
- [x] Clearer line numbers (weirdly not as simple as it sounds)
- [ ] Debugging keymap that works like PHPStorm
- [ ] Improve snippet expansion (and get rid of that stupid #endsection snippet)
- [ ] Better organising of buffers when opening side panels (like AI chat and test summary)
- [ ] Close test panel when opening debugger and vice versa using edgy
- [ ] Close terminal from inside terminal buffer
- [ ] Get shift key bindings working inside tmux
- [ ] Fix ctrl+shift+a keybinding for AI actions
- [ ] Get VectorCode working
- [ ] Add LSP symbols for Pest tests
- [ ] More prompts
- [ ] Give AI better context and tools for working with Hylark
- [ ] Figure out AI workspaces
- [ ] Figure out agentic workflow
- [ ] Figure out a better way to add relevant buffers to AI
- [ ] Better inline AI assistant
- [ ] Keymap to copy visual selection to chat
- [ ] Better register management
- [ ] Figure out debug expressions
- [ ] Better keymaps for debug movements
- [ ] Chat history
]]
-- " Mappings --- {{{
-- " Editing files - {{{
-- "Make it easy to edit the vimrc file
-- " }}}
--
-- "Changing unused ctrl bindings
-- "Turn on git blame
-- nnoremap <C-S-A> <CMD>Git blame<CR>
-- "List all tags in the current buffer (replaced pageup, use CTRL-u instead)
-- nnoremap <C-Q> <CMD>CocFzfList outline<CR>
-- "List all tags in directory
-- "nnoremap <C-S-B> <CMD>Tags<CR>
-- "List all the recently opened files (replaced scroll one line up, use "k")
-- nnoremap <C-E> <CMD>History<CR>
-- "Search within the current buffer (replaced pagedown, use CTRL-d instead)
-- "nnoremap <C-F> /
-- "Search within the whole project
-- nnoremap <C-F> <CMD>Rg<CR>
-- "Move line down (uses vim-unimpaired) (replaced move down, use "j")
-- nnoremap <C-J> <C-E>
-- "Move line up (uses vim-unimpaired) (replaced move up, use "k")
-- nnoremap <C-K> <C-Y>
-- "Does not work because of legacy reasons
-- " nnoremap <C-M>
-- "Search marks (replaced "j" clone)
-- nnoremap <C-N> <CMD>Marks<CR>
-- "Search version controlled files (replaced move up, use "k")
-- nnoremap <C-P> <CMD>GFiles<CR>
-- "Search all files in directory
-- nnoremap <C-S-P> <CMD>Files<CR>
-- "Toggle file draw
-- nnoremap <C-S-Q> <CMD>CHADopen<CR>
-- "Search all snippets (uses ultisnips)
-- nnoremap <C-S> <CMD>Snippets<CR>
-- "Search git history (replaced scroll one line up, use "k")
-- nnoremap <C-Y> <CMD>Commits<CR>
-- "Search git history within current buffer/selection
-- nnoremap <C-S-Y> <CMD>BCommits<CR>
--
-- "Turn on git blame
-- inoremap <C-S-A> <CMD>Git blame<CR>
-- "List all tags in the current buffer
-- inoremap <C-Q> <CMD>BTags<CR>
-- "List all tags in directory
-- inoremap <C-S-Q> <CMD>Tags<CR>
-- "List all the recently opened files (replaced inserting characters from below)
-- inoremap <C-E> <CMD>History<CR>
-- "Search within the current buffer
-- inoremap <C-F> <Esc>/
-- "Search within the whole project
-- inoremap <C-S-F> <CMD>Rg<CR>
-- "Move line down (uses vim-unimpaired) (replaced <CR> clone)
-- inoremap <C-J> <Esc>ddpi
-- "Move line up (uses vim-unimpaired) (replaced start digraph, use command instead)
-- inoremap <C-K> <Esc>ddkPi
-- "Does not work because of legacy reasons
-- " inoremap <C-M> <CMD>Marks<CR>
-- "Add line below (replaced execute single command in normal)
-- inoremap <C-O> <Esc>o
-- "Add line above
-- inoremap <C-S-O> <Esc>O
-- "Search version controlled files (replaced autocomplete reverse)
-- inoremap <C-P> <CMD>GFiles<CR>
-- "Search all files in directory
-- inoremap <C-S-P> <CMD>Files<CR>
-- "Toggle file draw (replaces CTRL-v clone)
-- inoremap <C-S-Q> <CMD>CHADopen<CR>
-- "Search all snippets (uses ultisnips)
-- inoremap <C-S> <CMD>Snippets<CR>
-- "Search git history (replaced inserting characters from above)
-- inoremap <C-Y> <CMD>Commits<CR>
-- "Search git history within current buffer/selection
-- inoremap <C-S-Y> <CMD>BCommits<CR>
--
-- "Add simple highlight removal
-- nnoremap <Leader><Space> :nohlsearch<CR>
--
-- "Convert tabs to spaces
-- nnoremap <Leader><Tab> :retab<CR>
--
-- "Git mappings
-- nnoremap ga :Git add %<CR>
-- nnoremap gb :Git blame<CR>
-- nnoremap gC :Git commit<CR>
-- nnoremap gp :Git push<CR>
-- nnoremap gP :Git pull<CR>
--
-- "Map movement keys to Escape
-- inoremap jj <Esc>
-- inoremap jk <Esc>
-- inoremap kk <Esc>
-- inoremap hh <Esc>
--
-- "Delete a line in insert mode
-- " inoremap <C-D> <Esc>ddi
--
-- "Use semicolon instead of colon for commands
-- nnoremap ; :
-- nnoremap : ;
--
-- "Append the line with a semicolon
-- inoremap <Leader>; <Esc>mzA;<Esc>`za
-- nnoremap <Leader>; mzA;<Esc>`za<Esc>
--
-- "Easily navigate items in the quickfix menu
-- nnoremap <Leader>] :cnext<CR>
-- nnoremap <Leader>[ :cprevious<CR>
--
-- "Indent arrays
-- nnoremap <Leader>{ mzF[`a<CR><Esc>``%i<CR><Esc>`z
-- nnoremap <Leader>} mzF[`a<CR><Esc>``%i<CR><Esc>`zvi[:s/,\s*/,\r/g<CR>vi[=<Esc>`z:nohlsearch<CR>
--
-- "A command to properly indent json code
-- command! FormatJSON %!python -m json.tool
--
-- " Allow saving of files as doas
-- command! W execute 'silent! w !doas /usr/bin/tee % >/dev/null' <BAR> edit!
-- command! X execute 'silent! x !doas /usr/bin/tee % >/dev/null' <BAR> edit!
--
-- " }}}
--
-- " Plugins --- {{{
--
-- " COC --- {{{
-- " Use tab for trigger completion with characters ahead and navigate
-- " NOTE: There's always complete item selected by default, you may want to enable
-- " no select by `"suggest.noselect": true` in your configuration file
-- " NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
-- " other plugin before putting this into your config
-- inoremap <silent><expr> <TAB>
-- \ coc#pum#visible() ? coc#pum#next(1) :
-- \ CheckBackspace() ? "\<Tab>" :
-- \ coc#refresh()
-- inoremap <expr><S-TAB> coc#pum#visible() ? coc#pum#prev(1) : "\<C-h>"
--
-- " Make <CR> to accept selected completion item or notify coc.nvim to format
-- " <C-g>u breaks current undo, please make your own choice
-- inoremap <silent><expr> <CR> coc#pum#visible() ? coc#pum#confirm()
-- \: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
--
-- function! CheckBackspace() abort
-- let col = col('.') - 1
-- return !col || getline('.')[col - 1] =~# '\s'
-- endfunction
--
-- if has('nvim')
-- inoremap <silent><expr> <c-space> coc#refresh()
-- else
-- inoremap <silent><expr> <c-@> coc#refresh()
-- endif
--
-- " Use `[g` and `]g` to navigate diagnostics
-- " Use `:CocDiagnostics` to get all diagnostics of current buffer in location list
-- nmap <silent> [g <Plug>(coc-diagnostic-prev)
-- nmap <silent> ]g <Plug>(coc-diagnostic-next)
--
-- " GoTo code navigation
-- nmap <silent> gd <Plug>(coc-definition)
-- nmap <silent> gy <Plug>(coc-type-definition)
-- nmap <silent> gi <Plug>(coc-implementation)
-- nmap <silent> gr <Plug>(coc-references)
--
-- " Use K to show documentation in preview window
-- nnoremap <silent> K :call ShowDocumentation()<CR>
--
-- function! ShowDocumentation()
-- if CocAction('hasProvider', 'hover')
-- call CocActionAsync('doHover')
-- else
-- call feedkeys('K', 'in')
-- endif
-- endfunction
--
-- " Highlight the symbol and its references when holding the cursor
-- autocmd CursorHold * silent call CocActionAsync('highlight')
--
-- " Symbol renaming
-- nmap <leader>rn <Plug>(coc-rename)
--
-- " Formatting selected code
-- xmap <leader>f <Plug>(coc-format-selected)
-- nmap <leader>f <Plug>(coc-format-selected)
--
-- augroup mygroup
-- autocmd!
-- " Setup formatexpr specified filetype(s)
-- autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
-- " Update signature help on jump placeholder
-- autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
-- augroup end
--
-- " Applying code actions to the selected code block
-- " Example: `<leader>aap` for current paragraph
-- xmap <leader>a <Plug>(coc-codeaction-selected)
-- nmap <leader>a <Plug>(coc-codeaction-selected)
--
-- " Remap keys for applying code actions at the cursor position
-- nmap <leader>ac <Plug>(coc-codeaction-cursor)
-- " Remap keys for apply code actions affect whole buffer
-- nmap <leader>as <Plug>(coc-codeaction-source)
-- " Apply the most preferred quickfix action to fix diagnostic on the current line
-- nmap <leader>qf <Plug>(coc-fix-current)
--
-- " Remap keys for applying refactor code actions
-- nmap <silent> <leader>re <Plug>(coc-codeaction-refactor)
-- xmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
-- nmap <silent> <leader>r <Plug>(coc-codeaction-refactor-selected)
--
-- " Run the Code Lens action on the current line
-- nmap <leader>cl <Plug>(coc-codelens-action)
--
-- " Map function and class text objects
-- " NOTE: Requires 'textDocument.documentSymbol' support from the language server
-- xmap if <Plug>(coc-funcobj-i)
-- omap if <Plug>(coc-funcobj-i)
-- xmap af <Plug>(coc-funcobj-a)
-- omap af <Plug>(coc-funcobj-a)
-- xmap ic <Plug>(coc-classobj-i)
-- omap ic <Plug>(coc-classobj-i)
-- xmap ac <Plug>(coc-classobj-a)
-- omap ac <Plug>(coc-classobj-a)
--
-- " Remap <C-f> and <C-b> to scroll float windows/popups
-- " if has('nvim-0.4.0') || has('patch-8.2.0750')
-- " nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
-- " nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
-- " inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
-- " inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
-- " vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
-- " vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
-- " endif
--
-- " Use CTRL-S for selections ranges
-- " Requires 'textDocument/selectionRange' support of language server
-- nmap <silent> <C-s> <Plug>(coc-range-select)
-- xmap <silent> <C-s> <Plug>(coc-range-select)
--
-- " Add `:Format` command to format current buffer
-- command! -nargs=0 Format :call CocActionAsync('format')
--
-- " Add `:Fold` command to fold current buffer
-- command! -nargs=? Fold :call CocAction('fold', <f-args>)
--
-- " Add `:OR` command for organize imports of the current buffer
-- command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
--
-- " Add (Neo)Vim's native statusline support
-- " NOTE: Please see `:h coc-status` for integrations with external plugins that
-- " provide custom statusline: lightline.vim, vim-airline
-- set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
--
--
-- " Mappings for CoCList
-- " Show all diagnostics
-- nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
-- " Manage extensions
-- nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
-- " Show commands
-- nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
-- " Find symbol of current document
-- nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
-- " Search workspace symbols
-- nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
-- " Do default action for next item
-- nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
-- " Do default action for previous item
-- nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
-- " Resume latest coc list
-- nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>
--
-- " }}}
--
-- " Emmet --- {{{
-- " Toggle emmet completion using <Tab> with <Leader>em
-- let g:emmet_completion = 0
-- function ToggleEmmet()
-- if g:emmet_completion
-- echo "Emmet completion off!"
-- let g:user_emmet_expandabbr_key=','
-- iunmap <Tab>
-- let g:emmet_completion = 0
-- else
-- echo "Emmet completion on!"
-- let g:user_emmet_expandabbr_key='<Tab>'
-- imap <Expr> <Tab> emmet#expandAbbrIntelligent("\<Tab>")
-- let g:emmet_completion = 1
-- endif
-- endfunction
-- nnoremap <Leader>em :call ToggleEmmet()<CR>
-- " }}}
--
-- " Markdown --- {{{
-- " Conceal markdown text
-- set conceallevel=3
-- " }}}
--
-- " AutoPairs --- {{{
-- let g:AutoPairsFlyMode = 0
-- let g:AutoPairsShortcutBackInsert = '<M-b>' " Use <M-B> to insert the closing parentheses if it jumped ahead by mistake
-- " }}}
--
-- " CHADTree --- {{{
-- let g:chadtree_settings = {
-- \ 'theme': {
-- \ 'icon_glyph_set': 'devicons',
-- \ 'text_colour_set': 'env',
-- \ 'icon_colour_set': 'github',
-- \ "discrete_colour_map": {
-- \ "black": "#21222c",
-- \ "red": "#ff5555",
-- \ "green": "#50fa7b",
-- \ "yellow": "#f1fa8c",
-- \ "blue": "#bd93f9",
-- \ "magenta": "#ff79c6",
-- \ "cyan": "#8be9fd",
-- \ "white": "#f8f8f2",
-- \ "bright_black": "#6272a4",
-- \ "bright_red": "#ff6e6e",
-- \ "bright_green": "#69ff94",
-- \ "bright_yellow": "#ffffa5",
-- \ "bright_blue": "#d6acff",
-- \ "bright_magenta": "#ff92df",
-- \ "bright_cyan": "#a4ffff",
-- \ "bright_white": "#ffffff"
-- \ }
-- \ }
-- \ }
-- " }}}
--
-- " Commentary --- {{{
-- " function s:set_commentary_format()
-- " echo "running command"
-- " if &filetype =~ 'vue\|html\|svelte'
-- " if searchpair('<\(script\|style\)', '', '</\(script\|style\)>', 'Wn')
-- " let b:commentary_format="// %s"
-- " else
-- " let b:commentary_format=&commentstring
-- " endif
-- " endif
-- " endfunction
--
-- " xnoremap gc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap gc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " onoremap gc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap gcc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap cgc :call <SID>set_commentary_format()<CR><Plug>Commentary
-- " nnoremap cgu :call <SID>set_commentary_format()<CR><Plug>Commentary<Plug>Commentary
-- " }}}
--
-- " Easymotion --- {{{
-- let g:EasyMotion_do_mapping = 0 " Disable default mappings
--
-- map <Leader> <Plug>(easymotion-prefix)
-- " Jump to anywhere you want with minimal keystrokes, with just one key binding.
-- " `s{char}{label}
-- nmap s <Plug>(easymotion-overwin-f)
--
-- " Turn on case-insensitive feature
-- let g:EasyMotion_smartcase = 1
--
-- " JK motions: Line motions
-- map <Leader>j <Plug>(easymotion-j)
-- map <Leader>k <Plug>(easymotion-k)
-- " }}}
--
-- " }}}
--
-- " PHP --- {{{
-- " function! RunPHPUnitTest()
-- " cd %:p:h
-- " normal! T yw
-- " let result = system("phpunit --filter " . @" . " " . bufname("%"))
-- " split __PHPUnit_Result__
-- " normal! ggdG
-- " setlocal buftype=nofile
-- " call append(0, split(result, '\v\n'))
-- " cd -
-- " endfunction
--
-- " nnoremap <F12> :call RunPHPUnitTest()<cr>
-- " }}}
--
-- " Moving around --- {{{
-- "Use capital H and L to move to the start and end of lines
-- nnoremap H ^
-- nnoremap L $
--
-- " }}}
--
-- " Operator mappings --- {{{
-- onoremap in( :<C-U>normal! f(vi(<CR>
-- onoremap il( :<C-U>normal! F)vi(<CR>
-- onoremap an( :<C-U>normal! f(va(<CR>
-- onoremap al( :<C-U>normal! F)va(<CR>
-- onoremap an{ :<C-U>normal! f{vi{<CR>
-- onoremap al{ :<C-U>normal! F}vi<CR>
-- " }}}
--
-- " Abbreviations --- {{{
-- iabbrev adn and
-- iabbrev waht what
-- iabbrev tehn then
-- iabbrev tihs this
-- iabbrev teh the
-- iabbrev Teh The
-- " }}}
--
-- " Auto-Commands --- {{{ -- " Auto-Commands --- {{{
-- --
-- "Automatically source the config files on save.
-- augroup autosourcing
-- autocmd!
-- autocmd BufWritePost $MYVIMRC source % "Source the vimrc file
-- augroup END
--
-- "Fold vimrc and zshrc files on open
-- augroup autofolding
-- autocmd!
-- autocmd BufReadPost $MYVIMRC :setlocal foldlevelstart=0
-- autocmd FileType vim setlocal foldmethod=marker
-- autocmd BufReadPost zsh :setlocal foldlevelstart=0
-- autocmd FileType zsh setlocal foldmethod=marker
-- augroup END
--
-- "Set commentary formats
-- function s:setcommentary()
-- if &commentstring =~ '/\*\s*%s\s*\*/'
-- let b:commentary_format="// %s"
-- endif
-- endfunction
--
-- augroup autocomment
-- autocmd!
-- autocmd FileType * call <SID>setcommentary()
-- augroup END
--
-- "Automatically save files
-- augroup autosaving
-- autocmd!
-- autocmd FocusLost * silent! wa "Save all files when moving away from the window
-- autocmd InsertLeave * silent! wa "Save all files when leaving insert mode
-- autocmd TextChanged * silent! wa "Save all files when text is changed
-- augroup END
--
-- augroup modes -- augroup modes
-- autocmd! -- autocmd!
-- autocmd FocusLost * call feedkeys("\<Esc>") "Go to normal mode when moving away -- autocmd FocusLost * call feedkeys("\<Esc>") "Go to normal mode when moving away

View File

@@ -12,4 +12,108 @@ vim.api.nvim_create_autocmd('TextYankPost', {
end, end,
}) })
local autosave_group = vim.api.nvim_create_augroup('autosaving', { clear = true })
vim.api.nvim_create_autocmd('FocusLost', {
group = autosave_group,
pattern = '*',
command = 'silent! wa', -- Save all files when moving away from the window
})
vim.api.nvim_create_autocmd('InsertLeave', {
group = autosave_group,
pattern = '*',
command = 'silent! wa', -- Save all files when leaving insert mode
})
vim.api.nvim_create_autocmd('SwapExists', {
desc = 'Always choose to delete the swap file, files are saved automatically',
group = vim.api.nvim_create_augroup('NoSwaps', { clear = true }),
callback = function(args)
vim.cmd("let v:swapchoice = 'd'")
end,
})
-- vim.api.nvim_create_autocmd('TextChanged', {
-- group = autosave_group,
-- pattern = '*',
-- command = 'silent! wa', -- Save all files when text is changed
-- })
vim.api.nvim_create_autocmd('User', {
pattern = 'OilActionsPost',
callback = function(event)
if event.data.actions.type == 'move' then
Snacks.rename.on_rename_file(event.data.actions.src_url, event.data.actions.dest_url)
end
end,
})
local fidget_group = vim.api.nvim_create_augroup('CodeCompanionFidgetHooks', { clear = true })
vim.api.nvim_create_autocmd({ 'User' }, {
pattern = 'CodeCompanionRequestStarted',
group = fidget_group,
callback = function(event)
local FidgetHelper = require 'utils.fidget_helper'
-- Pass event instead of request if the callback receives the full event object
local handle = FidgetHelper:create_progress_handle(event)
FidgetHelper:store_progress_handle(event.data.id, handle)
end,
})
vim.api.nvim_create_autocmd({ 'User' }, {
pattern = 'CodeCompanionRequestFinished',
group = fidget_group,
callback = function(event)
local FidgetHelper = require 'utils.fidget_helper'
local handle = FidgetHelper:pop_progress_handle(event.data.id)
if handle then
FidgetHelper:report_exit_status(handle, event)
handle:finish()
end
end,
})
-- vim.api.nvim_create_autocmd('BufEnter', {
-- callback = function(event)
-- local windows = vim.api.nvim_list_wins()
--
-- for _, window in ipairs(windows) do
-- local bufnr = vim.api.nvim_win_get_buf(window)
-- local ft = vim.api.nvim_get_option_value('filetype', { buf = bufnr })
-- if vim.api.nvim_get_option_value('buflisted', { buf = bufnr })
-- or ft == 'oil'
-- or ft == 'snacks_dashboard' then
-- return
-- end
-- end
-- vim.cmd 'qa'
-- end,
-- })
local modes_group = vim.api.nvim_create_augroup('modes', { clear = true })
vim.api.nvim_create_autocmd('FocusLost', {
group = modes_group,
pattern = '*',
command = 'call feedkeys("\\<Esc>")',
})
vim.api.nvim_create_autocmd('BufNewFile', {
group = modes_group,
pattern = '*',
command = 'call feedkeys("i")',
})
-- Reload LuaSnip snippets when saving files in the snippets directory
local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets'
vim.api.nvim_create_autocmd('BufWritePost', {
pattern = snippets_dir .. '/*.json', -- Adjust the path to match your snippets directory
desc = 'Reload LuaSnip snippets on save',
callback = function()
require('luasnip.loaders.from_vscode').lazy_load { paths = { snippets_dir } }
vim.notify('Snippets reloaded!', vim.log.levels.INFO)
end,
})
require('helpers').edit_cf('a', '/lua/autocmd.lua') require('helpers').edit_cf('a', '/lua/autocmd.lua')

View File

@@ -9,7 +9,50 @@ helpers.edit_cf = function(map, path)
end, { desc = 'Edit ' .. path .. ' in a new tab' }) end, { desc = 'Edit ' .. path .. ' in a new tab' })
end end
helpers.map = function(keys, func, opts, mode)
mode = mode or 'n'
vim.keymap.set(mode, keys, func, opts)
end
helpers.edit_cf('h', '/lua/helpers.lua') helpers.edit_cf('h', '/lua/helpers.lua')
---@param opts? { cmd?: string }
helpers.open_term = function(opts)
opts = opts or { cmd = '' }
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_option_value('bufhidden', 'wipe', { buf = buf })
vim.api.nvim_set_option_value('modifiable', false, { buf = buf })
local height = math.ceil(vim.o.lines * 0.9)
local width = math.ceil(vim.o.columns * 0.9)
local win = vim.api.nvim_open_win(buf, true, {
style = 'minimal',
relative = 'editor',
width = width,
height = height,
row = math.ceil((vim.o.lines - height) / 2),
col = math.ceil((vim.o.columns - width) / 2),
border = 'single',
})
vim.api.nvim_set_current_win(win)
vim.fn.jobstart(opts.cmd, {
term = true,
on_exit = function(_, _, _)
if vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true)
end
end,
})
vim.cmd.startinsert()
end
helpers.has_copilot = function()
return vim.fn.getenv('COPILOT_API_KEY') ~= vim.NIL
end
return helpers return helpers
-- nnoremap <Leader>ev :tabedit $MYVIMRC<CR> -- nnoremap <Leader>ev :tabedit $MYVIMRC<CR>

View File

@@ -1,9 +1,11 @@
-- [[ Basic Keymaps ]] -- Basic Keymaps
-- See `:help vim.keymap.set()` -- See `:help vim.keymap.set()`
local helpers = require 'helpers'
-- Swap : and ; around -- Swap : and ; around
vim.keymap.set('n', ':', ';') vim.keymap.set({ 'n', 'v' }, ':', ';')
vim.keymap.set('n', ';', ':') vim.keymap.set({ 'n', 'v' }, ';', ':')
-- Clear highlights on search when pressing <Esc> in normal mode -- Clear highlights on search when pressing <Esc> in normal mode
-- See `:help hlsearch` -- See `:help hlsearch`
@@ -12,6 +14,10 @@ vim.keymap.set('n', '<Esc>', '<cmd>nohlsearch<CR>')
-- Diagnostic keymaps -- Diagnostic keymaps
vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' }) vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagnostic [Q]uickfix list' })
vim.keymap.set({ 'n', 'v' }, 'c', '"zc', { desc = 'Change without copying to clipboard' })
vim.keymap.set({ 'n', 'v' }, 'x', '"zx', { desc = 'Cut without copying to clipboard' })
vim.keymap.set('v', 'p', '"zdP', { desc = 'Paste over selection without yanking replaced text' })
-- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier -- Exit terminal mode in the builtin terminal with a shortcut that is a bit easier
-- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which -- for people to discover. Otherwise, you normally need to press <C-\><C-n>, which
-- is not what someone will guess without a bit more experience. -- is not what someone will guess without a bit more experience.
@@ -20,24 +26,348 @@ vim.keymap.set('n', '<leader>q', vim.diagnostic.setloclist, { desc = 'Open diagn
-- or just use <C-\><C-n> to exit terminal mode -- or just use <C-\><C-n> to exit terminal mode
vim.keymap.set('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Exit terminal mode' }) vim.keymap.set('t', '<Esc><Esc>', '<C-\\><C-n>', { desc = 'Exit terminal mode' })
-- TIP: Disable arrow keys in normal mode vim.keymap.set('n', '<Leader>c', function()
-- vim.keymap.set('n', '<left>', '<cmd>echo "Use h to move!!"<CR>') vim.treesitter.inspect_tree()
-- vim.keymap.set('n', '<right>', '<cmd>echo "Use l to move!!"<CR>') end, { desc = 'Treesitter' })
-- vim.keymap.set('n', '<up>', '<cmd>echo "Use k to move!!"<CR>')
-- vim.keymap.set('n', '<down>', '<cmd>echo "Use j to move!!"<CR>') vim.keymap.set('n', '<C-S-D>', function()
local node = vim.treesitter.get_node {}
local range = { vim.treesitter.get_node_range(node) }
vim.api.nvim_win_set_cursor(0, { range[3] + 1, range[4] - 1 })
vim.fn.setpos("'x", { 0, range[1] + 1, range[2] + 1, 0 })
vim.cmd.normal 'v`x'
end, { desc = 'Select surrounding treesitter node' })
vim.keymap.set('v', '<C-S-D>', function()
local start = vim.api.nvim_win_get_cursor(0)
local start_row, start_column
if start[2] == 0 then
start_row = start[1] - 1
start_column = 0
else
start_row = start[1]
start_column = start[2] - 1
end
vim.api.nvim_win_set_cursor(0, { start_row, start_column })
local node = vim.treesitter.get_node {}
local range = { vim.treesitter.get_node_range(node) }
vim.api.nvim_win_set_cursor(0, { range[3] + 1, range[4] - 1 })
vim.fn.setpos("'x", { 0, range[1] + 1, range[2] + 1, 0 })
vim.cmd.normal 'i'
vim.cmd.normal 'v`x'
end, { desc = 'Select surrounding treesitter node' })
local swappable_nodes = { 'argument', 'array_element_initializer', 'simple_parameter', 'string', 'integer', 'member_call_expression', 'method_declaration' }
local function closest_swappable_node(node)
while node and not vim.list_contains(swappable_nodes, node:type()) and (not node:next_named_sibling() or not node:prev_named_sibling()) do
node = node:parent()
end
return node
end
vim.keymap.set({ 'n' }, '<C-S-h>', function()
local node = closest_swappable_node(vim.treesitter.get_node())
if not node then
return
end
local prev_node = node:prev_named_sibling()
while prev_node and not vim.list_contains(swappable_nodes, prev_node:type()) do
prev_node = prev_node:prev_named_sibling()
end
if prev_node == nil then
return
end
require('nvim-treesitter.ts_utils').swap_nodes(node, prev_node, 0, true)
end, { desc = 'Swap with node to the left' })
vim.keymap.set({ 'n' }, '<C-S-l>', function()
local node = closest_swappable_node(vim.treesitter.get_node())
if not node then
return
end
local next_node = node:next_named_sibling()
while next_node and not vim.list_contains(swappable_nodes, next_node:type()) do
next_node = next_node:next_named_sibling()
end
if next_node == nil then
return
end
require('nvim-treesitter.ts_utils').swap_nodes(node, next_node, 0, true)
end, { desc = 'Swap with node to the right' })
vim.keymap.set('n', '<C-S-j>', 'ddp', { desc = 'Move line down' })
vim.keymap.set('n', '<C-S-k>', 'ddkP', { desc = 'Move line up' })
vim.keymap.set('v', '<C-S-j>', 'do<Esc>p`[v`]', { desc = 'Move selection down' })
vim.keymap.set('v', '<C-S-k>', 'dkO<Esc>p`[v`]', { desc = 'Move selection up' })
-- Keybinds to make split navigation easier. -- Keybinds to make split navigation easier.
-- Use CTRL+<hjkl> to switch between windows -- Use CTRL+<hjkl> to switch between windows
-- --
-- See `:help wincmd` for a list of all window commands -- See `:help wincmd` for a list of all window commands
local function win_or_treesj(dir_cmd, desc)
return function()
local cur = vim.api.nvim_get_current_win()
vim.cmd('wincmd ' .. dir_cmd)
if vim.api.nvim_get_current_win() == cur then
local ok, treesj = pcall(require, 'treesj')
if ok and type(treesj.toggle) == 'function' then
treesj.toggle()
end
end
end, { desc = desc }
end
vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' }) vim.keymap.set('n', '<C-h>', '<C-w><C-h>', { desc = 'Move focus to the left window' })
vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' }) vim.keymap.set('n', '<C-l>', '<C-w><C-l>', { desc = 'Move focus to the right window' })
vim.keymap.set('n', '<C-j>', '<C-w><C-j>', { desc = 'Move focus to the lower window' }) vim.keymap.set('n', '<C-j>', (win_or_treesj)('j', 'Move focus to the lower window or treesj.toggle()'))
vim.keymap.set('n', '<C-k>', '<C-w><C-k>', { desc = 'Move focus to the upper window' }) vim.keymap.set('n', '<C-k>', (win_or_treesj)('k', 'Move focus to the upper window or treesj.toggle()'))
vim.keymap.set('n', '<C-S-h>', '<C-w>H', { desc = 'Move window to the left' }) vim.keymap.set({ 'i' }, '<C-J>', function()
vim.keymap.set('n', '<C-S-l>', '<C-w>L', { desc = 'Move window to the right' }) local ls = require 'luasnip'
vim.keymap.set('n', '<C-S-j>', '<C-w>J', { desc = 'Move window to the lower' }) if ls.choice_active() then
vim.keymap.set('n', '<C-S-k>', '<C-w>K', { desc = 'Move window to the upper' }) ls.change_choice(1)
end
end, { desc = 'Toggle snippet choice', silent = true })
vim.keymap.set({ 'i' }, '<C-k>', function()
local ls = require 'luasnip'
if ls.choice_active() then
ls.change_choice(-1)
end
end, { desc = 'Toggle snippet choice', silent = true })
vim.keymap.set({ 'i', 's' }, '<C-L>', function()
local ls = require 'luasnip'
if ls.expandable() then
ls.expand()
elseif ls.in_snippet() then
ls.jump(1)
end
end, { desc = 'Expand snippet', silent = true })
vim.keymap.set({ 'i', 's' }, '<C-H>', function()
local ls = require 'luasnip'
if ls.in_snippet() then
ls.jump(-1)
end
end, { desc = 'Go back a snippet slot', silent = true })
vim.keymap.set('n', '<Leader>.', '<Cmd>tabnext<CR>', { desc = 'Next tab' })
vim.keymap.set('n', '<Leader>,', '<Cmd>tabprevious<CR>', { desc = 'Previous tab' })
-- Overriding CTRL mappings because some of them are stupid
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-B>', '<CMD>Git blame<CR>', { desc = 'Git blame' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-Q>', '<CMD>Telescope lsp_document_symbols<CR>', { desc = 'Show symbols in current document' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-Q>', '<CMD>Telescope lsp_workspace_symbols<CR>', { desc = 'Show symbols in workspace' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-E>', '<CMD>Telescope oldfiles<CR>', { desc = 'Show recently opened files' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-P>', function()
require('telescope.builtin').find_files {
show_untracked = true,
no_ignore = false,
hidden = true,
}
end, { desc = 'Find all files' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-P>', function()
require('telescope.builtin').find_files {
show_untracked = true,
no_ignore = true,
hidden = true,
}
end, { desc = 'Find all files' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-f>', function()
require('telescope.builtin').live_grep {
hidden = true,
}
end, { desc = 'Search within the whole project' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-Y>', '<CMD>Telescope quickfix<CR>', { desc = 'Show quickfix list' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-Y>', '<CMD>Telescope quickfixhistory<CR>', { desc = 'Show quickfix history' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-A>', '<CMD>CodeCompanionChat Toggle<CR>', { desc = 'Open AI Actions' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-A>', '<CMD>CodeCompanionActions<CR>', { desc = 'Open AI Actions' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S>', function()
require('snacks').scratch()
end, { desc = 'Open scratchpad' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-S>', function()
require('snacks').scratch.select()
end, { desc = 'Open scratchpad buffers' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-T>', function()
require('snacks').terminal.toggle()
end, { desc = 'Open terminal' })
-- Editing helpers
vim.keymap.set('i', '<C-O>', '<Esc>o', { desc = 'Add line below' })
vim.keymap.set('i', '<C-S-O>', '<Esc>O', { desc = 'Add line above' })
local esc_keys = { 'jj', 'jk', 'kk' }
for _, key in ipairs(esc_keys) do
vim.keymap.set('i', key, '<Esc>', { desc = 'Exit insert mode' })
end
vim.keymap.set('i', '<C-D>', '<Esc>ddi', { desc = 'Delete line' })
vim.keymap.set('i', '<Leader>;', '<Esc>mzA;<Esc>`za', { desc = 'Append a semicolon' })
vim.keymap.set('n', '<Leader>;', 'mzA;<Esc>`za', { desc = 'Append a semicolon' })
vim.keymap.set('n', '<Leader>{', 'mzF[`a<CR><Esc>``%i<CR><Esc>`z', { desc = 'Indent an array' })
vim.keymap.set('n', '<Leader>}', 'mzF[`a<CR><Esc>``%i<CR><Esc>`zvi[:s/,\\s*/,\\r/g<CR>vi[=<Esc>`z:nohlsearch<CR>', { desc = 'Indent an array some other way?' })
-- Git mappings
vim.keymap.set('n', '<Leader>gb', '<CMD>Git blame<CR>', { desc = 'Git blame' })
vim.keymap.set('n', '<Leader>gd', '<CMD>Git diff<CR>', { desc = 'Git diff' })
vim.keymap.set('n', '<Leader>gdc', '<CMD>Git diff --cached<CR>', { desc = 'Git diff' })
vim.keymap.set('n', '<Leader>G', function()
helpers.open_term { cmd = 'lazygit' }
end, { desc = 'Git' })
-- Add keymaps for diff mode
vim.api.nvim_create_autocmd('BufEnter', {
callback = function()
if vim.wo.diff then
-- Keymaps for navigating hunks
vim.api.nvim_buf_set_keymap(0, 'n', '<Tab>', ']c', { noremap = true, silent = true, desc = 'Next hunk in diff mode' })
vim.api.nvim_buf_set_keymap(0, 'n', '<S-Tab>', '[c', { noremap = true, silent = true, desc = 'Previous hunk in diff mode' })
-- Keymaps for resolving conflicts
vim.api.nvim_buf_set_keymap(0, 'n', '<leader>dl', ':diffget LOCAL<CR>', { noremap = true, silent = true, desc = 'Get LOCAL changes' })
vim.api.nvim_buf_set_keymap(0, 'n', '<leader>dr', ':diffget REMOTE<CR>', { noremap = true, silent = true, desc = 'Get REMOTE changes' })
end
end,
})
-- AI mappings
-- vim.keymap.set('v', '<Leader>ae', '<CMD>CodeCompanion<CR>', { desc = 'Edit selection with AI' })
-- vim.keymap.set('n', '<Leader>ac', '<CMD>CodeCompanionCmd<CR>', { desc = 'Run Neovim commands with AI' })
vim.api.nvim_create_autocmd('FileType', {
pattern = 'codecompanion',
callback = function()
vim.keymap.set('i', '<Enter>', function()
require('codecompanion').last_chat():submit()
end, { buffer = true, desc = 'Use enter to send the message' })
vim.keymap.set('i', '<S-Enter>', '<Enter>', { buffer = true, desc = 'Use shift enter to start a new line' })
vim.keymap.set('n', '<Enter>', 'G', { buffer = true, desc = 'Use enter in normal mode to go to the end of the chat' })
local models = { vim.env.DEFAULT_AI_MODEL, vim.env.REASONING_MODEL, vim.env.FAST_MODEL }
-- Loop through models and create keymaps for each
for i, model in ipairs(models) do
vim.keymap.set('n', '<C-' .. i .. '>', 'mzggj0W"_C' .. model .. '<Esc>`z', { desc = 'Switch to ' .. model })
vim.keymap.set('i', '<C-' .. i .. '>', '<Esc>mzggj0W"_C' .. model .. '<Esc>`za', { desc = 'Switch to ' .. model })
end
end,
})
-- Search mappings
vim.keymap.set('n', '<Leader>sGb', '<CMD>Telescope git_branches<CR>', { desc = 'Search git branches' })
vim.keymap.set('n', '<Leader>sGc', '<CMD>Telescope git_commits<CR>', { desc = 'Search git history' })
vim.keymap.set('n', '<Leader>sGh', '<CMD>Telescope git_bcommits<CR>', { desc = 'Search git history within current buffer/selection' })
vim.keymap.set('n', '<Leader>sGs', '<CMD>Telescope git_status<CR>', { desc = 'Search git status' })
vim.keymap.set('n', '<Leader>sGS', '<CMD>Telescope git_stash<CR>', { desc = 'Search git stash' })
-- Misc
vim.keymap.set('n', '<Leader>]', '<CMD>cnext<CR>', { desc = 'Next item in quickfix list' })
vim.keymap.set('n', '<Leader>[', '<CMD>cprevious<CR>', { desc = 'Previous item in quickfix list' })
vim.keymap.set('n', 'gd', '<CMD>Telescope lsp_definitions<CR>', { desc = 'Go to definition' })
local function open_test()
require('neotest').summary.open()
require('neotest').output_panel.open()
end
-- Testing
-- local test_maps = {
-- {
-- keys = { '<F12>', '<Leader>tn' },
-- action = function()
-- require('neotest').run.run()
-- open_test()
-- end,
-- desc = 'Run nearest test',
-- },
-- {
-- keys = { '<F9>', '<Leader>ta' },
-- action = function()
-- require('neotest').run.run { suite = true }
-- open_test()
-- end,
-- desc = 'Run all tests in the project',
-- },
-- {
-- keys = { '<F11>', '<Leader>tp' },
-- action = function()
-- require('neotest').run.run_last()
-- open_test()
-- end,
-- desc = 'Run previous test again',
-- },
-- {
-- keys = { '<F10>', '<Leader>td' },
-- action = function()
-- local dap = require 'dap'
-- if dap.session() == nil then
-- dap.continue()
-- end
-- require('dapui').open()
-- local neotest = require 'neotest'
-- local bufnr = vim.api.nvim_get_current_buf()
-- local row = vim.api.nvim_win_get_cursor(0)[1] - 1
--
-- local adapters = neotest.state.adapter_ids()
-- local found = false
--
-- for _, adapter_id in ipairs(adapters) do
-- local tree = neotest.state.positions(adapter_id, { buffer = bufnr })
-- if tree then
-- local nearest = require('neotest.lib.positions').nearest(tree, row)
-- if nearest and nearest:data().type ~= 'file' then
-- neotest.run.run()
-- found = true
-- break
-- end
-- end
-- end
--
-- if not found then
-- neotest.run.run_last()
-- end
-- end,
-- desc = 'Run last test with debugger',
-- },
-- }
--
-- for _, map_info in ipairs(test_maps) do
-- for _, key in ipairs(map_info.keys) do
-- vim.keymap.set('n', key, map_info.action, { desc = map_info.desc })
-- end
-- end
-- vim.keymap.set('n', '<Leader>tf', function()
-- require('neotest').run.run(vim.fn.expand '%')
-- open_test()
-- end, { desc = 'Run all tests in the current file' })
-- vim.keymap.set('n', '<Leader>tc', function()
-- require('neotest').summary.close()
-- require('neotest').output_panel.close()
-- end, { desc = 'Close test panels' })
-- vim.keymap.set('i', '<Tab>', function()
-- local copilot = require 'copilot.suggestion'
-- local ls = require 'luasnip'
-- if copilot.is_visible() then
-- vim.api.nvim_echo({{'Accepting copilot suggestion'}}, false, {})
-- copilot.accept()
-- copilot.dismiss()
-- elseif ls.jumpable(1) then
-- vim.api.nvim_echo({{'Jumping in snippet'}}, false, {})
-- ls.jump()
-- else
-- vim.api.nvim_echo({{'Inserting tab'}}, false, {})
-- vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Tab>', true, true, true), 'n', true)
-- end
-- end, { desc = 'Luasnip accept copilot or jump forward' })
-- Leaving this commented out, I will try the format command instead
-- "A command to properly indent json code
-- command! FormatJSON %!python -m json.tool
-- Edit the snippet file for the current buffer filetype or the snippets
-- directory if the file does not exist
vim.keymap.set('n', '<Leader>es', function()
local ft = vim.bo.filetype
if ft == 'vue' then
ft = 'javascript'
end
local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets'
local snippets_file = snippets_dir .. '/' .. ft .. '.lua'
vim.cmd('tabedit ' .. snippets_file)
end, { desc = 'Edit snippets file' })
require('helpers').edit_cf('k', '/lua/keymap.lua') require('helpers').edit_cf('k', '/lua/keymap.lua')

View File

@@ -82,4 +82,6 @@ vim.opt.autowriteall = true
-- Add lines at 80 and 120 columns -- Add lines at 80 and 120 columns
vim.opt.colorcolumn = '80,120' vim.opt.colorcolumn = '80,120'
vim.opt.iskeyword:remove '$'
require('helpers').edit_cf('o', '/lua/opt.lua') require('helpers').edit_cf('o', '/lua/opt.lua')

3
lua/plugins/actually.lua Normal file
View File

@@ -0,0 +1,3 @@
return {
'mong8se/actually.nvim',
}

View File

@@ -0,0 +1,72 @@
-- AI code completion
if vim.fn.getenv 'COPILOT_API_KEY' ~= vim.NIL then
return {
'zbirenbaum/copilot.lua',
event = 'InsertEnter',
config = function()
require('copilot').setup {
suggestion = {
enabled = true,
auto_trigger = true,
keymap = {
accept = '<A-a>',
},
},
filetypes = {
yaml = true,
markdown = true,
gitcommit = true,
gitrebase = true,
},
}
end,
}
end
return {
'milanglacier/minuet-ai.nvim',
dependencies = { 'nvim-lua/plenary.nvim' },
config = function()
require('minuet').setup {
virtualtext = {
auto_trigger_ft = { '*' },
auto_trigger_ignore_ft = { 'help', 'TelescopePrompt', 'codecompanion', 'snacks_input' },
keymap = {
accept = '<A-A>',
accept_line = '<A-a>',
-- accept n lines (prompts for number)
-- e.g. "A-z 2 CR" will accept 2 lines
accept_n_lines = '<A-z>',
-- Cycle to prev completion item, or manually invoke completion
prev = '<A-[>',
-- Cycle to next completion item, or manually invoke completion
next = '<A-]>',
dismiss = '<A-e>',
},
},
provider = 'openai_compatible',
request_timeout = 3,
throttle = 500, -- Increase to reduce costs and avoid rate limits
debounce = 400, -- Increase to reduce costs and avoid rate limits
n_completions = 1,
before_cursor_filter_length = 10,
provider_options = {
openai_compatible = {
api_key = 'COMPLETION_OPENAI_API_KEY',
end_point = vim.env.COMPLETION_OPENAI_API_BASE .. '/v1/chat/completions',
model = vim.env.COMPLETION_MODEL,
name = 'Openrouter',
optional = {
max_tokens = 300,
top_p = 0.9,
provider = {
-- Prioritize throughput for faster completion
sort = 'throughput',
},
},
},
},
}
end,
}

67
lua/plugins/aider.lua Normal file
View File

@@ -0,0 +1,67 @@
require('helpers').edit_cf('pa', '/lua/plugins/aider.lua')
local change_model_function = function(model)
return function()
require('nvim_aider').api.send_command('/model', model)
end
end
return {
'GeorgesAlkhouri/nvim-aider',
cmd = 'Aider',
keys = {
{ '<leader>a/', '<cmd>Aider toggle<cr>', desc = 'Toggle Aider' },
{ '<leader>as', '<cmd>Aider send<cr>', desc = 'Send to Aider', mode = { 'n', 'v' } },
{ '<leader>ac', '<cmd>Aider command<cr>', desc = 'Aider Commands' },
{ '<leader>ab', '<cmd>Aider buffer<cr>', desc = 'Send Buffer' },
{ '<leader>a+', '<cmd>Aider add<cr>', desc = 'Add File' },
{ '<leader>a-', '<cmd>Aider drop<cr>', desc = 'Drop File' },
{ '<leader>ar', '<cmd>Aider add readonly<cr>', desc = 'Add Read-Only' },
{ '<leader>aR', '<cmd>Aider reset<cr>', desc = 'Reset Session' },
-- Example nvim-tree.lua integration if needed
{ '<leader>a+', '<cmd>AiderTreeAddFile<cr>', desc = 'Add File from Tree to Aider', ft = 'NvimTree' },
{ '<leader>a-', '<cmd>AiderTreeDropFile<cr>', desc = 'Drop File from Tree from Aider', ft = 'NvimTree' },
{ '<leader>am4', change_model_function 'gpt-4.1', desc = 'Switch aider model to GPT-4.1' },
{ '<leader>amo', change_model_function 'openai/o4-mini', desc = 'Switch aider model to o4-mini' },
{ '<leader>amg', change_model_function 'openai/gemini-2.5-pro', desc = 'Switch aider model to Gemini 2.5 Pro' },
{ '<leader>ams', change_model_function 'openai/claude-sonnet-4', desc = 'Switch aider model to Claude Sonnet 4' },
},
dependencies = {
'folke/snacks.nvim',
--- The below dependencies are optional
'catppuccin/nvim',
'nvim-tree/nvim-tree.lua',
--- Neo-tree integration
{
'nvim-neo-tree/neo-tree.nvim',
opts = function(_, opts)
-- Example mapping configuration (already set by default)
-- opts.window = {
-- mappings = {
-- ["+"] = { "nvim_aider_add", desc = "add to aider" },
-- ["-"] = { "nvim_aider_drop", desc = "drop from aider" }
-- ["="] = { "nvim_aider_add_read_only", desc = "add read-only to aider" }
-- }
-- }
require('nvim_aider.neo_tree').setup(opts)
end,
},
},
config = function()
require('nvim_aider').setup {
aider_cmd = 'aider',
args = {
'--config=$HOME/.config/aider/aider.yaml',
'--env-file=$(pwd)/aider.env',
'--watch',
'--architect',
},
auto_reload = true,
win = {
wo = { winbar = 'Aider' },
style = 'nvim_aider',
position = 'bottom',
},
}
end,
}

View File

@@ -2,7 +2,7 @@
-- https://github.com/windwp/nvim-autopairs -- https://github.com/windwp/nvim-autopairs
return { return {
"windwp/nvim-autopairs", 'windwp/nvim-autopairs',
event = "InsertEnter", event = 'InsertEnter',
opts = {}, opts = {},
} }

View File

@@ -1,72 +0,0 @@
require('helpers').edit_cf('pa', '/lua/plugins/avante.lua')
return {
'yetone/avante.nvim',
event = 'VeryLazy',
version = false, -- Never set this value to "*"! Never!
opts = {
-- add any opts here
-- for example
provider = 'aihubmix',
cursor_applying_provider = 'aihubmix_llama_versatile',
aihubmix = {
-- model = 'claude-3-7-sonnet-20250219',
model = 'DeepSeek-V3',
},
openai = {
endpoint = 'https://api.openai.com/v1',
model = 'gpt-4o', -- your desired model (or use gpt-4o, etc.)
timeout = 30000, -- Timeout in milliseconds, increase this for reasoning models
temperature = 0,
max_completion_tokens = 8192, -- Increase this to include reasoning tokens (for reasoning models)
--reasoning_effort = "medium", -- low|medium|high, only used for reasoning models
},
vendors = {
aihubmix_llama_versatile = {
__inherited_from = 'aihubmix',
model = 'llama-3.3-70b-versatile',
},
},
},
-- if you want to build from source then do `make BUILD_FROM_SOURCE=true`
build = 'make',
-- build = "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" -- for windows
dependencies = {
'nvim-treesitter/nvim-treesitter',
'stevearc/dressing.nvim',
'nvim-lua/plenary.nvim',
'MunifTanjim/nui.nvim',
--- The below dependencies are optional,
'echasnovski/mini.pick', -- for file_selector provider mini.pick
'nvim-telescope/telescope.nvim', -- for file_selector provider telescope
'hrsh7th/nvim-cmp', -- autocompletion for avante commands and mentions
'ibhagwan/fzf-lua', -- for file_selector provider fzf
'nvim-tree/nvim-web-devicons', -- or echasnovski/mini.icons
'zbirenbaum/copilot.lua', -- for providers='copilot'
{
-- support for image pasting
'HakonHarnes/img-clip.nvim',
event = 'VeryLazy',
opts = {
-- recommended settings
default = {
embed_image_as_base64 = false,
prompt_for_file_name = false,
drag_and_drop = {
insert_mode = true,
},
-- required for Windows users
use_absolute_path = true,
},
},
},
{
-- Make sure to set this up properly if you have lazy=true
'MeanderingProgrammer/render-markdown.nvim',
opts = {
file_types = { 'markdown', 'Avante' },
},
ft = { 'markdown', 'Avante' },
},
},
}

View File

@@ -4,34 +4,7 @@ return {
event = 'VimEnter', event = 'VimEnter',
version = '1.*', version = '1.*',
dependencies = { dependencies = {
-- Compatibility for Avante with Blink (it typically only works with cmp) -- 'L3MON4D3/LuaSnip',
'Kaiser-Yang/blink-cmp-avante',
-- Snippet Engine
{
'L3MON4D3/LuaSnip',
version = '2.*',
build = (function()
-- Build Step is needed for regex support in snippets.
-- This step is not supported in many windows environments.
-- Remove the below condition to re-enable on windows.
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
return
end
return 'make install_jsregexp'
end)(),
dependencies = {
-- `friendly-snippets` contains a variety of premade snippets.
-- See the README about individual language/framework/plugin snippets:
-- https://github.com/rafamadriz/friendly-snippets
{
'rafamadriz/friendly-snippets',
config = function()
require('luasnip.loaders.from_vscode').lazy_load()
end,
},
},
opts = {},
},
'folke/lazydev.nvim', 'folke/lazydev.nvim',
}, },
--- @module 'blink.cmp' --- @module 'blink.cmp'
@@ -59,7 +32,8 @@ return {
-- <c-k>: Toggle signature help -- <c-k>: Toggle signature help
-- --
-- See :h blink-cmp-config-keymap for defining your own keymap -- See :h blink-cmp-config-keymap for defining your own keymap
preset = 'default', preset = 'enter',
['<C-K>'] = false,
-- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see:
-- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps
@@ -68,24 +42,27 @@ return {
appearance = { appearance = {
-- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font' -- 'mono' (default) for 'Nerd Font Mono' or 'normal' for 'Nerd Font'
-- Adjusts spacing to ensure icons are aligned -- Adjusts spacing to ensure icons are aligned
nerd_font_variant = 'mono', nerd_font_variant = 'normal',
}, },
completion = { completion = {
-- By default, you may press `<c-space>` to show the documentation. -- By default, you may press `<c-space>` to show the documentation.
-- Optionally, set `auto_show = true` to show the documentation after a delay. -- Optionally, set `auto_show = true` to show the documentation after a delay.
documentation = { auto_show = false, auto_show_delay_ms = 500 }, documentation = { auto_show = true, auto_show_delay_ms = 200 },
}, },
sources = { sources = {
default = { 'avante', 'lsp', 'path', 'snippets', 'lazydev' }, default = { 'lsp', 'path', 'snippets', 'lazydev' },
providers = { providers = {
lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 }, lazydev = { module = 'lazydev.integrations.blink', score_offset = 100 },
avante = { module = 'blink-cmp-avante', name = 'Avante', opts = {} }, -- avante = { module = 'blink-cmp-avante', name = 'Avante', opts = {} },
},
per_filetype = {
codecompanion = { 'codecompanion' },
}, },
}, },
snippets = { preset = 'luasnip' }, -- snippets = { preset = 'luasnip' },
-- Blink.cmp includes an optional, recommended rust fuzzy matcher, -- Blink.cmp includes an optional, recommended rust fuzzy matcher,
-- which automatically downloads a prebuilt binary when enabled. -- which automatically downloads a prebuilt binary when enabled.

View File

@@ -0,0 +1,339 @@
return {
'olimorris/codecompanion.nvim',
config = function()
require('codecompanion').setup {
adapters = {
http = {
default = function()
if (require('helpers').has_copilot()) then
return require('codecompanion.adapters').extend('copilot', {
schema = {
model = {
default = vim.env.DEFAULT_AI_MODEL,
},
max_tokens = {
default = 1000000,
},
}
})
end
return require('codecompanion.adapters').extend('openai_compatible', {
env = {
url = vim.env.DEFAULT_OPENAI_API_BASE,
api_key = vim.env.DEFAULT_OPENAI_API_KEY,
chat_url = '/v1/chat/completions',
models_endpoint = '/v1/models',
},
schema = {
model = {
default = vim.env.DEFAULT_AI_MODEL,
},
max_tokens = {
default = 1000000,
},
},
})
end,
},
},
display = {
chat = {
show_settings = true,
start_in_insert_mode = false,
},
},
strategies = {
chat = {
adapter = 'default',
slash_commands = {
-- codebase = require('vectorcode.integrations').codecompanion.chat.make_slash_command(),
},
tools = {
-- vectorcode = {
-- description = 'Run VectorCode to retrieve the project context.',
-- callback = require('vectorcode.integrations').codecompanion.chat.make_tool(),
-- },
['cmd_runner'] = {
opts = {
requires_approval = false,
},
},
},
roles = {
---@type string|fun(adapter: CodeCompanion.Adapter): string
llm = function(adapter)
return 'CodeCompanion (' .. adapter.formatted_name .. ': ' .. adapter.parameters.model .. ')'
end,
},
keymaps = {
send = {
modes = { n = '<C-s>', i = '<C-s>' },
},
close = {
modes = { n = '<C-c>', i = '<C-c>' },
},
},
},
inline = {
adapter = {
name = 'default',
model = vim.env.FAST_MODEL,
},
},
cmd = {
adapter = {
name = 'default',
model = vim.env.FAST_MODEL,
},
},
},
extensions = {
mcphub = {
callback = 'mcphub.extensions.codecompanion',
opts = {
show_result_in_chat = true,
make_vars = true,
make_slash_commands = true,
},
},
},
system_prompt = function(opts)
local language = opts.language or 'English'
return string.format(
[[You are an AI programming assistant named "CodeCompanion". You are currently plugged into the Neovim text editor on a user's machine.
Your core tasks include:
- Answering general programming questions.
- Explaining how the code in a Neovim buffer works.
- Reviewing the selected code from a Neovim buffer.
- Generating unit tests for the selected code.
- Proposing fixes for problems in the selected code.
- Scaffolding code for a new workspace.
- Finding relevant code to the user's query.
- Proposing fixes for test failures.
- Answering questions about Neovim.
- Running tools.
You must:
- Follow the user's requirements carefully and to the letter.
- Keep your answers short and impersonal, especially if the user's context is outside your core tasks.
- Minimize additional prose unless clarification is needed.
- Use Markdown formatting in your answers.
- Include the programming language name at the start of each Markdown code block.
- Avoid including line numbers in code blocks.
- Avoid wrapping the whole response in triple backticks.
- Only return code that's directly relevant to the task at hand. You may omit code that isnt necessary for the solution.
- Avoid using H1, H2 or H3 headers in your responses as these are reserved for the user.
- Use actual line breaks in your responses; only use "\n" when you want a literal backslash followed by 'n'.
- All non-code text responses must be written in the %s language indicated.
- Multiple, different tools can be called as part of the same response.
- Use full path names when using tools to read and modify files.
When given a task:
1. Think step-by-step and, unless the user requests otherwise or the task is very simple, describe your plan in detailed pseudocode.
2. Output the final code in a single code block, ensuring that only relevant code is included.
3. End your response with a short suggestion for the next user turn that directly supports continuing the conversation.
4. Provide exactly one complete reply per conversation turn.
5. If necessary, execute multiple tools in a single turn.]],
language
)
end,
prompt_library = {
['Code Expert'] = {
strategy = 'chat',
description = 'Get some special advice from an LLM.',
opts = {
mapping = '<Leader>ce',
modes = { 'v' },
short_name = 'expert',
auto_submit = true,
stop_context_insertion = true,
user_prompt = true,
},
prompts = {
{
role = 'system',
content = function(context)
return 'I want you to act as a senior'
.. context.filetype
.. 'developer I will ask you specific questions and I want you to return concise explanations and codeblock examples.'
end,
},
{
role = 'user',
content = function(context)
local text = require('codecompanion.helpers.actions').get_code(context.start_line, context.end_line)
return 'I have the following code:\n\n```' .. context.filetype .. '\n' .. text .. '\n```\n\n'
end,
opts = {
contains_code = true,
},
},
},
},
['Games Master'] = {
strategy = 'chat',
description = 'A personal Games Master Assistant.',
opts = {
user_prompt = false,
},
prompts = {
{
role = 'system',
content = [[
You are a personal Games Master Assistant. You are currently plugged in to the Neovim text editor on a user's machine.
Your core tasks include:
- Crafting engaging role playing sessions
- Building immersive and authentic worlds
- Creating compelling characters for the players to interact with and drive the story
- Reviewing session summaries and building on them
- Providing advice on how to bring sessions to life
- Create exciting encounters to challenge the players
- Encounters can be combat, social, or exploration based
- There should always be a story reason for the encounter
- Combine player character backgrounds and motivations into the world
- Build tension and drama into the game
- Ensure each session provides opportunities for the players to engage with and drive the story
You must:
- Follow the user's requirements carefully and to the letter.
- Keep answers focused on the task at hand.
- Provide original ideas and suggestions.
- Use Markdown formatting in your answers.
- Use actual line breaks instead of '\n' in your response to begin new lines.
- Use '\n' only when you want a literal backslash followed by a character 'n'.
- All responses must be written in English.
- Multiple, different tools can be called as part of the same response.
- Help sessions be fast paced and fun.
- Ensure there are multiple soltuions to each problem.
- Avoid railroading the players.
When given a task:
1. Consider the existing world and characters. Use tools to gather information that may be relevant.
2. Provide exactly one complete reply per conversation turn.
3. If necessary, execute multiple tools in a single turn.
]],
},
{
role = 'user',
content = '',
},
},
},
['PHPStan Fixer'] = {
strategy = 'workflow',
description = 'Use a workflow to fix PHPStan errors until there are none left.',
opts = {
short_name = 'phpstan',
},
prompts = {
{
{
name = 'Run PHPStan',
role = 'user',
opts = { auto_submit = false },
content = function()
-- Enable turbo mode!!!
vim.g.codecompanion_auto_tool_mode = true
return [[PHPStan is a static analysis tool for PHP. It is currently reporting errors in the code. Your task is to fix these errors and run PHPStan again until there are no errors left.
First of all use the @cmd_runner tool to run the `composer type-check` command. This will run PHPStan and output type errors in the code.]]
end,
},
},
{
{
name = 'Fetch files',
role = 'user',
opts = { auto_submit = false },
content = function()
-- Enable turbo mode!!!
vim.g.codecompanion_auto_tool_mode = true
return 'PHPStan has reported errors. Look at the output and see where the files are reported. Use the @mcp tool to read all the offending files so you can implement the fixes.'
end,
},
},
{
{
name = 'Fix errors and run',
role = 'user',
opts = { auto_submit = false },
content = function()
-- Enable turbo mode!!!
vim.g.codecompanion_auto_tool_mode = true
return [[### Instructions
Now you have the errors and the appropriate context you can fix the errors.
### Steps to Follow
You are required to analyse the PHPStan errors and write code to fix them.
Reason through the errors and write out the possible causes and fixes for each.
1. Then use the @mcp tool to update the files with the fixes. When editing files use the full path name including the project name /Users/chris/Code/Sites/hylark/
2. After editing the files use the @cmd_runner tool again to run the `composer type-check` command to see if any errors remain.
We'll repeat this cycle until there are no errors. Ensure no deviations from these steps.
### Tips for fixing PHPStan errors
- Do not ignore the errors
- Use Webmozart Assert library to narrow types
- Most errors are due to missing docblocks or calling methods/parameters on types that PHPStan cannot infer
- Use fully qualified namespaces for classes in doc blocks
- The code is working so fixes should not change the behaviour of the code
- There are some custom types in this project that help define types
- closure<T> creates T|Closure(): T, you can add a second argument to specify the depth so closure<T, 2> creates T|Closure(): T|Closure(): (Closure(): T). This is useful because GraphQL queries can return closures.
- promise<T> creates T|SyncPromise<T>, as with closure, you can add a second argument for depth. You can also add a third argument if T is an array to allow adding promises to each value, so promise<array{a: int}, 1, 1> will create array{a: int}|SyncPromise<array{a: int}>|array{a: SyncPromise<int>}|SyncPromise<array{a: SyncPromise<int>}>. This is useful because GraphQL queries can return promises and arrays of promises.
- GraphQL schema types (these should only be used in the Query classes)
- GArgs<T> will look at the GraphQL schema and create an array type for the arguments of a field on one of the root types (Query or Mutation)
- GArgs<TType, TField> will create a type for the arguments of a field on a type
- GType<T> will create an type for a specific GraphQL type, input, interface, or enum
- GVal<T> will create a type for the return value of a field on one of the root types (Query or Mutation)
- GVal<TType, TField> will create a type for the return value of a field on a type
- pick<T, TKeys> will create an array from T with only the keys in TKeys (e.g. pick<array{a: int, b: int, c: int}, 'a'|'b'> will create array{a: int, b: int})
- except<T, TKeys> works like pick only it excludes the keys in TKeys (e.g. except<array{a: int, b: int, c: int}, 'a'|'b'> will create array{c: int})
- union<T, U> creates a union array of T and U (e.g. union<array{a: int}, array{b: int}> will create array{a: int, b: int})]]
end,
},
},
{
{
name = 'Repeat On Failure',
role = 'user',
opts = { auto_submit = false },
-- Scope this prompt to the cmd_runner tool
condition = function()
return _G.codecompanion_current_tool == 'cmd_runner'
end,
-- Repeat until the tests pass, as indicated by the testing flag
-- which the cmd_runner tool sets on the chat buffer
repeat_until = function(chat)
-- Check if the last message in the chat buffer contains "[ERROR] found"
local messages = chat.messages
local last_message = messages[#messages]
if last_message and last_message.role == 'assistant' then
local content = last_message.content
return not content:find '[ERROR] found'
end
return true
end,
content = 'PHPStan is still reporting errors. Edit the code to fix the errors and run PHPStan again.',
},
},
},
},
},
}
end,
dependencies = {
'nvim-lua/plenary.nvim',
'nvim-treesitter/nvim-treesitter',
-- 'Davidyz/VectorCode',
'ravitemer/mcphub.nvim',
},
}

View File

@@ -12,13 +12,14 @@ return { -- Autoformat
desc = '[F]ormat buffer', desc = '[F]ormat buffer',
}, },
}, },
opts = { config = function()
require('conform').setup({
notify_on_error = false, notify_on_error = false,
format_on_save = function(bufnr) format_on_save = function(bufnr)
-- Disable "format_on_save lsp_fallback" for languages that don't -- Disable "format_on_save lsp_fallback" for languages that don't
-- have a well standardized coding style. You can add additional -- have a well standardized coding style. You can add additional
-- languages here or re-enable it for the disabled ones. -- languages here or re-enable it for the disabled ones.
local disable_filetypes = { c = true, cpp = true } local disable_filetypes = { c = true, cpp = true, vue = true, js = true }
if disable_filetypes[vim.bo[bufnr].filetype] then if disable_filetypes[vim.bo[bufnr].filetype] then
return nil return nil
else else
@@ -30,11 +31,14 @@ return { -- Autoformat
end, end,
formatters_by_ft = { formatters_by_ft = {
lua = { 'stylua' }, lua = { 'stylua' },
php = { 'pint' },
-- Conform can also run multiple formatters sequentially -- Conform can also run multiple formatters sequentially
-- python = { "isort", "black" }, -- python = { "isort", "black" },
-- --
-- You can use 'stop_after_first' to run the first available formatter from the list -- You can use 'stop_after_first' to run the first available formatter from the list
-- javascript = { "prettierd", "prettier", stop_after_first = true }, -- javascript = { "prettierd", "prettier", stop_after_first = true },
}, },
}, log_level = vim.log.levels.DEBUG
})
end
} }

View File

@@ -1,3 +1,4 @@
require('helpers').edit_cf('pd', '/lua/plugins/debug.lua')
-- debug.lua -- debug.lua
-- --
-- Shows how to use the DAP plugin to debug your code. -- Shows how to use the DAP plugin to debug your code.
@@ -25,42 +26,42 @@ return {
keys = { keys = {
-- Basic debugging keymaps, feel free to change to your liking! -- Basic debugging keymaps, feel free to change to your liking!
{ {
'<F5>', '<Leader>dc',
function() function()
require('dap').continue() require('dap').continue()
end, end,
desc = 'Debug: Start/Continue', desc = 'Debug: Start/Continue',
}, },
{ {
'<F1>', '<Leader>di',
function() function()
require('dap').step_into() require('dap').step_into()
end, end,
desc = 'Debug: Step Into', desc = 'Debug: Step Into',
}, },
{ {
'<F2>', '<Leader>do',
function() function()
require('dap').step_over() require('dap').step_over()
end, end,
desc = 'Debug: Step Over', desc = 'Debug: Step Over',
}, },
{ {
'<F3>', '<Leader>du',
function() function()
require('dap').step_out() require('dap').step_out()
end, end,
desc = 'Debug: Step Out', desc = 'Debug: Step Out',
}, },
{ {
'<leader>b', '<leader>db',
function() function()
require('dap').toggle_breakpoint() require('dap').toggle_breakpoint()
end, end,
desc = 'Debug: Toggle Breakpoint', desc = 'Debug: Toggle Breakpoint',
}, },
{ {
'<leader>B', '<leader>dB',
function() function()
require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ') require('dap').set_breakpoint(vim.fn.input 'Breakpoint condition: ')
end, end,
@@ -68,11 +69,11 @@ return {
}, },
-- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception. -- Toggle to see last session result. Without this, you can't see session output in case of unhandled exception.
{ {
'<F7>', '<Leader>ds',
function() function()
require('dapui').toggle() require('dapui').toggle()
end, end,
desc = 'Debug: See last session result.', desc = 'Debug: Toggle UI',
}, },
}, },
config = function() config = function()
@@ -86,7 +87,28 @@ return {
-- You can provide additional configuration to the handlers, -- You can provide additional configuration to the handlers,
-- see mason-nvim-dap README for more information -- see mason-nvim-dap README for more information
handlers = {}, handlers = {
function(config)
require('mason-nvim-dap').default_setup(config)
end,
php = function(config)
config.configurations = {
{
type = 'php',
request = 'launch',
name = 'Listen for XDebug',
port = 9003,
log = true,
-- pathMappings = {
-- ['/var/www/html/'] = vim.fn.getcwd() .. '/',
-- },
hostname = '0.0.0.0',
},
}
require('mason-nvim-dap').default_setup(config)
end,
},
-- You'll need to check that you have the required things installed -- You'll need to check that you have the required things installed
-- online, please don't ask me how to install them :) -- online, please don't ask me how to install them :)
@@ -96,6 +118,28 @@ return {
}, },
} }
dap.adapters.php = {
type = 'executable',
command = 'node',
args = {
vim.fn.expand '$MASON/packages/php-debug-adapter/extension/out/phpDebug.js',
},
}
dap.configurations.php = {
{
type = 'php',
request = 'launch',
name = 'Listen for XDebug',
port = 9003,
log = true,
-- pathMappings = {
-- ['/var/www/html/'] = vim.fn.getcwd() .. '/',
-- },
hostname = '0.0.0.0',
},
}
-- Dap UI setup -- Dap UI setup
-- For more information, see |:help nvim-dap-ui| -- For more information, see |:help nvim-dap-ui|
dapui.setup { dapui.setup {
@@ -105,29 +149,73 @@ return {
icons = { expanded = '', collapsed = '', current_frame = '*' }, icons = { expanded = '', collapsed = '', current_frame = '*' },
controls = { controls = {
icons = { icons = {
pause = '', pause = '',
play = '', play = '',
step_into = '', step_into = '󰆹',
step_over = '', step_over = '󰆷',
step_out = '', step_out = '󰆸',
step_back = 'b', step_back = '',
run_last = '▶▶', run_last = '',
terminate = '', terminate = '',
disconnect = '', disconnect = '',
},
},
element_mappings = {
stacks = {
open = '<CR>',
expand = 'o',
}, },
}, },
} }
-- Change breakpoint icons -- Change breakpoint icons
-- vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' }) vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' })
-- vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' }) vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' })
-- local breakpoint_icons = vim.g.have_nerd_font local breakpoint_icons = vim.g.have_nerd_font
-- and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' } and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' }
-- or { Breakpoint = '●', BreakpointCondition = '⊜', BreakpointRejected = '⊘', LogPoint = '◆', Stopped = '⭔' } or { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' }
-- for type, icon in pairs(breakpoint_icons) do for type, icon in pairs(breakpoint_icons) do
-- local tp = 'Dap' .. type local tp = 'Dap' .. type
-- local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak' local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak'
-- vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl }) vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl })
end
local function get_php_ini_dir()
local handle = io.popen 'php --ini 2>/dev/null'
if not handle then
return nil
end
local result = handle:read '*a'
handle:close()
local dir = result:match 'Scan for additional .ini files in:%s+([^\n]+)'
if dir and dir:find '%(none%)' == nil then
return vim.trim(dir)
end
return nil
end
local function enable_xdebug()
local ini_dir = get_php_ini_dir()
if not ini_dir then
return
end
os.execute(string.format('mv "%s/20-xdebug.ini.disabled" "%s/20-xdebug.ini" 2>/dev/null', ini_dir, ini_dir))
end
local function disable_xdebug()
local ini_dir = get_php_ini_dir()
if not ini_dir then
return
end
os.execute(string.format('mv "%s/20-xdebug.ini" "%s/20-xdebug.ini.disabled" 2>/dev/null', ini_dir, ini_dir))
end
dap.listeners.after.event_initialized['xdebug_enable'] = enable_xdebug
dap.listeners.before.event_terminated['xdebug_disable'] = disable_xdebug
dap.listeners.before.event_exited['xdebug_disable'] = disable_xdebug
-- dap.listeners.after.event_output['neotest_display'] = function(_, body)
-- require('neotest').output.open { enter = true, last = true }
-- end -- end
dap.listeners.after.event_initialized['dapui_config'] = dapui.open dap.listeners.after.event_initialized['dapui_config'] = dapui.open

3
lua/plugins/dotenv.lua Normal file
View File

@@ -0,0 +1,3 @@
return {
'ellisonleao/dotenv.nvim',
}

101
lua/plugins/edgy.lua Normal file
View File

@@ -0,0 +1,101 @@
return {
"folke/edgy.nvim",
event = "VeryLazy",
init = function()
vim.opt.laststatus = 3
vim.opt.splitkeep = "screen"
end,
opts = {
bottom = {
-- toggleterm / lazyterm at the bottom with a height of 40% of the screen
{
ft = "toggleterm",
size = { height = 0.4 },
-- exclude floating windows
filter = function(buf, win)
return vim.api.nvim_win_get_config(win).relative == ""
end,
},
{
ft = "lazyterm",
title = "LazyTerm",
size = { height = 0.4 },
filter = function(buf)
return not vim.b[buf].lazyterm_cmd
end,
},
{
ft = "snack_terminal",
size = { height = 0.4 },
title = "%{b:snacks_terminal.id}: %{b:term_title}",
filter = function(_buf, win)
return vim.w[win].snacks_win
and vim.w[win].snacks_win.position == pos
and vim.w[win].snacks_win.relative == "editor"
and not vim.w[win].trouble_preview
end,
},
"Trouble",
{ ft = "qf", title = "QuickFix" },
{
ft = "help",
size = { height = 20 },
-- only show help buffers
filter = function(buf)
return vim.bo[buf].buftype == "help"
end,
},
{ ft = "spectre_panel", size = { height = 0.4 } },
},
left = {
-- Neo-tree filesystem always takes half the screen height
{
title = "Neo-Tree",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "filesystem"
end,
size = { height = 0.5 },
},
{
title = "Neo-Tree Git",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "git_status"
end,
pinned = true,
collapsed = true, -- show window as closed/collapsed on start
open = "Neotree position=right git_status",
},
{
title = "Neo-Tree Buffers",
ft = "neo-tree",
filter = function(buf)
return vim.b[buf].neo_tree_source == "buffers"
end,
pinned = true,
collapsed = true, -- show window as closed/collapsed on start
open = "Neotree position=top buffers",
},
{
title = function()
local buf_name = vim.api.nvim_buf_get_name(0) or "[No Name]"
return vim.fn.fnamemodify(buf_name, ":t")
end,
ft = "Outline",
pinned = true,
open = "SymbolsOutlineOpen",
},
-- any other neo-tree windows
"neo-tree",
},
right = {
{
title = 'Code Companion',
ft = 'codecompanion',
size = { width = 0.3 },
}
}
},
}

3
lua/plugins/fidget.lua Normal file
View File

@@ -0,0 +1,3 @@
return {
'j-hui/fidget.nvim',
}

10
lua/plugins/git_blame.lua Normal file
View File

@@ -0,0 +1,10 @@
return {
'f-person/git-blame.nvim',
event = 'VeryLazy',
opts = {
enabled = true, -- if you want to enable the plugin
message_template = ' <summary> • <date> • <author> • <<sha>>', -- template for the blame message, check the Message template section for more options
date_format = '%m-%d-%Y %H:%M:%S', -- template for the date, check Date format section for more options
virtual_text_column = 1, -- virtual text start column, check Start virtual text at column section for more options
},
}

View File

@@ -1,3 +1,4 @@
require('helpers').edit_cf('pg', '/lua/plugins/gitsigns.lua')
-- Adds git related signs to the gutter, as well as utilities for managing changes -- Adds git related signs to the gutter, as well as utilities for managing changes
-- See `:help gitsigns` -- See `:help gitsigns`
return { return {

View File

@@ -4,9 +4,13 @@ return {
event = { 'BufReadPre', 'BufNewFile' }, event = { 'BufReadPre', 'BufNewFile' },
config = function() config = function()
local lint = require 'lint' local lint = require 'lint'
lint.linters_by_ft = { -- lint.linters_by_ft = {
markdown = { 'markdownlint' }, -- markdown = { 'markdownlint' },
} -- }
lint.linters_by_ft['markdown'] = nil
lint.linters_by_ft['javascript'] = nil
lint.linters_by_ft['vue'] = nil
lint.linters_by_ft['html'] = nil
-- To allow other plugins to add linters to require('lint').linters_by_ft, -- To allow other plugins to add linters to require('lint').linters_by_ft,
-- instead set linters_by_ft like this: -- instead set linters_by_ft like this:

View File

@@ -1,99 +1,41 @@
-- Main LSP Configuration -- Main LSP Configuration
require('helpers').edit_cf('pl', '/lua/plugins/lsp.lua')
return { return {
'neovim/nvim-lspconfig', 'neovim/nvim-lspconfig',
dependencies = { dependencies = {
-- Automatically install LSPs and related tools to stdpath for Neovim
-- Mason must be loaded before its dependents so we need to set it up here.
-- NOTE: `opts = {}` is the same as calling `require('mason').setup({})`
{ 'williamboman/mason.nvim', opts = {} }, { 'williamboman/mason.nvim', opts = {} },
'williamboman/mason-lspconfig.nvim', 'williamboman/mason-lspconfig.nvim',
'WhoIsSethDaniel/mason-tool-installer.nvim', 'WhoIsSethDaniel/mason-tool-installer.nvim',
-- Useful status updates for LSP.
{ 'j-hui/fidget.nvim', opts = {} }, { 'j-hui/fidget.nvim', opts = {} },
-- Allows extra capabilities provided by blink.cmp
'saghen/blink.cmp', 'saghen/blink.cmp',
'folke/lazydev.nvim', 'folke/lazydev.nvim',
}, },
build = function()
vim.fn.system 'composer global require jetbrains/phpstorm-stubs friendsofphp/php-cs-fixer'
end,
config = function() config = function()
-- Brief aside: **What is LSP?**
--
-- LSP is an initialism you've probably heard, but might not understand what it is.
--
-- LSP stands for Language Server Protocol. It's a protocol that helps editors
-- and language tooling communicate in a standardized fashion.
--
-- In general, you have a "server" which is some tool built to understand a particular
-- language (such as `gopls`, `lua_ls`, `rust_analyzer`, etc.). These Language Servers
-- (sometimes called LSP servers, but that's kind of like ATM Machine) are standalone
-- processes that communicate with some "client" - in this case, Neovim!
--
-- LSP provides Neovim with features like:
-- - Go to definition
-- - Find references
-- - Autocompletion
-- - Symbol Search
-- - and more!
--
-- Thus, Language Servers are external tools that must be installed separately from
-- Neovim. This is where `mason` and related plugins come into play.
--
-- If you're wondering about lsp vs treesitter, you can check out the wonderfully
-- and elegantly composed help section, `:help lsp-vs-treesitter`
-- This function gets run when an LSP attaches to a particular buffer. -- This function gets run when an LSP attaches to a particular buffer.
-- That is to say, every time a new file is opened that is associated with -- That is to say, every time a new file is opened that is associated with
-- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this -- an lsp (for example, opening `main.rs` is associated with `rust_analyzer`) this
-- function will be executed to configure the current buffer -- function will be executed to configure the current buffer
vim.api.nvim_create_autocmd('LspAttach', { vim.api.nvim_create_autocmd('LspAttach', {
group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), group = vim.api.nvim_create_augroup('lsp-attach', { clear = true }),
callback = function(event) callback = function(event)
-- NOTE: Remember that Lua is a real programming language, and as such it is possible
-- to define small helper and utility functions so you don't have to repeat yourself.
--
-- In this case, we create a function that lets us more easily define mappings specific
-- for LSP related items. It sets the mode, buffer and description for us each time.
local map = function(keys, func, desc, mode) local map = function(keys, func, desc, mode)
mode = mode or 'n' require('helpers').map(keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }, mode)
vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc })
end end
-- Rename the variable under your cursor.
-- Most Language Servers support renaming across files, etc.
map('grn', vim.lsp.buf.rename, '[R]e[n]ame') map('grn', vim.lsp.buf.rename, '[R]e[n]ame')
-- Execute a code action, usually your cursor needs to be on top of an error
-- or a suggestion from your LSP for this to activate.
map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' }) map('gra', vim.lsp.buf.code_action, '[G]oto Code [A]ction', { 'n', 'x' })
-- Find references for the word under your cursor.
map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') map('grr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences')
-- Jump to the implementation of the word under your cursor.
-- Useful when your language has ways of declaring types without an actual implementation.
map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') map('gri', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation')
-- Jump to the definition of the word under your cursor.
-- This is where a variable was first declared, or where a function is defined, etc.
-- To jump back, press <C-t>.
map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') map('grd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition')
-- WARN: This is not Goto Definition, this is Goto Declaration.
-- For example, in C this would take you to the header.
map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') map('grD', vim.lsp.buf.declaration, '[G]oto [D]eclaration')
-- Fuzzy find all the symbols in your current document.
-- Symbols are things like variables, functions, types, etc.
map('gO', require('telescope.builtin').lsp_document_symbols, 'Open Document Symbols') map('gO', require('telescope.builtin').lsp_document_symbols, 'Open Document Symbols')
-- Fuzzy find all the symbols in your current workspace.
-- Similar to document symbols, except searches over your entire project.
map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Open Workspace Symbols') map('gW', require('telescope.builtin').lsp_dynamic_workspace_symbols, 'Open Workspace Symbols')
-- Jump to the type of the word under your cursor.
-- Useful when you're not sure what type a variable is and you want to see
-- the definition of its *type*, not where it was *defined*.
map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition') map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition')
-- This function resolves a difference between neovim nightly (version 0.11) and stable (version 0.10) -- This function resolves a difference between neovim nightly (version 0.11) and stable (version 0.10)
@@ -116,7 +58,7 @@ return {
-- When you move your cursor, the highlights will be cleared (the second autocommand). -- When you move your cursor, the highlights will be cleared (the second autocommand).
local client = vim.lsp.get_client_by_id(event.data.client_id) local client = vim.lsp.get_client_by_id(event.data.client_id)
if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then
local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) local highlight_augroup = vim.api.nvim_create_augroup('lsp-highlight', { clear = false })
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
buffer = event.buf, buffer = event.buf,
group = highlight_augroup, group = highlight_augroup,
@@ -130,18 +72,14 @@ return {
}) })
vim.api.nvim_create_autocmd('LspDetach', { vim.api.nvim_create_autocmd('LspDetach', {
group = vim.api.nvim_create_augroup('kickstart-lsp-detach', { clear = true }), group = vim.api.nvim_create_augroup('lsp-detach', { clear = true }),
callback = function(event2) callback = function(event2)
vim.lsp.buf.clear_references() vim.lsp.buf.clear_references()
vim.api.nvim_clear_autocmds { group = 'kickstart-lsp-highlight', buffer = event2.buf } vim.api.nvim_clear_autocmds { group = 'lsp-highlight', buffer = event2.buf }
end, end,
}) })
end end
-- The following code creates a keymap to toggle inlay hints in your
-- code, if the language server you are using supports them
--
-- This may be unwanted, since they displace some of your code
if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_inlayHint, event.buf) then
map('<leader>th', function() map('<leader>th', function()
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf }) vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = event.buf })
@@ -150,8 +88,6 @@ return {
end, end,
}) })
-- Diagnostic Config
-- See :help vim.diagnostic.Opts
vim.diagnostic.config { vim.diagnostic.config {
severity_sort = true, severity_sort = true,
float = { border = 'rounded', source = 'if_many' }, float = { border = 'rounded', source = 'if_many' },
@@ -179,14 +115,7 @@ return {
}, },
} }
-- LSP servers and clients are able to communicate to each other what features they support.
-- By default, Neovim doesn't support everything that is in the LSP specification.
-- When you add blink.cmp, luasnip, etc. Neovim now has *more* capabilities.
-- So, we create new capabilities with blink.cmp, and then broadcast that to the servers.
local capabilities = require('blink.cmp').get_lsp_capabilities()
-- Enable the following language servers -- Enable the following language servers
-- Feel free to add/remove any LSPs that you want here. They will automatically be installed.
-- --
-- Add any additional override configuration in the following tables. Available keys are: -- Add any additional override configuration in the following tables. Available keys are:
-- - cmd (table): Override the default command used to start the server -- - cmd (table): Override the default command used to start the server
@@ -194,68 +123,94 @@ return {
-- - capabilities (table): Override fields in capabilities. Can be used to disable certain LSP features. -- - capabilities (table): Override fields in capabilities. Can be used to disable certain LSP features.
-- - settings (table): Override the default settings passed when initializing the server. -- - settings (table): Override the default settings passed when initializing the server.
-- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/ -- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/
local servers = {
-- clangd = {},
-- gopls = {},
-- pyright = {},
-- rust_analyzer = {},
-- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs
--
-- Some languages (like typescript) have entire language plugins that can be useful:
-- https://github.com/pmizio/typescript-tools.nvim
--
-- But for many setups, the LSP (`ts_ls`) will work just fine
-- ts_ls = {},
--
local mason_registry = require 'mason-registry'
local vue_language_server_path = vim.fn.expand '$MASON/packages/vue-language-server/node_modules/@vue/language-server'
local servers = {
clangd = {},
pyright = {},
rust_analyzer = {},
lua_ls = { lua_ls = {
-- cmd = { ... },
-- filetypes = { ... },
-- capabilities = {},
settings = { settings = {
Lua = { Lua = {
completion = { completion = {
callSnippet = 'Replace', callSnippet = 'Replace',
}, },
-- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings
-- diagnostics = { disable = { 'missing-fields' } },
}, },
}, },
}, },
phpactor = {},
vtsls = {
settings = {
vtsls = {
tsserver = {
globalPlugins = {
{
name = '@vue/typescript-plugin',
location = vue_language_server_path,
languages = { 'vue' },
configNamespace = 'typescript',
},
},
},
},
javascript = {
preferences = {
importModuleSpecifierPreference = 'non-relative',
importModuleSpecifierEnding = 'js',
},
},
},
filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
},
['vue-language-server'] = {
on_init = function(client)
client.handlers['tsserver/request'] = function(_, result, context)
local clients = vim.lsp.get_clients { bufnr = context.bufnr, name = 'vtsls' }
if #clients == 0 then
vim.notify('Could not find `vtsls` lsp client, `vue-language-server` would not work without it.', vim.log.levels.ERROR)
return
end
local ts_client = clients[1]
local param = unpack(result)
local id, command, payload = unpack(param)
ts_client:exec_cmd({
title = 'vue_request_forward', -- You can give title anything as it's used to represent a command in the UI, `:h Client:exec_cmd`
command = 'typescript.tsserverRequest',
arguments = {
command,
payload,
},
}, { bufnr = context.bufnr }, function(_, r)
local response_data = { { id, r.body } }
---@diagnostic disable-next-line: param-type-mismatch
client:notify('tsserver/response', response_data)
end)
end
end,
},
} }
-- Ensure the servers and tools above are installed
--
-- To check the current status of installed tools and/or manually install
-- other tools, you can run
-- :Mason
--
-- You can press `g?` for help in this menu.
--
-- `mason` had to be setup earlier: to configure its options see the
-- `dependencies` table for `nvim-lspconfig` above.
--
-- You can add other tools here that you want Mason to install
-- for you, so that they are available from within Neovim.
local ensure_installed = vim.tbl_keys(servers or {}) local ensure_installed = vim.tbl_keys(servers or {})
vim.list_extend(ensure_installed, { vim.list_extend(ensure_installed, {
'stylua', -- Used to format Lua code 'stylua', -- Used to format Lua code
}) })
-- LSP servers and clients are able to communicate to each other what features they support.
-- By default, Neovim doesn't support everything that is in the LSP specification.
-- When you add blink.cmp, luasnip, etc. Neovim now has *more* capabilities.
-- So, we create new capabilities with blink.cmp, and then broadcast that to the servers.
local capabilities = require('blink.cmp').get_lsp_capabilities()
for name, cfg in pairs(servers) do
cfg.capabilities = vim.tbl_deep_extend('force', {}, capabilities, cfg.capabilities or {})
vim.lsp.config(name, cfg) -- new Neovim 0.11 API
end
require('mason-tool-installer').setup { ensure_installed = ensure_installed } require('mason-tool-installer').setup { ensure_installed = ensure_installed }
require('mason-lspconfig').setup { require('mason').setup {}
ensure_installed = {}, -- explicitly set to an empty table (Kickstart populates installs via mason-tool-installer) require('mason-lspconfig').setup {}
automatic_installation = false,
handlers = {
function(server_name)
local server = servers[server_name] or {}
-- This handles overriding only values explicitly passed
-- by the server configuration above. Useful when disabling
-- certain features of an LSP (for example, turning off formatting for ts_ls)
server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {})
require('lspconfig')[server_name].setup(server)
end,
},
}
end, end,
} }

View File

@@ -1,6 +1,6 @@
-- Collection of various small independent plugins/modules -- Collection of various small independent plugins/modules
return { return {
"echasnovski/mini.nvim", 'echasnovski/mini.nvim',
config = function() config = function()
-- Better Around/Inside textobjects -- Better Around/Inside textobjects
-- --
@@ -8,28 +8,64 @@ return {
-- - va) - [V]isually select [A]round [)]paren -- - va) - [V]isually select [A]round [)]paren
-- - yinq - [Y]ank [I]nside [N]ext [Q]uote -- - yinq - [Y]ank [I]nside [N]ext [Q]uote
-- - ci' - [C]hange [I]nside [']quote -- - ci' - [C]hange [I]nside [']quote
require("mini.ai").setup({ n_lines = 500 }) require('mini.ai').setup { n_lines = 500 }
-- Add/delete/replace surroundings (brackets, quotes, etc.) -- Add/delete/replace surroundings (brackets, quotes, etc.)
-- --
-- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren -- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren
-- - sd' - [S]urround [D]elete [']quotes -- - sd' - [S]urround [D]elete [']quotes
-- - sr)' - [S]urround [R]eplace [)] ['] -- - sr)' - [S]urround [R]eplace [)] [']
require("mini.surround").setup() require('mini.surround').setup {
mappings = {
add = 'ys',
delete = 'ds',
replace = 'cs',
},
}
require('mini.pairs').setup()
require('mini.jump').setup {
mappings = {
repeat_jump = ':',
},
}
local MiniJump2d = require 'mini.jump2d'
MiniJump2d.setup {
spotter = MiniJump2d.gen_spotter.union(
MiniJump2d.gen_spotter.pattern('[([{][^$]', 'end'),
MiniJump2d.gen_spotter.pattern('%$.', 'end'),
MiniJump2d.gen_spotter.pattern('->.', 'end'),
MiniJump2d.gen_spotter.pattern('^%s*%S', 'end')
),
mappings = {
start_jumping = 'S',
},
allowed_lines = {
blank = false,
cursor_at = false,
fold = false,
},
}
require('mini.splitjoin').setup()
require('mini.map').setup()
-- Simple and easy statusline. -- Simple and easy statusline.
-- You could remove this setup call if you don't like it, -- You could remove this setup call i you don't like it,
-- and try some other statusline plugin -- and try some other statusline plugin
local statusline = require("mini.statusline") local statusline = require 'mini.statusline'
-- set use_icons to true if you have a Nerd Font -- set use_icons to true if you have a Nerd Font
statusline.setup({ use_icons = vim.g.have_nerd_font }) statusline.setup { use_icons = vim.g.have_nerd_font }
-- You can configure sections in the statusline by overriding their -- You can configure sections in the statusline by overriding their
-- default behavior. For example, here we set the section for -- default behavior. For example, here we set the section for
-- cursor location to LINE:COLUMN -- cursor location to LINE:COLUMN
---@diagnostic disable-next-line: duplicate-set-field ---@diagnostic disable-next-line: duplicate-set-field
statusline.section_location = function() statusline.section_location = function()
return "%2l:%-2v" return '%2l:%-2v'
end end
-- ... and there is more! -- ... and there is more!

View File

@@ -1,28 +0,0 @@
-- Neo-tree is a Neovim plugin to browse the file system
-- https://github.com/nvim-neo-tree/neo-tree.nvim
return {
'nvim-neo-tree/neo-tree.nvim',
version = '*',
dependencies = {
'nvim-lua/plenary.nvim',
'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended
'MunifTanjim/nui.nvim',
},
cmd = 'Neotree',
keys = {
{ '\\', ':Neotree reveal<CR>', desc = 'NeoTree reveal', silent = true },
},
opts = {
filesystem = {
window = {
mappings = {
['\\'] = 'close_window',
},
},
filtered_items = {
hide_dotfiles = false,
},
},
},
}

24
lua/plugins/oil.lua Normal file
View File

@@ -0,0 +1,24 @@
-- Filesystem manager
-- require('helpers').edit_cf('po', '/lua/plugins/oil.lua')
--
-- vim.keymap.set('n', '-', '<CMD>Oil<CR>', { desc = 'Open parent directory' })
return {
'stevearc/oil.nvim',
---@module 'oil'
---@type oil.SetupOpts
opts = {
view_options = {
show_hidden = true,
},
keymaps = {
['<C-p>'] = false,
['-'] = false,
},
},
-- Optional dependencies
dependencies = { { 'echasnovski/mini.icons', opts = {} } },
-- dependencies = { "nvim-tree/nvim-web-devicons" }, -- use if you prefer nvim-web-devicons
-- Lazy loading is not recommended because it is very tricky to make it work correctly in all situations.
lazy = false,
}

34
lua/plugins/quicker.lua Normal file
View File

@@ -0,0 +1,34 @@
vim.keymap.set("n", "<leader>q", function()
require("quicker").toggle()
end, { desc = "Toggle quickfix" })
vim.keymap.set("n", "<leader>l", function()
require("quicker").toggle({ loclist = true })
end, { desc = "Toggle loclist" })
return {
'stevearc/quicker.nvim',
ft = 'qf',
---@module "quicker"
---@type quicker.SetupOptions
opts = {},
config = function()
require('quicker').setup({
keys = {
{
">",
function()
require("quicker").expand({ before = 2, after = 2, add_to_existing = true })
end,
desc = "Expand quickfix context",
},
{
"<",
function()
require("quicker").collapse()
end,
desc = "Collapse quickfix context",
},
},
})
end,
}

9
lua/plugins/refactor.lua Normal file
View File

@@ -0,0 +1,9 @@
return {
"ThePrimeagen/refactoring.nvim",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-treesitter/nvim-treesitter",
},
lazy = false,
opts = {},
}

View File

@@ -0,0 +1,10 @@
return {
'MeanderingProgrammer/render-markdown.nvim',
dependencies = { 'nvim-treesitter/nvim-treesitter', 'echasnovski/mini.nvim' }, -- if you use the mini.nvim suite
-- dependencies = { 'nvim-treesitter/nvim-treesitter', 'echasnovski/mini.icons' }, -- if you use standalone mini plugins
-- dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-tree/nvim-web-devicons' }, -- if you prefer nvim-web-devicons
---@module 'render-markdown'
---@type render.md.UserConfig
opts = {},
ft = { 'markdown', 'codecompanion' },
}

75
lua/plugins/snacks.lua Normal file
View File

@@ -0,0 +1,75 @@
return {
'folke/snacks.nvim',
priority = 1000,
lazy = false,
---@type snacks.Config
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
bigfile = { enabled = true },
dashboard = {
enabled = true,
preset = {
keys = {
{ icon = '', key = 'f', desc = 'Find File', action = ":lua Snacks.dashboard.pick('files')" },
{ icon = '', key = 'n', desc = 'New File', action = ':ene | startinsert' },
{ icon = '', key = 'g', desc = 'Find Text', action = ":lua Snacks.dashboard.pick('live_grep')" },
{ icon = '', key = 'r', desc = 'Recent Files', action = ":lua Snacks.dashboard.pick('oldfiles')" },
{ icon = '', key = 'c', desc = 'Config', action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})" },
-- { icon = " ", key = "s", desc = "Restore Session", section = "session" },
{ icon = '󰒲 ', key = 'L', desc = 'Lazy', action = ':Lazy', enabled = package.loaded.lazy ~= nil },
{ icon = '', key = 'q', desc = 'Quit', action = ':qa' },
},
},
sections = {
{ section = 'header' },
{ section = 'keys', gap = 1, padding = 1 },
{
pane = 2,
icon = '',
title = 'Projects',
section = 'projects',
indent = 2,
padding = 1,
session = false,
dirs = function()
return {
vim.fn.expand '~/Code/Sites/runcats',
vim.fn.expand '~/Code/Sites/moovaza',
vim.fn.expand '~/Code/Sites/tuxtoolkit',
vim.fn.expand '~/Code/Sites/chrisstarling',
vim.fn.stdpath 'config',
}
end,
},
{ pane = 2, icon = '', title = 'Recent Files', section = 'recent_files', indent = 2, padding = 1 },
{
pane = 2,
icon = '',
title = 'Git Status',
section = 'terminal',
enabled = function()
return Snacks.git.get_root() ~= nil
end,
cmd = 'git status --short --branch --renames',
height = 5,
padding = 1,
ttl = 5 * 60,
indent = 3,
},
},
},
indent = { enabled = true },
input = { enabled = true },
notifier = { enabled = true },
quickfile = { enabled = true },
scope = { enabled = true },
-- scroll = { enabled = true },
statuscolumn = { enabled = true },
words = { enabled = true },
terminal = { enabled = true },
scratch = { enabled = true },
rename = { enabled = true },
},
}

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

@@ -0,0 +1,26 @@
return {
'L3MON4D3/LuaSnip',
version = '2.*',
build = (function()
-- Build Step is needed for regex support in snippets.
-- This step is not supported in many windows environments.
-- Remove the below condition to re-enable on windows.
if vim.fn.has 'win32' == 1 or vim.fn.executable 'make' == 0 then
return
end
return 'make install_jsregexp'
end)(),
config = function()
local ls = require 'luasnip'
ls.filetype_extend('vue', { 'javascript' })
local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets'
require('luasnip.loaders.from_lua').load {
paths = { snippets_dir },
}
ls.setup {
update_events = 'TextChanged,TextChangedI',
enable_autosnippets = true,
}
end,
opts = {},
}

6
lua/plugins/suda.lua Normal file
View File

@@ -0,0 +1,6 @@
return {
'lambdalisue/vim-suda',
config = function()
vim.g.suda_smart_edit = 1
end,
}

View File

@@ -1,27 +1,27 @@
-- Fuzzy Finder (files, lsp, etc) -- Fuzzy Finder (files, lsp, etc)
-- See :help telescope -- See :help telescope
return { return {
"nvim-telescope/telescope.nvim", 'nvim-telescope/telescope.nvim',
event = "VimEnter", event = 'VimEnter',
dependencies = { dependencies = {
"nvim-lua/plenary.nvim", 'nvim-lua/plenary.nvim',
{ -- If encountering errors, see telescope-fzf-native README for installation instructions { -- If encountering errors, see telescope-fzf-native README for installation instructions
"nvim-telescope/telescope-fzf-native.nvim", 'nvim-telescope/telescope-fzf-native.nvim',
-- `build` is used to run some command when the plugin is installed/updated. -- `build` is used to run some command when the plugin is installed/updated.
-- This is only run then, not every time Neovim starts up. -- This is only run then, not every time Neovim starts up.
build = "make", build = 'make',
-- `cond` is a condition used to determine whether this plugin should be -- `cond` is a condition used to determine whether this plugin should be
-- installed and loaded. -- installed and loaded.
cond = function() cond = function()
return vim.fn.executable("make") == 1 return vim.fn.executable 'make' == 1
end, end,
}, },
{ "nvim-telescope/telescope-ui-select.nvim" }, { 'nvim-telescope/telescope-ui-select.nvim' },
-- Useful for getting pretty icons, but requires a Nerd Font. -- Useful for getting pretty icons, but requires a Nerd Font.
{ "nvim-tree/nvim-web-devicons", enabled = vim.g.have_nerd_font }, { 'nvim-tree/nvim-web-devicons', enabled = vim.g.have_nerd_font },
}, },
config = function() config = function()
-- Telescope is a fuzzy finder that comes with a lot of different things that -- Telescope is a fuzzy finder that comes with a lot of different things that
@@ -45,7 +45,7 @@ return {
-- [[ Configure Telescope ]] -- [[ Configure Telescope ]]
-- See `:help telescope` and `:help telescope.setup()` -- See `:help telescope` and `:help telescope.setup()`
require("telescope").setup({ require('telescope').setup {
-- You can put your default mappings / updates / etc. in here -- You can put your default mappings / updates / etc. in here
-- All the info you're looking for is in `:help telescope.setup()` -- All the info you're looking for is in `:help telescope.setup()`
-- --
@@ -56,50 +56,67 @@ return {
-- }, -- },
-- pickers = {} -- pickers = {}
extensions = { extensions = {
["ui-select"] = { ['ui-select'] = {
require("telescope.themes").get_dropdown(), require('telescope.themes').get_dropdown(),
}, },
}, },
}) defaults = {
mappings = {
i = {
-- Insert mode mappings for Telescope
['<C-j>'] = 'move_selection_next',
['<C-k>'] = 'move_selection_previous',
},
n = {
-- Normal mode mappings for Telescope
['<C-j>'] = 'move_selection_next',
['<C-k>'] = 'move_selection_previous',
},
},
file_ignore_patterns = {
'.obsidian',
},
},
}
-- Enable Telescope extensions if they are installed -- Enable Telescope extensions if they are installed
pcall(require("telescope").load_extension, "fzf") pcall(require('telescope').load_extension, 'fzf')
pcall(require("telescope").load_extension, "ui-select") pcall(require('telescope').load_extension, 'ui-select')
-- See `:help telescope.builtin` -- See `:help telescope.builtin`
local builtin = require("telescope.builtin") local builtin = require 'telescope.builtin'
vim.keymap.set("n", "<leader>sh", builtin.help_tags, { desc = "[S]earch [H]elp" }) vim.keymap.set('n', '<leader>sh', builtin.help_tags, { desc = '[S]earch [H]elp' })
vim.keymap.set("n", "<leader>sk", builtin.keymaps, { desc = "[S]earch [K]eymaps" }) vim.keymap.set('n', '<leader>sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' })
vim.keymap.set("n", "<leader>sf", builtin.find_files, { desc = "[S]earch [F]iles" }) vim.keymap.set('n', '<leader>sf', builtin.find_files, { desc = '[S]earch [F]iles' })
vim.keymap.set("n", "<leader>ss", builtin.builtin, { desc = "[S]earch [S]elect Telescope" }) vim.keymap.set('n', '<leader>ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' })
vim.keymap.set("n", "<leader>sw", builtin.grep_string, { desc = "[S]earch current [W]ord" }) vim.keymap.set('n', '<leader>sw', builtin.grep_string, { desc = '[S]earch current [W]ord' })
vim.keymap.set("n", "<leader>sg", builtin.live_grep, { desc = "[S]earch by [G]rep" }) vim.keymap.set('n', '<leader>sg', builtin.live_grep, { desc = '[S]earch by [G]rep' })
vim.keymap.set("n", "<leader>sd", builtin.diagnostics, { desc = "[S]earch [D]iagnostics" }) vim.keymap.set('n', '<leader>sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' })
vim.keymap.set("n", "<leader>sr", builtin.resume, { desc = "[S]earch [R]esume" }) vim.keymap.set('n', '<leader>sr', builtin.resume, { desc = '[S]earch [R]esume' })
vim.keymap.set("n", "<leader>s.", builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' }) vim.keymap.set('n', '<leader>s.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' })
vim.keymap.set("n", "<leader><leader>", builtin.buffers, { desc = "[ ] Find existing buffers" }) vim.keymap.set('n', '<leader><leader>', builtin.buffers, { desc = '[ ] Find existing buffers' })
-- Slightly advanced example of overriding default behavior and theme -- Slightly advanced example of overriding default behavior and theme
vim.keymap.set("n", "<leader>/", function() vim.keymap.set('n', '<leader>/', function()
-- You can pass additional configuration to Telescope to change the theme, layout, etc. -- You can pass additional configuration to Telescope to change the theme, layout, etc.
builtin.current_buffer_fuzzy_find(require("telescope.themes").get_dropdown({ builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown {
winblend = 10, winblend = 10,
previewer = false, previewer = false,
})) })
end, { desc = "[/] Fuzzily search in current buffer" }) end, { desc = '[/] Fuzzily search in current buffer' })
-- It's also possible to pass additional configuration options. -- It's also possible to pass additional configuration options.
-- See `:help telescope.builtin.live_grep()` for information about particular keys -- See `:help telescope.builtin.live_grep()` for information about particular keys
vim.keymap.set("n", "<leader>s/", function() vim.keymap.set('n', '<leader>s/', function()
builtin.live_grep({ builtin.live_grep {
grep_open_files = true, grep_open_files = true,
prompt_title = "Live Grep in Open Files", prompt_title = 'Live Grep in Open Files',
}) }
end, { desc = "[S]earch [/] in Open Files" }) end, { desc = '[S]earch [/] in Open Files' })
-- Shortcut for searching your Neovim configuration files -- Shortcut for searching your Neovim configuration files
vim.keymap.set("n", "<leader>sn", function() vim.keymap.set('n', '<leader>sn', function()
builtin.find_files({ cwd = vim.fn.stdpath("config") }) builtin.find_files { cwd = vim.fn.stdpath 'config' }
end, { desc = "[S]earch [N]eovim files" }) end, { desc = '[S]earch [N]eovim files' })
end, end,
} }

View File

@@ -1,7 +1,7 @@
-- Highlight todo, notes, etc in comments -- Highlight todo, notes, etc in comments
return { return {
"folke/todo-comments.nvim", 'folke/todo-comments.nvim',
event = "VimEnter", event = 'VimEnter',
dependencies = { "nvim-lua/plenary.nvim" }, dependencies = { 'nvim-lua/plenary.nvim' },
opts = { signs = false }, opts = { signs = false },
} }

10
lua/plugins/treesj.lua Normal file
View File

@@ -0,0 +1,10 @@
return {
'Wansmer/treesj',
lazy = true,
dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter`
config = function()
require('treesj').setup({
use_default_keymaps = false,
})
end,
}

9
lua/plugins/yanky.lua Normal file
View File

@@ -0,0 +1,9 @@
-- For when I'm ready
return {
-- "gbprod/yanky.nvim",
-- opts = {
-- -- your configuration comes here
-- -- or leave it empty to use the default settings
-- -- refer to the configuration section below
-- },
}

32
lua/plugins/yazi.lua Normal file
View File

@@ -0,0 +1,32 @@
---@type LazySpec
return {
'mikavilpas/yazi.nvim',
version = '*', -- use the latest stable version
event = 'VeryLazy',
dependencies = {
{ 'nvim-lua/plenary.nvim', lazy = true },
},
keys = {
-- 👇 in this section, choose your own keymappings!
{
'-',
mode = { 'n', 'v' },
'<cmd>Yazi<cr>',
desc = 'Open yazi at the current file',
},
{
-- Open in the current working directory
'\\',
'<cmd>Yazi cwd<cr>',
desc = "Open the file manager in nvim's working directory",
},
},
---@type YaziConfig | {}
opts = {
-- if you want to open yazi instead of netrw, see below for more info
open_for_directories = false,
keymaps = {
show_help = '<f1>',
},
},
}

294
lua/projects.lua Normal file
View File

@@ -0,0 +1,294 @@
-- Project specific settings
local M = {}
-- Helper to create mappings
local helpers = require 'helpers'
local map = helpers.map
-- Get the last folder name from a path
local function project_name_from_cwd(cwd)
return vim.fn.fnamemodify(cwd, ':t')
end
local function command_with_dir(dir, cmd)
if dir then
return '!cd ' .. dir .. ' && ' .. cmd
end
return '!' .. cmd
end
local function make_laravel_file(dir, cmd)
local cwd = vim.fn.getcwd()
if dir then
vim.fn.chdir(dir)
end
vim.ui.input({ prompt = 'Make: ' .. cmd }, function(input)
if input == nil then
vim.fn.chdir(cwd)
return
end
local output = vim.system({ 'vendor/bin/sail', 'artisan', 'make:' .. cmd, input }):wait().stdout
local new_file = output:match '%[([%w%./]+)%]'
if new_file ~= nil then
vim.cmd('edit ' .. new_file)
end
vim.fn.chdir(cwd)
end)
end
local function get_scope_from_file(filename)
local ext = filename:match '%.(%w+)$'
local base_name = filename:match '^(%w+)%.?%w*$'
local extensionSuffixes = {
php = { 'Controller', 'Repository', 'StoreRequest', 'UpdateRequest', 'Request', 'Resource', 'Test', 'Observer', 'Policy', 'Seeder', 'Factory' },
['[jt]s'] = { 'Service' },
}
for suffix_type, _ in pairs(extensionSuffixes) do
if ext:match(suffix_type) then
local suffixes = extensionSuffixes[suffix_type]
for _, suffix in ipairs(suffixes) do
local scope = base_name:match('^(%w+)' .. suffix .. '$')
if scope then
return scope
end
end
end
end
return base_name
end
local function navigate_using_suffix(suffix)
local scope = get_scope_from_file(vim.fn.expand '%:t')
local file_name = scope .. suffix
local file_path = vim.system({ 'git', 'ls-files', file_name, '**/' .. file_name }):wait().stdout
if file_path ~= '' then
vim.cmd('edit ' .. file_path)
else
vim.notify('File ' .. file_name .. ' not found in git ls-files', vim.log.levels.ERROR)
end
end
local function create_navigation_maps(maps)
for key, suffix_and_name in pairs(maps) do
map('<Leader>n' .. key, function()
navigate_using_suffix(suffix_and_name[1])
end, { desc = 'Navigate to relevant ' .. suffix_and_name[2] })
end
end
local function create_bookmark(key, bookmark)
map('<Leader>b' .. key, function()
vim.cmd('edit ' .. bookmark)
end, { desc = 'Navigate to ' .. bookmark })
end
local function create_bookmark_maps(maps)
for key, bookmark in pairs(maps) do
create_bookmark(key, bookmark)
end
end
local function laravel_bookmarks_with_dir(dir)
create_bookmark_maps {
['e'] = dir .. '.env',
['l'] = dir .. 'storage/logs/laravel.log',
['w'] = dir .. 'routes/web.php',
['a'] = dir .. 'routes/api.php',
['m'] = dir .. 'database/migrations',
['dc'] = dir .. 'app/Core/',
['dd'] = dir .. 'app/Data/',
['dE'] = dir .. 'app/Enums/',
['de'] = dir .. 'app/Events/',
['dh'] = dir .. 'app/Http/',
['dj'] = dir .. 'app/Jobs/',
['dl'] = dir .. 'app/Listeners/',
['dM'] = dir .. 'app/Mail/',
['dm'] = dir .. 'app/Models/',
['dn'] = dir .. 'app/Notifications/',
['do'] = dir .. 'app/Observers/',
['dp'] = dir .. 'app/Providers/',
['pa'] = dir .. 'app/Providers/AppServiceProvider.php',
['pe'] = dir .. 'app/Providers/EventServiceProvider.php',
['cA'] = dir .. 'config/app.php',
['ca'] = dir .. 'config/auth.php',
['cb'] = dir .. 'config/broadcasting.php',
['cd'] = dir .. 'config/database.php',
['cf'] = dir .. 'config/filesystems.php',
['ch'] = dir .. 'config/filesystems.php',
['cl'] = dir .. 'config/logging.php',
['cm'] = dir .. 'config/mail.php',
['cq'] = dir .. 'config/queue.php',
['cS'] = dir .. 'config/services.php',
['cs'] = dir .. 'config/session.php',
}
end
local function laravel_keymaps(dir)
map('sl ', command_with_dir(dir, 'vendor/bin/sail '), { desc = 'Run sail command' }, 'c')
map('art ', command_with_dir(dir, 'php artisan '), { desc = 'Run artisan command' }, 'c')
map('sart ', command_with_dir(dir, 'vendor/bin/sail artisan '), { desc = 'Run artisan command with sail' }, 'c')
map('cmp ', command_with_dir(dir, 'composer '), { desc = 'Run composer script' }, 'c')
map('<Leader>pm', ':' .. command_with_dir(dir, 'vendor/bin/sail artisan migrate<CR>'))
map('<Leader>pr', ':' .. command_with_dir(dir, 'vendor/bin/sail artisan migrate:rollback<CR>'))
map('<Leader>pM', ':' .. command_with_dir(dir, 'vendor/bin/sail artisan make:'))
create_navigation_maps {
['m'] = { '.php', 'model' },
['c'] = { 'Controller.php', 'controller' },
['p'] = { 'Policy.php', 'policy' },
['R'] = { 'Resource.php', 'resource' },
['r'] = { 'Request.php', 'request' },
['t'] = { 'Test.php', 'test file' },
}
if dir == nil then
dir = ''
end
laravel_bookmarks_with_dir(dir)
end
local function laravel_makes(dir)
for key, name in pairs {
c = 'controller',
d = 'data',
e = 'event',
f = 'factory',
j = 'job',
l = 'listener',
ma = 'mail',
mi = 'migration',
mo = 'model',
mw = 'middleware',
n = 'notification',
o = 'observer',
pi = 'model --pivot',
po = 'policy',
pr = 'provider',
t = 'test --pest',
v = 'view',
x = 'exception',
} do
map('<Leader>m' .. key, function()
make_laravel_file(dir, name)
end, { desc = 'Make and navigate to relevant ' .. name })
end
end
-- Define per-project configuration here.
-- Keys are folder names (last segment of your cwd).
local PROJECTS = {
-- Example: a repo folder
['runcats'] = function(dir)
-- local dump_buf = vim.api.nvim_create_buf(false, true)
-- vim.api.nvim_set_option_value('bufhidden', 'hide', { buf = dump_buf })
-- vim.api.nvim_set_option_value('modifiable', false, { buf = dump_buf })
--
-- vim.fn.jobstart('cd server && sail artisan dump-server', {
-- term = true,
-- })
-- map('<leader>dd', function()
-- local height = math.ceil(vim.o.lines * 0.8)
-- local width = math.ceil(vim.o.columns * 0.8)
-- vim.api.nvim_open_win(dump_buf, true, {
-- style = 'minimal',
-- relative = 'editor',
-- width = width,
-- height = height,
-- row = math.ceil((vim.o.lines - height) / 2),
-- col = math.ceil((vim.o.columns - width) / 2),
-- border = 'single',
-- })
--
-- vim.cmd.startinsert()
-- end, { desc = 'Open the dump-server window' })
map(
'<leader>pl',
':cexpr system("cd server && vendor/bin/phpstan analyse --no-progress --error-format=raw --memory-limit=2G -vv") <CR>',
{ desc = 'Run lint' }
)
map('<leader>pd', function()
helpers.open_term { cmd = 'lazysql mysql://root@localhost:3306/runcats' }
end, { desc = 'Open database manager' })
map('s ', '!cd server && ', { desc = 'Run command in server directory' }, 'c')
map('c ', '!cd client && ', { desc = 'Run command in client directory' }, 'c')
laravel_keymaps 'server/'
laravel_makes 'server/'
map('yrn ', '!cd client && yarn ', { desc = 'Run yarn script' }, 'c')
map('<Leader>pt', ':!cd server && php artisan typescript:transform --format<CR>', { desc = 'Compile typescript' })
require('conform').formatters.pint = {
append_args = {
'--config=' .. dir .. '/server/pint.json',
},
}
create_bookmark('E', dir .. '/client/src/types/api/endpointMap.d.ts')
create_bookmark('q', dir .. '/client/quasar.config.ts')
create_bookmark('db', dir .. '/client/src/boot')
create_bookmark('ds', dir .. '/client/src/stores')
create_bookmark('dS', dir .. '/client/src/services')
end,
['hylark'] = function(dir)
map('<leader>pl', ':cexpr system("vendor/bin/phpstan analyse --no-progress --error-format=raw --memory-limit=2G -vv") <CR>', { desc = 'Run lint' })
map('<leader>pd', function()
helpers.open_term { cmd = 'lazysql pgsql://homestead:password@localhost:5432/homestead' }
end, { desc = 'Open database manager' })
laravel_keymaps()
laravel_makes()
map('yrn ', '!cd frontend && yarn ', { desc = 'Run yarn script' }, 'c')
map('<Leader>pm', ':vendor/bin/sail composer migrate<CR>')
end,
default = function() end,
}
local last_applied = nil
function M.apply(cwd)
local dir = cwd or vim.fn.getcwd()
local name = project_name_from_cwd(dir)
if last_applied == name then
return
end
last_applied = name
local setup = PROJECTS[name] or PROJECTS.default
if type(setup) == 'function' then
setup(dir)
vim.notify(('Project config loaded: %s'):format(name), vim.log.levels.INFO, { title = 'projects.lua' })
end
end
-- Apply on startup and when the working directory changes
do
local grp = vim.api.nvim_create_augroup('ProjectConfig', { clear = true })
vim.api.nvim_create_autocmd('VimEnter', {
group = grp,
callback = function()
M.apply()
end,
})
vim.api.nvim_create_autocmd('DirChanged', {
group = grp,
callback = function(args)
-- args.file is the new cwd for DirChanged
M.apply(args and args.file or nil)
end,
})
end
-- Optional command to manually re-apply
vim.api.nvim_create_user_command('ProjectReload', function()
last_applied = nil
M.apply()
end, {})
-- Keep your helper line
require('helpers').edit_cf('w', '/lua/projects.lua')

1
lua/snippets/all.lua Normal file
View File

@@ -0,0 +1 @@
return {}

128
lua/snippets/javascript.lua Normal file
View File

@@ -0,0 +1,128 @@
local ls = require 'luasnip'
local s = ls.snippet
local sn = ls.snippet_node
local fn = ls.function_node
local ms = ls.multi_snippet
local t = ls.text_node
local c = ls.choice_node
local i = ls.insert_node
local f = ls.function_node
local d = ls.dynamic_node
local fmt = require('luasnip.extras.fmt').fmt
local rep = require('luasnip.extras').rep
local extend_decorator = require 'luasnip.util.extend_decorator'
local fmta = extend_decorator.apply(fmt, { delimiters = '#~' })
local utils = require 'snippets.snip_utils'
local tr = utils.tr
local etr = utils.etr
local atr = utils.atr
local ctr = utils.ctr
local bs = utils.bs
return {
s(etr('du ', 'Dump a variable to the console'), fmta('console.log(#~);', { i(0) })),
s(
etr('vue', 'Vue Single File Component skeleton'),
fmta(
[[
<template>
</template>
<script setup>
#~
</script>
<style scoped>
</style>
]],
{ i(0) }
)
),
bs(atr('t ', 'this'), fmta('this.#~', { i(0) })),
s(etr('return ', 'Add semicolon after return'), fmta('return #~;', { i(0) })),
s(etr('rt ', 'return alias'), fmta('return #~;', { i(0) })),
s(etr('const', 'const declaration'), {
c(1, {
sn(nil, fmta('const #~ = #~;', { i(1, 'variableName'), i(2, 'value') })),
sn(
nil,
fmta(
[[
const #~ = (#~) => {
#~
}
]],
{ i(1), i(2), i(3) }
)
),
}),
}),
s(
etr('fn ', 'function block'),
fmta(
[[
function #~(#~) {
#~
}
]],
{ i(1), i(2), i(0) }
)
),
bs(atr('fn ', 'function block'), {
c(1, {
sn(
nil,
fmta(
[[
(#~) => {
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmta(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
}),
}),
bs(atr('afn ', 'async function block'), {
c(1, {
sn(
nil,
fmta(
[[
async (#~) => {
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmta(
[[
async function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
}),
}),
}

613
lua/snippets/php.lua Normal file
View File

@@ -0,0 +1,613 @@
local ls = require 'luasnip'
local s = ls.snippet
local sn = ls.snippet_node
local fn = ls.function_node
local ms = ls.multi_snippet
local t = ls.text_node
local c = ls.choice_node
local i = ls.insert_node
local f = ls.function_node
local d = ls.dynamic_node
local fmt = require('luasnip.extras.fmt').fmt
local rep = require('luasnip.extras').rep
local extend_decorator = require 'luasnip.util.extend_decorator'
local fmta = extend_decorator.apply(fmt, { delimiters = '#~' })
local utils = require 'snippets.snip_utils'
local tr = utils.tr
local etr = utils.etr
local Etr = utils.Etr
local atr = utils.atr
local ctr = utils.ctr
local bs = utils.bs
local function psr_namespace()
local path = vim.fn.expand '%'
-- Get the directory of the path
local dir = vim.fs.dirname(path)
-- Loop through parent directories to find composer.json
while dir ~= '/' and dir ~= nil do
local composer_json_path = dir .. '/composer.json'
if vim.fn.filereadable(composer_json_path) == 1 then
break
end
dir = vim.fs.dirname(dir)
end
-- If no composer.json found, return empty string
if dir == '/' or dir == nil then
return ''
end
-- Decode composer.json and get PSR-4 autoload mappings
local composer = vim.json.decode(vim.iter(vim.fn.readfile(dir .. '/composer.json')):join '')
local psr4 = composer['autoload'] and composer['autoload']['psr-4']
-- If no PSR-4 mappings, return empty string
if not psr4 then
return ''
end
-- Get the relative path from the composer.json directory
local relative_path = path:sub(#dir + 2)
-- Loop through PSR-4 mappings
for namespace, map in pairs(psr4) do
-- Check if the relative path matches the mapping
if relative_path:match('^' .. map:gsub('/', '%%/')) then
-- Extract the suffix of the path after the mapping, removing the filename
local suffix = relative_path:sub(#map + 1):match '^(.*)/[^/]+%.php$' or ''
local trimmed = namespace:gsub('\\$', '')
return trimmed .. (suffix ~= '' and ('\\' .. suffix:gsub('/', '\\')) or '')
end
end
end
local function class_name(args, snip)
local filename = snip.env.TM_FILENAME or ''
return filename:match '([^%.]+)' or 'ClassName'
end
return {
---------------
-- DEBUGGING --
---------------
s(etr('du ', 'Dump a variable to the dump server', { priority = 1001 }), fmta('dump(#~);', { i(0) })),
bs(etr('du ', 'Dump a variable to the dump server'), fmta('dump(#~)', { i(0) })),
s(etr('r ', 'ray', { priority = 1001 }), fmta('ray(#~);', { i(0) })),
bs(etr('r ', 'ray'), fmta('ray(#~)', { i(0) })),
s(etr('dt ', 'Dump PHPStan type definition'), fmta('\\PhpStan\\dumpType(#~);', { i(0) })),
s(
etr('ql ', 'Log all queries'),
fmta(
[[
\Illuminate\Support\Facades\DB::listen(function (\Illuminate\Database\Events\QueryExecuted $e) {
dump($e->sql, $e->bindings);
});
#~
]],
{ i(0) }
)
),
--------------
-- COMMENTS --
--------------
s(etr('/**', 'Docblock comment'), {
c(1, {
sn(
nil,
fmta(
[[
/**
* #~
*/
]],
{ i(1) }
)
),
sn(nil, fmta('/** #~ */', { i(1) })),
}),
}),
s(etr('@v', '@var docblock'), fmta('/** @var #~ $#~ */', { i(1), i(0) })),
s(ctr('@v', '@var docblock'), fmta('@var #~ $#~', { i(1), i(0) })),
s(Etr('@pi', '@phpstan-ignore'), fmta('// @phpstan-ignore #~ (#~)', { i(1), i(0) })),
s(ctr('* @pr', 'Class property docblock'), fmta('* @property #~ $#~', { i(1), i(0) })),
s(ctr('* @pb', 'Class boolean property docblock'), fmta('* @property bool $#~', { i(0) })),
s(ctr('* @pi', 'Class int property docblock'), fmta('* @property int $#~', { i(0) })),
s(ctr('* @ps', 'Class string property docblock'), fmta('* @property string $#~', { i(0) })),
s(ctr('* @pc', 'Class collection property docblock'), fmta('* @property \\Illuminate\\Database\\Eloquent\\Collection<#~> $#~', { i(1), i(0) })),
s(ctr('* @pd', 'Class date property docblock'), fmta('* @property \\Illuminate\\Support\\Carbon $#~', { i(0) })),
s(
etr('@pm', 'Model magic properties docblock'),
fmta(
[[
/**
* @property int $id
* #~
* @property \Illuminate\Support\Carbon $created_at
* @property \Illuminate\Support\Carbon $updated_at
*
* Relationships
* #~
*/
]],
{ i(1), i(0) }
)
),
------------
-- SYNTAX --
------------
s(
etr('if ', 'if block'),
fmta(
[[
if (#~) {
#~
}
]],
{ i(1), i(0) }
)
),
s(
etr('fe ', 'foreach block'),
fmta(
[[
foreach (#~ as #~) {
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(etr('foreach', 'foreach block'), fmta('fe', {})),
s(
etr('for ', 'for block'),
fmta(
[[
for (#~; #~; #~) {
#~
}
]],
{ i(1, '$i'), i(2), i(3, '$i++'), i(0) }
)
),
s(etr('return ', 'Add semicolon after return'), fmta('return #~;', { i(0) })),
s(atr(' use ', 'Add use to function'), fmta(' use (#~)', { i(0) })),
s(etr('rt ', 'return alias'), fmta('return #~;', { i(0) })),
bs(atr('fn ', 'Shorthand function block'), {
c(1, {
sn(nil, fmta('fn (#~) => #~', { i(1), i(2) })),
sn(
nil,
fmta(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
}),
}),
bs(atr('fun ', 'Shorthand function block'), {
c(1, {
sn(
nil,
fmta(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmta(
[[
function (#~) use (#~) {
#~
}
]],
{ i(1), i(2), i(3) }
)
),
}),
}),
-- s(
-- etr('con', 'Constructor function block'),
-- c(1, {
-- sn(
-- nil,
-- fmta(
-- [[
-- public function __construct(#~)
-- {
-- #~
-- }
-- ]],
-- { i(1), i(2) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- public function __construct(
-- #~
-- ) {
-- #~
-- }
-- ]],
-- { i(1), i(2) }
-- )
-- ),
-- })
-- ),
bs(atr('function', 'Shorthand function block'), fmta('fun', {})),
bs(atr('s%$', 'string type parameter'), fmta('string $#~', { i(0, 'var') })),
bs(atr('i%$', 'int type parameter'), fmta('int $#~', { i(0, 'var') })),
bs(atr('b%$', 'bool type parameter'), fmta('bool $#~', { i(0, 'var') })),
bs(atr('a%$', 'array type parameter'), fmta('array $#~', { i(0, 'var') })),
s(atr('$ ', 'Expand $this->'), fmta('$this->#~', { i(0) })),
bs(etr('am ', 'array_map function'), {
c(1, {
sn(nil, fmta('array_map(fn (#~) => #~, #~)', { i(2), i(3), i(1) })),
sn(
nil,
fmta(
[[
array_map(function (#~) {
#~
}, #~)
]],
{ i(2), i(0), i(1) }
)
),
}),
}),
bs(etr('array_map', 'array_map function'), fmta('am', {})),
bs(etr('af ', 'array_filter function'), {
c(1, {
sn(nil, fmta('array_filter(#~, fn (#~) => #~)', { i(1), i(2), i(3) })),
sn(
nil,
fmta(
[[
array_filter(#~, function (#~) {
#~
})
]],
{ i(1), i(2), i(0) }
)
),
}),
}),
bs(etr('array_filter', 'array_filter function'), fmta('af', {})),
s(
etr('php', 'php class'),
fmta(
[[
<?php
declare(strict_types=1);
namespace #~;
class #~
{
public function __construct()
{
#~
}
}
]],
{ f(psr_namespace, {}), f(class_name, {}), i(0) }
)
),
s(
etr('met', 'public class method'),
fmta(
[[
public function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
etr('pmet', 'protected class method'),
fmta(
[[
protected function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
etr('smet', 'public static class method'),
fmta(
[[
public static function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
etr('spmet', 'protected static class method'),
fmta(
[[
protected static function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
-------------
-- PROJECT --
-------------
s(
etr('test', 'Create a test function'),
fmta(
[[
test('#~', function () {
#~
});
]],
{ i(1), i(0) }
)
),
s(
etr('it ', 'Create a test function'),
fmta(
[[
it('#~', function () {
#~
});
]],
{ i(1), i(0) }
)
),
s(etr('nn ', 'Assert not null'), fmta('Assert::notNull(#~)', { i(0) })),
-------------
-- LARAVEL --
-------------
s(
etr('bt', 'belongsTo Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\#~, $this>
*/
public function #~(): BelongsTo
{
return $this->belongsTo(#~::class);
}
]],
{ rep(1), i(2), i(1) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\#~, $this>
*/
public function #~(): BelongsTo
{
return $this->belongsTo(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
})
),
s(
etr('hm', 'hasMany Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\#~, $this>
*/
public function #~(): HasMany
{
return $this->hasOne(#~::class);
}
]],
{ rep(1), i(2), i(1) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\#~, $this>
*/
public function #~(): HasMany
{
return $this->hasOne(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
})
),
s(
etr('ho', 'hasOne Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\#~, $this>
*/
public function #~(): HasOne
{
return $this->hasOne(#~::class);
}
]],
{ rep(1), i(2), i(1) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\#~, $this>
*/
public function #~(): HasOne
{
return $this->hasOne(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
})
),
s(
etr('bm', 'belongsToMany Laravel relationship method'),
c(1, {
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\#~, $this>
*/
public function #~(): BelongsToMany
{
return $this->belongsToMany(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(3) }
)
),
sn(
nil,
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\#~, $this>
*/
public function #~(): BelongsToMany
{
return $this->belongsToMany(#~::class, #~, #~);
}
]],
{ rep(1), i(2), i(1), i(3), i(4) }
)
),
})
),
-- s(
-- atr('->wr', 'Eloquent where method'),
-- c(0, {
-- sn(nil, fmta("->where('#~', #~)", { i(1), i(0) })),
-- sn(nil, fmta('->where(fn ($query) => #~)', { i(0) })),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->where(function ($query) {
-- #~
-- })
-- ]],
-- { i(0) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->where(function ($query) use (#~) {
-- #~
-- })
-- ]],
-- { i(1), i(0) }
-- )
-- ),
-- })
-- ),
-- s(atr('->wi', 'Eloquent where in method'), fmta("->whereIn('#~', #~)", { i(1), i(0) })),
-- s(atr('->wn', 'Eloquent where not in method'), fmta("->whereNotIn('#~', #~)", { i(1), i(0) })),
-- s(
-- atr('->wha', 'Eloquent where has method'),
-- c(0, {
-- sn(nil, fmta("->whereHas('#~')", { i(1) })),
-- sn(nil, fmta("->whereHas('#~', fn ($query) => #~)", { i(1), i(0) })),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereHas('#~', function ($query) {
-- #~
-- })
-- ]],
-- { i(1), i(0) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereHas('#~', function ($query) use (#~) {
-- #~
-- })
-- ]],
-- { i(1), i(2), i(0) }
-- )
-- ),
-- })
-- ),
-- s(
-- atr('->we', 'Eloquent where exists method'),
-- c(0, {
-- sn(nil, fmta('->whereExists(fn ($query) => #~)', { i(0) })),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereExists(function ($query) {
-- #~
-- })
-- ]],
-- { i(0) }
-- )
-- ),
-- sn(
-- nil,
-- fmta(
-- [[
-- ->whereExists(function ($query) use (#~) {
-- #~
-- })
-- ]],
-- { i(1), i(0) }
-- )
-- ),
-- })
-- ),
}

152
lua/snippets/snip_utils.lua Normal file
View File

@@ -0,0 +1,152 @@
local ls = require 'luasnip'
local s = ls.snippet
local sn = ls.snippet_node
local fn = ls.function_node
local ms = ls.multi_snippet
local t = ls.text_node
local c = ls.choice_node
local i = ls.insert_node
local f = ls.function_node
local d = ls.dynamic_node
local fmt = require('luasnip.extras.fmt').fmt
local rep = require('luasnip.extras').rep
local line_begin = require('luasnip.extras.conditions').line_begin
local line_end = require('luasnip.extras.conditions').line_end
local extend_decorator = require 'luasnip.util.extend_decorator'
local fmta = extend_decorator.apply(fmt, { delimiters = '#~' })
local utils = {}
--- Check if the trigger is at the beginning of a line
---@param line_to_cursor string
---@param matched_trigger string
---@return boolean
utils.line_begin = function(line_to_cursor, matched_trigger)
return line_to_cursor:sub(1, -(#matched_trigger + 1)):match '^%s*$'
end
--- Check if the trigger is on an empty line
---@param _ string
---@param matched_trigger string
---@return boolean
utils.empty_line = function(_, matched_trigger)
return vim.api.nvim_get_current_line():match('^%s*' .. vim.pesc(matched_trigger) .. '$')
end
--- Check if the trigger is at the start of a file
---@param line_to_cursor string
---@param matched_trigger string
---@return boolean
utils.file_begin = function(line_to_cursor, matched_trigger)
local line_number = vim.fn.line '.'
return line_number == 1 and line_begin(line_to_cursor, matched_trigger)
end
--- Check if the trigger is inside a string
---@return boolean
utils.in_string = function()
local node_type = vim.treesitter.get_node():type()
return node_type == 'string_content' or node_type == 'string'
end
--- Check if the trigger is inside a comment
---@return boolean
utils.in_comment = function()
local node_type = vim.treesitter.get_node():type()
return node_type == 'comment'
end
--- Check if the trigger is not inside a string or a comment
---@return boolean
utils.not_in_string_or_comment = function()
return (not utils.in_string()) and (not utils.in_comment())
end
--- Create a basic auto expand trigger
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.tr = function(trigger, description, options)
return vim.tbl_extend('force', {
trig = trigger,
desc = description,
snippetType = 'autosnippet',
}, options or {})
end
--- Create a trigger for an empty line snippet
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.etr = function(trigger, description, options)
return utils.tr(trigger, description, vim.tbl_extend('force', { condition = utils.empty_line }, options or {}))
end
--- Create a trigger for a comment trigger
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.ctr = function(trigger, description, options)
return utils.tr(trigger, description, vim.tbl_extend('force', { condition = utils.in_comment }, options or {}))
end
--- Create a trigger for a snippet to expand anywhere outside a string/comment
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.atr = function(trigger, description, options)
return utils.tr(
trigger,
description,
vim.tbl_extend('force', {
regTrig = true,
wordTrig = false,
condition = utils.not_in_string_or_comment,
}, options or {})
)
end
--- Create a trigger for a snippet to expand at the end of a line
---@param trigger string
---@param description? string
---@param options? table
---@return table
utils.Etr = function(trigger, description, options)
return utils.tr(
trigger,
description,
vim.tbl_extend('force', {
condition = line_end
}, options or {})
)
end
--- Create a snippet that will expand anywhere but in the middle of a word
---@param trigger any
---@param nodes any
---@param options? any
---@return table
utils.bs = function(trigger, nodes, options)
local btrigger
if type(trigger) == 'string' then
btrigger = utils.atr('([^%w_-])' .. trigger)
else
btrigger = vim.tbl_extend('keep', utils.atr('([^%w_-])' .. trigger.trig), trigger)
end
return ms(
{
trigger,
btrigger,
},
vim.list_extend({ fn(function(args, snip)
return snip.captures[1] or ''
end) }, nodes),
options
)
end
return utils

View File

@@ -0,0 +1,53 @@
local progress = require 'fidget.progress'
local M = {}
M.handles = {}
function M:store_progress_handle(id, handle)
M.handles[id] = handle
end
function M:pop_progress_handle(id)
local handle = M.handles[id]
M.handles[id] = nil
return handle
end
function M:create_progress_handle(request)
-- Ensure request.data and request.data.adapter exist before accessing them
local strategy = request.data and request.data.strategy or 'unknown'
local adapter_info = request.data and request.data.adapter or {}
return progress.handle.create {
title = ' Requesting assistance (' .. strategy .. ')',
message = 'In progress...',
lsp_client = {
name = M:llm_role_title(adapter_info),
},
}
end
function M:llm_role_title(adapter)
local parts = {}
-- Use adapter.formatted_name if available, otherwise default
local name = adapter.formatted_name or 'LLM'
table.insert(parts, name)
if adapter.model and adapter.model ~= '' then
table.insert(parts, '(' .. adapter.model .. ')')
end
return table.concat(parts, ' ')
end
function M:report_exit_status(handle, request)
-- Ensure request.data exists before accessing status
local status = request.data and request.data.status or 'unknown'
if status == 'success' then
handle.message = 'Completed'
elseif status == 'error' then
handle.message = ' Error'
else -- Includes "cancelled" or any other status
handle.message = '󰜺 Cancelled/Other'
end
end
return M

8
lua/visuals.lua Normal file
View File

@@ -0,0 +1,8 @@
require('helpers').edit_cf('c', '/lua/visuals.lua')
local line_number_color = '#5d6487'
vim.cmd('highlight LineNr guifg=' .. line_number_color)
vim.cmd('highlight LineNrAbove guifg=' .. line_number_color)
vim.cmd('highlight LineNrBelow guifg=' .. line_number_color)
vim.api.nvim_set_hl(0, "CopilotSuggestion", { fg = "#888888", italic = true })