Compare commits

8 Commits

Author SHA1 Message Date
Chris
a086657031 Treesitter update 2025-12-10 14:19:07 +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
16 changed files with 813 additions and 476 deletions

View File

@@ -30,7 +30,7 @@ vim.api.nvim_create_autocmd('SwapExists', {
desc = 'Always choose to delete the swap file, files are saved automatically', desc = 'Always choose to delete the swap file, files are saved automatically',
group = vim.api.nvim_create_augroup('NoSwaps', { clear = true }), group = vim.api.nvim_create_augroup('NoSwaps', { clear = true }),
callback = function(args) callback = function(args)
vim.cmd("let v:swapchoice = 'd'") vim.cmd "let v:swapchoice = 'd'"
end, end,
}) })
@@ -116,4 +116,33 @@ vim.api.nvim_create_autocmd('BufWritePost', {
end, end,
}) })
vim.api.nvim_create_autocmd('FileType', {
pattern = {
'bash',
'c',
'diff',
'html',
'lua',
'luadoc',
'markdown',
'markdown_inline',
'query',
'vim',
'vimdoc',
'php',
'javascript',
'typescript',
'json',
},
callback = function()
-- syntax highlighting, provided by Neovim
vim.treesitter.start()
-- folds, provided by Neovim
vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
vim.wo.foldmethod = 'expr'
-- indentation, provided by nvim-treesitter
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end,
})
require('helpers').edit_cf('a', '/lua/autocmd.lua') require('helpers').edit_cf('a', '/lua/autocmd.lua')

View File

