Compare commits

42 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
39 changed files with 1924 additions and 751 deletions

View File

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

View File

@@ -12,6 +12,7 @@ require 'keymap'
require 'autocmd' require 'autocmd'
require 'lazy_init' require 'lazy_init'
require 'visuals' require 'visuals'
require 'projects'
require('helpers').edit_cf('v', '/init.lua') require('helpers').edit_cf('v', '/init.lua')
@@ -19,7 +20,7 @@ require('helpers').edit_cf('v', '/init.lua')
TODO: Neovim configurations I want to add: TODO: Neovim configurations I want to add:
- [x] Clearer line numbers (weirdly not as simple as it sounds) - [x] Clearer line numbers (weirdly not as simple as it sounds)
- [ ] Debugging keymap that works like PHPStorm - [ ] Debugging keymap that works like PHPStorm
- [ ] Improve snippet expansion (an get rid of that stupid #endsection snippet) - [ ] 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) - [ ] 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 test panel when opening debugger and vice versa using edgy
- [ ] Close terminal from inside terminal buffer - [ ] Close terminal from inside terminal buffer

View File

@@ -26,6 +26,14 @@ vim.api.nvim_create_autocmd('InsertLeave', {
command = 'silent! wa', -- Save all files when leaving insert mode 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', { -- vim.api.nvim_create_autocmd('TextChanged', {
-- group = autosave_group, -- group = autosave_group,
-- pattern = '*', -- pattern = '*',

View File

@@ -16,5 +16,43 @@ 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,6 +1,8 @@
-- [[ 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', 'v' }, ':', ';') vim.keymap.set({ 'n', 'v' }, ':', ';')
vim.keymap.set({ 'n', 'v' }, ';', ':') vim.keymap.set({ 'n', 'v' }, ';', ':')
@@ -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,19 +26,127 @@ 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' })
vim.keymap.set('n', '<Leader>c', function()
vim.treesitter.inspect_tree()
end, { desc = 'Treesitter' })
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>tabnext<CR>', { desc = 'Next tab' })
vim.keymap.set('n', '<Leader>,', '<Cmd>tabprevious<CR>', { desc = 'Previous tab' }) vim.keymap.set('n', '<Leader>,', '<Cmd>tabprevious<CR>', { desc = 'Previous tab' })
@@ -56,7 +170,7 @@ vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-S-P>', function()
hidden = true, hidden = true,
} }
end, { desc = 'Find all files' }) end, { desc = 'Find all files' })
vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-F>', function() vim.keymap.set({ 'n', 'v', 'c', 'i' }, '<C-f>', function()
require('telescope.builtin').live_grep { require('telescope.builtin').live_grep {
hidden = true, hidden = true,
} }
@@ -89,24 +203,12 @@ vim.keymap.set('n', '<Leader>{', 'mzF[`a<CR><Esc>``%i<CR><Esc>`z', { desc = 'Ind
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?' }) 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 -- Git mappings
vim.keymap.set('n', '<Leader>gaf', '<CMD>Git add %<CR>', { desc = 'Git add current file' })
vim.keymap.set('n', '<Leader>gaa', '<CMD>Git add --all<CR>', { desc = 'Git add all unstaged changes' })
vim.keymap.set('n', '<Leader>gap', '<CMD>Git add --patch --all<CR>', { desc = 'Git add all unstaged changes interactively' })
vim.keymap.set('n', '<Leader>gb', '<CMD>Git blame<CR>', { desc = 'Git blame' }) vim.keymap.set('n', '<Leader>gb', '<CMD>Git blame<CR>', { desc = 'Git blame' })
vim.keymap.set('n', '<Leader>gcm', '<CMD>Git commit -v<CR>', { desc = 'Git commit' })
vim.keymap.set('n', '<Leader>gp', '<CMD>Git push<CR>', { desc = 'Git push' })
vim.keymap.set('n', '<Leader>gup', '<CMD>Git pull --rebase<CR>', { desc = 'Git pull --rebase' })
vim.keymap.set('n', '<Leader>gsb', '<CMD>Git status<CR>', { desc = 'Git status' })
vim.keymap.set('n', '<Leader>gd', '<CMD>Git diff<CR>', { desc = 'Git diff' }) vim.keymap.set('n', '<Leader>gd', '<CMD>Git diff<CR>', { desc = 'Git diff' })
vim.keymap.set('n', '<Leader>gf', '<CMD>Git fetch<CR>', { desc = 'Git fetch' })
vim.keymap.set('n', '<Leader>gdc', '<CMD>Git diff --cached<CR>', { desc = 'Git diff' }) vim.keymap.set('n', '<Leader>gdc', '<CMD>Git diff --cached<CR>', { desc = 'Git diff' })
vim.keymap.set('n', '<Leader>gl', '<CMD>Git log<CR>', { desc = 'Git log' }) vim.keymap.set('n', '<Leader>G', function()
vim.keymap.set('n', '<Leader>gun', '<CMD>Git reset -- %<CR>', { desc = 'Git unstage file' }) helpers.open_term { cmd = 'lazygit' }
vim.keymap.set('n', '<Leader>gco', '<CMD>Git checkout -- %<CR>', { desc = 'Git checkout' }) end, { desc = 'Git' })
vim.keymap.set('n', '<Leader>G', '<CMD>Git', { desc = 'Git' })
vim.keymap.set('n', '<Leader>gsta', '<CMD>Git stash push<CR>', { desc = 'Git stash' })
vim.keymap.set('n', '<Leader>gstA', '<CMD>Git stash apply<CR>', { desc = 'Git stash apply' })
vim.keymap.set('n', '<Leader>gstp', '<CMD>Git stash pop<CR>', { desc = 'Git stash pop' })
-- Add keymaps for diff mode -- Add keymaps for diff mode
vim.api.nvim_create_autocmd('BufEnter', { vim.api.nvim_create_autocmd('BufEnter', {
@@ -135,7 +237,7 @@ vim.api.nvim_create_autocmd('FileType', {
vim.keymap.set('i', '<S-Enter>', '<Enter>', { buffer = true, desc = 'Use shift enter to start a new line' }) 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' }) vim.keymap.set('n', '<Enter>', 'G', { buffer = true, desc = 'Use enter in normal mode to go to the end of the chat' })
local models = { 'gpt-4.1', 'gemini-2.5-pro', 'gemini-2.0-flash-001', 'claude-3.7-sonnet-thought', 'o4-mini' } local models = { vim.env.DEFAULT_AI_MODEL, vim.env.REASONING_MODEL, vim.env.FAST_MODEL }
-- Loop through models and create keymaps for each -- Loop through models and create keymaps for each
for i, model in ipairs(models) do 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('n', '<C-' .. i .. '>', 'mzggj0W"_C' .. model .. '<Esc>`z', { desc = 'Switch to ' .. model })
@@ -156,84 +258,101 @@ vim.keymap.set('n', '<Leader>]', '<CMD>cnext<CR>', { desc = 'Next item in quickf
vim.keymap.set('n', '<Leader>[', '<CMD>cprevious<CR>', { desc = 'Previous 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' }) vim.keymap.set('n', 'gd', '<CMD>Telescope lsp_definitions<CR>', { desc = 'Go to definition' })
local function open_test() local function open_test()
require('neotest').summary.open() require('neotest').summary.open()
require('neotest').output_panel.open() require('neotest').output_panel.open()
end end
-- Testing -- Testing
local test_maps = { -- local test_maps = {
{ -- {
keys = { '<F12>', '<Leader>tn' }, -- keys = { '<F12>', '<Leader>tn' },
action = function() -- action = function()
require('neotest').run.run() -- require('neotest').run.run()
open_test() -- open_test()
end, -- end,
desc = 'Run nearest test', -- desc = 'Run nearest test',
}, -- },
{ -- {
keys = { '<F9>', '<Leader>ta' }, -- keys = { '<F9>', '<Leader>ta' },
action = function() -- action = function()
require('neotest').run.run { suite = true } -- require('neotest').run.run { suite = true }
open_test() -- open_test()
end, -- end,
desc = 'Run all tests in the project', -- desc = 'Run all tests in the project',
}, -- },
{ -- {
keys = { '<F11>', '<Leader>tp' }, -- keys = { '<F11>', '<Leader>tp' },
action = function() -- action = function()
require('neotest').run.run_last() -- require('neotest').run.run_last()
open_test() -- open_test()
end, -- end,
desc = 'Run previous test again', -- desc = 'Run previous test again',
}, -- },
{ -- {
keys = { '<F10>', '<Leader>td' }, -- keys = { '<F10>', '<Leader>td' },
action = function() -- action = function()
local dap = require 'dap' -- local dap = require 'dap'
if dap.session() == nil then -- if dap.session() == nil then
dap.continue() -- dap.continue()
end -- end
require('dapui').open() -- require('dapui').open()
local neotest = require 'neotest' -- local neotest = require 'neotest'
local bufnr = vim.api.nvim_get_current_buf() -- local bufnr = vim.api.nvim_get_current_buf()
local row = vim.api.nvim_win_get_cursor(0)[1] - 1 -- 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' })
local adapters = neotest.state.adapter_ids() -- vim.keymap.set('i', '<Tab>', function()
local found = false -- local copilot = require 'copilot.suggestion'
-- local ls = require 'luasnip'
for _, adapter_id in ipairs(adapters) do -- if copilot.is_visible() then
local tree = neotest.state.positions(adapter_id, { buffer = bufnr }) -- vim.api.nvim_echo({{'Accepting copilot suggestion'}}, false, {})
if tree then -- copilot.accept()
local nearest = require('neotest.lib.positions').nearest(tree, row) -- copilot.dismiss()
if nearest and nearest:data().type ~= 'file' then -- elseif ls.jumpable(1) then
neotest.run.run() -- vim.api.nvim_echo({{'Jumping in snippet'}}, false, {})
found = true -- ls.jump()
break -- else
end -- vim.api.nvim_echo({{'Inserting tab'}}, false, {})
end -- vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes('<Tab>', true, true, true), 'n', true)
end -- end
-- end, { desc = 'Luasnip accept copilot or jump forward' })
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' })
-- Leaving this commented out, I will try the format command instead -- Leaving this commented out, I will try the format command instead
-- "A command to properly indent json code -- "A command to properly indent json code
@@ -243,8 +362,11 @@ end, { desc = 'Close test panels' })
-- directory if the file does not exist -- directory if the file does not exist
vim.keymap.set('n', '<Leader>es', function() vim.keymap.set('n', '<Leader>es', function()
local ft = vim.bo.filetype local ft = vim.bo.filetype
if ft == 'vue' then
ft = 'javascript'
end
local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets' local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets'
local snippets_file = snippets_dir .. '/' .. ft .. '.json' local snippets_file = snippets_dir .. '/' .. ft .. '.lua'
vim.cmd('tabedit ' .. snippets_file) vim.cmd('tabedit ' .. snippets_file)
end, { desc = 'Edit snippets file' }) end, { desc = 'Edit snippets file' })

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,
}

View File

@@ -1,5 +1,11 @@
require('helpers').edit_cf('pa', '/lua/plugins/aider.lua') 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 { return {
'GeorgesAlkhouri/nvim-aider', 'GeorgesAlkhouri/nvim-aider',
cmd = 'Aider', cmd = 'Aider',
@@ -15,71 +21,10 @@ return {
-- Example nvim-tree.lua integration if needed -- Example nvim-tree.lua integration if needed
{ '<leader>a+', '<cmd>AiderTreeAddFile<cr>', desc = 'Add File from Tree to Aider', ft = 'NvimTree' }, { '<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>a-', '<cmd>AiderTreeDropFile<cr>', desc = 'Drop File from Tree from Aider', ft = 'NvimTree' },
-- Open aider with gpt-4.1 as the main model { '<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>a?', { '<leader>amg', change_model_function 'openai/gemini-2.5-pro', desc = 'Switch aider model to Gemini 2.5 Pro' },
-- function() { '<leader>ams', change_model_function 'openai/claude-sonnet-4', desc = 'Switch aider model to Claude Sonnet 4' },
-- require('nvim_aider').setup {
-- aider_cmd = 'aider',
-- args = {
-- '--config=$HOME/.config/aider/aider.yaml',
-- '--env-file=$(pwd)/.aider.env',
-- '--model=gpt-4.1',
-- },
-- auto_reload = true,
-- win = {
-- wo = { winbar = 'Aider (GPT-4.1)' },
-- style = 'nvim_aider',
-- position = 'bottom',
-- },
-- }
-- vim.cmd 'Aider toggle'
-- end,
-- desc = 'Open Aider with GPT-4.1',
-- },
-- {
-- '<leader>a>',
-- function()
-- require('nvim_aider').setup {
-- aider_cmd = 'aider',
-- args = {
-- '--config=$HOME/.config/aider/aider.yaml',
-- '--env-file=$(pwd)/.aider.env',
-- '--model=openai/gemini-2.5-pro',
-- '--architect',
-- },
-- auto_reload = true,
-- win = {
-- wo = { winbar = 'Aider (Gemini-2.5-Pro)' },
-- style = 'nvim_aider',
-- position = 'bottom',
-- },
-- }
-- vim.cmd 'Aider toggle'
-- end,
-- desc = 'Open Aider with Gemini 2.5 Pro',
-- },
-- {
-- '<leader>a4',
-- function()
-- require('nvim_aider').api.send_command('/model', 'gpt-4.1')
-- end,
-- desc = 'Switch aider model to GPT-4.1',
-- },
-- {
-- '<leader>ao',
-- function()
-- require('nvim_aider').api.send_command('/model', 'o4-mini')
-- end,
-- desc = 'Switch aider model to o4-mini',
-- },
-- {
-- '<leader>ag',
-- function()
-- require('nvim_aider').api.send_command('/model', 'openai/gemini-2.5-pro')
-- end,
-- desc = 'Switch aider model to Gemini 2.5 Pro',
-- },
}, },
dependencies = { dependencies = {
'folke/snacks.nvim', 'folke/snacks.nvim',
@@ -107,7 +52,7 @@ return {
aider_cmd = 'aider', aider_cmd = 'aider',
args = { args = {
'--config=$HOME/.config/aider/aider.yaml', '--config=$HOME/.config/aider/aider.yaml',
'--env-file=$(pwd)/.aider.env', '--env-file=$(pwd)/aider.env',
'--watch', '--watch',
'--architect', '--architect',
}, },

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,75 +0,0 @@
return {}
-- 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 = 'openai',
-- api_key_name = 'AIHUBMIX_API_KEY',
-- endpoint = 'https://aihubmix.com/v1',
-- 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,10 +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',
'folke/lazydev.nvim', 'folke/lazydev.nvim',
}, },
--- @module 'blink.cmp' --- @module 'blink.cmp'
@@ -36,6 +33,7 @@ return {
-- --
-- See :h blink-cmp-config-keymap for defining your own keymap -- See :h blink-cmp-config-keymap for defining your own keymap
preset = 'enter', 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
@@ -54,7 +52,7 @@ return {
}, },
sources = { sources = {
default = { 'codecompanion', '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 = {} },
@@ -64,7 +62,7 @@ return {
}, },
}, },
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

@@ -1,69 +1,50 @@
vim.cmd [[cab cc CodeCompanion]]
return { return {
'olimorris/codecompanion.nvim', 'olimorris/codecompanion.nvim',
opts = function(_, opts) config = function()
opts.adapters = { require('codecompanion').setup {
gpt = function() adapters = {
http = {
default = function()
if (require('helpers').has_copilot()) then
return require('codecompanion.adapters').extend('copilot', { return require('codecompanion.adapters').extend('copilot', {
schema = { schema = {
model = { model = {
default = 'gpt-4.1', default = vim.env.DEFAULT_AI_MODEL,
}, },
max_tokens = { max_tokens = {
default = 1000000, default = 1000000,
}, },
},
})
end,
flash = function()
return require('codecompanion.adapters').extend('copilot', {
schema = {
model = {
default = 'gemini-2.0-flash-001',
},
max_tokens = {
default = 1000000,
},
},
})
end,
gemini = function()
return require('codecompanion.adapters').extend('copilot', {
schema = {
model = {
default = 'gemini-2.5-pro',
},
max_tokens = {
default = 1000000,
},
},
})
end,
sonnet = function()
return require('codecompanion.adapters').extend('copilot', {
schema = {
model = {
default = 'claude-3.7-sonnet',
},
max_tokens = {
default = 1000000,
},
},
})
end,
} }
})
opts.display = { 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 = { chat = {
show_settings = true, show_settings = true,
start_in_insert_mode = false, start_in_insert_mode = false,
}, },
} },
strategies = {
opts.strategies = {
chat = { chat = {
adapter = 'gpt', adapter = 'default',
slash_commands = { slash_commands = {
-- codebase = require('vectorcode.integrations').codecompanion.chat.make_slash_command(), -- codebase = require('vectorcode.integrations').codecompanion.chat.make_slash_command(),
}, },
@@ -94,11 +75,19 @@ return {
}, },
}, },
inline = { inline = {
adapter = 'flash', adapter = {
name = 'default',
model = vim.env.FAST_MODEL,
}, },
} },
cmd = {
opts.extensions = { adapter = {
name = 'default',
model = vim.env.FAST_MODEL,
},
},
},
extensions = {
mcphub = { mcphub = {
callback = 'mcphub.extensions.codecompanion', callback = 'mcphub.extensions.codecompanion',
opts = { opts = {
@@ -107,9 +96,8 @@ return {
make_slash_commands = true, make_slash_commands = true,
}, },
}, },
} },
system_prompt = function(opts)
opts.system_prompt = function(opts)
local language = opts.language or 'English' local language = opts.language or 'English'
return string.format( 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. [[You are an AI programming assistant named "CodeCompanion". You are currently plugged into the Neovim text editor on a user's machine.
@@ -149,12 +137,11 @@ When given a task:
5. If necessary, execute multiple tools in a single turn.]], 5. If necessary, execute multiple tools in a single turn.]],
language language
) )
end end,
prompt_library = {
opts.prompt_library = {
['Code Expert'] = { ['Code Expert'] = {
strategy = 'chat', strategy = 'chat',
description = 'Get some special adcvice from an LLM.', description = 'Get some special advice from an LLM.',
opts = { opts = {
mapping = '<Leader>ce', mapping = '<Leader>ce',
modes = { 'v' }, modes = { 'v' },
@@ -340,6 +327,7 @@ We'll repeat this cycle until there are no errors. Ensure no deviations from the
}, },
}, },
}, },
},
} }
end, end,
dependencies = { dependencies = {

View File

@@ -12,7 +12,8 @@ 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
@@ -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 +0,0 @@
return {
'github/copilot.vim',
}

View File

@@ -121,7 +121,9 @@ return {
dap.adapters.php = { dap.adapters.php = {
type = 'executable', type = 'executable',
command = 'node', command = 'node',
args = { '/Users/chris/.local/src/vscode-php-debug/out/phpDebug.js' }, args = {
vim.fn.expand '$MASON/packages/php-debug-adapter/extension/out/phpDebug.js',
},
} }
dap.configurations.php = { dap.configurations.php = {
@@ -160,10 +162,10 @@ return {
}, },
element_mappings = { element_mappings = {
stacks = { stacks = {
open = "<CR>", open = '<CR>',
expand = "o", expand = 'o',
} },
} },
} }
-- Change breakpoint icons -- Change breakpoint icons

View File

@@ -4,9 +4,10 @@ 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['javascript'] = nil
lint.linters_by_ft['vue'] = nil lint.linters_by_ft['vue'] = nil
lint.linters_by_ft['html'] = nil lint.linters_by_ft['html'] = nil

View File

@@ -13,6 +13,9 @@ return {
'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()
-- 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
@@ -125,7 +128,6 @@ return {
local vue_language_server_path = vim.fn.expand '$MASON/packages/vue-language-server/node_modules/@vue/language-server' local vue_language_server_path = vim.fn.expand '$MASON/packages/vue-language-server/node_modules/@vue/language-server'
local servers = { local servers = {
clangd = {}, clangd = {},
gopls = {},
pyright = {}, pyright = {},
rust_analyzer = {}, rust_analyzer = {},
lua_ls = { lua_ls = {
@@ -137,13 +139,7 @@ return {
}, },
}, },
}, },
phpactor = { phpactor = {},
init_options = {
['language_server_phpstan.enabled'] = false,
['language_server_psalm.enabled'] = false,
['language_server_php_cs_fixer.enabled'] = false,
},
},
vtsls = { vtsls = {
settings = { settings = {
vtsls = { vtsls = {
@@ -158,13 +154,19 @@ return {
}, },
}, },
}, },
javascript = {
preferences = {
importModuleSpecifierPreference = 'non-relative',
importModuleSpecifierEnding = 'js',
},
},
}, },
filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' }, filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' },
}, },
['vue-language-server'] = { ['vue-language-server'] = {
on_init = function(client) on_init = function(client)
client.handlers['tsserver/request'] = function(_, result, context) client.handlers['tsserver/request'] = function(_, result, context)
local clients = vim.lsp.get_clients({ bufnr = context.bufnr, name = 'vtsls' }) local clients = vim.lsp.get_clients { bufnr = context.bufnr, name = 'vtsls' }
if #clients == 0 then if #clients == 0 then
vim.notify('Could not find `vtsls` lsp client, `vue-language-server` would not work without it.', vim.log.levels.ERROR) vim.notify('Could not find `vtsls` lsp client, `vue-language-server` would not work without it.', vim.log.levels.ERROR)
return return
@@ -186,7 +188,7 @@ return {
client:notify('tsserver/response', response_data) client:notify('tsserver/response', response_data)
end) end)
end end
end end,
}, },
} }

View File

@@ -1,16 +0,0 @@
return {
'ravitemer/mcphub.nvim',
dependencies = {
'nvim-lua/plenary.nvim', -- Required for Job and HTTP requests
},
-- uncomment the following line to load hub lazily
cmd = 'MCPHub', -- lazy load
build = 'npm install -g mcp-hub@latest', -- Installs required mcp-hub npm module
-- uncomment this if you don't want mcp-hub to be available globally or can't use -g
-- build = "bundled_build.lua", -- Use this and set use_bundled_binary = true in opts (see Advanced configuration)
config = function()
require('mcphub').setup({
auto_approve = true,
})
end,
}

View File

@@ -25,16 +25,36 @@ return {
require('mini.pairs').setup() require('mini.pairs').setup()
-- require('mini.jump').setup() require('mini.jump').setup {
mappings = {
repeat_jump = ':',
},
}
require('mini.jump2d').setup() 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.splitjoin').setup()
require('mini.map').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

View File

@@ -1,39 +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 = function(_, opts)
local function on_move(data)
Snacks.rename.on_rename_file(data.source, data.destination)
end
local events = require("neo-tree.events")
opts.event_handlers = opts.event_handlers or {}
vim.list_extend(opts.event_handlers, {
{ event = events.FILE_MOVED, handler = on_move },
{ event = events.FILE_RENAMED, handler = on_move },
})
opts.filesystem = {
window = {
mappings = {
['\\'] = 'close_window',
},
},
filtered_items = {
hide_dotfiles = false,
},
}
end,
}

View File

@@ -1,27 +0,0 @@
require('helpers').edit_cf('pt', '/lua/plugins/neotest.lua')
return {
'nvim-neotest/neotest',
lazy = true,
dependencies = {
'nvim-neotest/nvim-nio',
'nvim-lua/plenary.nvim',
'antoinemadec/FixCursorHold.nvim',
'nvim-treesitter/nvim-treesitter',
-- Adapters
'V13Axel/neotest-pest',
-- "olimorris/neotest-phpunit",
},
config = function()
require('neotest').setup {
adapters = {
require 'neotest-pest' {
sail_enabled = function()
return false
end,
parallel = 10,
},
-- require('neotest-phpunit'),
},
}
end,
}

View File

@@ -1,7 +1,7 @@
-- Filesystem manager -- Filesystem manager
require('helpers').edit_cf('po', '/lua/plugins/oil.lua') -- require('helpers').edit_cf('po', '/lua/plugins/oil.lua')
--
vim.keymap.set('n', '-', '<CMD>Oil<CR>', { desc = 'Open parent directory' }) -- vim.keymap.set('n', '-', '<CMD>Oil<CR>', { desc = 'Open parent directory' })
return { return {
'stevearc/oil.nvim', 'stevearc/oil.nvim',
@@ -13,6 +13,7 @@ return {
}, },
keymaps = { keymaps = {
['<C-p>'] = false, ['<C-p>'] = false,
['-'] = false,
}, },
}, },
-- Optional dependencies -- Optional dependencies

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,
}

View File

@@ -11,21 +11,16 @@ return {
return 'make install_jsregexp' return 'make install_jsregexp'
end)(), end)(),
config = function() config = function()
local ls = require 'luasnip'
ls.filetype_extend('vue', { 'javascript' })
local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets' local snippets_dir = vim.fn.stdpath 'config' .. '/lua/snippets'
require('luasnip.loaders.from_vscode').lazy_load { require('luasnip.loaders.from_lua').load {
paths = { snippets_dir }, paths = { snippets_dir },
} }
ls.setup {
update_events = 'TextChanged,TextChangedI',
enable_autosnippets = true,
}
end, 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 = {}, 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,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,
}

View File

@@ -1,13 +0,0 @@
require('helpers').edit_cf('pv', '/lua/plugins/vectorcode.lua')
return {}
-- return {
-- 'Davidyz/VectorCode',
-- version = '*', -- optional, depending on whether you're on nightly or release
-- dependencies = { 'nvim-lua/plenary.nvim' },
-- build = 'pipx upgrade vectorcode',
-- cmd = 'VectorCode', -- if you're lazy-loading VectorCode
-- opts = {
-- async_backend = 'lsp',
-- },
-- }

View File

@@ -1,8 +0,0 @@
if vim.loop.os_uname().sysname == 'Darwin' then
return {
'wakatime/vim-wakatime',
lazy = false,
}
else
return {}
end

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')

View File

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

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

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

View File

@@ -1,9 +0,0 @@
{
"Log function": {
"prefix": "du",
"body": [
"console.log($0);"
],
"description": "Log variable"
}
}

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) }
)
),
}),
}),
}

