Files
nvim/lua/snippets/php.lua

605 lines
17 KiB
Lua
Raw Normal View History

2025-09-08 09:20:42 +01:00
local ls = require 'luasnip'
2025-08-26 18:23:14 +01:00
local s = ls.snippet
2025-12-08 00:52:01 +00:00
local sn = ls.snippet_node
2025-12-08 16:33:11 +00:00
local fn = ls.function_node
2025-08-26 18:23:14 +01:00
local t = ls.text_node
2025-12-08 00:52:01 +00:00
local c = ls.choice_node
2025-08-26 18:23:14 +01:00
local i = ls.insert_node
local f = ls.function_node
2025-12-08 00:52:01 +00:00
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 function line_begin(line_to_cursor, matched_trigger)
-- +1 because `string.sub("abcd", 1, -2)` -> abc
return line_to_cursor:sub(1, -(#matched_trigger + 1)):match '^%s*$'
end
local function empty_line(_, matched_trigger)
return vim.api.nvim_get_current_line():match('^%s*' .. vim.pesc(matched_trigger) .. '$')
end
local function file_begin(line_to_cursor, matched_trigger)
local line_number = vim.fn.line '.'
return line_number == 1 and line_begin(line_to_cursor, matched_trigger)
end
2025-12-08 16:33:11 +00:00
local function in_string()
local node_type = vim.treesitter.get_node():type()
return node_type == 'string_content' or node_type == 'string'
end
local function in_comment()
local node_type = vim.treesitter.get_node():type()
return node_type == 'comment'
end
local function not_in_string_or_comment()
return (not in_string()) and (not in_comment())
end
local function tr(trigger, description, condition)
condition = condition or empty_line
2025-12-08 00:52:01 +00:00
return {
trig = trigger,
desc = description,
snippetType = 'autosnippet',
2025-12-08 16:33:11 +00:00
condition = condition,
2025-12-08 00:52:01 +00:00
}
end
2025-12-08 16:33:11 +00:00
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,
}
2025-12-08 00:52:01 +00:00
end
2025-08-26 18:23:14 +01:00
2025-11-12 09:21:21 +00:00
local function psr_namespace(_, snip)
2025-11-15 13:55:47 +00:00
-- 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
2025-08-26 18:23:14 +01:00
end
local function class_name(args, snip)
2025-09-08 09:20:42 +01:00
local filename = snip.env.TM_FILENAME or ''
return filename:match '([^%.]+)' or 'ClassName'
2025-08-26 18:23:14 +01:00
end
2025-12-08 00:52:01 +00:00
local function snippet_aliases(triggers, description, snippet)
local snips = {}
for key, trigger in ipairs(triggers) do
snips[key] = s(tr(trigger, description), snippet())
end
return snips
end
2025-12-08 16:33:11 +00:00
local function fmtc(snipp, nodes)
return fmta(
'#~' .. snipp,
vim.list_extend({ fn(function(args, snip)
return snip.captures[1]
end) }, nodes)
)
end
2025-12-08 00:52:01 +00:00
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
2025-12-08 16:33:11 +00:00
return result
2025-12-08 00:52:01 +00:00
end
return flatten {
---------------
-- DEBUGGING --
---------------
s(tr('du ', 'Dump a variable to the dump server'), fmta('dump(#~);', { i(0) })),
2025-12-08 16:33:11 +00:00
s(atr('([^%w])du ', 'Dump a variable to the dump server'), fmtc('dump(#~)', { i(0) })),
s(tr('r ', 'ray'), fmta('ray(#~);', { i(0) })),
s(atr('([^%w])r ', 'ray'), fmtc('ray(#~)', { i(0) })),
2025-12-08 00:52:01 +00:00
s(tr('dt ', 'Dump PHPStan type definition'), fmta('\\PhpStan\\dumpType(#~);', { i(0) })),
s(
tr('ql ', 'Log all queries'),
fmta(
[[
\Illuminate\Support\Facades\DB::listen(function (\Illuminate\Database\Events\QueryExecuted $e) {
dump($e->sql, $e->bindings);
});
#~
]],
{ i(0) }
)
),
--------------
-- COMMENTS --
--------------
2025-12-08 16:33:11 +00:00
s(tr('/**', 'Docblock comment'), {
c(1, {
sn(
nil,
fmta(
[[
/**
* #~
*/
]],
{ i(1) }
)
),
sn(nil, fmta('/** #~ */', { i(1) })),
}),
}),
2025-12-08 00:52:01 +00:00
s(tr('@v', '@var docblock'), fmta('/** @var #~ $#~ */', { i(1), i(0) })),
2025-12-08 16:33:11 +00:00
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('* @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) })),
2025-12-08 00:52:01 +00:00
s(
tr('@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(
2025-12-08 16:33:11 +00:00
tr('if ', 'if block'),
2025-12-08 00:52:01 +00:00
fmta(
[[
if (#~) {
#~
}
]],
{ i(1), i(0) }
)
),
s(
tr('fe ', 'foreach block'),
fmta(
[[
foreach (#~ as #~) {
#~
}
]],
{ i(1), i(2), i(0) }
)
),
2025-12-08 16:33:11 +00:00
s(tr('foreach', 'foreach block'), fmta('fe', {})),
s(
tr('for ', 'for block'),
fmta(
[[
for (#~; #~; #~) {
#~
}
]],
{ i(1, '$i'), i(2), i(3, '$i++'), i(0) }
)
),
2025-12-08 00:52:01 +00:00
s(tr('return ', 'Add semicolon after return'), fmta('return #~;', { i(0) })),
2025-12-08 16:33:11 +00:00
s(atr(' use ', 'Add use to function'), fmta(' use (#~)', { i(0) })),
s(tr('rt ', 'return alias'), fmta('return #~;', { i(0) })),
s(
atr('([^%w])fn ', 'Shorthand function block'),
c(0, {
sn(nil, fmtc('fn (#~) => #~', { i(1), i(2) })),
sn(
nil,
fmtc(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
})
),
s(
atr('([^%w])fun ', 'Shorthand function block'),
c(0, {
sn(
nil,
fmtc(
[[
function (#~) {
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmtc(
[[
function (#~) use (#~) {
#~
}
]],
{ i(1), i(2), i(3) }
)
),
})
),
s(
tr('con', 'Constructor function block'),
c(0, {
sn(
nil,
fmta(
[[
public function __construct(#~)
{
#~
}
]],
{ i(1), i(2) }
)
),
sn(
nil,
fmta(
[[
public function __construct(
#~
) {
#~
}
]],
{ i(1), i(2) }
)
),
})
),
s(atr('([^%w])function', 'Shorthand function block'), fmtc('fun', {})),
s(atr('([^%w])s%$', 'string type parameter'), fmtc('string $#~', { i(0, 'var') })),
s(atr('([^%w])i%$', 'int type parameter'), fmtc('int $#~', { i(0, 'var') })),
s(atr('([^%w])b%$', 'bool type parameter'), fmtc('bool $#~', { i(0, 'var') })),
s(atr('([^%w])a%$', 'array type parameter'), fmtc('array $#~', { i(0, 'var') })),
s(atr('$ ', 'Expand $this->'), fmta('$this->#~', { i(0) })),
s(
atr('([^%w])am ', 'array_map function'),
c(0, {
sn(nil, fmtc('array_map(fn (#~) => #~, #~)', { i(2), i(3), i(1) })),
sn(
nil,
fmtc(
[[
array_map(function (#~) {
#~
}, #~)
]],
{ i(2), i(0), i(1) }
)
),
2025-12-08 00:52:01 +00:00
})
2025-12-08 16:33:11 +00:00
),
s(atr('([^%w])array_map', 'array_map function'), fmtc('am', {})),
s(
atr('([^%w])af ', 'array_filter function'),
c(0, {
sn(nil, fmtc('array_filter(#~, fn (#~) => #~)', { i(1), i(2), i(3) })),
sn(
nil,
fmtc(
[[
array_filter(#~, function (#~) {
#~
})
]],
{ i(1), i(2), i(0) }
)
),
2025-12-08 00:52:01 +00:00
})
2025-12-08 16:33:11 +00:00
),
s(atr('([^%w])array_filter', 'array_filter function'), fmtc('af', {})),
2025-12-08 00:52:01 +00:00
s(
tr('php', 'php class'),
fmta(
[[
<?php
declare(strict_types=1);
namespace #~
class #~
{
public function __construct()
{
#~
}
}
]],
{ f(psr_namespace, {}), f(class_name, {}), i(0) }
)
),
s(
tr('met', 'public class method'),
fmta(
[[
public function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
tr('pmet', 'protected class method'),
fmta(
[[
protected function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
tr('smet', 'public static class method'),
fmta(
[[
public static function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
s(
tr('spmet', 'protected static class method'),
fmta(
[[
protected static function #~(#~)
{
#~
}
]],
{ i(1), i(2), i(0) }
)
),
-------------
-- PROJECT --
-------------
s(
tr('test', 'Create a test function'),
fmta(
[[
test(#~ function () {
#~
})
]],
{ i(1), i(0) }
)
),
s(tr('nn ', 'Assert not null'), fmta('Assert::notNull(#~)', { i(0) })),
-------------
-- LARAVEL --
-------------
s(
tr('bt', 'belongsTo Laravel relationship method'),
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\#~, $this>
*/
public function #~(): BelongsTo
{
return $this->belongsTo(#~::class);
}
]],
{ rep(1), i(0), i(1) }
)
),
s(
tr('hm', 'hasMany Laravel relationship method'),
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany<\App\Models\#~, $this>
*/
public function #~(): HasMany
{
return $this->hasOne(#~::class);
}
]],
{ rep(1), i(0), i(1) }
)
),
s(
tr('ho', 'hasOne Laravel relationship method'),
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\#~, $this>
*/
public function #~(): HasOne
{
return $this->hasOne(#~::class);
}
]],
{ rep(1), i(0), i(1) }
)
),
s(
tr('bm', 'belongsToMany Laravel relationship method'),
fmta(
[[
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\#~, $this>
*/
public function #~(): BelongsToMany
{
return $this->belongsToMany(#~::class, #~);
}
]],
{ rep(1), i(2), i(1), i(0) }
)
),
2025-12-08 16:33:11 +00:00
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('->wh', '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) }
)
),
})
),
2025-08-26 18:23:14 +01:00
}