Compare commits
35 Commits
d4ecc5aa67
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 847c71a194 | |||
|
|
78b8bf177c | ||
|
|
4f8e722f13 | ||
| 1f58b9f136 | |||
|
|
4d3aada204 | ||
|
|
d53821dbf7 | ||
| e89dbcac87 | |||
| 5bf1ec232e | |||
| aded597ffe | |||
|
|
282301e206 | ||
| 9bd219f053 | |||
| 0cce7837f2 | |||
|
|
f79e89d335 | ||
|
|
1f5a3d19f2 | ||
| dc5d2e20ff | |||
| 256a5695ed | |||
| 2a4578e1eb | |||
| 52ae098ac6 | |||
| 1c96d03649 | |||
|
|
344623eaf6 | ||
| f16cb91875 | |||
| 8e2d413e0a | |||
| 2062c442b2 | |||
|
|
2255489fd8 | ||
| a21a1a3386 | |||
| 529cfa79c8 | |||
| f8f6d8e776 | |||
| 5016dd4ee8 | |||
| 37b4d8a6e4 | |||
|
|
d44eac696f | ||
|
|
5c08ce032e | ||
| 9415b1df07 | |||
| 406e5cfe8e | |||
|
|
6a0c90bf26 | ||
|
|
7744e83086 |
@@ -1 +0,0 @@
|
|||||||
AIHUBMIX_API_KEY=
|
|
||||||
1
init.lua
1
init.lua
@@ -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')
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
291
lua/keymap.lua
291
lua/keymap.lua
@@ -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' }, ';', ':')
|
||||||
@@ -24,19 +26,127 @@ vim.keymap.set('v', 'p', '"zdP', { desc = 'Paste over selection without yanking
|
|||||||
-- 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' })
|
||||||
@@ -60,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,
|
||||||
}
|
}
|
||||||
@@ -93,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', {
|
||||||
@@ -139,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 })
|
||||||
@@ -160,84 +258,85 @@ 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 adapters = neotest.state.adapter_ids()
|
||||||
local found = false
|
-- local found = false
|
||||||
|
--
|
||||||
for _, adapter_id in ipairs(adapters) do
|
-- for _, adapter_id in ipairs(adapters) do
|
||||||
local tree = neotest.state.positions(adapter_id, { buffer = bufnr })
|
-- local tree = neotest.state.positions(adapter_id, { buffer = bufnr })
|
||||||
if tree then
|
-- if tree then
|
||||||
local nearest = require('neotest.lib.positions').nearest(tree, row)
|
-- local nearest = require('neotest.lib.positions').nearest(tree, row)
|
||||||
if nearest and nearest:data().type ~= 'file' then
|
-- if nearest and nearest:data().type ~= 'file' then
|
||||||
neotest.run.run()
|
-- neotest.run.run()
|
||||||
found = true
|
-- found = true
|
||||||
break
|
-- break
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
|
--
|
||||||
if not found then
|
-- if not found then
|
||||||
neotest.run.run_last()
|
-- neotest.run.run_last()
|
||||||
end
|
-- end
|
||||||
end,
|
-- end,
|
||||||
desc = 'Run last test with debugger',
|
-- desc = 'Run last test with debugger',
|
||||||
},
|
-- },
|
||||||
}
|
-- }
|
||||||
|
--
|
||||||
for _, map_info in ipairs(test_maps) do
|
-- for _, map_info in ipairs(test_maps) do
|
||||||
for _, key in ipairs(map_info.keys) do
|
-- for _, key in ipairs(map_info.keys) do
|
||||||
vim.keymap.set('n', key, map_info.action, { desc = map_info.desc })
|
-- vim.keymap.set('n', key, map_info.action, { desc = map_info.desc })
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
vim.keymap.set('n', '<Leader>tf', function()
|
-- vim.keymap.set('n', '<Leader>tf', function()
|
||||||
require('neotest').run.run(vim.fn.expand '%')
|
-- require('neotest').run.run(vim.fn.expand '%')
|
||||||
open_test()
|
-- open_test()
|
||||||
end, { desc = 'Run all tests in the current file' })
|
-- end, { desc = 'Run all tests in the current file' })
|
||||||
vim.keymap.set('n', '<Leader>tc', function()
|
-- vim.keymap.set('n', '<Leader>tc', function()
|
||||||
require('neotest').summary.close()
|
-- require('neotest').summary.close()
|
||||||
require('neotest').output_panel.close()
|
-- require('neotest').output_panel.close()
|
||||||
end, { desc = 'Close test panels' })
|
-- end, { desc = 'Close test panels' })
|
||||||
|
|
||||||
-- vim.keymap.set('i', '<Tab>', function()
|
-- vim.keymap.set('i', '<Tab>', function()
|
||||||
-- local copilot = require 'copilot.suggestion'
|
-- local copilot = require 'copilot.suggestion'
|
||||||
|
|||||||
72
lua/plugins/ai-completion.lua
Normal file
72
lua/plugins/ai-completion.lua
Normal 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,
|
||||||
|
}
|
||||||
@@ -21,10 +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' },
|
||||||
{ '<leader>am4', change_model_function('gpt-4.1'), desc = 'Switch aider model to GPT-4.1' },
|
{ '<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>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>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' },
|
{ '<leader>ams', change_model_function 'openai/claude-sonnet-4', desc = 'Switch aider model to Claude Sonnet 4' },
|
||||||
},
|
},
|
||||||
dependencies = {
|
dependencies = {
|
||||||
'folke/snacks.nvim',
|
'folke/snacks.nvim',
|
||||||
@@ -52,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',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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 = {},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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' },
|
|
||||||
-- },
|
|
||||||
-- },
|
|
||||||
-- }
|
|
||||||
@@ -4,7 +4,7 @@ return {
|
|||||||
event = 'VimEnter',
|
event = 'VimEnter',
|
||||||
version = '1.*',
|
version = '1.*',
|
||||||
dependencies = {
|
dependencies = {
|
||||||
'L3MON4D3/LuaSnip',
|
-- 'L3MON4D3/LuaSnip',
|
||||||
'folke/lazydev.nvim',
|
'folke/lazydev.nvim',
|
||||||
},
|
},
|
||||||
--- @module 'blink.cmp'
|
--- @module 'blink.cmp'
|
||||||
@@ -33,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
|
||||||
@@ -51,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 = {} },
|
||||||
@@ -61,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.
|
||||||
|
|||||||
@@ -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,9 +137,8 @@ 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 advice from an LLM.',
|
description = 'Get some special advice from an LLM.',
|
||||||
@@ -340,6 +327,7 @@ We'll repeat this cycle until there are no errors. Ensure no deviations from the
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
end,
|
end,
|
||||||
dependencies = {
|
dependencies = {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
return {
|
|
||||||
'zbirenbaum/copilot.lua',
|
|
||||||
event = 'InsertEnter',
|
|
||||||
config = function()
|
|
||||||
require('copilot').setup {
|
|
||||||
suggestion = {
|
|
||||||
enabled = true,
|
|
||||||
auto_trigger = true,
|
|
||||||
keymap = {
|
|
||||||
accept = '<Tab>',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
filetypes = {
|
|
||||||
yaml = true,
|
|
||||||
markdown = true,
|
|
||||||
gitcommit = true,
|
|
||||||
gitrebase = true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
@@ -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,
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -1,58 +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 },
|
|
||||||
},
|
|
||||||
|
|
||||||
build = function()
|
|
||||||
if vim.fn.executable 'fd' == 0 then
|
|
||||||
local install_cmd
|
|
||||||
if vim.fn.has 'mac' == 1 then
|
|
||||||
install_cmd = 'brew install fd'
|
|
||||||
elseif vim.fn.has 'unix' == 1 then
|
|
||||||
if vim.fn.filereadable '/etc/arch-release' == 1 then
|
|
||||||
install_cmd = 'sudo pacman -S --noconfirm fd'
|
|
||||||
else
|
|
||||||
install_cmd = 'sudo apt-get install -y fd-find'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
vim.notify("Please install 'fd' manually for neo-tree.", vim.log.levels.WARN)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
vim.fn.system(install_cmd)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
@@ -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,
|
|
||||||
}
|
|
||||||
@@ -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
34
lua/plugins/quicker.lua
Normal 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,
|
||||||
|
}
|
||||||
@@ -17,6 +17,10 @@ return {
|
|||||||
require('luasnip.loaders.from_lua').load {
|
require('luasnip.loaders.from_lua').load {
|
||||||
paths = { snippets_dir },
|
paths = { snippets_dir },
|
||||||
}
|
}
|
||||||
|
ls.setup {
|
||||||
|
update_events = 'TextChanged,TextChangedI',
|
||||||
|
enable_autosnippets = true,
|
||||||
|
}
|
||||||
end,
|
end,
|
||||||
opts = {},
|
opts = {},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
10
lua/plugins/treesj.lua
Normal 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,
|
||||||
|
}
|
||||||
@@ -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',
|
|
||||||
-- },
|
|
||||||
-- }
|
|
||||||
@@ -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
32
lua/plugins/yazi.lua
Normal 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
294
lua/projects.lua
Normal 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,45 +1,128 @@
|
|||||||
local ls = require 'luasnip'
|
local ls = require 'luasnip'
|
||||||
local s = ls.snippet
|
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 t = ls.text_node
|
||||||
|
local c = ls.choice_node
|
||||||
local i = ls.insert_node
|
local i = ls.insert_node
|
||||||
local f = ls.function_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 {
|
return {
|
||||||
s('du', { t 'console.log(', i(0), t ');' }),
|
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) }
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
s('vue', {
|
bs(atr('t ', 'this'), fmta('this.#~', { i(0) })),
|
||||||
t { '<template>', '' },
|
|
||||||
t { '', '</template>', '', '', '<script setup>', '' },
|
s(etr('return ', 'Add semicolon after return'), fmta('return #~;', { i(0) })),
|
||||||
i(0),
|
s(etr('rt ', 'return alias'), fmta('return #~;', { i(0) })),
|
||||||
t { '', '</script>', '', '', '<style scoped>', '', '.o-share-page {', '}', '', '</style>' },
|
|
||||||
|
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('fun', {
|
s(
|
||||||
t 'function ',
|
etr('fn ', 'function block'),
|
||||||
i(1),
|
fmta(
|
||||||
t '(',
|
[[
|
||||||
i(2),
|
function #~(#~) {
|
||||||
t ') {',
|
#~
|
||||||
t { '', ' ' },
|
}
|
||||||
i(0),
|
]],
|
||||||
t { '', '}' },
|
{ 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) }
|
||||||
|
)
|
||||||
|
),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
s('afun', {
|
bs(atr('afn ', 'async function block'), {
|
||||||
t 'async function ',
|
c(1, {
|
||||||
i(1),
|
sn(
|
||||||
t '(',
|
nil,
|
||||||
i(2),
|
fmta(
|
||||||
t ') {',
|
[[
|
||||||
t { '', ' ' },
|
async (#~) => {
|
||||||
i(0),
|
#~
|
||||||
t { '', '}' },
|
}
|
||||||
|
]],
|
||||||
|
{ i(1), i(2) }
|
||||||
|
)
|
||||||
|
),
|
||||||
|
sn(
|
||||||
|
nil,
|
||||||
|
fmta(
|
||||||
|
[[
|
||||||
|
async function (#~) {
|
||||||
|
#~
|
||||||
|
}
|
||||||
|
]],
|
||||||
|
{ i(1), i(2) }
|
||||||
|
)
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
s('()', {
|
|
||||||
t '() => {',
|
|
||||||
t { '', ' ' },
|
|
||||||
i(0),
|
|
||||||
t { '', '}' },
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,63 @@
|
|||||||
local ls = require 'luasnip'
|
local ls = require 'luasnip'
|
||||||
local s = ls.snippet
|
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 t = ls.text_node
|
||||||
|
local c = ls.choice_node
|
||||||
local i = ls.insert_node
|
local i = ls.insert_node
|
||||||
local f = ls.function_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 function get_psr4_root()
|
local utils = require 'snippets.snip_utils'
|
||||||
local handle = io.popen [[php -r "echo array_keys(json_decode(file_get_contents('composer.json'), true)['autoload']['psr-4'])[0];"]]
|
local tr = utils.tr
|
||||||
local ns_root = handle and handle:read '*a' or ''
|
local etr = utils.etr
|
||||||
if handle then
|
local Etr = utils.Etr
|
||||||
handle:close()
|
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
|
end
|
||||||
ns_root = ns_root:gsub('\\$', '') -- Remove trailing backslash
|
dir = vim.fs.dirname(dir)
|
||||||
return ns_root
|
end
|
||||||
|
-- If no composer.json found, return empty string
|
||||||
|
if dir == '/' or dir == nil then
|
||||||
|
return ''
|
||||||
end
|
end
|
||||||
|
|
||||||
local function psr_namespace(args, snip)
|
-- Decode composer.json and get PSR-4 autoload mappings
|
||||||
local path = snip.env.TM_FILENAME_FULL or ''
|
local composer = vim.json.decode(vim.iter(vim.fn.readfile(dir .. '/composer.json')):join '')
|
||||||
local composer_root = get_psr4_root()
|
local psr4 = composer['autoload'] and composer['autoload']['psr-4']
|
||||||
-- Find the directory mapped by composer.json
|
|
||||||
local root_dir = composer_root:gsub('\\', '/')
|
-- If no PSR-4 mappings, return empty string
|
||||||
local ns = path:match(root_dir .. '/(.*)/[^/]+%.php$')
|
if not psr4 then
|
||||||
if ns then
|
return ''
|
||||||
return composer_root .. '\\' .. ns:gsub('/', '\\')
|
end
|
||||||
else
|
|
||||||
return composer_root ~= '' and composer_root or 'App'
|
-- 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
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -33,78 +67,547 @@ local function class_name(args, snip)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
s('du', { t 'dump(', i(1), t ');' }),
|
---------------
|
||||||
s('dt', { t '\\PhpStan\\dumpType(', i(1), t ');' }),
|
-- DEBUGGING --
|
||||||
s('ql', {
|
---------------
|
||||||
t '\\Illuminate\\Support\\Facades\\DB::listen(function (\\Illuminate\\Database\\Events\\QueryExecuted $e) {',
|
s(etr('du ', 'Dump a variable to the dump server', { priority = 1001 }), fmta('dump(#~);', { i(0) })),
|
||||||
t { '', ' dump($e->sql, $e->bindings);' },
|
bs(etr('du ', 'Dump a variable to the dump server'), fmta('dump(#~)', { i(0) })),
|
||||||
t { '', '});' },
|
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('test', {
|
|
||||||
t 'test(',
|
|
||||||
i(1),
|
|
||||||
t ', function () {',
|
|
||||||
t { '', ' ' },
|
|
||||||
i(2),
|
|
||||||
t { '', ');' },
|
|
||||||
}),
|
|
||||||
s('/**', {
|
|
||||||
t '/**',
|
|
||||||
t { '', ' * ' },
|
|
||||||
i(1),
|
|
||||||
t { '', ' */' },
|
|
||||||
}),
|
|
||||||
s('@p', { t '@property ', i(1), t ' $', i(2) }),
|
|
||||||
s('@pb', { t '@property bool $', i(1) }),
|
|
||||||
s('@ps', { t '@property string $', i(1) }),
|
|
||||||
s('@pi', { t '@property int $', i(1) }),
|
|
||||||
s('@pc', { t '@property \\Illuminate\\Support\\Collection<int, ', i(1), t '> $', i(2) }),
|
|
||||||
s('@pd', { t '@property \\Illuminate\\Support\\Carbon $', i(1) }),
|
|
||||||
s('@pp', {
|
|
||||||
t '/**',
|
|
||||||
t { '', ' * @property int $id' },
|
|
||||||
t { '', ' * ' },
|
|
||||||
i(1),
|
|
||||||
t { '', ' * @property \\Illuminate\\Support\\Carbon $created_at' },
|
|
||||||
t { '', ' * @property \\Illuminate\\Support\\Carbon $updated_at' },
|
|
||||||
t { '', ' *', ' * Relationships' },
|
|
||||||
t { '', ' * ' },
|
|
||||||
i(2),
|
|
||||||
t { '', ' */' },
|
|
||||||
}),
|
|
||||||
s('php', {
|
|
||||||
t '<?php',
|
|
||||||
t { '', '', '' },
|
|
||||||
t 'namespace ',
|
|
||||||
f(psr_namespace, {}),
|
|
||||||
t ';',
|
|
||||||
t { '', '', 'class ' },
|
|
||||||
f(class_name, {}),
|
|
||||||
t { '', '{' },
|
|
||||||
t { '', '' },
|
|
||||||
i(0),
|
|
||||||
t { '', '', '}' },
|
|
||||||
}),
|
|
||||||
s('pub', {
|
|
||||||
t 'public function ',
|
|
||||||
i(1),
|
|
||||||
t '(',
|
|
||||||
i(2),
|
|
||||||
t ')',
|
|
||||||
t { '', '{' },
|
|
||||||
t { '', ' ' },
|
|
||||||
i(3),
|
|
||||||
t { '', '}' },
|
|
||||||
}),
|
|
||||||
s('pro', {
|
|
||||||
t 'protected function ',
|
|
||||||
i(1),
|
|
||||||
t '(',
|
|
||||||
i(2),
|
|
||||||
t ')',
|
|
||||||
t { '', '{' },
|
|
||||||
t { '', ' ' },
|
|
||||||
i(3),
|
|
||||||
t { '', '}' },
|
|
||||||
}),
|
}),
|
||||||
|
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
152
lua/snippets/snip_utils.lua
Normal 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
|
||||||
Reference in New Issue
Block a user