@@ -27,37 +27,112 @@ vim.keymap.set('v', 'p', '"zdP', { desc = 'Paste over selection without yanking
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.keymap.set('n', '<Leader>c', function()
local node = require('nvim-treesitter.ts_utils').get_node_at_cursor() vim.treesitter.inspect_tree()
if node then end, { desc = 'Treesitter' })
print(node:type())
-- 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 else
print 'No node found at cursor' start_row = start[1]
start_column = start[2] - 1
end end
end, { desc = 'Log node' }) 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({ 'i' }, '<C-J>', function() vim.keymap.set({ 'i' }, '<C-J>', function()
local ls = require 'luasnip' local ls = require 'luasnip'
print('jj')
if ls.choice_active() then if ls.choice_active() then
ls.change_choice(1) ls.change_choice(1)
end end
end, { silent = true }) end, { desc = 'Toggle snippet choice', silent = true })
vim.keymap.set({ 'i' }, '<C-k>', function() vim.keymap.set({ 'i' }, '<C-k>', function()
local ls = require 'luasnip' local ls = require 'luasnip'
print('kk')
if ls.choice_active() then if ls.choice_active() then
ls.change_choice(-1) ls.change_choice(-1)
end end
end, { silent = true }) end, { desc = 'Toggle snippet choice', silent = true })
vim.keymap.set({ 'i', 's' }, '<C-L>', function() vim.keymap.set({ 'i', 's' }, '<C-L>', function()
local ls = require 'luasnip' local ls = require 'luasnip'
if ls.expandable() then if ls.expandable() then
@@ -65,18 +140,13 @@ vim.keymap.set({ 'i', 's' }, '<C-L>', function()
elseif ls.in_snippet() then elseif ls.in_snippet() then
ls.jump(1) ls.jump(1)
end end
end, { silent = true }) end, { desc = 'Expand snippet', silent = true })
vim.keymap.set({ 'i', 's' }, '<C-H>', function() vim.keymap.set({ 'i', 's' }, '<C-H>', function()
local ls = require 'luasnip' local ls = require 'luasnip'
if ls.in_snippet() then if ls.in_snippet() then
ls.jump(-1) ls.jump(-1)
end end
end, { silent = true }) end, { desc = 'Go back a snippet slot', silent = true })
vim.keymap.set('n', '<C-S-h>', '<C-w>H', { desc = 'Move window to the left' })
vim.keymap.set('n', '<C-S-l>', '<C-w>L', { desc = 'Move window to the right' })
vim.keymap.set('n', '<C-S-j>', '<C-w>J', { desc = 'Move window to the lower' })
vim.keymap.set('n', '<C-S-k>', '<C-w>K', { desc = 'Move window to the upper' })
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' })
@@ -193,79 +263,79 @@ local function open_test()
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'

View File

@@ -31,7 +31,7 @@ return {
require('minuet').setup { require('minuet').setup {
virtualtext = { virtualtext = {
auto_trigger_ft = { '*' }, auto_trigger_ft = { '*' },
auto_trigger_ignore_ft = { 'help', 'TelescopePrompt', 'codecompanion' }, auto_trigger_ignore_ft = { 'help', 'TelescopePrompt', 'codecompanion', 'snacks_input' },
keymap = { keymap = {
accept = '<A-A>', accept = '<A-A>',
accept_line = '<A-a>', accept_line = '<A-a>',

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

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

View File

@@ -0,0 +1,153 @@
-- Highlight, edit, and navigate code
return {
-- 'nvim-treesitter/nvim-treesitter-textobjects',
-- lazy = true,
-- branch = 'main',
-- dependencies = {
-- 'nvim-treesitter/nvim-treesitter',
-- },
-- config = function()
-- -- configuration
-- require('nvim-treesitter-textobjects').setup {
-- select = {
-- lookahead = true,
-- selection_modes = {
-- ['@parameter.outer'] = 'v', -- charwise
-- ['@function.outer'] = 'V', -- linewise
-- ['@class.outer'] = 'V', -- blockwise
-- },
-- include_surrounding_whitespace = false,
-- },
-- move = {
-- set_jumps = true,
-- },
-- }
-- for keys, query in
-- {
-- -- or you use the queries from supported languages with textobjects.scm
-- ['af'] = '@function.outer',
-- ['if'] = '@function.inner',
-- ['aC'] = '@class.outer',
-- ['iC'] = '@class.inner',
-- ['ay'] = '@conditional.outer',
-- ['iy'] = '@conditional.inner',
-- ['aj'] = '@loop.outer',
-- ['ij'] = '@loop.inner',
-- ['is'] = '@statement.inner',
-- ['as'] = '@statement.outer',
-- ['ac'] = '@comment.outer',
-- ['ic'] = '@comment.inner',
-- ['ap'] = '@comment.parameter',
-- ['ip'] = '@comment.parameter',
-- ['an'] = '@local.scope',
-- }
-- do
-- vim.keymap.set({ 'n', 'x', 'o' }, keys, function()
-- require('nvim-treesitter-textobjects.select').select_textobject(query, 'textobjects')
-- end)
-- end
-- for keys, query in
-- {
-- -- or you use the queries from supported languages with textobjects.scm
-- [']'] = '@function.outer',
-- ['o'] = { '@loop.inner', '@loop.outer' },
-- ['n'] = '@local.scope',
-- ['y'] = '@conditional.outer',
-- ['e'] = '@statement.outer',
-- ['/'] = '@comment.outer',
-- }
-- do
-- vim.keymap.set({ 'n', 'x', 'o' }, ']' .. keys, function()
-- require('nvim-treesitter-textobjects.move').goto_next_start(query, 'textobjects')
-- end)
-- vim.keymap.set({ 'n', 'x', 'o' }, '[' .. keys, function()
-- require('nvim-treesitter-textobjects.move').goto_previous_start(query, 'textobjects')
-- end)
-- end
-- -- require('nvim-treesitter.configs').setup {
-- -- incremental_selection = {
-- -- enable = true,
-- -- keymaps = {
-- -- -- mappings for incremental selection (visual mappings)
-- -- init_selection = '<C-S-D>', -- maps in normal mode to init the node/scope selection
-- -- node_incremental = '<C-S-D>', -- increment to the upper named parent
-- -- scope_incremental = '<C-S-U>', -- increment to the upper scope (as defined in locals.scm)
-- -- node_decremental = '<C-S-S>', -- decrement to the previous node
-- -- },
-- -- },
-- -- textobjects = {
-- -- -- syntax-aware textobjects
-- -- enable = true,
-- -- keymaps = {
-- -- ['iL'] = {
-- -- -- you can define your own textobjects directly here
-- -- go = '(function_definition) @function',
-- -- },
-- -- -- or you use the queries from supported languages with textobjects.scm
-- -- ['af'] = '@function.outer',
-- -- ['if'] = '@function.inner',
-- -- ['aC'] = '@class.outer',
-- -- ['iC'] = '@class.inner',
-- -- ['ay'] = '@conditional.outer',
-- -- ['iy'] = '@conditional.inner',
-- -- ['aj'] = '@loop.outer',
-- -- ['ij'] = '@loop.inner',
-- -- ['is'] = '@statement.inner',
-- -- ['as'] = '@statement.outer',
-- -- ['ac'] = '@comment.outer',
-- -- ['ic'] = '@comment.inner',
-- -- ['ap'] = '@comment.parameter',
-- -- ['ip'] = '@comment.parameter',
-- -- },
-- -- move = {
-- -- enable = true,
-- -- set_jumps = true, -- whether to set jumps in the jumplist
-- -- goto_next_start = {
-- -- [']m'] = '@function.outer',
-- -- [']]'] = '@class.outer',
-- -- },
-- -- goto_next_end = {
-- -- [']M'] = '@function.outer',
-- -- [']['] = '@class.outer',
-- -- },
-- -- goto_previous_start = {
-- -- ['[m'] = '@function.outer',
-- -- ['[['] = '@class.outer',
-- -- },
-- -- goto_previous_end = {
-- -- ['[M'] = '@function.outer',
-- -- ['[]'] = '@class.outer',
-- -- },
-- -- },
-- -- select = {
-- -- enable = true,
-- -- keymaps = {
-- -- -- You can use the capture groups defined in textobjects.scm
-- -- ['af'] = '@function.outer',
-- -- ['if'] = '@function.inner',
-- -- ['ac'] = '@class.outer',
-- -- ['ic'] = '@class.inner',
-- -- -- Or you can define your own textobjects like this
-- -- ['iF'] = {
-- -- python = '(function_definition) @function',
-- -- cpp = '(function_definition) @function',
-- -- c = '(function_definition) @function',
-- -- java = '(method_declaration) @function',
-- -- go = '(method_declaration) @function',
-- -- },
-- -- },
-- -- },
-- -- },
-- -- }
-- end,
-- opts = {},
-- -- There are additional nvim-treesitter modules that you can use to interact
-- -- with nvim-treesitter. You should go explore a few and see what interests you:
-- --
-- -- - Incremental selection: Included, see `:help nvim-treesitter-incremental-selection-mod`
-- -- - Show your current context: https://github.com/nvim-treesitter/nvim-treesitter-context
-- -- - Treesitter + textobjects: https://github.com/nvim-treesitter/nvim-treesitter-textobjects
}

View File

@@ -2,10 +2,11 @@
return { return {
'nvim-treesitter/nvim-treesitter', 'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate', build = ':TSUpdate',
main = 'nvim-treesitter.configs', -- Sets main module to use for opts branch = 'main',
-- [[ Configure Treesitter ]] See `:help nvim-treesitter` -- [[ Configure Treesitter ]] See `:help nvim-treesitter`
opts = { config = function()
ensure_installed = { require('nvim-treesitter').setup {}
require('nvim-treesitter').install {
'bash', 'bash',
'c', 'c',
'diff', 'diff',
@@ -17,18 +18,13 @@ return {
'query', 'query',
'vim', 'vim',
'vimdoc', 'vimdoc',
}, 'php',
-- Autoinstall languages that are not installed 'javascript',
auto_install = true, 'typescript',
highlight = { 'json',
enable = true, }
-- Some languages depend on vim's regex highlighting system (such as Ruby) for indent rules. end,
-- If you are experiencing weird indenting issues, add the language to opts = {},
-- the list of additional_vim_regex_highlighting and disabled languages for indent.
additional_vim_regex_highlighting = { 'ruby' },
},
indent = { enable = true, disable = { 'ruby' } },
},
-- There are additional nvim-treesitter modules that you can use to interact -- There are additional nvim-treesitter modules that you can use to interact
-- with nvim-treesitter. You should go explore a few and see what interests you: -- with nvim-treesitter. You should go explore a few and see what interests you:
-- --

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

View File

@@ -18,6 +18,26 @@ local function command_with_dir(dir, cmd)
return '!' .. cmd return '!' .. cmd
end 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 function get_scope_from_file(filename)
local ext = filename:match '%.(%w+)$' local ext = filename:match '%.(%w+)$'
local base_name = filename:match '^(%w+)%.?%w*$' local base_name = filename:match '^(%w+)%.?%w*$'
@@ -130,6 +150,33 @@ local function laravel_keymaps(dir)
laravel_bookmarks_with_dir(dir) laravel_bookmarks_with_dir(dir)
end 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. -- Define per-project configuration here.
-- Keys are folder names (last segment of your cwd). -- Keys are folder names (last segment of your cwd).
local PROJECTS = { local PROJECTS = {
@@ -170,6 +217,7 @@ local PROJECTS = {
map('s ', '!cd server && ', { desc = 'Run command in server directory' }, 'c') map('s ', '!cd server && ', { desc = 'Run command in server directory' }, 'c')
map('c ', '!cd client && ', { desc = 'Run command in client directory' }, 'c') map('c ', '!cd client && ', { desc = 'Run command in client directory' }, 'c')
laravel_keymaps 'server' laravel_keymaps 'server'
laravel_makes 'server'
map('yrn ', '!cd client && yarn ', { desc = 'Run yarn script' }, 'c') map('yrn ', '!cd client && yarn ', { desc = 'Run yarn script' }, 'c')
map('<Leader>pt', ':!cd server && php artisan typescript:transform --format<CR>', { desc = 'Compile typescript' }) map('<Leader>pt', ':!cd server && php artisan typescript:transform --format<CR>', { desc = 'Compile typescript' })
require('conform').formatters.pint = { require('conform').formatters.pint = {
@@ -191,6 +239,7 @@ local PROJECTS = {
helpers.open_term { cmd = 'lazysql pgsql://homestead:password@localhost:5432/homestead' } helpers.open_term { cmd = 'lazysql pgsql://homestead:password@localhost:5432/homestead' }
end, { desc = 'Open database manager' }) end, { desc = 'Open database manager' })
laravel_keymaps() laravel_keymaps()
laravel_makes()
map('yrn ', '!cd frontend && yarn ', { desc = 'Run yarn script' }, 'c') map('yrn ', '!cd frontend && yarn ', { desc = 'Run yarn script' }, 'c')
map('<Leader>pm', ':vendor/bin/sail composer migrate<CR>') map('<Leader>pm', ':vendor/bin/sail composer migrate<CR>')
end, end,

View File

@@ -2,6 +2,7 @@ local ls = require 'luasnip'
local s = ls.snippet local s = ls.snippet
local sn = ls.snippet_node local sn = ls.snippet_node
local fn = ls.function_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 c = ls.choice_node
local i = ls.insert_node local i = ls.insert_node
@@ -9,100 +10,54 @@ local f = ls.function_node
local d = ls.dynamic_node local d = ls.dynamic_node
local fmt = require('luasnip.extras.fmt').fmt local fmt = require('luasnip.extras.fmt').fmt
local rep = require('luasnip.extras').rep local rep = require('luasnip.extras').rep
local line_begin = require('luasnip.extras.conditions').line_begin
local extend_decorator = require 'luasnip.util.extend_decorator' local extend_decorator = require 'luasnip.util.extend_decorator'
local fmta = extend_decorator.apply(fmt, { delimiters = '#~' }) local fmta = extend_decorator.apply(fmt, { delimiters = '#~' })
local function line_begin(line_to_cursor, matched_trigger) local utils = require 'snippets.snip_utils'
-- +1 because `string.sub("abcd", 1, -2)` -> abc local tr = utils.tr
return line_to_cursor:sub(1, -(#matched_trigger + 1)):match '^%s*$' local etr = utils.etr
end local atr = utils.atr
local ctr = utils.ctr
local bs = utils.bs
local function empty_line(_, matched_trigger) local function psr_namespace()
return vim.api.nvim_get_current_line():match('^%s*' .. vim.pesc(matched_trigger) .. '$') local path = vim.fn.expand '%'
end -- 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
local function file_begin(line_to_cursor, matched_trigger) -- Decode composer.json and get PSR-4 autoload mappings
local line_number = vim.fn.line '.' local composer = vim.json.decode(vim.iter(vim.fn.readfile(dir .. '/composer.json')):join '')
return line_number == 1 and line_begin(line_to_cursor, matched_trigger) local psr4 = composer['autoload'] and composer['autoload']['psr-4']
end
local function in_string() -- If no PSR-4 mappings, return empty string
local node_type = vim.treesitter.get_node():type() if not psr4 then
return node_type == 'string_content' or node_type == 'string' return ''
end end
local function in_comment() -- Get the relative path from the composer.json directory
local node_type = vim.treesitter.get_node():type() local relative_path = path:sub(#dir + 2)
return node_type == 'comment' -- Loop through PSR-4 mappings
end for namespace, map in pairs(psr4) do
-- Check if the relative path matches the mapping
local function not_in_string_or_comment() if relative_path:match('^' .. map:gsub('/', '%%/')) then
return (not in_string()) and (not in_comment()) -- Extract the suffix of the path after the mapping, removing the filename
end local suffix = relative_path:sub(#map + 1):match '^(.*)/[^/]+%.php$' or ''
local trimmed = namespace:gsub('\\$', '')
local function tr(trigger, description, condition) return trimmed .. (suffix ~= '' and ('\\' .. suffix:gsub('/', '\\')) or '')
condition = condition or empty_line end
return { end
trig = trigger,
desc = description,
snippetType = 'autosnippet',
condition = condition,
}
end
local function ctr(trigger, description)
return tr(trigger, description, in_comment)
end
local function atr(trigger, description)
return {
trig = trigger,
desc = description,
snippetType = 'autosnippet',
regTrig = true,
wordTrig = false,
condition = not_in_string_or_comment,
}
end
local function psr_namespace(_, snip)
-- local path = snip.env.TM_FILENAME_FULL or ''
-- -- 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 + 2):match('^(.*)/[^/]+%.php$') or ''
-- local trimmed = namespace:gsub('\\$', '')
-- return trimmed .. (suffix ~= '' and ('\\' .. suffix:gsub('/', '\\')) or '')
-- end
-- end
end end
local function class_name(args, snip) local function class_name(args, snip)
@@ -110,52 +65,17 @@ local function class_name(args, snip)
return filename:match '([^%.]+)' or 'ClassName' return filename:match '([^%.]+)' or 'ClassName'
end end
local function snippet_aliases(triggers, description, snippet) return {
local snips = {}
for key, trigger in ipairs(triggers) do
snips[key] = s(tr(trigger, description), snippet())
end
return snips
end
local function fmtc(snipp, nodes)
return fmta(
'#~' .. snipp,
vim.list_extend({ fn(function(args, snip)
return snip.captures[1]
end) }, nodes)
)
end
local function flatten(tbl)
local result = {}
local index = 1
for _, val in ipairs(tbl) do
if type(val) == 'table' and vim.tbl_islist(val) then
for _, val2 in ipairs(val) do
result[index] = val2
index = index + 1
end
else
result[index] = val
index = index + 1
end
end
return result
end
return flatten {
--------------- ---------------
-- DEBUGGING -- -- DEBUGGING --
--------------- ---------------
s(tr('du ', 'Dump a variable to the dump server'), fmta('dump(#~);', { i(0) })), s(etr('du ', 'Dump a variable to the dump server'), fmta('dump(#~);', { i(0) })),
s(atr('([^%w])du ', 'Dump a variable to the dump server'), fmtc('dump(#~)', { i(0) })), bs(atr('du ', 'Dump a variable to the dump server'), fmta('dump(#~)', { i(0) })),
s(tr('r ', 'ray'), fmta('ray(#~);', { i(0) })), s(etr('r ', 'ray'), fmta('ray(#~);', { i(0) })),
s(atr('([^%w])r ', 'ray'), fmtc('ray(#~)', { i(0) })), bs(atr('r ', 'ray'), fmta('ray(#~)', { i(0) })),
s(tr('dt ', 'Dump PHPStan type definition'), fmta('\\PhpStan\\dumpType(#~);', { i(0) })), s(etr('dt ', 'Dump PHPStan type definition'), fmta('\\PhpStan\\dumpType(#~);', { i(0) })),
s( s(
tr('ql ', 'Log all queries'), etr('ql ', 'Log all queries'),
fmta( fmta(
[[ [[
\Illuminate\Support\Facades\DB::listen(function (\Illuminate\Database\Events\QueryExecuted $e) { \Illuminate\Support\Facades\DB::listen(function (\Illuminate\Database\Events\QueryExecuted $e) {
@@ -169,7 +89,7 @@ return flatten {
-------------- --------------
-- COMMENTS -- -- COMMENTS --
-------------- --------------
s(tr('/**', 'Docblock comment'), { s(etr('/**', 'Docblock comment'), {
c(1, { c(1, {
sn( sn(
nil, nil,
@@ -185,7 +105,7 @@ return flatten {
sn(nil, fmta('/** #~ */', { i(1) })), sn(nil, fmta('/** #~ */', { i(1) })),
}), }),
}), }),
s(tr('@v', '@var docblock'), fmta('/** @var #~ $#~ */', { i(1), i(0) })), s(etr('@v', '@var docblock'), fmta('/** @var #~ $#~ */', { i(1), i(0) })),
s(ctr('@v', '@var docblock'), fmta('@var #~ $#~', { i(1), i(0) })), s(ctr('@v', '@var docblock'), fmta('@var #~ $#~', { i(1), i(0) })),
s(ctr('* @pr', 'Class property docblock'), fmta('* @property #~ $#~', { 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('* @pb', 'Class boolean property docblock'), fmta('* @property bool $#~', { i(0) })),
@@ -194,7 +114,7 @@ return flatten {
s(ctr('* @pc', 'Class collection property docblock'), fmta('* @property \\Illuminate\\Database\\Eloquent\\Collection<#~> $#~', { i(1), 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(ctr('* @pd', 'Class date property docblock'), fmta('* @property \\Illuminate\\Support\\Carbon $#~', { i(0) })),
s( s(
tr('@pm', 'Model magic properties docblock'), etr('@pm', 'Model magic properties docblock'),
fmta( fmta(
[[ [[
/** /**
@@ -214,7 +134,7 @@ return flatten {
-- SYNTAX -- -- SYNTAX --
------------ ------------
s( s(
tr('if ', 'if block'), etr('if ', 'if block'),
fmta( fmta(
[[ [[
if (#~) { if (#~) {
@@ -225,7 +145,7 @@ return flatten {
) )
), ),
s( s(
tr('fe ', 'foreach block'), etr('fe ', 'foreach block'),
fmta( fmta(
[[ [[
foreach (#~ as #~) { foreach (#~ as #~) {
@@ -235,9 +155,9 @@ return flatten {
{ i(1), i(2), i(0) } { i(1), i(2), i(0) }
) )
), ),
s(tr('foreach', 'foreach block'), fmta('fe', {})), s(etr('foreach', 'foreach block'), fmta('fe', {})),
s( s(
tr('for ', 'for block'), etr('for ', 'for block'),
fmta( fmta(
[[ [[
for (#~; #~; #~) { for (#~; #~; #~) {
@@ -247,32 +167,30 @@ return flatten {
{ i(1, '$i'), i(2), i(3, '$i++'), i(0) } { i(1, '$i'), i(2), i(3, '$i++'), i(0) }
) )
), ),
s(tr('return ', 'Add semicolon after return'), fmta('return #~;', { 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(atr(' use ', 'Add use to function'), fmta(' use (#~)', { i(0) })),
s(tr('rt ', 'return alias'), fmta('return #~;', { i(0) })), s(etr('rt ', 'return alias'), fmta('return #~;', { i(0) })),
s( bs(etr('fn ', 'Shorthand function block'), {
atr('([^%w])fn ', 'Shorthand function block'), c(1, {
c(0, { sn(nil, fmta('fn (#~) => #~', { i(1), i(2) })),
sn(nil, fmtc('fn (#~) => #~', { i(1), i(2) })),
sn( sn(
nil, nil,
fmtc( fmta(
[[ [[
function (#~) { function (#~) {
#~ #~
} }
]], ]],
{ i(1), i(2) } { i(1), i(2) }
) )
), ),
}) }),
), }),
s( bs(etr('fun ', 'Shorthand function block'), {
atr('([^%w])fun ', 'Shorthand function block'), c(1, {
c(0, {
sn( sn(
nil, nil,
fmtc( fmta(
[[ [[
function (#~) { function (#~) {
#~ #~
@@ -283,7 +201,7 @@ return flatten {
), ),
sn( sn(
nil, nil,
fmtc( fmta(
[[ [[
function (#~) use (#~) { function (#~) use (#~) {
#~ #~
@@ -292,11 +210,11 @@ return flatten {
{ i(1), i(2), i(3) } { i(1), i(2), i(3) }
) )
), ),
}) }),
), }),
s( s(
tr('con', 'Constructor function block'), etr('con', 'Constructor function block'),
c(0, { c(1, {
sn( sn(
nil, nil,
fmta( fmta(
@@ -324,19 +242,18 @@ return flatten {
), ),
}) })
), ),
s(atr('([^%w])function', 'Shorthand function block'), fmtc('fun', {})), bs(atr('function', 'Shorthand function block'), fmta('fun', {})),
s(atr('([^%w])s%$', 'string type parameter'), fmtc('string $#~', { i(0, 'var') })), bs(atr('s%$', 'string type parameter'), fmta('string $#~', { i(0, 'var') })),
s(atr('([^%w])i%$', 'int type parameter'), fmtc('int $#~', { i(0, 'var') })), bs(atr('i%$', 'int type parameter'), fmta('int $#~', { i(0, 'var') })),
s(atr('([^%w])b%$', 'bool type parameter'), fmtc('bool $#~', { i(0, 'var') })), bs(atr('b%$', 'bool type parameter'), fmta('bool $#~', { i(0, 'var') })),
s(atr('([^%w])a%$', 'array type parameter'), fmtc('array $#~', { i(0, 'var') })), bs(atr('a%$', 'array type parameter'), fmta('array $#~', { i(0, 'var') })),
s(atr('$ ', 'Expand $this->'), fmta('$this->#~', { i(0) })), s(atr('$ ', 'Expand $this->'), fmta('$this->#~', { i(0) })),
s( bs(etr('am ', 'array_map function'), {
atr('([^%w])am ', 'array_map function'), c(1, {
c(0, { sn(nil, fmta('array_map(fn (#~) => #~, #~)', { i(2), i(3), i(1) })),
sn(nil, fmtc('array_map(fn (#~) => #~, #~)', { i(2), i(3), i(1) })),
sn( sn(
nil, nil,
fmtc( fmta(
[[ [[
array_map(function (#~) { array_map(function (#~) {
#~ #~
@@ -345,16 +262,15 @@ return flatten {
{ i(2), i(0), i(1) } { i(2), i(0), i(1) }
) )
), ),
}) }),
), }),
s(atr('([^%w])array_map', 'array_map function'), fmtc('am', {})), bs(etr('array_map', 'array_map function'), fmta('am', {})),
s( bs(etr('af ', 'array_filter function'), {
atr('([^%w])af ', 'array_filter function'), c(1, {
c(0, { sn(nil, fmta('array_filter(#~, fn (#~) => #~)', { i(1), i(2), i(3) })),
sn(nil, fmtc('array_filter(#~, fn (#~) => #~)', { i(1), i(2), i(3) })),
sn( sn(
nil, nil,
fmtc( fmta(
[[ [[
array_filter(#~, function (#~) { array_filter(#~, function (#~) {
#~ #~
@@ -363,18 +279,18 @@ return flatten {
{ i(1), i(2), i(0) } { i(1), i(2), i(0) }
) )
), ),
}) }),
), }),
s(atr('([^%w])array_filter', 'array_filter function'), fmtc('af', {})), bs(etr('array_filter', 'array_filter function'), fmta('af', {})),
s( s(
tr('php', 'php class'), etr('php', 'php class'),
fmta( fmta(
[[ [[
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace #~ namespace #~;
class #~ class #~
{ {
@@ -388,7 +304,7 @@ return flatten {
) )
), ),
s( s(
tr('met', 'public class method'), etr('met', 'public class method'),
fmta( fmta(
[[ [[
public function #~(#~) public function #~(#~)
@@ -400,7 +316,7 @@ return flatten {
) )
), ),
s( s(
tr('pmet', 'protected class method'), etr('pmet', 'protected class method'),
fmta( fmta(
[[ [[
protected function #~(#~) protected function #~(#~)
@@ -412,7 +328,7 @@ return flatten {
) )
), ),
s( s(
tr('smet', 'public static class method'), etr('smet', 'public static class method'),
fmta( fmta(
[[ [[
public static function #~(#~) public static function #~(#~)
@@ -424,7 +340,7 @@ return flatten {
) )
), ),
s( s(
tr('spmet', 'protected static class method'), etr('spmet', 'protected static class method'),
fmta( fmta(
[[ [[
protected static function #~(#~) protected static function #~(#~)
@@ -439,7 +355,7 @@ return flatten {
-- PROJECT -- -- PROJECT --
------------- -------------
s( s(
tr('test', 'Create a test function'), etr('test', 'Create a test function'),
fmta( fmta(
[[ [[
test(#~ function () { test(#~ function () {
@@ -449,69 +365,149 @@ return flatten {
{ i(1), i(0) } { i(1), i(0) }
) )
), ),
s(tr('nn ', 'Assert not null'), fmta('Assert::notNull(#~)', { i(0) })), s(etr('nn ', 'Assert not null'), fmta('Assert::notNull(#~)', { i(0) })),
------------- -------------
-- LARAVEL -- -- LARAVEL --
------------- -------------
s( s(
tr('bt', 'belongsTo Laravel relationship method'), etr('bt', 'belongsTo Laravel relationship method'),
fmta( c(0, {
[[ sn(
/** nil,
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\#~, $this> fmta(
*/ [[
public function #~(): BelongsTo /**
{ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\#~, $this>
return $this->belongsTo(#~::class); */
} public function #~(): BelongsTo
]], {
{ rep(1), i(0), i(1) } return $this->belongsTo(#~::class);
) }
]],
{ rep(1), i(0), 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(0) }
)
),
})
), ),
s( s(
tr('hm', 'hasMany Laravel relationship method'), etr('hm', 'hasMany Laravel relationship method'),
fmta( c(0, {
[[ sn(
/** nil,
* @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\#~, $this> fmta(
*/ [[
public function #~(): HasMany /**
{ * @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\#~, $this>
return $this->hasOne(#~::class); */
} public function #~(): HasMany
]], {
{ rep(1), i(0), i(1) } return $this->hasOne(#~::class);
) }
]],
{ rep(1), i(0), 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(0) }
)
),
})
), ),
s( s(
tr('ho', 'hasOne Laravel relationship method'), etr('ho', 'hasOne Laravel relationship method'),
fmta( c(0, {
[[ sn(
/** nil,
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\#~, $this> fmta(
*/ [[
public function #~(): HasOne /**
{ * @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\#~, $this>
return $this->hasOne(#~::class); */
} public function #~(): HasOne
]], {
{ rep(1), i(0), i(1) } return $this->hasOne(#~::class);
) }
]],
{ rep(1), i(0), 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(0) }
)
),
})
), ),
s( s(
tr('bm', 'belongsToMany Laravel relationship method'), etr('bm', 'belongsToMany Laravel relationship method'),
fmta( c(0, {
[[ sn(
/** nil,
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\#~, $this> fmta(
*/ [[
public function #~(): BelongsToMany /**
{ * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\#~, $this>
return $this->belongsToMany(#~::class, #~); */
} public function #~(): BelongsToMany
]], {
{ rep(1), i(2), i(1), i(0) } return $this->belongsToMany(#~::class, #~);
) }
]],
{ rep(1), i(2), i(1), i(0) }
)
),
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(0) }
)
),
})
), ),
s( s(
atr('->wr', 'Eloquent where method'), atr('->wr', 'Eloquent where method'),

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

@@ -0,0 +1,136 @@
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 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 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