diff --git a/lua/laravel/options/default.lua b/lua/laravel/options/default.lua index 509a474..b29121a 100644 --- a/lua/laravel/options/default.lua +++ b/lua/laravel/options/default.lua @@ -10,7 +10,7 @@ ---@class PickersFeature ---@field enable boolean ----@field provider 'telescope'|'ui.select'|'fzf-lua' +---@field provider 'telescope'|'ui.select'|'fzf-lua'|'snacks' ---@class LaravelFeatures ---@field route_info RouteInfoFeature @@ -59,6 +59,7 @@ return { require("laravel.providers.telescope_provider"), require("laravel.providers.fzf_lua_provider"), require("laravel.providers.ui_select_provider"), + require("laravel.providers.snacks_provider"), require("laravel.providers.user_command_provider"), require("laravel.providers.status_provider"), require("laravel.providers.diagnostics_provider"), diff --git a/lua/laravel/pickers/common/actions.lua b/lua/laravel/pickers/common/actions.lua index 848b570..18cfca4 100644 --- a/lua/laravel/pickers/common/actions.lua +++ b/lua/laravel/pickers/common/actions.lua @@ -12,6 +12,11 @@ local function go(route) vim.fn.search(route.uri:gsub("api", "") .. "") elseif vim.tbl_contains(route.middlewares, "web") then vim.cmd("edit routes/web.php") + -- TODO: use the get or post to find the right route or view + -- get or view can be for GET + -- post if not we need the resources + -- can improce this with a treesitter query ? + -- should be able to look for specif methods if route.uri == "/" then vim.fn.search("['\"]/['\"]") else diff --git a/lua/laravel/pickers/fzf_lua/format_entry.lua b/lua/laravel/pickers/fzf_lua/format_entry.lua index e0e8f62..b591d58 100644 --- a/lua/laravel/pickers/fzf_lua/format_entry.lua +++ b/lua/laravel/pickers/fzf_lua/format_entry.lua @@ -1,11 +1,11 @@ local M = {} local function split_string(input) - local group, command = input:match("([^:]+):([^:]+)") - if not group then - command = input - end - return group, command + local group, command = input:match("([^:]+):([^:]+)") + if not group then + command = input + end + return group, command end local function formatCommandText(command) @@ -20,10 +20,7 @@ local function formatCommandText(command) end function M.gen_from_artisan(commands) - local string_names = vim - .iter(commands) - :map(formatCommandText) - :totable() + local string_names = vim.iter(commands):map(formatCommandText):totable() local command_hash = {} for _, command in ipairs(commands) do @@ -34,10 +31,7 @@ function M.gen_from_artisan(commands) end function M.gen_from_composer(commands) - local string_names = vim - .iter(commands) - :map(formatCommandText) - :totable() + local string_names = vim.iter(commands):map(formatCommandText):totable() local command_hash = {} for _, command in ipairs(commands) do @@ -96,12 +90,12 @@ function M.gen_from_related(relations) end local function formatRouteText(route) - local uri = require("fzf-lua").utils.ansi_codes.magenta(route.uri) - if route.name ~= nil and route.name ~= "" then - return string.format("[%s] %s", require("fzf-lua").utils.ansi_codes.blue(route.name), uri) - end - - return uri + return string.format( + "%s [%s] %s", + vim.iter(route.methods):join("|"), + require("fzf-lua").utils.ansi_codes.blue(route.name or ""), + require("fzf-lua").utils.ansi_codes.magenta(route.uri) + ) end function M.gen_from_routes(routes) diff --git a/lua/laravel/pickers/fzf_lua/pickers/artisan.lua b/lua/laravel/pickers/fzf_lua/pickers/artisan.lua index 84afcc1..9dc3e5a 100644 --- a/lua/laravel/pickers/fzf_lua/pickers/artisan.lua +++ b/lua/laravel/pickers/fzf_lua/pickers/artisan.lua @@ -18,24 +18,25 @@ function ui_artisan_picker:new(cache_commands_repository) end function ui_artisan_picker:run(opts) - opts = opts or {} - return self.commands_repository:all():thenCall(function(commands) local command_names, command_table = format_entry(commands) - fzf_exec(command_names, { - actions = { - ["default"] = function(selected) - local command = command_table[selected[1]] - actions.artisan_run(command) - end, - }, - prompt = "Artisan > ", - previewer = CommandPreviewer(command_table), - fzf_opts = { - ["--preview-window"] = "nohidden,70%", - }, - }) + fzf_exec( + command_names, + vim.tbl_extends("force", { + actions = { + ["default"] = function(selected) + local command = command_table[selected[1]] + actions.artisan_run(command) + end, + }, + prompt = "Artisan > ", + previewer = CommandPreviewer(command_table), + fzf_opts = { + ["--preview-window"] = "nohidden,70%", + }, + }, opts or {}) + ) end, function(error) vim.api.nvim_err_writeln(error) end) diff --git a/lua/laravel/pickers/fzf_lua/pickers/commands.lua b/lua/laravel/pickers/fzf_lua/pickers/commands.lua index 7fd98e3..b85409c 100644 --- a/lua/laravel/pickers/fzf_lua/pickers/commands.lua +++ b/lua/laravel/pickers/fzf_lua/pickers/commands.lua @@ -3,10 +3,10 @@ local fzf_exec = require("fzf-lua").fzf_exec local commands_picker = {} -function commands_picker:new(runner, options) +function commands_picker:new(runner, user_commands_repository) local instance = { runner = runner, - options = options, + user_commands_repository = user_commands_repository, } setmetatable(instance, self) self.__index = self @@ -15,47 +15,30 @@ function commands_picker:new(runner, options) end function commands_picker:run(opts) - opts = opts or {} - - local commands = {} - - for command_name, group_commands in pairs(self.options:get().user_commands) do - for name, details in pairs(group_commands) do - table.insert(commands, { - executable = command_name, - name = name, - display = string.format("[%s] %s", command_name, name), - cmd = details.cmd, - desc = details.desc, - opts = details.opts or {}, - }) - end - end - - if vim.tbl_isempty(commands) then - vim.notify("No user command defined in the config", vim.log.levels.WARN, {}) - return - end - - local command_names, command_table = format_entry(commands) - - fzf_exec(command_names, { - actions = { - ["default"] = function(selected) - local command = command_table[selected[1]] - self.runner:run(command.executable, command.cmd, command.opts) - end, - }, - prompt = "User Commands > ", - fzf_opts = { - ["--preview-window"] = "nohidden,70%", - ["--preview"] = function(selected) - local command = command_table[selected[1]] - - return command.desc - end - }, - }) + self.user_commands_repository:all():thenCall(function(commands) + local command_names, command_table = format_entry(commands) + + fzf_exec( + command_names, + vim.tbl_extend("force", { + actions = { + ["default"] = function(selected) + local command = command_table[selected[1]] + self.runner:run(command.executable, command.cmd, command.opts) + end, + }, + prompt = "User Commands > ", + fzf_opts = { + ["--preview-window"] = "nohidden,70%", + ["--preview"] = function(selected) + local command = command_table[selected[1]] + + return command.desc + end, + }, + }, opts or {}) + ) + end) end return commands_picker diff --git a/lua/laravel/pickers/snacks/format_entry.lua b/lua/laravel/pickers/snacks/format_entry.lua new file mode 100644 index 0000000..f4d56f7 --- /dev/null +++ b/lua/laravel/pickers/snacks/format_entry.lua @@ -0,0 +1,65 @@ +local function split_string(input) + local group, command = input:match("([^:]+):([^:]+)") + if not group then + command = input + end + return group, command +end + +local M = {} + +local function format_command_text(command) + local group, cmd = split_string(command) + local out = {} + if group then + table.insert(out, { group, "@string" }) + table.insert(out, { ":", "@string" }) + end + table.insert(out, { cmd, "@keyword" }) + + return out +end + +M.command = function(item, _) + return format_command_text(item.value.name) +end + +M.composer_command = function(item, _) + return format_command_text(item.value.name) +end + +M.user_command = function(item, _) + return { + { string.format("[%s]", item.value.executable), "@string" }, + { " ", "@string" }, + { item.value.name, "@keyword" }, + } +end + +M.history = function(item, _) + return { + { item.value.name, "@keyword" }, + { " ", "@string" }, + { table.concat(item.value.args, " "), "@string" }, + } +end + +M.related = function(item, _) + return { + { item.value.class_name, "@string" }, + { item.value.type, "@keyword" }, + { item.value.extra_information or "", "@string" }, + } +end + +M.route = function(item, _) + return { + { vim.iter(item.value.methods):join("|"), "@string" }, + { " ", "@string" }, + { item.value.name, "@keyword" }, + { " ", "@string" }, + { item.value.uri, "@string" }, + } +end + +return M diff --git a/lua/laravel/pickers/snacks/pickers/artisan.lua b/lua/laravel/pickers/snacks/pickers/artisan.lua new file mode 100644 index 0000000..798b351 --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/artisan.lua @@ -0,0 +1,45 @@ +local snacks = require("snacks").picker +local common_actions = require("laravel.pickers.common.actions") +local preview = require("laravel.pickers.snacks.preview") +local format_entry = require("laravel.pickers.snacks.format_entry") + +---@class LaravelPickersSnacksArtisan +---@field commands_repository CommandsRepository +local artisan_picker = {} + +function artisan_picker:new(cache_commands_repository) + local instance = { + commands_repository = cache_commands_repository, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function artisan_picker:run(opts) + return self.commands_repository:all():thenCall(function(commands) + snacks.pick(vim.tbl_extend("force", { + title = "Artisan Commands", + items = vim + .iter(commands) + :map(function(command) + return { + value = command, + text = command.name, + } + end) + :totable(), + format = format_entry.command, + preview = preview.command, + confirm = function(picker, item) + picker:close() + if item then + common_actions.artisan_run(item.value) + end + end, + }, opts or {})) + end) +end + +return artisan_picker diff --git a/lua/laravel/pickers/snacks/pickers/commands.lua b/lua/laravel/pickers/snacks/pickers/commands.lua new file mode 100644 index 0000000..2a18508 --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/commands.lua @@ -0,0 +1,43 @@ +local snacks = require("snacks").picker +local format_entry = require("laravel.pickers.snacks.format_entry") +local preview = require("laravel.pickers.snacks.preview") + +local commands_picker = {} + +function commands_picker:new(runner, user_commands_repository) + local instance = { + runner = runner, + user_commands_repository = user_commands_repository, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function commands_picker:run(opts) + self.user_commands_repository:all():thenCall(function(commands) + snacks.pick(vim.tbl_extend("force", { + title = "User Commands", + items = vim + .iter(commands) + :map(function(command) + return { + value = command, + text = command.display, + } + end) + :totable(), + format = format_entry.user_command, + preview = preview.user_command, + confirm = function(picker, item) + picker:close() + if item then + self.runner:run(item.value.executable, item.value.cmd, item.value.opts) + end + end, + }, opts or {})) + end) +end + +return commands_picker diff --git a/lua/laravel/pickers/snacks/pickers/composer.lua b/lua/laravel/pickers/snacks/pickers/composer.lua new file mode 100644 index 0000000..d81e5dc --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/composer.lua @@ -0,0 +1,43 @@ +local snacks = require("snacks").picker +local common_actions = require("laravel.pickers.common.actions") +local preview = require("laravel.pickers.snacks.preview") +local format_entry = require("laravel.pickers.snacks.format_entry") + +local composer_picker = {} + +function composer_picker:new(composer_repository) + local instance = { + composer_repository = composer_repository, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function composer_picker:run(opts) + return self.composer_repository:all():thenCall(function(commands) + snacks.pick(vim.tbl_extend("force", { + title = "Composer Commands", + items = vim + .iter(commands) + :map(function(command) + return { + value = command, + text = command.name, + } + end) + :totable(), + format = format_entry.composer_command, + preview = preview.composer_command, + confirm = function(picker, item) + picker:close() + if item then + common_actions.composer_run(item.value) + end + end, + }, opts or {})) + end) +end + +return composer_picker diff --git a/lua/laravel/pickers/snacks/pickers/history.lua b/lua/laravel/pickers/snacks/pickers/history.lua new file mode 100644 index 0000000..53ad050 --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/history.lua @@ -0,0 +1,42 @@ +local snacks = require("snacks").picker +local format_entry = require("laravel.pickers.snacks.format_entry") + +local history_picker = {} + +function history_picker:new(history, runner) + local instance = { + history_provider = history, + runner = runner, + } + setmetatable(instance, self) + self.__index = self + return instance +end + +function history_picker:run(opts) + snacks.pick(vim.tbl_extend("force", { + title = "Laravel Commands History", + items = vim + .iter(self.history_provider:get()) + :map(function(history_entry) + return { + value = history_entry, + text = string.format("%s %s", history_entry.name, table.concat(history_entry.args, " ")), + } + end) + :totable(), + format = format_entry.history, + preview = "none", + layout = { + preview = false, + }, + confirm = function(picker, item) + picker:close() + if item then + self.runner:run(item.value.name, item.value.args, item.value.opts) + end + end, + }, opts or {})) +end + +return history_picker diff --git a/lua/laravel/pickers/snacks/pickers/make.lua b/lua/laravel/pickers/snacks/pickers/make.lua new file mode 100644 index 0000000..852ead1 --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/make.lua @@ -0,0 +1,47 @@ +local snacks = require("snacks").picker +local common_actions = require("laravel.pickers.common.actions") +local preview = require("laravel.pickers.snacks.preview") +local format_entry = require("laravel.pickers.snacks.format_entry") +local is_make_command = require("laravel.utils").is_make_command + +local make_picker = {} + +function make_picker:new(cache_commands_repository) + local instance = { + commands_repository = cache_commands_repository, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function make_picker:run(opts) + return self.commands_repository:all():thenCall(function(commands) + snacks.pick(vim.tbl_extend("force", { + title = "Artisan Commands", + items = vim + .iter(commands) + :filter(function(command) + return is_make_command(command.name) + end) + :map(function(command) + return { + value = command, + text = command.name, + } + end) + :totable(), + format = format_entry.command, + preview = preview.command, + confirm = function(picker, item) + picker:close() + if item then + common_actions.make_run(item.value) + end + end, + }, opts or {})) + end) +end + +return make_picker diff --git a/lua/laravel/pickers/snacks/pickers/related.lua b/lua/laravel/pickers/snacks/pickers/related.lua new file mode 100644 index 0000000..beb1ab2 --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/related.lua @@ -0,0 +1,45 @@ +local snacks = require("snacks").picker +local format_entry = require("laravel.pickers.snacks.format_entry") +local common_actions = require("laravel.pickers.common.actions") + +local related_picker = {} + +function related_picker:new(related) + local instance = { + related = related, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function related_picker:run(opts) + return self.related:get(vim.api.nvim_get_current_buf()):thenCall(function(related) + snacks.pick(vim.tbl_extend("force", { + title = "Related", + items = vim + .iter(related) + :map(function(item) + return { + value = item, + text = string.format("%s %s %s", item.class_name, item.type, item.extra_information), + } + end) + :totable(), + + format = format_entry.related, + layout = { + preview = false, + }, + confirm = function(picker, item) + picker:close() + if item then + common_actions.open_relation(item.value) + end + end, + }, opts or {})) + end) +end + +return related_picker diff --git a/lua/laravel/pickers/snacks/pickers/resources.lua b/lua/laravel/pickers/snacks/pickers/resources.lua new file mode 100644 index 0000000..34b11a5 --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/resources.lua @@ -0,0 +1,53 @@ +local snacks = require("snacks").picker + +local resources_picker = {} + +function resources_picker:new(options) + local instance = { + options = options, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function resources_picker:run(opts) + local resources = {} + for name, path in pairs(self.options:get().resources) do + if vim.fn.isdirectory(path) == 1 then + table.insert(resources, { + name = name, + path = path, + }) + end + end + + if vim.tbl_isempty(resources) then + vim.notify("No resources defined in the config", vim.log.levels.WARN, {}) + return + end + + snacks.pick(vim.tbl_extend("force", { + title = "Resources", + items = vim + .iter(resources) + :map(function(resource) + return { + value = resource, + text = resource.name, + file = resource.path, + } + end) + :totable(), + preview = "directory", + confirm = function(picker, item) + picker:close() + if item then + snacks.files({ cwd = item.value.path }) + end + end, + }, opts or {})) +end + +return resources_picker diff --git a/lua/laravel/pickers/snacks/pickers/routes.lua b/lua/laravel/pickers/snacks/pickers/routes.lua new file mode 100644 index 0000000..9a62ab6 --- /dev/null +++ b/lua/laravel/pickers/snacks/pickers/routes.lua @@ -0,0 +1,43 @@ +local snacks = require("snacks").picker +local common_actions = require("laravel.pickers.common.actions") +local preview = require("laravel.pickers.snacks.preview") +local format_entry = require("laravel.pickers.snacks.format_entry") + +local routes_picker = {} + +function routes_picker:new(cache_routes_repository) + local instance = { + routes_repository = cache_routes_repository, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function routes_picker:run(opts) + self.routes_repository:all():thenCall(function(routes) + snacks.pick(vim.tbl_extend("force", { + title = "Routes", + items = vim + .iter(routes) + :map(function(route) + return { + value = route, + text = string.format("%s %s %s", vim.iter(route.methods):join(" "), route.uri, route.name or ""), + } + end) + :totable(), + format = format_entry.route, + preview = preview.route, + confirm = function(picker, item) + picker:close() + if item then + common_actions.go(item.value) + end + end, + }, opts or {})) + end) +end + +return routes_picker diff --git a/lua/laravel/pickers/snacks/preview.lua b/lua/laravel/pickers/snacks/preview.lua new file mode 100644 index 0000000..f3638a5 --- /dev/null +++ b/lua/laravel/pickers/snacks/preview.lua @@ -0,0 +1,35 @@ +local preview = require("laravel.pickers.common.preview") + +local M = {} + +local function _preview(ctx, prev) + ctx.preview:reset() + ctx.preview:set_lines(prev.lines) + + vim.bo[ctx.preview.win.buf].modifiable = true + local hl = vim.api.nvim_create_namespace("laravel") + for _, value in pairs(prev.highlights) do + vim.api.nvim_buf_add_highlight(ctx.preview.win.buf, hl, value[1], value[2], value[3], value[4]) + end + + vim.bo[ctx.preview.win.buf].modifiable = false +end + +M.command = function(ctx) + _preview(ctx, preview.command(ctx.item.value)) +end + +M.composer_command = function(ctx) + _preview(ctx, preview.composer(ctx.item.value)) +end + +M.user_command = function(ctx) + ctx.preview:reset() + ctx.preview:set_lines({ ctx.item.value.desc }) +end + +M.route = function(ctx) + _preview(ctx, preview.route(ctx.item.value)) +end + +return M diff --git a/lua/laravel/pickers/telescope/make_entry.lua b/lua/laravel/pickers/telescope/make_entry.lua index 247b598..7ddc4f1 100644 --- a/lua/laravel/pickers/telescope/make_entry.lua +++ b/lua/laravel/pickers/telescope/make_entry.lua @@ -58,7 +58,7 @@ function M.gen_from_laravel_routes(opts) return function(route) return M.set_default_entry_mt({ value = route, - ordinal = vim.fn.join({ route.uri, route.name or "" }, " "), + ordinal = string.format("%s %s %s", vim.iter(route.methods):join(" "), route.uri, route.name or "" ), display = make_display, route_method = vim.fn.join(route.methods, "|"), }, opts) diff --git a/lua/laravel/pickers/telescope/pickers/commands.lua b/lua/laravel/pickers/telescope/pickers/commands.lua index af897f4..b3d6bb0 100644 --- a/lua/laravel/pickers/telescope/pickers/commands.lua +++ b/lua/laravel/pickers/telescope/pickers/commands.lua @@ -7,10 +7,10 @@ local previewers = require("telescope.previewers") local commands_picker = {} -function commands_picker:new(runner, options) +function commands_picker:new(runner, user_commands_repository) local instance = { runner = runner, - options = options, + user_commands_repository = user_commands_repository, } setmetatable(instance, self) self.__index = self @@ -19,64 +19,44 @@ function commands_picker:new(runner, options) end function commands_picker:run(opts) - opts = opts or {} - - local commands = {} - - for command_name, group_commands in pairs(self.options:get().user_commands) do - for name, details in pairs(group_commands) do - table.insert(commands, { - executable = command_name, - name = name, - display = string.format("[%s] %s", command_name, name), - cmd = details.cmd, - desc = details.desc, - opts = details.opts or {}, - }) - end - end - - if vim.tbl_isempty(commands) then - vim.notify("No user command defined in the config", vim.log.levels.WARN, {}) - return - end - - pickers - .new(opts, { - prompt_title = "User Commands", - finder = finders.new_table({ - results = commands, - entry_maker = function(command) - return { - value = command, - display = command.display, - ordinal = command.display, - } + self.user_commands_repository:all():thenCall(function(commands) + pickers + .new(opts, { + prompt_title = "User Commands", + finder = finders.new_table({ + results = commands, + entry_maker = function(command) + return { + value = command, + display = command.display, + ordinal = command.display, + } + end, + }), + previewer = previewers.new_buffer_previewer({ + title = "Description", + get_buffer_by_name = function(_, entry) + return entry.value.name + end, + define_preview = function(self_preview, entry) + vim.api.nvim_buf_set_lines(self_preview.state.bufnr, 0, -1, false, { entry.value.desc }) + end, + }), + sorter = conf.file_sorter(), + attach_mappings = function(_, map) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + local command = entry.value + + self.runner:run(command.executable, command.cmd, command.opts) + end) + + return true end, - }), - previewer = previewers.new_buffer_previewer({ - title = "Description", - get_buffer_by_name = function(_, entry) - return entry.value.name - end, - define_preview = function(self_preview, entry) - vim.api.nvim_buf_set_lines(self_preview.state.bufnr, 0, -1, false, { entry.value.desc }) - end, - }), - sorter = conf.file_sorter(), - attach_mappings = function(_, map) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - local command = entry.value - - self.runner:run(command.executable, command.cmd, command.opts) - end) - - return true - end, - }) - :find() + }) + :find() + end) end return commands_picker diff --git a/lua/laravel/pickers/telescope/pickers/composer.lua b/lua/laravel/pickers/telescope/pickers/composer.lua index 53ccd3e..ab86bcf 100644 --- a/lua/laravel/pickers/telescope/pickers/composer.lua +++ b/lua/laravel/pickers/telescope/pickers/composer.lua @@ -20,11 +20,9 @@ function composer_picker:new(composer_repository) end function composer_picker:run(opts) - opts = opts or {} - return self.composer_repository:all():thenCall(function(commands) pickers - .new(opts, { + .new(opts or {}, { prompt_title = "Composer commands", finder = finders.new_table({ results = commands, diff --git a/lua/laravel/pickers/telescope/pickers/history.lua b/lua/laravel/pickers/telescope/pickers/history.lua index 57a80c5..a393e8c 100644 --- a/lua/laravel/pickers/telescope/pickers/history.lua +++ b/lua/laravel/pickers/telescope/pickers/history.lua @@ -15,10 +15,8 @@ function history_picker:new(history) end function history_picker:run(opts) - opts = opts or {} - pickers - .new(opts, { + .new(opts or {}, { prompt_title = "Laravel Command History", finder = finders.new_table({ results = self.history_provider:get(), diff --git a/lua/laravel/pickers/ui_select/pickers/commands.lua b/lua/laravel/pickers/ui_select/pickers/commands.lua index f651a76..fd51853 100644 --- a/lua/laravel/pickers/ui_select/pickers/commands.lua +++ b/lua/laravel/pickers/ui_select/pickers/commands.lua @@ -1,9 +1,9 @@ local commands_picker = {} -function commands_picker:new(runner, options) +function commands_picker:new(runner, user_commands_repository) local instance = { runner = runner, - options = options, + user_commands_repository = user_commands_repository, } setmetatable(instance, self) self.__index = self @@ -12,38 +12,22 @@ function commands_picker:new(runner, options) end function commands_picker:run(opts) - opts = opts or {} - - local commands = {} - - for command_name, group_commands in pairs(self.options:get().user_commands) do - for name, details in pairs(group_commands) do - table.insert(commands, { - executable = command_name, - name = name, - display = string.format("[%s] %s", command_name, name), - cmd = details.cmd, - desc = details.desc, - opts = details.opts or {}, - }) - end - end - - if vim.tbl_isempty(commands) then - vim.notify("No user command defined in the config", vim.log.levels.WARN, {}) - return - end - - vim.ui.select(commands, { - prompt_title = "User Commands", - format_item = function(command) - return command.display - end, - kind = "resources", - }, function(command) - if command ~= nil then - self.runner:run(command.executable, command.cmd, command.opts) - end + self.user_commands_repository:all():thenCall(function(commands) + vim.ui.select( + commands, + vim.tbl_extend("force", { + prompt_title = "User Commands", + format_item = function(command) + return command.display + end, + kind = "resources", + }, opts or {}), + function(command) + if command ~= nil then + self.runner:run(command.executable, command.cmd, command.opts) + end + end + ) end) end diff --git a/lua/laravel/providers/laravel_provider.lua b/lua/laravel/providers/laravel_provider.lua index dbfe0aa..dd0e40d 100644 --- a/lua/laravel/providers/laravel_provider.lua +++ b/lua/laravel/providers/laravel_provider.lua @@ -12,6 +12,7 @@ function laravel_provider:register(app) app:bindIf("artisan", "laravel.services.artisan") app:bindIf("class", "laravel.services.class") app:bindIf("model", "laravel.services.model") + app:bindIf("related", "laravel.services.related") app:bindIf("composer", "laravel.services.composer") app:bindIf("runner", "laravel.services.runner") app:bindIf("ui_handler", "laravel.services.ui_handler") diff --git a/lua/laravel/providers/repositories_provider.lua b/lua/laravel/providers/repositories_provider.lua index 08665bb..0bec890 100644 --- a/lua/laravel/providers/repositories_provider.lua +++ b/lua/laravel/providers/repositories_provider.lua @@ -18,6 +18,8 @@ function repositories_provider:register(app) app:bindIf('cache_configs_repository', 'laravel.repositories.cache_configs_repository') app:bindIf('composer_repository', 'laravel.repositories.composer_repository') + + app:bindIf('user_commands_repository', 'laravel.repositories.user_commands_repository') end function repositories_provider:boot(app) diff --git a/lua/laravel/providers/snacks_provider.lua b/lua/laravel/providers/snacks_provider.lua new file mode 100644 index 0000000..ae4e54c --- /dev/null +++ b/lua/laravel/providers/snacks_provider.lua @@ -0,0 +1,24 @@ +---@class LaravelSnacksProvider : LaravelProvider +local snacks_provider = {} + +function snacks_provider:register(app) + local _, ok = pcall(require, "snacks") + if not ok then + return + end + + app:singeltonIf("snacks.pickers", function() + return { + artisan = "laravel.pickers.snacks.pickers.artisan", + commands = "laravel.pickers.snacks.pickers.commands", + composer = "laravel.pickers.snacks.pickers.composer", + history = "laravel.pickers.snacks.pickers.history", + make = "laravel.pickers.snacks.pickers.make", + related = "laravel.pickers.snacks.pickers.related", + resources = "laravel.pickers.snacks.pickers.resources", + routes = "laravel.pickers.snacks.pickers.routes", + } + end) +end + +return snacks_provider diff --git a/lua/laravel/repositories/user_commands_repository.lua b/lua/laravel/repositories/user_commands_repository.lua new file mode 100644 index 0000000..7fa4aba --- /dev/null +++ b/lua/laravel/repositories/user_commands_repository.lua @@ -0,0 +1,42 @@ +local promise = require("promise") + +---@class UserCommandsRepository +---@field options LaravelOptionsService +local user_commands_repository = {} + +function user_commands_repository:new(options) + local instance = { options = options } + + setmetatable(instance, self) + self.__index = self + + return instance +end + +function user_commands_repository:all() + local commands = {} + + for command_name, group_commands in pairs(self.options:get().user_commands) do + for name, details in pairs(group_commands) do + table.insert(commands, { + executable = command_name, + name = name, + display = string.format("[%s] %s", command_name, name), + cmd = details.cmd, + desc = details.desc, + opts = details.opts or {}, + }) + end + end + + return promise:new(function(resolve, reject) + if vim.tbl_isempty(commands) then + reject("No user command defined in the config") + return + end + + resolve(commands) + end) +end + +return user_commands_repository diff --git a/lua/laravel/services/related.lua b/lua/laravel/services/related.lua new file mode 100644 index 0000000..123b652 --- /dev/null +++ b/lua/laravel/services/related.lua @@ -0,0 +1,66 @@ +local related = {} + +local types = { "observers", "relations", "policy" } + +local build_relation = function(info, relation_type) + if next(info) == nil then + return nil + end + if relation_type == "observers" and info["observer"][2] ~= nil then + return { + class = info["observer"][2], + type = relation_type, + extra_information = info["event"], + } + elseif relation_type == "relations" then + return { + class = info["related"], + type = relation_type, + extra_information = info["type"] .. " " .. info["name"], + } + elseif relation_type == "policy" then + return { + class = info[1], + type = relation_type, + extra_information = "", + } + end + return nil +end + +function related:new(model) + local instance = { + model = model, + } + setmetatable(instance, self) + self.__index = self + + return instance +end + +function related:get(bufnr) + return self.model:parse(bufnr):thenCall(function(info) + local relations = {} + for _, relation_type in ipairs(types) do + if info[relation_type] and #info[relation_type] > 0 then + if type(info[relation_type]) == "table" and info[relation_type][1] then + for _, inf in ipairs(info[relation_type]) do + local relation = build_relation(inf, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + else + local relation = build_relation({ info[relation_type] }, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + end + end + + return relations + end) +end + +return related