View File

@@ -1,26 +0,0 @@
{
"name": "example-snippets",
"contributes": {
"snippets": [
{
"language": [
"all"
],
"path": "./snippets/all.json"
},
{
"language": [
"php"
],
"path": "./php.json"
},
{
"language": [
"javascript",
"vue"
],
"path": "./javascript-vue.json"
}
]
}
}

View File

@@ -1,78 +0,0 @@
{
"Dump function": {
"prefix": "du",
"body": [
"dump($0);"
],
"description": "Dump variable"
},
"Type dump function": {
"prefix": "dt",
"body": [
"\\PhpStan\\dumpType($0);"
],
"description": "Dump PHPStan type"
},
"Test case": {
"prefix": "test",
"body": [
"test($1, function () {",
" $0",
"});"
],
"description": "Test case"
},
"Create doc block": {
"prefix": "/**",
"body": [
"/**",
" * $0",
" */"
]
},
"DocBlock property": {
"prefix": "@p",
"body": "@property $1 $$0",
"description": "DocBlock property"
},
"DocBlock boolean property": {
"prefix": "@pb",
"body": "@property bool $$0",
"description": "DocBlock boolean property"
},
"DocBlock string property": {
"prefix": "@ps",
"body": "@property string $$0",
"description": "DocBlock string property"
},
"DocBlock int property": {
"prefix": "@pi",
"body": "@property int $$0",
"description": "DocBlock int property"
},
"DocBlock Collection property": {
"prefix": "@pc",
"body": "@property \\Illuminate\\Support\\Collection<int, $1> $$0",
"description": "DocBlock int property"
},
"DocBlock date property": {
"prefix": "@pd",
"body": "@property \\Illuminate\\Support\\Carbon $$0",
"description": "DocBlock date property"
},
"DocBlock model properties": {
"prefix": "@pp",
"body": [
"/**",
" * @property int $$id",
" * $1",
" * @property \\Illuminate\\Support\\Carbon $$created_at",
" * @property \\Illuminate\\Support\\Carbon $$updated_at",
" *",
" * Relationships",
" * $2",
" */"
],
"description": "DocBlock model properties"
}
}

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

@@ -4,3 +4,5 @@ local line_number_color = '#5d6487'
vim.cmd('highlight LineNr guifg=' .. line_number_color) vim.cmd('highlight LineNr guifg=' .. line_number_color)
vim.cmd('highlight LineNrAbove guifg=' .. line_number_color) vim.cmd('highlight LineNrAbove guifg=' .. line_number_color)
vim.cmd('highlight LineNrBelow guifg=' .. line_number_color) vim.cmd('highlight LineNrBelow guifg=' .. line_number_color)
vim.api.nvim_set_hl(0, "CopilotSuggestion", { fg = "#888888", italic = true })