From 38bc76fdb2346f2fcf0d14707346b29a5215a3ca Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Wed, 20 Sep 2023 22:34:37 +0200 Subject: [PATCH 01/55] Refactor base code --- lua/.luarc.json | 4 - lua/laravel/_autocommands.lua | 15 -- lua/laravel/_container.lua | 25 -- lua/laravel/_lsp/init.lua | 13 +- lua/laravel/_lsp/intelephense.lua | 6 +- lua/laravel/_lsp/phpactor.lua | 8 +- lua/laravel/application/init.lua | 153 ------------ lua/laravel/autocommands.lua | 13 + lua/laravel/command.lua | 63 ----- lua/laravel/commands.lua | 61 ----- lua/laravel/commands/init.lua | 29 +++ lua/laravel/commands/utils.lua | 18 ++ lua/laravel/{_config.lua => config.lua} | 52 ++-- lua/laravel/dev.lua | 45 ---- lua/laravel/environment/docker_compose.lua | 4 +- lua/laravel/environment/get_env.lua | 14 ++ lua/laravel/environment/init.lua | 33 ++- lua/laravel/environment/native.lua | 1 + lua/laravel/environment/resolver.lua | 11 +- lua/laravel/init.lua | 44 +--- lua/laravel/notify.lua | 13 + lua/laravel/resources.lua | 65 ----- lua/laravel/resources/create.lua | 27 ++ lua/laravel/resources/is_resource.lua | 5 + lua/laravel/resources/open.lua | 31 +++ .../{route_info.lua => route_info/init.lua} | 35 ++- lua/laravel/routes.lua | 88 ------- lua/laravel/routes/go.lua | 27 ++ lua/laravel/routes/init.lua | 26 ++ lua/laravel/{route.lua => routes/utils.lua} | 11 - lua/laravel/run.lua | 16 ++ lua/laravel/runners/async.lua | 6 +- lua/laravel/runners/buffer.lua | 15 +- lua/laravel/runners/sync.lua | 4 +- lua/laravel/runners/terminal.lua | 4 +- lua/laravel/telescope/pickers/commands.lua | 82 +++++++ lua/laravel/telescope/pickers/related.lua | 139 +++++++++++ lua/laravel/telescope/pickers/routes.lua | 61 +++++ lua/laravel/telescope/ui_run.lua | 68 +++++ lua/laravel/tinker.lua | 25 -- lua/laravel/tinker/get_selection.lua | 20 ++ lua/laravel/tinker/init.lua | 28 +++ lua/laravel/user-commands/composer.lua | 56 ----- lua/laravel/user-commands/docker_compose.lua | 93 ------- lua/laravel/user-commands/laravel_info.lua | 34 --- lua/laravel/user-commands/npm.lua | 29 --- lua/laravel/user-commands/sail.lua | 96 -------- lua/laravel/user-commands/yarn.lua | 29 --- .../artisan.lua | 11 +- lua/laravel/user_commands/bun.lua | 17 ++ lua/laravel/user_commands/composer.lua | 44 ++++ .../user_commands/create_user_command.lua | 22 ++ lua/laravel/user_commands/docker_compose.lua | 82 +++++++ .../{user-commands => user_commands}/init.lua | 4 +- lua/laravel/user_commands/laravel/info.lua | 35 +++ .../laravel/init.lua} | 14 +- lua/laravel/user_commands/npm.lua | 17 ++ lua/laravel/user_commands/sail.lua | 83 +++++++ lua/laravel/user_commands/yarn.lua | 17 ++ lua/laravel/utils.lua | 55 ----- lua/telescope/_extensions/laravel.lua | 232 +----------------- lua/telescope/pickers/related.lua | 134 ---------- 62 files changed, 1060 insertions(+), 1452 deletions(-) delete mode 100644 lua/.luarc.json delete mode 100644 lua/laravel/_autocommands.lua delete mode 100644 lua/laravel/_container.lua delete mode 100644 lua/laravel/application/init.lua create mode 100644 lua/laravel/autocommands.lua delete mode 100644 lua/laravel/command.lua delete mode 100644 lua/laravel/commands.lua create mode 100644 lua/laravel/commands/init.lua create mode 100644 lua/laravel/commands/utils.lua rename lua/laravel/{_config.lua => config.lua} (74%) delete mode 100644 lua/laravel/dev.lua create mode 100644 lua/laravel/environment/get_env.lua create mode 100644 lua/laravel/notify.lua delete mode 100644 lua/laravel/resources.lua create mode 100644 lua/laravel/resources/create.lua create mode 100644 lua/laravel/resources/is_resource.lua create mode 100644 lua/laravel/resources/open.lua rename lua/laravel/{route_info.lua => route_info/init.lua} (85%) delete mode 100644 lua/laravel/routes.lua create mode 100644 lua/laravel/routes/go.lua create mode 100644 lua/laravel/routes/init.lua rename lua/laravel/{route.lua => routes/utils.lua} (68%) create mode 100644 lua/laravel/run.lua create mode 100644 lua/laravel/telescope/pickers/commands.lua create mode 100644 lua/laravel/telescope/pickers/related.lua create mode 100644 lua/laravel/telescope/pickers/routes.lua create mode 100644 lua/laravel/telescope/ui_run.lua delete mode 100644 lua/laravel/tinker.lua create mode 100644 lua/laravel/tinker/get_selection.lua create mode 100644 lua/laravel/tinker/init.lua delete mode 100644 lua/laravel/user-commands/composer.lua delete mode 100644 lua/laravel/user-commands/docker_compose.lua delete mode 100644 lua/laravel/user-commands/laravel_info.lua delete mode 100644 lua/laravel/user-commands/npm.lua delete mode 100644 lua/laravel/user-commands/sail.lua delete mode 100644 lua/laravel/user-commands/yarn.lua rename lua/laravel/{user-commands => user_commands}/artisan.lua (83%) create mode 100644 lua/laravel/user_commands/bun.lua create mode 100644 lua/laravel/user_commands/composer.lua create mode 100644 lua/laravel/user_commands/create_user_command.lua create mode 100644 lua/laravel/user_commands/docker_compose.lua rename lua/laravel/{user-commands => user_commands}/init.lua (71%) create mode 100644 lua/laravel/user_commands/laravel/info.lua rename lua/laravel/{user-commands/laravel.lua => user_commands/laravel/init.lua} (64%) create mode 100644 lua/laravel/user_commands/npm.lua create mode 100644 lua/laravel/user_commands/sail.lua create mode 100644 lua/laravel/user_commands/yarn.lua delete mode 100644 lua/laravel/utils.lua delete mode 100644 lua/telescope/pickers/related.lua diff --git a/lua/.luarc.json b/lua/.luarc.json deleted file mode 100644 index e1b9d70..0000000 --- a/lua/.luarc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", - "Lua.workspace.checkThirdParty": false -} \ No newline at end of file diff --git a/lua/laravel/_autocommands.lua b/lua/laravel/_autocommands.lua deleted file mode 100644 index c40de59..0000000 --- a/lua/laravel/_autocommands.lua +++ /dev/null @@ -1,15 +0,0 @@ -local autocommands = {} - -autocommands.dir_changed = function(opts) - -- register an auto comamnds for the event DirChanged - -- this should calla the setup again with the provided options - local group = vim.api.nvim_create_augroup("laravel", {}) - vim.api.nvim_create_autocmd({ "DirChanged" }, { - group = group, - callback = function() - require("laravel").setup(opts) - end, - }) -end - -return autocommands diff --git a/lua/laravel/_container.lua b/lua/laravel/_container.lua deleted file mode 100644 index 9e7f75c..0000000 --- a/lua/laravel/_container.lua +++ /dev/null @@ -1,25 +0,0 @@ -local storage = {} - -return { - get = function(key, default) - if storage[key] ~= nil then - return storage[key] - end - - if type(default) == "function" then - return default() - end - return default - end, - set = function(key, value) - storage[key] = value - return value - end, - unset = function(key) - storage[key] = nil - return nil - end, - purge = function() - storage = {} - end, -} diff --git a/lua/laravel/_lsp/init.lua b/lua/laravel/_lsp/init.lua index df2f25a..301c5c1 100644 --- a/lua/laravel/_lsp/init.lua +++ b/lua/laravel/_lsp/init.lua @@ -1,7 +1,7 @@ local phpactor = require "laravel._lsp.phpactor" local intelephense = require "laravel._lsp.intelephense" -local utils = require "laravel.utils" -local application = require "laravel.application" +local notify = require("laravel.notify") +local config = require "laravel.config" local servers = { phpactor = phpactor, @@ -17,8 +17,7 @@ local get_client = function(server_name) if not client then local server = require("lspconfig")[server_name] - local config = server.make_config(vim.fn.getcwd()) - local client_id = vim.lsp.start(config) + local client_id = vim.lsp.start(server.make_config(vim.fn.getcwd())) client = vim.lsp.get_client_by_id(client_id) new_instance = true end @@ -29,18 +28,18 @@ end ---@param full_class string ---@param method string local go_to = function(full_class, method) - local server_name = application.get_options().lsp_server + local server_name = config.options.lsp_server local server = servers[server_name] if server == nil then - utils.notify("Route open", { msg = "No server name " .. server_name, level = "WARN" }) + notify("Route open", { msg = "No server name " .. server_name, level = "WARN" }) return end local client, is_new_instance = get_client(server_name) if not client then - utils.notify("Route open", { msg = "Can't get lsp client", level = "WARN" }) + notify("Route open", { msg = "Can't get lsp client", level = "WARN" }) return end diff --git a/lua/laravel/_lsp/intelephense.lua b/lua/laravel/_lsp/intelephense.lua index 3107d54..20f415c 100644 --- a/lua/laravel/_lsp/intelephense.lua +++ b/lua/laravel/_lsp/intelephense.lua @@ -1,5 +1,5 @@ local lsp_utils = require "laravel._lsp.utils" -local laravel_utils = require "laravel.utils" +local notify = require("laravel.notify") ---@param client table ---@param is_new_instance boolean @@ -25,7 +25,7 @@ local function go_to(client, is_new_instance, full_class, method) end if class_location == nil then - laravel_utils.notify("Route Open", { msg = "Could not find class for : " .. full_class, level = "WARN" }) + notify("Route Open", { msg = "Could not find class for : " .. full_class, level = "WARN" }) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -41,7 +41,7 @@ local function go_to(client, is_new_instance, full_class, method) vim.lsp.buf_request(0, "textDocument/documentSymbol", params, function(method_err, method_server_result, _, _) if method_err then - laravel_utils.notify( + notify( "Route Open", { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" } ) diff --git a/lua/laravel/_lsp/phpactor.lua b/lua/laravel/_lsp/phpactor.lua index d96b4ac..d0b8fc9 100644 --- a/lua/laravel/_lsp/phpactor.lua +++ b/lua/laravel/_lsp/phpactor.lua @@ -1,5 +1,5 @@ local lsp_utils = require "laravel._lsp.utils" -local laravel_utils = require "laravel.utils" +local notify = require("laravel.notify") ---@param client table ---@param is_new_instance boolean @@ -14,7 +14,7 @@ local function go_to(client, is_new_instance, full_class, method) local locations = vim.lsp.util.symbols_to_items(resp.result or {}, nil) or {} if vim.tbl_isempty(locations) then - laravel_utils.notify("Route Open", { msg = "Empty response looking for class: " .. full_class, level = "WARN" }) + notify("Route Open", { msg = "Empty response looking for class: " .. full_class, level = "WARN" }) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -30,7 +30,7 @@ local function go_to(client, is_new_instance, full_class, method) end if class_location == nil then - laravel_utils.notify("Route Open", { msg = "Could not find class for : " .. full_class, level = "WARN" }) + notify("Route Open", { msg = "Could not find class for : " .. full_class, level = "WARN" }) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -46,7 +46,7 @@ local function go_to(client, is_new_instance, full_class, method) vim.lsp.buf_request(0, "textDocument/documentSymbol", params, function(method_err, method_server_result, _, _) if method_err then - laravel_utils.notify( + notify( "Route Open", { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" } ) diff --git a/lua/laravel/application/init.lua b/lua/laravel/application/init.lua deleted file mode 100644 index 111eb2e..0000000 --- a/lua/laravel/application/init.lua +++ /dev/null @@ -1,153 +0,0 @@ -local container = require "laravel._container" -local environment = require "laravel.environment" -local utils = require "laravel.utils" -local runners = require "laravel.runners" - -local app = nil - ----@param options laravel.config -local initialize = function(options) - app = nil - - if vim.fn.filereadable "artisan" == 0 then - return - end - - local resolvedEnv = environment.initialize(options.environment.environments, options.environment.resolver) - -- fill with the environment - if not resolvedEnv then - utils.notify("App", { msg = "Could not initialize environment", level = "ERROR" }) - return - end - - app = { - envSetup = resolvedEnv, - environment = resolvedEnv(), - options = options, - } -end - ----@param command string ----@return boolean -local has_command = function(command) - local executable = app.environment.executables[command] - - return executable ~= nil -end - ----@param command string ----@param args table -local build_command = function(command, args) - local out = {} - if not has_command(command) then - utils.notify("Build command", { - msg = string.format("Command %s not available in environment", command), - level = "ERROR", - }) - - return - end - - local executable = app.environment.executables[command] - - for _, part in ipairs(executable) do - table.insert(out, part) - end - - for _, part in ipairs(args) do - table.insert(out, part) - end - return out -end - -local warmup = function() - app.environment = app.envSetup() - require("laravel.commands").load() - require("laravel.routes").load() -end - ----@return boolean -local ready = function() - return app ~= nil -end - ----@param command string ----@param args table ----@param opts table ----@return table, boolean -local run = function(command, args, opts) - opts = opts or {} - local is_tinker = command == "artisan" and args[1] == "tinker" - - local cmd = build_command(command, args) - local runner = opts.runner or app.options.commands_runner[args[1]] or app.options.default_runner - - local result, ok = runners[runner](cmd, opts) - - local function getChannel() - if runner == "buffer" then - return result.job - elseif runner == "terminal" then - return result.term_id - end - end - - if ok and is_tinker then - container.set("tinker", getChannel()) - vim.api.nvim_create_autocmd({ "BufDelete" }, { - buffer = result.buff, - callback = function() - container.unset "tinker" - end, - }) - end - - return result, ok -end - ----@param decorated function -local check_ready = function(decorated) - return function(...) - if not ready() then - utils.notify( - "application", - { level = "ERROR", msg = "The application is not ready for current working directory" } - ) - end - - return decorated(...) - end -end - -return { - initialize = initialize, - - run = check_ready(run), - - has_command = check_ready(has_command), - - warmup = check_ready(warmup), - - ready = ready, - - container = container, - - get_options = check_ready(function() - return app.options - end), - - get_info = function() - local info = { - ready = ready(), - } - - if not ready() then - return info - end - - info.options = app.options - info.environment = app.environment - - return info - end, -} diff --git a/lua/laravel/autocommands.lua b/lua/laravel/autocommands.lua new file mode 100644 index 0000000..6a71ffd --- /dev/null +++ b/lua/laravel/autocommands.lua @@ -0,0 +1,13 @@ +local M = {} + +function M.setup() + local environment = require("laravel.environment") + + local group = vim.api.nvim_create_augroup("laravel", {}) + vim.api.nvim_create_autocmd({ "DirChanged" }, { + group = group, + callback = environment.setup, + }) +end + +return M diff --git a/lua/laravel/command.lua b/lua/laravel/command.lua deleted file mode 100644 index c6fd15c..0000000 --- a/lua/laravel/command.lua +++ /dev/null @@ -1,63 +0,0 @@ -local application = require "laravel.application" - ----@class CommandArgument ----@field name string ----@field is_required boolean ----@field is_array boolean ----@field description string ----@field default string - ----@class CommandOption ----@field name string ----@field shortcut string|nil ----@field accept_value boolean ----@field is_value_required boolean ----@field is_multiple boolean ----@field description string ----@field default any - ----@class CommandDefinition ----@field arguments CommandArgument[] ----@field options CommandOption[] - ----@class LaravelCommand ----@field name string ----@field description string ----@field usage string[] ----@field help string ----@field hidden boolean ----@field definition CommandDefinition ----@field runner string - -local M = {} - ----Gets list of commands from the raw json ----@param json string ----@return LaravelCommand[] -M.from_json = function(json) - local cmds = {} - - if json == "" or json == nil or #json == 0 then - return cmds - end - - for _, cmd in ipairs(vim.fn.json_decode(json).commands) do - if not cmd.hidden then - table.insert(cmds, cmd) - end - end - return cmds -end - ---- Gets the runner for a given command ----@param command LaravelCommand -M.get_runner = function(command) - local runner = application.get_options().commands_runner[command.name] - if runner ~= nil then - return runner - end - - return application.get_options().default_runner -end - -return M diff --git a/lua/laravel/commands.lua b/lua/laravel/commands.lua deleted file mode 100644 index 3b3409c..0000000 --- a/lua/laravel/commands.lua +++ /dev/null @@ -1,61 +0,0 @@ -local log = require("laravel.dev").log -local application = require "laravel.application" -local laravel_command = require "laravel.command" -local utils = require "laravel.utils" - -local container_key = "artisan_commands" - -return { - clean = function() - application.container.unset(container_key) - end, - - list = function() - if not application.ready() then - utils.notify( - "Commands List", - { level = "ERROR", msg = "The application is not ready for current working directory" } - ) - return nil - end - - local commands = application.container.get(container_key) - if commands then - return commands - end - -- return the commands - local result, ok = application.run("artisan", { "list", "--format=json" }, { runner = "sync" }) - if not ok then - return nil - end - - if result.exit_code == 1 then - log.error("app.commands(): stdout", result.out) - log.error("app.commands(): stderr", result.err) - return nil - end - - commands = laravel_command.from_json(result.out) - - if #commands > 0 then - application.container.set(container_key, commands) - end - - return commands - end, - - load = function() - application.run("artisan", { "list", "--format=json" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code == 1 then - application.container.unset(container_key) - end - local commands = laravel_command.from_json(j:result()) - if #commands > 0 then - application.container.set(container_key, commands) - end - end, - }) - end, -} diff --git a/lua/laravel/commands/init.lua b/lua/laravel/commands/init.lua new file mode 100644 index 0000000..ede3fb3 --- /dev/null +++ b/lua/laravel/commands/init.lua @@ -0,0 +1,29 @@ +local run = require "laravel.run" +local utils = require "laravel.commands.utils" +local notify = require "laravel.notify" + +local M = {} + +M.list = {} + +function M.load() + local result, ok = run("artisan", { "list", "--format=json" }, { runner = "sync" }) + if not ok or result.exit_code == 1 then + notify( + "Commands.Load", + { + msg = string.format("Failed to get commands %s %s", vim.inspect(result.out), vim.inspect(result.err)), + level = "ERROR", + } + ) + M.list = {} + + return false + end + + M.list = utils.from_json(result.out) + + return true +end + +return M diff --git a/lua/laravel/commands/utils.lua b/lua/laravel/commands/utils.lua new file mode 100644 index 0000000..46fe299 --- /dev/null +++ b/lua/laravel/commands/utils.lua @@ -0,0 +1,18 @@ +local M = {} + +M.from_json = function(json) + local cmds = {} + + if json == "" or json == nil or #json == 0 then + return cmds + end + + for _, cmd in ipairs(vim.fn.json_decode(json).commands) do + if not cmd.hidden then + table.insert(cmds, cmd) + end + end + return cmds +end + +return M diff --git a/lua/laravel/_config.lua b/lua/laravel/config.lua similarity index 74% rename from lua/laravel/_config.lua rename to lua/laravel/config.lua index b7442ec..eb5ef93 100644 --- a/lua/laravel/_config.lua +++ b/lua/laravel/config.lua @@ -1,38 +1,21 @@ ----@class split ----@field relative string ----@field position string ----@field size string ----@field enter boolean -local split = { - relative = "editor", - position = "right", - size = "30%", - enter = true, -} - ----@class route_info ----@field enable boolean ----@field position string +local M = {} ----@class laravel.config ----@field split split ----@field bind_telescope boolean ----@field default_runner string ----@field lsp_server string ----@field resources table ----@field register_user_commands boolean ----@field commands_runner table ----@field route_info route_info -local config = { - split = split, - bind_telescope = true, - register_user_commands = true, +---@class LaravelOptions +M.defaults = { + split = { + relative = "editor", + position = "right", + size = "30%", + enter = true, + }, lsp_server = "phpactor", + register_user_commands = true, + bind_telescope = true, + default_runner = "buffer", route_info = { enable = true, position = "right", }, - default_runner = "buffer", commands_runner = { ["dump-server"] = "persist", ["queue:listen"] = "persist", @@ -43,7 +26,7 @@ local config = { ["db"] = "terminal", }, environment = { - resolver = require "laravel.environment.resolver"(true, true, nil), + resolver = require ("laravel.environment.resolver")(true, true, nil), environments = { ["local"] = require("laravel.environment.native").setup(), ["sail"] = require("laravel.environment.sail").setup(), @@ -87,4 +70,11 @@ local config = { }, } -return config +--- @type LaravelOptions +M.options = {} + +function M.setup(options) + M.options = vim.tbl_deep_extend("force", {}, M.defaults, options or {}) +end + +return M diff --git a/lua/laravel/dev.lua b/lua/laravel/dev.lua deleted file mode 100644 index d359230..0000000 --- a/lua/laravel/dev.lua +++ /dev/null @@ -1,45 +0,0 @@ -local M = {} - -function M.reload() - require("plenary.reload").reload_module "laravel" -end - -local log_levels = { "trace", "debug", "info", "warn", "error", "fatal" } - -local function set_log_level() - local log_level = vim.env.LARAVEL_LOG or vim.g.laravel_log_level - - for _, level in pairs(log_levels) do - if level == log_level then - return log_level - end - end - - return "warn" -- default, if user hasn't set to one from log_levels -end - -local log_level = set_log_level() - -M.log = require("plenary.log").new { - plugin = "laravel", - level = log_level, -} - -local log_key = os.time() - -local function override(key) - local fn = M.log[key] - M.log[key] = function(...) - fn(log_key, ...) - end -end - -for _, v in pairs(log_levels) do - override(v) -end - -function M.get_log_key() - return log_key -end - -return M diff --git a/lua/laravel/environment/docker_compose.lua b/lua/laravel/environment/docker_compose.lua index 1e408fa..2303e4c 100644 --- a/lua/laravel/environment/docker_compose.lua +++ b/lua/laravel/environment/docker_compose.lua @@ -1,4 +1,4 @@ -local utils = require "laravel.utils" +local get_env = require("laravel.environment.get_env") local M = {} @@ -8,7 +8,7 @@ M.setup = function(opts) return function() opts = opts or {} - local container = utils.get_env "APP_SERVICE" or opts.container_name or "app" + local container = get_env "APP_SERVICE" or opts.container_name or "app" local cmd = opts.cmd or { "docker", "compose", "exec", "-it", container } diff --git a/lua/laravel/environment/get_env.lua b/lua/laravel/environment/get_env.lua new file mode 100644 index 0000000..98e4fb2 --- /dev/null +++ b/lua/laravel/environment/get_env.lua @@ -0,0 +1,14 @@ +return function(var) + local envVal + if vim.fn.exists "*DotenvGet" == 1 then + envVal = vim.fn.DotenvGet(var) + else + envVal = vim.fn.eval("$" .. var) + end + + if envVal == "" then + return nil + end + + return envVal +end diff --git a/lua/laravel/environment/init.lua b/lua/laravel/environment/init.lua index c936de9..5452e9a 100644 --- a/lua/laravel/environment/init.lua +++ b/lua/laravel/environment/init.lua @@ -1,9 +1,30 @@ -local environment = {} +local config = require "laravel.config" +local user_commands = require "laravel.user_commands" ----@param environments table ----@param resolver function -environment.initialize = function(environments, resolver) - return resolver(environments) +local M = {} + +M.environment = {} + +function M.setup() + M.environment = config.options.environment.resolver(config.options.environment.environments) + if type(M.environment) == "function" then + M.environment = M.environment() + end + + user_commands.setup() + if config.options.route_info.enable then + require("laravel.route_info").setup() + end +end + +---@param name string +---@return string[]|nil +function M.get_executable(name) + local executable = M.environment.executables[name] + if executable == nil then + return nil + end + return executable end -return environment +return M diff --git a/lua/laravel/environment/native.lua b/lua/laravel/environment/native.lua index bb12687..e803679 100644 --- a/lua/laravel/environment/native.lua +++ b/lua/laravel/environment/native.lua @@ -10,6 +10,7 @@ M.setup = function(opts) artisan = opts.artisan or { "php", "artisan" }, composer = opts.composer or { "composer" }, npm = opts.npm or { "npm" }, + bun = opts.bun or { "bun" }, yarn = opts.yarn or { "yarn" }, php = opts.php or { "php" }, } diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua index 74d4c7d..5537fa1 100644 --- a/lua/laravel/environment/resolver.lua +++ b/lua/laravel/environment/resolver.lua @@ -1,15 +1,16 @@ -local utils = require "laravel.utils" +local notify = require("laravel.notify") +local get_env = require("laravel.environment.get_env") ---@param env_check boolean ---@param auto_discovery boolean ---@param default string|nil return function(env_check, auto_discovery, default) return function(environments) - local env_name = utils.get_env "NVIM_LARAVEL_ENV" + local env_name = get_env "NVIM_LARAVEL_ENV" if env_check and env_name ~= nil then local environment = environments[env_name] if environment == nil then - utils.notify("Environment resolver", { + notify("Environment resolver", { msg = "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", level = "ERROR", }) @@ -41,7 +42,7 @@ return function(env_check, auto_discovery, default) if default then local environment = environments[default] if environment == nil then - utils.notify( + notify( "Environment resolver", { msg = "Default define as " .. default .. " but there is no environment define", level = "ERROR" } ) @@ -51,7 +52,7 @@ return function(env_check, auto_discovery, default) end end - utils.notify( + notify( "Environment resolver", { msg = "Could not resolve any environment please check your configuration", level = "ERROR" } ) diff --git a/lua/laravel/init.lua b/lua/laravel/init.lua index 78e9701..0742365 100644 --- a/lua/laravel/init.lua +++ b/lua/laravel/init.lua @@ -1,44 +1,16 @@ -local Dev = require "laravel.dev" -local defaults = require "laravel._config" -local application = require "laravel.application" -local _autocommands = require "laravel._autocommands" - -local log = Dev.log - local M = {} ----Set up laravel plugin ----@param opts laravel.config|nil +---@param opts? LaravelOptions function M.setup(opts) - log.trace "setup(): Setting up..." - log.trace("setup(): log_key", Dev.get_log_key()) - - _autocommands.dir_changed(opts or {}) - - local options = vim.tbl_deep_extend("force", defaults, opts or {}) - - application.initialize(options) - - if not application.ready() then - return - end - - application.warmup() - - -- TODO: remove once 0.9 was general available - if vim.fn.has "nvim-0.9.0" ~= 1 then - vim.treesitter.query.get = vim.treesitter.get_query - vim.treesitter.query.set = vim.treesitter.set_query - end - - log.debug("setup(): Complete config", options) + local config = require "laravel.config" + local environment = require "laravel.environment" + local autocmds = require "laravel.autocommands" - if options.register_user_commands then - require("laravel.user-commands").setup() - end + config.setup(opts) + autocmds.setup() - if options.route_info.enable then - require("laravel.route_info").register() + if vim.fn.filereadable "artisan" ~= 0 then + environment.setup() end end diff --git a/lua/laravel/notify.lua b/lua/laravel/notify.lua new file mode 100644 index 0000000..2a3e88d --- /dev/null +++ b/lua/laravel/notify.lua @@ -0,0 +1,13 @@ +return function (funname, opts) + local level = vim.log.levels[opts.level] + if not level then + error("Invalid error level", 2) + end + local body = string.format("[laravel.%s]: %s", funname, opts.msg) + if opts.raw ~= nil then + body = opts.raw + end + vim.notify(body, level, { + title = "Laravel.nvim", + }) +end diff --git a/lua/laravel/resources.lua b/lua/laravel/resources.lua deleted file mode 100644 index ba645bb..0000000 --- a/lua/laravel/resources.lua +++ /dev/null @@ -1,65 +0,0 @@ -local log = require("laravel.dev").log -local utils = require "laravel.utils" -local application = require "laravel.application" - -local M = {} - ----Opens the resource ----@param resource string ----@param name string -M.open = function(resource, name) - local directory = application.get_options().resources[resource] - local filename = "" - if type(directory) == "function" then - local err - filename, err = directory(name) - if err ~= nil then - log.error("resource.open(): Error getting the name", err) - return - end - filename = filename[1] - elseif type(directory) == "string" then - filename = string.format("%s/%s.php", directory, name) - end - - if vim.fn.findfile(filename) then - local uri = vim.uri_from_fname(string.format("%s/%s", vim.fn.getcwd(), filename)) - local buffer = vim.uri_to_bufnr(uri) - vim.api.nvim_win_set_buf(0, buffer) - - return - end - - utils.notify("resources.open", { - msg = string.format("Can't find resource %s", filename), - level = "INFO", - }) -end - ---- Identifies if the given command is a resource ----@param name string ----@return boolean -M.is_resource = function(name) - return application.get_options().resources[name] ~= nil -end - ---- Creates the resource and opens the file ----@param cmd table -M.create = function(cmd) - if not M.is_resource(cmd[1]) then - log.error("resource.create(): Invalid command", cmd) - return - end - - local resource = cmd[1] - local name = cmd[2] - - application.run("artisan", cmd, { - runner = "async", - callback = function() - M.open(resource, name) - end, - }) -end - -return M diff --git a/lua/laravel/resources/create.lua b/lua/laravel/resources/create.lua new file mode 100644 index 0000000..3113eae --- /dev/null +++ b/lua/laravel/resources/create.lua @@ -0,0 +1,27 @@ +local run = require "laravel.run" +local is_resource = require "laravel.resources.is_resource" +local open = require("laravel.resources.open") +local notify = require "laravel.notify" + +return function(command) + local resource = command[1] + local name = command[2] + + if not is_resource(resource) then + notify( + "Resource.Create", + { level = "ERROR", msg = string.format("Command %s is not a resource creation suported", resource) } + ) + + return false + end + + run('artisan', command, { + runner = 'async', + callback = function () + open(resource, name) + end + }) + + return true +end diff --git a/lua/laravel/resources/is_resource.lua b/lua/laravel/resources/is_resource.lua new file mode 100644 index 0000000..db81908 --- /dev/null +++ b/lua/laravel/resources/is_resource.lua @@ -0,0 +1,5 @@ +local config = require "laravel.config" + +return function(resource) + return config.options.resources[resource] ~= nil +end diff --git a/lua/laravel/resources/open.lua b/lua/laravel/resources/open.lua new file mode 100644 index 0000000..62d8cfa --- /dev/null +++ b/lua/laravel/resources/open.lua @@ -0,0 +1,31 @@ +local config = require "laravel.config" +local notify = require "laravel.notify" + +return function(resource, name) + local directory = config.options.resources[resource] + local filename = "" + if type(directory) == "function" then + local err + filename, err = directory(name) + if err ~= nil then + notify("Resource.Open", { level = "ERROR", msg = "Error getting the name" }) + return + end + filename = filename[1] + elseif type(directory) == "string" then + filename = string.format("%s/%s.php", directory, name) + end + + if vim.fn.findfile(filename) then + local uri = vim.uri_from_fname(string.format("%s/%s", vim.fn.getcwd(), filename)) + local buffer = vim.uri_to_bufnr(uri) + vim.api.nvim_win_set_buf(0, buffer) + + return + end + + notify("Resource.Open", { + msg = string.format("Can't find resource %s", filename), + level = "INFO", + }) +end diff --git a/lua/laravel/route_info.lua b/lua/laravel/route_info/init.lua similarity index 85% rename from lua/laravel/route_info.lua rename to lua/laravel/route_info/init.lua index 8228485..703a35d 100644 --- a/lua/laravel/route_info.lua +++ b/lua/laravel/route_info/init.lua @@ -1,16 +1,10 @@ -local utils = require "laravel.utils" -local laravel_routes = require "laravel.routes" -local application = require "laravel.application" +local notify = require("laravel.notify") +local routes = require "laravel.routes" +local config = require "laravel.config" local get_node_text = vim.treesitter.get_node_text -local options = application.get_options().route_info - --- TODO: remove once 0.9 was general available -if vim.fn.has "nvim-0.9.0" ~= 1 then - vim.treesitter.query.get = vim.treesitter.get_query - vim.treesitter.query.set = vim.treesitter.set_query -end +local options = config.options.route_info vim.treesitter.query.set( "php", @@ -72,15 +66,16 @@ local function set_route_to_methods(event) vim.api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1) vim.diagnostic.reset(namespace, bufnr) - local routes = laravel_routes.list() - if routes == nil then - return + if #routes.list == 0 then + if not routes.load() then + return + end end local php_parser = vim.treesitter.get_parser(bufnr, "php") local tree = php_parser:parse()[1] if tree == nil then - utils.notify("route_info.set_route_to_methods", { msg = "Could not retrive syntax tree", level = "WARN" }) + notify("route_info.set_route_to_methods", { msg = "Could not retrive syntax tree", level = "WARN" }) return end @@ -119,7 +114,7 @@ local function set_route_to_methods(event) end local errors = {} - for _, route in pairs(routes) do + for _, route in pairs(routes.list) do local found = false for _, method in pairs(class_methods) do local action_full = route.action @@ -153,12 +148,14 @@ end local group = vim.api.nvim_create_augroup("laravel.route_info", {}) -local register = function() +local M = {} + +function M.setup() vim.api.nvim_create_autocmd({ "BufWritePost" }, { pattern = { "routes/*.php" }, group = group, callback = function() - laravel_routes.load() + routes.load() end, }) @@ -169,6 +166,4 @@ local register = function() }) end -return { - register = register, -} +return M diff --git a/lua/laravel/routes.lua b/lua/laravel/routes.lua deleted file mode 100644 index 23b7701..0000000 --- a/lua/laravel/routes.lua +++ /dev/null @@ -1,88 +0,0 @@ -local log = require("laravel.dev").log -local application = require "laravel.application" -local laravel_route = require "laravel.route" -local utils = require "laravel.utils" -local lsp = require "laravel._lsp" - -local container_key = "artisan_routes" - ----@param route LaravelRoute -local go_to = function(route) - if route.action == "Closure" then - if vim.tbl_contains(route.middlewares, "api") then - vim.cmd "edit routes/api.php" - vim.fn.search(route.uri:gsub("api", "") .. "") - elseif vim.tbl_contains(route.middlewares, "web") then - vim.cmd "edit routes/web.php" - if route.uri == "/" then - vim.fn.search "['\"]/['\"]" - else - vim.fn.search("/" .. route.uri) - end - else - utils.notify("Route", { msg = "Could not open the route location", level = "WARN" }) - return - end - - vim.cmd "normal zt" - return - end - - local action = vim.fn.split(route.action, "@") - lsp.go_to(action[1], action[2]) -end - -return { - load = function() - application.run("artisan", { "route:list", "--json" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code == 1 then - application.container.unset(container_key) - return - end - local routes = laravel_route.from_json(j:result()) - if #routes > 0 then - application.container.set(container_key, routes) - end - end, - }) - end, - clean = function() - application.container.unset(container_key) - end, - list = function() - if not application.ready() then - utils.notify( - "Route List", - { level = "ERROR", msg = "The application is not ready for current working directory" } - ) - return nil - end - - local routes = application.container.get(container_key) - if routes then - return routes - end - - local result, ok = application.run("artisan", { "route:list", "--json" }, { runner = "sync" }) - if not ok then - return nil - end - - if result.exit_code == 1 then - log.error("app.routes(): stdout", result.out) - log.error("app.routes(): stderr", result.err) - return nil - end - - routes = laravel_route.from_json(result.out) - - if #routes > 0 then - application.container.set(container_key, routes) - end - - return routes - end, - go_to = go_to, -} diff --git a/lua/laravel/routes/go.lua b/lua/laravel/routes/go.lua new file mode 100644 index 0000000..5d3e0f4 --- /dev/null +++ b/lua/laravel/routes/go.lua @@ -0,0 +1,27 @@ +local notify = require "laravel.notify" +local lsp = require "laravel._lsp" + +return function(route) + if route.action == "Closure" then + if vim.tbl_contains(route.middlewares, "api") then + vim.cmd "edit routes/api.php" + vim.fn.search(route.uri:gsub("api", "") .. "") + elseif vim.tbl_contains(route.middlewares, "web") then + vim.cmd "edit routes/web.php" + if route.uri == "/" then + vim.fn.search "['\"]/['\"]" + else + vim.fn.search("/" .. route.uri) + end + else + notify("Route", { msg = "Could not open the route location", level = "WARN" }) + return + end + + vim.cmd "normal zt" + return + end + + local action = vim.fn.split(route.action, "@") + lsp.go_to(action[1], action[2]) +end diff --git a/lua/laravel/routes/init.lua b/lua/laravel/routes/init.lua new file mode 100644 index 0000000..0a6cb78 --- /dev/null +++ b/lua/laravel/routes/init.lua @@ -0,0 +1,26 @@ +local run = require "laravel.run" +local notify = require "laravel.notify" +local utils = require "laravel.routes.utils" + +local M = {} + +M.list = {} + +function M.load() + local result, ok = run("artisan", { "route:list", "--json" }, { runner = "sync" }) + if not ok or result.exit_code == 1 then + notify( + "Routes.Load", + { msg = string.format("Failed to get routes %s %s", result.out, result.err), level = "ERROR" } + ) + M.list = {} + + return false + end + + M.list = utils.from_json(result.out) + + return true +end + +return M diff --git a/lua/laravel/route.lua b/lua/laravel/routes/utils.lua similarity index 68% rename from lua/laravel/route.lua rename to lua/laravel/routes/utils.lua index bbaba91..6c6eb53 100644 --- a/lua/laravel/route.lua +++ b/lua/laravel/routes/utils.lua @@ -1,11 +1,3 @@ ----@class LaravelRoute ----@field uri string ----@field action string ----@field domain string|nil ----@field methods string[] ----@field middlewares string[] ----@field name string|nil - local M = {} local function check_nil(value) @@ -15,9 +7,6 @@ local function check_nil(value) return value end ---- Gets list of routes from the raw json ----@param json string ----@return LaravelRoute[] M.from_json = function(json) local routes = {} if json == "" or json == nil or #json == 0 then diff --git a/lua/laravel/run.lua b/lua/laravel/run.lua new file mode 100644 index 0000000..72bc23c --- /dev/null +++ b/lua/laravel/run.lua @@ -0,0 +1,16 @@ +local config = require "laravel.config" +local environment = require "laravel.environment" +local runners = require "laravel.runners" + +---@param name string +---@param args string[] +---@param opts table|nil +return function (name, args, opts) + opts = opts or {} + local executable = environment.get_executable(name) + local cmd = vim.fn.extend(executable, args) + + local runner = opts.runner or config.options.commands_runner[args[1]] or config.options.default_runner + + return runners[runner](cmd, opts) +end diff --git a/lua/laravel/runners/async.lua b/lua/laravel/runners/async.lua index 97784eb..1ad16bd 100644 --- a/lua/laravel/runners/async.lua +++ b/lua/laravel/runners/async.lua @@ -1,5 +1,5 @@ local Job = require "plenary.job" -local utils = require "laravel.utils" +local notify = require("laravel.notify") --- Runs and returns the command inmediately ---@param cmd table @@ -8,7 +8,7 @@ local utils = require "laravel.utils" return function(cmd, opts) opts = opts or {} if type(cmd) ~= "table" then - utils.notify("runner.async", { + notify("runner.async", { msg = "cmd has to be a table", level = "ERROR", }) @@ -16,7 +16,7 @@ return function(cmd, opts) end if type(opts.callback) ~= "function" then - utils.notify("runner.async", { + notify("runner.async", { msg = "callback not pass", level = "ERROR", }) diff --git a/lua/laravel/runners/buffer.lua b/lua/laravel/runners/buffer.lua index 4de383e..c8a785e 100644 --- a/lua/laravel/runners/buffer.lua +++ b/lua/laravel/runners/buffer.lua @@ -1,5 +1,6 @@ local Split = require "nui.split" -local utils = require "laravel.utils" +local notify = require("laravel.notify") +local config = require("laravel.config") ---@param cmd table ---@return string @@ -49,17 +50,11 @@ end ---@param opts table ---@return table, boolean return function(cmd, opts) - local options = require("laravel.application").get_options() local default = { open = true, focus = true, buf_name = nil, - split = { - relative = options.split.relative, - position = options.split.position, - size = options.split.size, - enter = options.split.enter, - }, + split = config.options.split, } opts = vim.tbl_deep_extend("force", default, opts or {}) @@ -70,7 +65,7 @@ return function(cmd, opts) if opts.buf_name then if vim.fn.bufexists(opts.buf_name) == 1 then - utils.notify("Buffer Run", { + notify("Buffer Run", { msg = string.format("Buffer with the name `%s` already exists", opts.buf_name), level = "ERROR", }) @@ -119,7 +114,7 @@ return function(cmd, opts) end end, pty = true, - width = options.split.width, + width = config.options.split.width, }) require("laravel._jobs").register(job_id, bufnr) diff --git a/lua/laravel/runners/sync.lua b/lua/laravel/runners/sync.lua index b97efbd..c55c670 100644 --- a/lua/laravel/runners/sync.lua +++ b/lua/laravel/runners/sync.lua @@ -1,12 +1,12 @@ local Job = require "plenary.job" -local utils = require "laravel.utils" +local notify = require("laravel.notify") --- Runs and returns the command immediately ---@param cmd table ---@return table, boolean return function(cmd) if type(cmd) ~= "table" then - utils.notify("runners.sync", { + notify("runners.sync", { msg = "cmd has to be a table", level = "ERROR", }) diff --git a/lua/laravel/runners/terminal.lua b/lua/laravel/runners/terminal.lua index c71b8c9..b7284f1 100644 --- a/lua/laravel/runners/terminal.lua +++ b/lua/laravel/runners/terminal.lua @@ -1,13 +1,13 @@ +local config = require "laravel.config" --- Runs in a new terminal and can operate in the terminal ---@param cmd table ---@param opts table ---@return table, boolean return function(cmd, opts) - local options = require("laravel.application").get_options() local default = { focus = true, split = { - cmd = options.split.cmd, + cmd = config.options.split.cmd, }, } diff --git a/lua/laravel/telescope/pickers/commands.lua b/lua/laravel/telescope/pickers/commands.lua new file mode 100644 index 0000000..84766fe --- /dev/null +++ b/lua/laravel/telescope/pickers/commands.lua @@ -0,0 +1,82 @@ +local actions = require "telescope.actions" +local action_state = require "telescope.actions.state" +local conf = require("telescope.config").values +local finders = require "telescope.finders" +local pickers = require "telescope.pickers" +local previewers = require "telescope.previewers" +local preview = require "laravel.telescope.preview" +local commands = require "laravel.commands" +local ui_run = require "laravel.telescope.ui_run" + +return function(opts) + opts = opts or {} + + if #commands.list == 0 then + if not commands.load() then + return + end + end + + pickers + .new(opts, { + prompt_title = "Artisan commands", + finder = finders.new_table { + results = commands.list, + entry_maker = function(command) + return { + value = command, + display = command.name, + ordinal = command.name, + } + end, + }, + previewer = previewers.new_buffer_previewer { + title = "Help", + get_buffer_by_name = function(_, entry) + return entry.value.name + end, + define_preview = function(self, entry) + local command_preview = preview.command(entry.value) + + vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, command_preview.lines) + + local hl = vim.api.nvim_create_namespace "laravel" + for _, value in pairs(command_preview.highlights) do + vim.api.nvim_buf_add_highlight(self.state.bufnr, hl, value[1], value[2], value[3], value[4]) + end + 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 + + vim.schedule(function() + ui_run(command) + end) + end) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + local command = entry.value + + vim.schedule(function() + ui_run(command, true) + end) + end) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + local command = entry.value + + vim.schedule(function() + ui_run(command) + end) + end) + return true + end, + }) + :find() +end diff --git a/lua/laravel/telescope/pickers/related.lua b/lua/laravel/telescope/pickers/related.lua new file mode 100644 index 0000000..067684d --- /dev/null +++ b/lua/laravel/telescope/pickers/related.lua @@ -0,0 +1,139 @@ +local pickers = require "telescope.pickers" +local run = require "laravel.run" +local lsp = require "laravel._lsp" +local make_entry = require "laravel.telescope.make_entry" +local finders = require "telescope.finders" +local conf = require("telescope.config").values +local actions = require "telescope.actions" +local action_state = require "telescope.actions.state" +local notify = require("laravel.notify") + +return function(opts) + opts = opts or {} + + local file_type = vim.bo.filetype + local lang = vim.treesitter.language.get_lang(file_type) + if lang ~= "php" then + return false + end + + local get_model_class_name = function() + local query = vim.treesitter.query.parse( + lang, + [[ (namespace_definition name: (namespace_name) @namespace) + (class_declaration name: (name) @class) ]] + ) + local tree = vim.treesitter.get_parser():parse()[1]:root() + local bufNr = vim.fn.bufnr() + local class = "" + for id, node, _ in query:iter_captures(tree, bufNr, tree:start(), tree:end_()) do + if query.captures[id] == "class" then + class = class .. "\\" .. vim.treesitter.get_node_text(node, 0) + elseif query.captures[id] == "namespace" then + class = vim.treesitter.get_node_text(node, 0) .. class + end + end + return class + end + + local class = get_model_class_name() + if class ~= "" then + local result, ok = run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) + if not ok then + notify( + "Artisan", + { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" } + ) + return nil + end + + if result.exit_code ~= 0 or string.sub(result.out[1], 1, 1) ~= "{" or string.sub(result.out[1], -1) ~= "}" then + notify( + "Artisan", + { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } + ) + return nil + end + + local model_info = vim.fn.json_decode(result.out[1]) + if model_info == nil then + notify( + "Artisan", + { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } + ) + return nil + end + + ---@return ModelRelation|nil + 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 + + local relations = {} + local types = { "observers", "relations", "policy" } + for _, relation_type in ipairs(types) do + if model_info[relation_type] ~= vim.NIL and #model_info[relation_type] > 0 then + if type(model_info[relation_type]) == "table" and model_info[relation_type][1] ~= vim.NIL then + for _, info in ipairs(model_info[relation_type]) do + local relation = build_relation(info, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + else + local relation = build_relation({ model_info[relation_type] }, relation_type) + if relation ~= nil then + table.insert(relations, relation) + end + end + end + end + + pickers + .new(opts, { + prompt_title = "Related Files", + finder = finders.new_table { + results = relations, + entry_maker = make_entry.gen_from_model_relations(opts), + }, + sorter = conf.prefilter_sorter { + sorter = conf.generic_sorter(opts or {}), + }, + attach_mappings = function(_, map) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + vim.schedule(function() + local action = vim.fn.split(entry.value.class, "@") + lsp.go_to(action[1], action[2]) + end) + end) + + return true + end, + }) + :find() + end +end diff --git a/lua/laravel/telescope/pickers/routes.lua b/lua/laravel/telescope/pickers/routes.lua new file mode 100644 index 0000000..f47ef43 --- /dev/null +++ b/lua/laravel/telescope/pickers/routes.lua @@ -0,0 +1,61 @@ +local actions = require "telescope.actions" +local action_state = require "telescope.actions.state" +local conf = require("telescope.config").values +local finders = require "telescope.finders" +local pickers = require "telescope.pickers" +local previewers = require "telescope.previewers" +local preview = require "laravel.telescope.preview" +local make_entry = require "laravel.telescope.make_entry" +local routes = require "laravel.routes" +local go = require("laravel.routes.go") + +return function(opts) + opts = opts or {} + + if #routes.list == 0 then + if not routes.load() then + return + end + end + + pickers + .new(opts, { + prompt_title = "Artisan Routes", + finder = finders.new_table { + results = routes.list, + entry_maker = opts.entry_maker or make_entry.gen_from_laravel_routes(opts), + }, + previewer = previewers.new_buffer_previewer { + title = "Help", + get_buffer_by_name = function(_, entry) + return entry.value.name + end, + define_preview = function(self, entry) + local route_preview = preview.route(entry.value) + + vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, route_preview.lines) + + local hl = vim.api.nvim_create_namespace "laravel" + for _, value in pairs(route_preview.highlights) do + vim.api.nvim_buf_add_highlight(self.state.bufnr, hl, value[1], value[2], value[3], value[4]) + end + end, + }, + sorter = conf.prefilter_sorter { + tag = "route_method", + sorter = conf.generic_sorter(opts or {}), + }, + attach_mappings = function(_, map) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + vim.schedule(function() + go(entry.value) + end) + end) + + return true + end, + }) + :find() +end diff --git a/lua/laravel/telescope/ui_run.lua b/lua/laravel/telescope/ui_run.lua new file mode 100644 index 0000000..cd2f03a --- /dev/null +++ b/lua/laravel/telescope/ui_run.lua @@ -0,0 +1,68 @@ +local application_run = require "laravel.run" +local is_resource = require "laravel.resources.is_resource" +local create = require("laravel.resources.create") + +return function(command, ask_options, runner) + local function build_prompt(argument) + local prompt = "Argument " .. argument.name .. " " + if argument.is_required then + prompt = prompt .. "" + else + prompt = prompt .. "" + end + + return prompt .. ":" + end + + local function get_arguments(args, callback, values) + if #args == 0 then + callback(values) + return + end + + vim.ui.input({ prompt = build_prompt(args[1]) }, function(value) + if value == "" and args[1].is_required then + return + end + table.insert(values, value) + table.remove(args, 1) + get_arguments(args, callback, values) + end) + end + + local function run(args, options) + local cmd = { command.name } + for _, arg in pairs(args) do + table.insert(cmd, arg) + end + + if options ~= nil and options ~= "" then + for _, value in pairs(vim.fn.split(options, " ")) do + table.insert(cmd, value) + end + end + + if is_resource(cmd[1]) then + return create(cmd) + end + + application_run("artisan", cmd, { runner = runner }) + end + + local args = {} + for _, argument in pairs(command.definition.arguments) do + table.insert(args, argument) + end + + get_arguments(args, function(values) + if ask_options then + vim.ui.input({ prompt = "Options" }, function(options) + run(values, options) + end) + return + end + run(values, nil) + end, {}) + + return true +end diff --git a/lua/laravel/tinker.lua b/lua/laravel/tinker.lua deleted file mode 100644 index 1a18523..0000000 --- a/lua/laravel/tinker.lua +++ /dev/null @@ -1,25 +0,0 @@ -local utils = require "laravel.utils" -local application = require "laravel.application" - -local function trim(s) - return s:match "^%s*(.-)%s*$" -end - -local send_to_tinker = function() - local lines = utils.get_visual_selection() - if nil == application.container.get "tinker" then - application.run("artisan", { "tinker" }, { focus = false }) - if nil == application.container.get "tinker" then - utils.notify("Send To Tinker", { msg = "Tinker terminal id not found and could create it", level = "ERROR" }) - return - end - end - - for _, line in ipairs(lines) do - vim.api.nvim_chan_send(application.container.get "tinker", trim(line) .. "\n") - end -end - -return { - send_to_tinker = send_to_tinker, -} diff --git a/lua/laravel/tinker/get_selection.lua b/lua/laravel/tinker/get_selection.lua new file mode 100644 index 0000000..945ae13 --- /dev/null +++ b/lua/laravel/tinker/get_selection.lua @@ -0,0 +1,20 @@ +local function get_vsel() + local bufnr = vim.api.nvim_win_get_buf(0) + local start = vim.fn.getpos "v" -- [bufnum, lnum, col, off] + local _end = vim.fn.getpos "." -- [bufnum, lnum, col, off] + if start[2] > _end[2] then + local x = _end + _end = start + start = x + end + return { + bufnr = bufnr, + mode = vim.fn.mode(), + pos = { start[2], start[3], _end[2], _end[3] }, + } +end + +return function() + local sel = get_vsel() + return vim.api.nvim_buf_get_lines(sel.bufnr, sel.pos[1] - 1, sel.pos[3], false) +end diff --git a/lua/laravel/tinker/init.lua b/lua/laravel/tinker/init.lua new file mode 100644 index 0000000..6263153 --- /dev/null +++ b/lua/laravel/tinker/init.lua @@ -0,0 +1,28 @@ +local notify = require("laravel.notify") +local run = require("laravel.run") +local get_selection = require("laravel.tinker.get_selection") + +local function trim(s) + return s:match "^%s*(.-)%s*$" +end + +local M = {} + +M.current_terminal = nil + +function M.send_to_tinker () + local lines = get_selection() + if nil == M.current_terminal then + run("artisan", { "tinker" }, { focus = false }) + if nil == M.current_terminal then + notify("Send To Tinker", { msg = "Tinker terminal id not found and could create it", level = "ERROR" }) + return + end + end + + for _, line in ipairs(lines) do + vim.api.nvim_chan_send(M.current_terminal, trim(line) .. "\n") + end +end + +return M diff --git a/lua/laravel/user-commands/composer.lua b/lua/laravel/user-commands/composer.lua deleted file mode 100644 index 3c5b905..0000000 --- a/lua/laravel/user-commands/composer.lua +++ /dev/null @@ -1,56 +0,0 @@ -local utils = require "laravel.utils" -local application = require "laravel.application" - -local commands = { - update = function(cmd) - table.insert(cmd, 1, "update") - application.run("composer", cmd, {}) - end, - - install = function() - application.run("composer", { "install" }, {}) - end, - - ---@param cmd table - require = function(cmd) - table.insert(cmd, 1, "require") - application.run("composer", cmd, {}) - end, - - remove = function(cmd) - if #cmd == 0 then - utils.notify("composer.remove", { msg = "Need arguement for composer remove", level = "ERROR" }) - return - end - table.insert(cmd, 1, "remove") - application.run("composer", cmd, {}) - end, - - ["dump-autoload"] = function() - application.run("composer", { "dump-autoload" }, { - runner = "async", - callback = function() - utils.notify("composer.dump-autoload", { msg = "Completed", level = "INFO" }) - end, - }) - end, -} - -return { - setup = function() - vim.api.nvim_create_user_command("Composer", function(args) - local command = args.fargs[1] - if commands[command] ~= nil then - table.remove(args.fargs, 1) - return commands[command](args.fargs) - end - - return application.run("composer", args.fargs, {}) - end, { - nargs = "+", - complete = function() - return vim.tbl_keys(commands) - end, - }) - end, -} diff --git a/lua/laravel/user-commands/docker_compose.lua b/lua/laravel/user-commands/docker_compose.lua deleted file mode 100644 index 120ba5c..0000000 --- a/lua/laravel/user-commands/docker_compose.lua +++ /dev/null @@ -1,93 +0,0 @@ -local log = require("laravel.dev").log -local utils = require "laravel.utils" -local application = require "laravel.application" - -local commands = { - up = function() - application.run("compose", { "up", "-d" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("compose.up(): stdout", j:result()) - log.error("compose.up(): stderr", j:result()) - utils.notify("compose.up", { msg = "Error on Compose up", level = "ERROR" }) - - return - end - utils.notify("compose.up", { msg = "Completed", level = "INFO" }) - end, - }) - end, - - ps = function() - application.run("compose", { "ps" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("compose.ps(): stdout", j:result()) - log.error("compose.ps(): stderr", j:result()) - utils.notify("compose.ps", { msg = "Failed to run compose up", level = "ERROR" }) - - return - end - utils.notify("compose.ps", { raw = j:result(), level = "INFO" }) - end, - }) - end, - - restart = function() - application.run("compose", { "restart" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("compose.restart(): stdout", j:result()) - log.error("compose.restart(): stderr", j:result()) - utils.notify("compose.restart", { msg = "Failed to restart compose", level = "ERROR" }) - - return - end - utils.notify("compose.restart", { msg = "compose restart complete", level = "INFO" }) - end, - }) - utils.notify("compose.restart", { msg = "compose restart starting", level = "INFO" }) - end, - - down = function() - application.run("compose", { "down" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("compose.down(): stdout", j:result()) - log.error("compose.down(): stderr", j:result()) - utils.notify("compose.down", { msg = "Failed to down compose", level = "ERROR" }) - - return - end - utils.notify("compose.down", { msg = "compose Down complete", level = "INFO" }) - end, - }) - end, -} - -return { - setup = function() - if not application.has_command "compose" then - return - end - - vim.api.nvim_create_user_command("DockerCompose", function(args) - local command = args.fargs[1] - if commands[command] ~= nil then - table.remove(args.fargs, 1) - return commands[command](unpack(args.fargs)) - end - - application.run("compose", args.fargs, {}) - end, { - nargs = "+", - complete = function() - return vim.tbl_keys(commands) - end, - }) - end, -} diff --git a/lua/laravel/user-commands/laravel_info.lua b/lua/laravel/user-commands/laravel_info.lua deleted file mode 100644 index 79e3385..0000000 --- a/lua/laravel/user-commands/laravel_info.lua +++ /dev/null @@ -1,34 +0,0 @@ -local application = require "laravel.application" -local Popup = require "nui.popup" -local event = require("nui.utils.autocmd").event - -return { - setup = function() - vim.api.nvim_create_user_command("LaravelInfo", function() - -- TODO: show information about the current state of the plugin - - local popup = Popup { - enter = true, - focusable = true, - border = { - style = "rounded", - }, - position = "50%", - size = { - width = "80%", - height = "60%", - }, - } - - -- mount/open the component - popup:mount() - - -- unmount component when cursor leaves buffer - popup:on(event.BufLeave, function() - popup:unmount() - end) - - vim.api.nvim_buf_set_lines(popup.bufnr, 0, 1, false, vim.fn.split(vim.inspect(application.get_info()), "\n")) - end, {}) - end, -} diff --git a/lua/laravel/user-commands/npm.lua b/lua/laravel/user-commands/npm.lua deleted file mode 100644 index 7c895bf..0000000 --- a/lua/laravel/user-commands/npm.lua +++ /dev/null @@ -1,29 +0,0 @@ -local application = require "laravel.application" - -local commands = { - dev = function() - return application.run("npm", { "run", "dev" }, { runner = "persist" }) - end, - build = function() - return application.run("npm", { "run", "build" }, {}) - end, -} - -return { - setup = function() - vim.api.nvim_create_user_command("Npm", function(args) - local command = args.fargs[1] - if commands[command] ~= nil then - table.remove(args.fargs, 1) - return commands[command](unpack(args.fargs)) - end - - return application.run("npm", args.fargs, {}) - end, { - nargs = "+", - complete = function() - return vim.tbl_keys(commands) - end, - }) - end, -} diff --git a/lua/laravel/user-commands/sail.lua b/lua/laravel/user-commands/sail.lua deleted file mode 100644 index cf00db7..0000000 --- a/lua/laravel/user-commands/sail.lua +++ /dev/null @@ -1,96 +0,0 @@ -local log = require("laravel.dev").log -local utils = require "laravel.utils" -local application = require "laravel.application" - -local commands = { - up = function() - application.run("sail", { "up", "-d" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("sail.up(): stdout", j:result()) - log.error("sail.up(): stderr", j:result()) - utils.notify("sail.up", { msg = "Error on Sail up", level = "ERROR" }) - - return - end - utils.notify("sail.up", { msg = "Completed", level = "INFO" }) - end, - }) - end, - shell = function() - application.run("sail", { "shell" }, {}) - end, - - ps = function() - application.run("sail", { "ps" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("sail.ps(): stdout", j:result()) - log.error("sail.ps(): stderr", j:result()) - utils.notify("sail.ps", { msg = "Failed to run Sail up", level = "ERROR" }) - - return - end - utils.notify("sail.ps", { raw = vim.fn.join(j:result(), "\n"), level = "INFO" }) - end, - }) - end, - - restart = function() - application.run("sail", { "restart" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("sail.restart(): stdout", j:result()) - log.error("sail.restart(): stderr", j:result()) - utils.notify("sail.restart", { msg = "Failed to restart Sail", level = "ERROR" }) - - return - end - utils.notify("sail.restart", { msg = "Sail restart complete", level = "INFO" }) - end, - }) - utils.notify("sail.restart", { msg = "Sail restart starting", level = "INFO" }) - end, - - down = function() - application.run("sail", { "down" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - log.error("sail.down(): stdout", j:result()) - log.error("sail.down(): stderr", j:result()) - utils.notify("sail.down", { msg = "Failed to down Sail", level = "ERROR" }) - - return - end - utils.notify("sail.down", { msg = "Sail Down complete", level = "INFO" }) - end, - }) - end, -} - -return { - setup = function() - if not application.has_command "sail" then - return - end - - vim.api.nvim_create_user_command("Sail", function(args) - local command = args.fargs[1] - if commands[command] ~= nil then - table.remove(args.fargs, 1) - return commands[command](unpack(args.fargs)) - end - - return application.run("sail", args.fargs, {}) - end, { - nargs = "+", - complete = function() - return vim.tbl_keys(commands) - end, - }) - end, -} diff --git a/lua/laravel/user-commands/yarn.lua b/lua/laravel/user-commands/yarn.lua deleted file mode 100644 index ce06c4c..0000000 --- a/lua/laravel/user-commands/yarn.lua +++ /dev/null @@ -1,29 +0,0 @@ -local application = require "laravel.application" - -local commands = { - dev = function() - require("laravel.yarn").run({ "run", "dev" }, "persist") - end, - build = function() - require("laravel.yarn").run { "run", "build" } - end, -} - -return { - setup = function() - vim.api.nvim_create_user_command("Yarn", function(args) - local command = args.fargs[1] - if commands[command] ~= nil then - table.remove(args.fargs, 1) - return commands[command](unpack(args.fargs)) - end - - return application.run("yarn", args.fargs, {}) - end, { - nargs = "+", - complete = function() - return vim.tbl_keys(commands) - end, - }) - end, -} diff --git a/lua/laravel/user-commands/artisan.lua b/lua/laravel/user_commands/artisan.lua similarity index 83% rename from lua/laravel/user-commands/artisan.lua rename to lua/laravel/user_commands/artisan.lua index 9b0a437..c35ecb5 100644 --- a/lua/laravel/user-commands/artisan.lua +++ b/lua/laravel/user_commands/artisan.lua @@ -1,5 +1,6 @@ local laravel_commands = require "laravel.commands" -local application = require "laravel.application" +local config = require "laravel.config" +local run = require "laravel.run" local function get_artisan_auto_complete(current_match, full_command) -- avoid getting autocomplete for when parameter is expected @@ -7,7 +8,7 @@ local function get_artisan_auto_complete(current_match, full_command) return {} end local complete_list = {} - local commands = laravel_commands.list() + local commands = laravel_commands.list if not commands then return complete_list end @@ -25,19 +26,21 @@ return { setup = function() vim.api.nvim_create_user_command("Artisan", function(args) if args.args == "" then - if application.get_options().bind_telescope then + if config.options.bind_telescope then local ok, telescope = pcall(require, "telescope") if ok then return telescope.extensions.laravel.commands() end end + return end + local resources = require "laravel.resources" if resources.is_resource(args.fargs[1]) then return resources.create(args.fargs) end - return application.run("artisan", args.fargs, {}) + return run("artisan", args.fargs, {}) end, { nargs = "*", complete = get_artisan_auto_complete, diff --git a/lua/laravel/user_commands/bun.lua b/lua/laravel/user_commands/bun.lua new file mode 100644 index 0000000..cbd0f38 --- /dev/null +++ b/lua/laravel/user_commands/bun.lua @@ -0,0 +1,17 @@ +local run = require "laravel.run" +local create_user_command = require "laravel.user_commands.create_user_command" + +local M = {} + +function M.setup() + return create_user_command("Bun", "bun", { + dev = function() + run("bun", { "run", "dev" }, { runner = "persist" }) + end, + build = function() + run("bun", { "run", "build" }) + end, + }) +end + +return M diff --git a/lua/laravel/user_commands/composer.lua b/lua/laravel/user_commands/composer.lua new file mode 100644 index 0000000..b5cd083 --- /dev/null +++ b/lua/laravel/user_commands/composer.lua @@ -0,0 +1,44 @@ +local notify = require "laravel.notify" +local create_user_command = require "laravel.user_commands.create_user_command" +local run = require "laravel.run" + +local M = {} + +function M.setup() + return create_user_command("Composer", "composer", { + update = function(cmd) + table.insert(cmd, 1, "update") + run("composer", cmd, {}) + end, + + install = function() + run("composer", { "install" }, {}) + end, + + ---@param cmd table + require = function(cmd) + table.insert(cmd, 1, "require") + run("composer", cmd, {}) + end, + + remove = function(cmd) + if #cmd == 0 then + notify("composer.remove", { msg = "Need arguement for composer remove", level = "ERROR" }) + return + end + table.insert(cmd, 1, "remove") + run("composer", cmd, {}) + end, + + ["dump-autoload"] = function() + run("composer", { "dump-autoload" }, { + runner = "async", + callback = function() + notify("composer.dump-autoload", { msg = "Completed", level = "INFO" }) + end, + }) + end, + }) +end + +return M diff --git a/lua/laravel/user_commands/create_user_command.lua b/lua/laravel/user_commands/create_user_command.lua new file mode 100644 index 0000000..10c8faa --- /dev/null +++ b/lua/laravel/user_commands/create_user_command.lua @@ -0,0 +1,22 @@ +local run = require "laravel.run" + +return function(name, executable, commands, opts) + vim.api.nvim_create_user_command( + name, + function(args) + local command = args.fargs[1] + if commands[command] ~= nil then + table.remove(args.fargs, 1) + return commands[command](unpack(args.fargs)) + end + + return run(executable, args.fargs, {}) + end, + vim.tbl_deep_extend("force", { + nargs = "+", + complete = function() + return vim.tbl_keys(commands) + end, + }, opts or {}) + ) +end diff --git a/lua/laravel/user_commands/docker_compose.lua b/lua/laravel/user_commands/docker_compose.lua new file mode 100644 index 0000000..10ec7e0 --- /dev/null +++ b/lua/laravel/user_commands/docker_compose.lua @@ -0,0 +1,82 @@ +local run = require "laravel.run" +local notify = require "laravel.notify" +local environment = require "laravel.environment" +local create_user_command = require "laravel.user_commands.create_user_command" + +local M = {} + +function M.setup() + if environment.get_executable "compose" == nil then + return + end + + create_user_command("DockerCompose", "compose", { + up = function() + run("compose", { "up", "-d" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify( + "compose.up", + { msg = string.format("Error on Compose up. %s", vim.inspection(j:result())), level = "ERROR" } + ) + + return + end + notify("compose.up", { msg = "Completed", level = "INFO" }) + end, + }) + end, + + ps = function() + run("compose", { "ps" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify("compose.ps", { msg = "Failed to run compose up", level = "ERROR" }) + + return + end + notify("compose.ps", { raw = j:result(), level = "INFO" }) + end, + }) + end, + + restart = function() + run("compose", { "restart" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify( + "compose.restart", + { msg = string.format("Failed to restart compose. %s", vim.inspect(j:result())), level = "ERROR" } + ) + + return + end + notify("compose.restart", { msg = "compose restart complete", level = "INFO" }) + end, + }) + notify("compose.restart", { msg = "compose restart starting", level = "INFO" }) + end, + + down = function() + run("compose", { "down" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify( + "compose.down", + { msg = string.format("Failed to down compose. %s", vim.inspect(j:result())), level = "ERROR" } + ) + + return + end + notify("compose.down", { msg = "compose Down complete", level = "INFO" }) + end, + }) + end, + }) +end + +return M diff --git a/lua/laravel/user-commands/init.lua b/lua/laravel/user_commands/init.lua similarity index 71% rename from lua/laravel/user-commands/init.lua rename to lua/laravel/user_commands/init.lua index c52b99f..c55439a 100644 --- a/lua/laravel/user-commands/init.lua +++ b/lua/laravel/user_commands/init.lua @@ -2,10 +2,10 @@ local M = {} local modules = { "artisan", + "bun", "composer", "docker_compose", "laravel", - "laravel_info", "npm", "sail", "yarn", @@ -13,7 +13,7 @@ local modules = { M.setup = function() for _, module in pairs(modules) do - require(string.format("laravel.user-commands.%s", module)).setup() + require(string.format("laravel.user_commands.%s", module)).setup() end end diff --git a/lua/laravel/user_commands/laravel/info.lua b/lua/laravel/user_commands/laravel/info.lua new file mode 100644 index 0000000..47ec245 --- /dev/null +++ b/lua/laravel/user_commands/laravel/info.lua @@ -0,0 +1,35 @@ +local Popup = require "nui.popup" +local event = require("nui.utils.autocmd").event +local environment = require "laravel.environment" +local config = require "laravel.config" + +return function() + local popup = Popup { + enter = true, + focusable = true, + border = { + style = "rounded", + }, + position = "50%", + size = { + width = "80%", + height = "60%", + }, + } + + -- mount/open the component + popup:mount() + + -- unmount component when cursor leaves buffer + popup:on(event.BufLeave, function() + popup:unmount() + end) + + vim.api.nvim_buf_set_lines( + popup.bufnr, + 0, + 1, + false, + vim.fn.split(vim.inspect { environment = environment.environment, options = config.options }, "\n") + ) +end diff --git a/lua/laravel/user-commands/laravel.lua b/lua/laravel/user_commands/laravel/init.lua similarity index 64% rename from lua/laravel/user-commands/laravel.lua rename to lua/laravel/user_commands/laravel/init.lua index b59fd89..3b206cf 100644 --- a/lua/laravel/user-commands/laravel.lua +++ b/lua/laravel/user_commands/laravel/init.lua @@ -1,10 +1,11 @@ -local utils = require "laravel.utils" -local application = require "laravel.application" +local notify = require "laravel.notify" +local run = require "laravel.run" local commands = { ["cache:clean"] = function() - application.container.purge() - utils.notify("laravel.cache:clean", { msg = "Cache cleaned", level = "INFO" }) + require("laravel.commands").list = {} + require("laravel.routes").list = {} + notify("laravel.cache:clean", { msg = "Cache cleaned", level = "INFO" }) end, ["routes"] = function() return require("telescope").extensions.laravel.routes() @@ -13,11 +14,12 @@ local commands = { return require("telescope").extensions.laravel.commands() end, ["test:watch"] = function() - return application.run("artisan", { "test" }, { runner = "watch" }) + return run("artisan", { "test" }, { runner = "watch" }) end, ["related"] = function() return require("telescope").extensions.laravel.related() end, + ["info"] = require "laravel.user_commands.laravel.info", } return { @@ -29,7 +31,7 @@ return { return commands[command](unpack(args.fargs)) end - utils.notify("laravel", { msg = "Unkown command", level = "ERROR" }) + notify("laravel", { msg = "Unkown command", level = "ERROR" }) end, { nargs = "+", complete = function() diff --git a/lua/laravel/user_commands/npm.lua b/lua/laravel/user_commands/npm.lua new file mode 100644 index 0000000..c604d98 --- /dev/null +++ b/lua/laravel/user_commands/npm.lua @@ -0,0 +1,17 @@ +local run = require "laravel.run" +local create_user_command = require "laravel.user_commands.create_user_command" + +local M = {} + +function M.setup() + return create_user_command("Npm", 'npm', { + dev = function() + run("npm", { "run", "dev" }, { runner = "persist" }) + end, + build = function() + run("npm", { "run", "build" }) + end, + }) +end + +return M diff --git a/lua/laravel/user_commands/sail.lua b/lua/laravel/user_commands/sail.lua new file mode 100644 index 0000000..898319b --- /dev/null +++ b/lua/laravel/user_commands/sail.lua @@ -0,0 +1,83 @@ +local run = require "laravel.run" +local notify = require "laravel.notify" +local environment = require "laravel.environment" +local create_user_command = require "laravel.user_commands.create_user_command" + +local M = {} + +function M.setup() + if environment.get_executable "sail" == nil then + return + end + + create_user_command("Sail", "sail", { + up = function() + run("sail", { "up", "-d" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify("sail.up", { msg = string.format("Error on Sail up. %s", vim.inspect(j:result())), level = "ERROR" }) + + return + end + notify("sail.up", { msg = "Completed", level = "INFO" }) + end, + }) + end, + + shell = function() + run("sail", { "shell" }, {}) + end, + + ps = function() + run("sail", { "ps" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify("sail.ps", { msg = "Failed to run Sail up", level = "ERROR" }) + + return + end + notify("sail.ps", { raw = vim.fn.join(j:result(), "\n"), level = "INFO" }) + end, + }) + end, + + restart = function() + run("sail", { "restart" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify( + "sail.restart", + { msg = string.format("Failed to restart Sail. %s", vim.inspect(j:result())), level = "ERROR" } + ) + + return + end + notify("sail.restart", { msg = "Sail restart complete", level = "INFO" }) + end, + }) + notify("sail.restart", { msg = "Sail restart starting", level = "INFO" }) + end, + + down = function() + run("sail", { "down" }, { + runner = "async", + callback = function(j, exit_code) + if exit_code ~= 0 then + notify( + "sail.down", + { msg = string.format("Failed to down Sail. Error: %s", vim.inspect(j:result())), level = "ERROR" } + ) + + return + end + notify("sail.down", { msg = "Sail Down complete", level = "INFO" }) + end, + }) + end, + }) +end + +return M diff --git a/lua/laravel/user_commands/yarn.lua b/lua/laravel/user_commands/yarn.lua new file mode 100644 index 0000000..e154ef4 --- /dev/null +++ b/lua/laravel/user_commands/yarn.lua @@ -0,0 +1,17 @@ +local run = require "laravel.run" +local create_user_command = require "laravel.user_commands.create_user_command" + +local M = {} + +function M.setup() + return create_user_command("Yarn", "yarn", { + dev = function() + run("yarn", { "run", "dev" }, { runner = "persist" }) + end, + build = function() + run("yarn", { "run", "build" }) + end, + }) +end + +return M diff --git a/lua/laravel/utils.lua b/lua/laravel/utils.lua deleted file mode 100644 index 045f128..0000000 --- a/lua/laravel/utils.lua +++ /dev/null @@ -1,55 +0,0 @@ -local utils = {} - ----@param funname string ----@param opts table -function utils.notify(funname, opts) - local level = vim.log.levels[opts.level] - if not level then - error("Invalid error level", 2) - end - local body = string.format("[laravel.%s]: %s", funname, opts.msg) - if opts.raw ~= nil then - body = opts.raw - end - vim.notify(body, level, { - title = "Laravel.nvim", - }) -end - -utils.get_visual_selection = function() - local sel = utils.get_vsel() - return vim.api.nvim_buf_get_lines(sel.bufnr, sel.pos[1] - 1, sel.pos[3], false) -end - -utils.get_vsel = function() - local bufnr = vim.api.nvim_win_get_buf(0) - local start = vim.fn.getpos "v" -- [bufnum, lnum, col, off] - local _end = vim.fn.getpos "." -- [bufnum, lnum, col, off] - if start[2] > _end[2] then - local x = _end - _end = start - start = x - end - return { - bufnr = bufnr, - mode = vim.fn.mode(), - pos = { start[2], start[3], _end[2], _end[3] }, - } -end - -utils.get_env = function(var) - local envVal - if vim.fn.exists "*DotenvGet" == 1 then - envVal = vim.fn.DotenvGet(var) - else - envVal = vim.fn.eval("$" .. var) - end - - if envVal == "" then - return nil - end - - return envVal -end - -return utils diff --git a/lua/telescope/_extensions/laravel.lua b/lua/telescope/_extensions/laravel.lua index 6d65e3a..9ac8b8f 100644 --- a/lua/telescope/_extensions/laravel.lua +++ b/lua/telescope/_extensions/laravel.lua @@ -1,231 +1,7 @@ -local make_related = require "telescope.pickers.related" -local telescope = require "telescope" -local actions = require "telescope.actions" -local action_state = require "telescope.actions.state" -local conf = require("telescope.config").values -local finders = require "telescope.finders" -local pickers = require "telescope.pickers" -local previewers = require "telescope.previewers" -local preview = require "laravel.telescope.preview" -local make_entry = require "laravel.telescope.make_entry" -local laravel_commands = require "laravel.commands" -local laravel_routes = require "laravel.routes" -local application = require "laravel.application" -local lsp = require "laravel._lsp" - ----@class ModelRelation ----@field class string ----@field type string ----@field extra_information string - ---- runs a command from telescope ----@param command LaravelCommand ----@param ask_options boolean | nil ----@param runner string | nil -local function run_command(command, ask_options, runner) - -- use ui.input - -- problem it uses callbacks and how to control the flow for multiple - -- problem everything needs to be done in the callback because it does not block the execution - -- it will feel like javascript callback hell - -- since will have to for reach argument do an internal loop and from that pass a callback and so far - - ---@param argument CommandArgument - ---@return string - local function build_prompt(argument) - local prompt = "Argument " .. argument.name .. " " - if argument.is_required then - prompt = prompt .. "" - else - prompt = prompt .. "" - end - - return prompt .. ":" - end - - local function get_arguments(args, callback, values) - if #args == 0 then - callback(values) - return - end - - vim.ui.input({ prompt = build_prompt(args[1]) }, function(value) - if value == "" and args[1].is_required then - return - end - table.insert(values, value) - table.remove(args, 1) - get_arguments(args, callback, values) - end) - end - - local function run(args, options) - local cmd = { command.name } - for _, arg in pairs(args) do - table.insert(cmd, arg) - end - - if options ~= nil and options ~= "" then - for _, value in pairs(vim.fn.split(options, " ")) do - table.insert(cmd, value) - end - end - - local resources = require "laravel.resources" - if resources.is_resource(cmd[1]) then - return resources.create(cmd) - end - - application.run("artisan", cmd, { runner = runner }) - end - - local args = {} - for _, argument in pairs(command.definition.arguments) do - table.insert(args, argument) - end - - get_arguments(args, function(values) - if ask_options then - vim.ui.input({ prompt = "Options" }, function(options) - run(values, options) - end) - return - end - run(values, nil) - end, {}) - - return true -end - -local commands = function(opts) - opts = opts or {} - - local commands = laravel_commands.list() - - if commands == nil then - return - end - - pickers - .new(opts, { - prompt_title = "Artisan commands", - finder = finders.new_table { - results = commands, - entry_maker = function(command) - return { - value = command, - display = command.name, - ordinal = command.name, - } - end, - }, - previewer = previewers.new_buffer_previewer { - title = "Help", - get_buffer_by_name = function(_, entry) - return entry.value.name - end, - define_preview = function(self, entry) - local command_preview = preview.command(entry.value) - - vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, command_preview.lines) - - local hl = vim.api.nvim_create_namespace "laravel" - for _, value in pairs(command_preview.highlights) do - vim.api.nvim_buf_add_highlight(self.state.bufnr, hl, value[1], value[2], value[3], value[4]) - end - 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() - ---@type LaravelCommand command - local command = entry.value - - vim.schedule(function() - run_command(command) - end) - end) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - ---@type LaravelCommand command - local command = entry.value - - vim.schedule(function() - run_command(command, true) - end) - end) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - ---@type LaravelCommand command - local command = entry.value - - vim.schedule(function() - run_command(command) - end) - end) - return true - end, - }) - :find() -end - -local routes = function(opts) - opts = opts or {} - - local routes = laravel_routes.list() - if routes == nil then - return - end - - pickers - .new(opts, { - prompt_title = "Artisan Routes", - finder = finders.new_table { - results = routes, - entry_maker = opts.entry_maker or make_entry.gen_from_laravel_routes(opts), - }, - previewer = previewers.new_buffer_previewer { - title = "Help", - get_buffer_by_name = function(_, entry) - return entry.value.name - end, - define_preview = function(self, entry) - local route_preview = preview.route(entry.value) - - vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, route_preview.lines) - - local hl = vim.api.nvim_create_namespace "laravel" - for _, value in pairs(route_preview.highlights) do - vim.api.nvim_buf_add_highlight(self.state.bufnr, hl, value[1], value[2], value[3], value[4]) - end - end, - }, - sorter = conf.prefilter_sorter { - tag = "route_method", - sorter = conf.generic_sorter(opts or {}), - }, - attach_mappings = function(_, map) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - vim.schedule(function() - laravel_routes.go_to(entry.value) - end) - end) - - return true - end, - }) - :find() -end - -return telescope.register_extension { +return require("telescope").register_extension { exports = { - commands = commands, - routes = routes, - related = make_related(pickers, application, lsp, make_entry, finders, conf, actions, action_state), + commands = require "laravel.telescope.pickers.commands", + routes = require "laravel.telescope.pickers.routes", + related = require "laravel.telescope.pickers.related", }, } diff --git a/lua/telescope/pickers/related.lua b/lua/telescope/pickers/related.lua deleted file mode 100644 index 860578e..0000000 --- a/lua/telescope/pickers/related.lua +++ /dev/null @@ -1,134 +0,0 @@ -local make_related = function(pickers, application, lsp, make_entry, finders, conf, actions, action_state) - local utils = require "laravel.utils" - return function(opts) - opts = opts or {} - - local file_type = vim.bo.filetype - local lang = vim.treesitter.language.get_lang(file_type) - if lang ~= "php" then - return false - end - - local get_model_class_name = function() - local query = vim.treesitter.query.parse( - lang, - [[ (namespace_definition name: (namespace_name) @namespace) - (class_declaration name: (name) @class) ]] - ) - local tree = vim.treesitter.get_parser():parse()[1]:root() - local bufNr = vim.fn.bufnr() - local class = "" - for id, node, _ in query:iter_captures(tree, bufNr, tree:start(), tree:end_()) do - if query.captures[id] == "class" then - class = class .. "\\" .. vim.treesitter.get_node_text(node, 0) - elseif query.captures[id] == "namespace" then - class = vim.treesitter.get_node_text(node, 0) .. class - end - end - return class - end - - local class = get_model_class_name() - if class ~= "" then - local result, ok = application.run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) - if not ok then - utils.notify( - "Artisan", - { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" } - ) - return nil - end - - if result.exit_code ~= 0 or string.sub(result.out[1], 1, 1) ~= "{" or string.sub(result.out[1], -1) ~= "}" then - utils.notify( - "Artisan", - { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } - ) - return nil - end - - local model_info = vim.fn.json_decode(result.out[1]) - if model_info == nil then - utils.notify( - "Artisan", - { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } - ) - return nil - end - - ---@return ModelRelation|nil - 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 - - local relations = {} - local types = { "observers", "relations", "policy" } - for _, relation_type in ipairs(types) do - if model_info[relation_type] ~= vim.NIL and #model_info[relation_type] > 0 then - if type(model_info[relation_type]) == "table" and model_info[relation_type][1] ~= vim.NIL then - for _, info in ipairs(model_info[relation_type]) do - local relation = build_relation(info, relation_type) - if relation ~= nil then - table.insert(relations, relation) - end - end - else - local relation = build_relation({ model_info[relation_type] }, relation_type) - if relation ~= nil then - table.insert(relations, relation) - end - end - end - end - - pickers - .new(opts, { - prompt_title = "Related Files", - finder = finders.new_table { - results = relations, - entry_maker = make_entry.gen_from_model_relations(opts), - }, - sorter = conf.prefilter_sorter { - sorter = conf.generic_sorter(opts or {}), - }, - attach_mappings = function(_, map) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - vim.schedule(function() - local action = vim.fn.split(entry.value.class, "@") - lsp.go_to(action[1], action[2]) - end) - end) - - return true - end, - }) - :find() - end - end -end - -return make_related From bb5b4ffdff5749c0605460cc4e8c840d3efdde71 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Mon, 25 Sep 2023 07:50:53 +0200 Subject: [PATCH 02/55] prevent error depending on loading --- lua/laravel/route_info/init.lua | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lua/laravel/route_info/init.lua b/lua/laravel/route_info/init.lua index 703a35d..11c1cff 100644 --- a/lua/laravel/route_info/init.lua +++ b/lua/laravel/route_info/init.lua @@ -1,24 +1,10 @@ -local notify = require("laravel.notify") +local notify = require "laravel.notify" local routes = require "laravel.routes" local config = require "laravel.config" local get_node_text = vim.treesitter.get_node_text - local options = config.options.route_info -vim.treesitter.query.set( - "php", - "laravel_route_info", - [[ - (namespace_definition (namespace_name) @namespace) - (class_declaration (name) @class) - (method_declaration - (visibility_modifier) @visibility - (name) @method - ) - ]] -) - local function is_same_class(action, class) return string.sub(action, 1, string.len(class)) == class end @@ -80,6 +66,22 @@ local function set_route_to_methods(event) end local query = vim.treesitter.query.get("php", "laravel_route_info") + if query == nil then + vim.treesitter.query.set( + "php", + "laravel_route_info", + [[ + (namespace_definition (namespace_name) @namespace) + (class_declaration (name) @class) + (method_declaration + (visibility_modifier) @visibility + (name) @method + ) + ]] + ) + + query = vim.treesitter.query.get("php", "laravel_route_info") + end local class, class_namespace, methods, visibilities = "", "", {}, {} local class_pos = 0 From 090f2666a5741098903a96f04094f32dcf8e5320 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Mon, 25 Sep 2023 08:57:13 +0200 Subject: [PATCH 03/55] fix styles --- lua/laravel/_lsp/init.lua | 2 +- lua/laravel/_lsp/intelephense.lua | 7 ++----- lua/laravel/_lsp/phpactor.lua | 7 ++----- lua/laravel/autocommands.lua | 2 +- lua/laravel/commands/init.lua | 11 ++++------- lua/laravel/config.lua | 2 +- lua/laravel/environment/docker_compose.lua | 2 +- lua/laravel/environment/resolver.lua | 4 ++-- lua/laravel/notify.lua | 2 +- lua/laravel/resources/create.lua | 10 +++++----- lua/laravel/run.lua | 2 +- lua/laravel/runners/async.lua | 2 +- lua/laravel/runners/buffer.lua | 4 ++-- lua/laravel/runners/sync.lua | 2 +- lua/laravel/telescope/pickers/related.lua | 7 ++----- lua/laravel/telescope/pickers/routes.lua | 2 +- lua/laravel/telescope/ui_run.lua | 2 +- lua/laravel/tinker/init.lua | 8 ++++---- lua/laravel/user_commands/npm.lua | 2 +- 19 files changed, 34 insertions(+), 46 deletions(-) diff --git a/lua/laravel/_lsp/init.lua b/lua/laravel/_lsp/init.lua index 301c5c1..ff7c30e 100644 --- a/lua/laravel/_lsp/init.lua +++ b/lua/laravel/_lsp/init.lua @@ -1,6 +1,6 @@ local phpactor = require "laravel._lsp.phpactor" local intelephense = require "laravel._lsp.intelephense" -local notify = require("laravel.notify") +local notify = require "laravel.notify" local config = require "laravel.config" local servers = { diff --git a/lua/laravel/_lsp/intelephense.lua b/lua/laravel/_lsp/intelephense.lua index 20f415c..a8e5de9 100644 --- a/lua/laravel/_lsp/intelephense.lua +++ b/lua/laravel/_lsp/intelephense.lua @@ -1,5 +1,5 @@ local lsp_utils = require "laravel._lsp.utils" -local notify = require("laravel.notify") +local notify = require "laravel.notify" ---@param client table ---@param is_new_instance boolean @@ -41,10 +41,7 @@ local function go_to(client, is_new_instance, full_class, method) vim.lsp.buf_request(0, "textDocument/documentSymbol", params, function(method_err, method_server_result, _, _) if method_err then - notify( - "Route Open", - { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" } - ) + notify("Route Open", { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" }) if is_new_instance then vim.lsp.stop_client(client.id) end diff --git a/lua/laravel/_lsp/phpactor.lua b/lua/laravel/_lsp/phpactor.lua index d0b8fc9..37f3516 100644 --- a/lua/laravel/_lsp/phpactor.lua +++ b/lua/laravel/_lsp/phpactor.lua @@ -1,5 +1,5 @@ local lsp_utils = require "laravel._lsp.utils" -local notify = require("laravel.notify") +local notify = require "laravel.notify" ---@param client table ---@param is_new_instance boolean @@ -46,10 +46,7 @@ local function go_to(client, is_new_instance, full_class, method) vim.lsp.buf_request(0, "textDocument/documentSymbol", params, function(method_err, method_server_result, _, _) if method_err then - notify( - "Route Open", - { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" } - ) + notify("Route Open", { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" }) if is_new_instance then vim.lsp.stop_client(client.id) end diff --git a/lua/laravel/autocommands.lua b/lua/laravel/autocommands.lua index 6a71ffd..fa5f7aa 100644 --- a/lua/laravel/autocommands.lua +++ b/lua/laravel/autocommands.lua @@ -1,7 +1,7 @@ local M = {} function M.setup() - local environment = require("laravel.environment") + local environment = require "laravel.environment" local group = vim.api.nvim_create_augroup("laravel", {}) vim.api.nvim_create_autocmd({ "DirChanged" }, { diff --git a/lua/laravel/commands/init.lua b/lua/laravel/commands/init.lua index ede3fb3..c7a9e3a 100644 --- a/lua/laravel/commands/init.lua +++ b/lua/laravel/commands/init.lua @@ -9,13 +9,10 @@ M.list = {} function M.load() local result, ok = run("artisan", { "list", "--format=json" }, { runner = "sync" }) if not ok or result.exit_code == 1 then - notify( - "Commands.Load", - { - msg = string.format("Failed to get commands %s %s", vim.inspect(result.out), vim.inspect(result.err)), - level = "ERROR", - } - ) + notify("Commands.Load", { + msg = string.format("Failed to get commands %s %s", vim.inspect(result.out), vim.inspect(result.err)), + level = "ERROR", + }) M.list = {} return false diff --git a/lua/laravel/config.lua b/lua/laravel/config.lua index eb5ef93..691b44a 100644 --- a/lua/laravel/config.lua +++ b/lua/laravel/config.lua @@ -26,7 +26,7 @@ M.defaults = { ["db"] = "terminal", }, environment = { - resolver = require ("laravel.environment.resolver")(true, true, nil), + resolver = require "laravel.environment.resolver"(true, true, nil), environments = { ["local"] = require("laravel.environment.native").setup(), ["sail"] = require("laravel.environment.sail").setup(), diff --git a/lua/laravel/environment/docker_compose.lua b/lua/laravel/environment/docker_compose.lua index 2303e4c..b7bb3b8 100644 --- a/lua/laravel/environment/docker_compose.lua +++ b/lua/laravel/environment/docker_compose.lua @@ -1,4 +1,4 @@ -local get_env = require("laravel.environment.get_env") +local get_env = require "laravel.environment.get_env" local M = {} diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua index 5537fa1..7da704b 100644 --- a/lua/laravel/environment/resolver.lua +++ b/lua/laravel/environment/resolver.lua @@ -1,5 +1,5 @@ -local notify = require("laravel.notify") -local get_env = require("laravel.environment.get_env") +local notify = require "laravel.notify" +local get_env = require "laravel.environment.get_env" ---@param env_check boolean ---@param auto_discovery boolean diff --git a/lua/laravel/notify.lua b/lua/laravel/notify.lua index 2a3e88d..e110fd9 100644 --- a/lua/laravel/notify.lua +++ b/lua/laravel/notify.lua @@ -1,4 +1,4 @@ -return function (funname, opts) +return function(funname, opts) local level = vim.log.levels[opts.level] if not level then error("Invalid error level", 2) diff --git a/lua/laravel/resources/create.lua b/lua/laravel/resources/create.lua index 3113eae..0812798 100644 --- a/lua/laravel/resources/create.lua +++ b/lua/laravel/resources/create.lua @@ -1,6 +1,6 @@ local run = require "laravel.run" local is_resource = require "laravel.resources.is_resource" -local open = require("laravel.resources.open") +local open = require "laravel.resources.open" local notify = require "laravel.notify" return function(command) @@ -16,11 +16,11 @@ return function(command) return false end - run('artisan', command, { - runner = 'async', - callback = function () + run("artisan", command, { + runner = "async", + callback = function() open(resource, name) - end + end, }) return true diff --git a/lua/laravel/run.lua b/lua/laravel/run.lua index 72bc23c..d87b4f1 100644 --- a/lua/laravel/run.lua +++ b/lua/laravel/run.lua @@ -5,7 +5,7 @@ local runners = require "laravel.runners" ---@param name string ---@param args string[] ---@param opts table|nil -return function (name, args, opts) +return function(name, args, opts) opts = opts or {} local executable = environment.get_executable(name) local cmd = vim.fn.extend(executable, args) diff --git a/lua/laravel/runners/async.lua b/lua/laravel/runners/async.lua index 1ad16bd..ddea87d 100644 --- a/lua/laravel/runners/async.lua +++ b/lua/laravel/runners/async.lua @@ -1,5 +1,5 @@ local Job = require "plenary.job" -local notify = require("laravel.notify") +local notify = require "laravel.notify" --- Runs and returns the command inmediately ---@param cmd table diff --git a/lua/laravel/runners/buffer.lua b/lua/laravel/runners/buffer.lua index c8a785e..4f1ddae 100644 --- a/lua/laravel/runners/buffer.lua +++ b/lua/laravel/runners/buffer.lua @@ -1,6 +1,6 @@ local Split = require "nui.split" -local notify = require("laravel.notify") -local config = require("laravel.config") +local notify = require "laravel.notify" +local config = require "laravel.config" ---@param cmd table ---@return string diff --git a/lua/laravel/runners/sync.lua b/lua/laravel/runners/sync.lua index c55c670..f7bb716 100644 --- a/lua/laravel/runners/sync.lua +++ b/lua/laravel/runners/sync.lua @@ -1,5 +1,5 @@ local Job = require "plenary.job" -local notify = require("laravel.notify") +local notify = require "laravel.notify" --- Runs and returns the command immediately ---@param cmd table diff --git a/lua/laravel/telescope/pickers/related.lua b/lua/laravel/telescope/pickers/related.lua index 067684d..5131cb1 100644 --- a/lua/laravel/telescope/pickers/related.lua +++ b/lua/laravel/telescope/pickers/related.lua @@ -6,7 +6,7 @@ local finders = require "telescope.finders" local conf = require("telescope.config").values local actions = require "telescope.actions" local action_state = require "telescope.actions.state" -local notify = require("laravel.notify") +local notify = require "laravel.notify" return function(opts) opts = opts or {} @@ -40,10 +40,7 @@ return function(opts) if class ~= "" then local result, ok = run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) if not ok then - notify( - "Artisan", - { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" } - ) + notify("Artisan", { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" }) return nil end diff --git a/lua/laravel/telescope/pickers/routes.lua b/lua/laravel/telescope/pickers/routes.lua index f47ef43..d1b84fc 100644 --- a/lua/laravel/telescope/pickers/routes.lua +++ b/lua/laravel/telescope/pickers/routes.lua @@ -7,7 +7,7 @@ local previewers = require "telescope.previewers" local preview = require "laravel.telescope.preview" local make_entry = require "laravel.telescope.make_entry" local routes = require "laravel.routes" -local go = require("laravel.routes.go") +local go = require "laravel.routes.go" return function(opts) opts = opts or {} diff --git a/lua/laravel/telescope/ui_run.lua b/lua/laravel/telescope/ui_run.lua index cd2f03a..358653e 100644 --- a/lua/laravel/telescope/ui_run.lua +++ b/lua/laravel/telescope/ui_run.lua @@ -1,6 +1,6 @@ local application_run = require "laravel.run" local is_resource = require "laravel.resources.is_resource" -local create = require("laravel.resources.create") +local create = require "laravel.resources.create" return function(command, ask_options, runner) local function build_prompt(argument) diff --git a/lua/laravel/tinker/init.lua b/lua/laravel/tinker/init.lua index 6263153..8d06bf2 100644 --- a/lua/laravel/tinker/init.lua +++ b/lua/laravel/tinker/init.lua @@ -1,6 +1,6 @@ -local notify = require("laravel.notify") -local run = require("laravel.run") -local get_selection = require("laravel.tinker.get_selection") +local notify = require "laravel.notify" +local run = require "laravel.run" +local get_selection = require "laravel.tinker.get_selection" local function trim(s) return s:match "^%s*(.-)%s*$" @@ -10,7 +10,7 @@ local M = {} M.current_terminal = nil -function M.send_to_tinker () +function M.send_to_tinker() local lines = get_selection() if nil == M.current_terminal then run("artisan", { "tinker" }, { focus = false }) diff --git a/lua/laravel/user_commands/npm.lua b/lua/laravel/user_commands/npm.lua index c604d98..9afe7a6 100644 --- a/lua/laravel/user_commands/npm.lua +++ b/lua/laravel/user_commands/npm.lua @@ -4,7 +4,7 @@ local create_user_command = require "laravel.user_commands.create_user_command" local M = {} function M.setup() - return create_user_command("Npm", 'npm', { + return create_user_command("Npm", "npm", { dev = function() run("npm", { "run", "dev" }, { runner = "persist" }) end, From b972ca03daf4459ce4b16815b35f637a5c70c35a Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Mon, 2 Oct 2023 08:23:18 +0200 Subject: [PATCH 04/55] add tests and fix argument pass to command --- .gitignore | 1 + .neoconf.json | 15 ++++++++ lua/laravel/user_commands/composer.lua | 5 +-- .../user_commands/create_user_command.lua | 2 +- tests/command/composer_spec.lua | 17 +++++++++ tests/init.lua | 36 +++++++++++++++++++ tests/run | 3 ++ 7 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 .neoconf.json create mode 100644 tests/command/composer_spec.lua create mode 100644 tests/init.lua create mode 100755 tests/run diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8bdf483 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.tests diff --git a/.neoconf.json b/.neoconf.json new file mode 100644 index 0000000..f0c23f8 --- /dev/null +++ b/.neoconf.json @@ -0,0 +1,15 @@ +{ + "neodev": { + "library": { + "plugins": [ + "plenary.nvim" + ] + } + }, + "lspconfig": { + "lua_ls": { + "Lua.runtime.version": "LuaJIT", + "Lua.workspace.checkThirdParty": false + } + } +} diff --git a/lua/laravel/user_commands/composer.lua b/lua/laravel/user_commands/composer.lua index b5cd083..a6b29e8 100644 --- a/lua/laravel/user_commands/composer.lua +++ b/lua/laravel/user_commands/composer.lua @@ -11,8 +11,9 @@ function M.setup() run("composer", cmd, {}) end, - install = function() - run("composer", { "install" }, {}) + install = function(cmd) + table.insert(cmd, 1, "install") + run("composer", cmd, {}) end, ---@param cmd table diff --git a/lua/laravel/user_commands/create_user_command.lua b/lua/laravel/user_commands/create_user_command.lua index 10c8faa..0282a80 100644 --- a/lua/laravel/user_commands/create_user_command.lua +++ b/lua/laravel/user_commands/create_user_command.lua @@ -7,7 +7,7 @@ return function(name, executable, commands, opts) local command = args.fargs[1] if commands[command] ~= nil then table.remove(args.fargs, 1) - return commands[command](unpack(args.fargs)) + return commands[command](args.fargs) end return run(executable, args.fargs, {}) diff --git a/tests/command/composer_spec.lua b/tests/command/composer_spec.lua new file mode 100644 index 0000000..c48ebc5 --- /dev/null +++ b/tests/command/composer_spec.lua @@ -0,0 +1,17 @@ +describe("Composer user command", function() + local spy = require('luassert.spy') + + local s = spy.new(function() end) + package.loaded['laravel.run'] = s + require('laravel.user_commands.composer').setup() + + it('require formats the parameter', function() + vim.cmd [[Composer require laravel/folio]] + assert.spy(s).was.called_with('composer', { "require", "laravel/folio" }, {}) + end) + + it('passes the arguments to the install', function() + vim.cmd [[Composer install --options]] + assert.spy(s).was.called_with('composer', { "install", "--options" }, {}) + end) +end) diff --git a/tests/init.lua b/tests/init.lua new file mode 100644 index 0000000..a72b101 --- /dev/null +++ b/tests/init.lua @@ -0,0 +1,36 @@ +local M = {} + +function M.root(root) + local f = debug.getinfo(1, "S").source:sub(2) + return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "") +end + +---@param plugin string +function M.load(plugin) + local name = plugin:match(".*/(.*)") + local package_root = M.root(".tests/site/pack/deps/start/") + if not vim.loop.fs_stat(package_root .. name) then + print("Installing " .. plugin) + vim.fn.mkdir(package_root, "p") + vim.fn.system({ + "git", + "clone", + "--depth=1", + "https://github.com/" .. plugin .. ".git", + package_root .. "/" .. name, + }) + end +end + +function M.setup() + vim.cmd([[set runtimepath=$VIMRUNTIME]]) + vim.opt.runtimepath:append(M.root()) + vim.opt.packpath = { M.root(".tests/site") } + M.load("nvim-lua/plenary.nvim") + vim.env.XDG_CONFIG_HOME = M.root(".tests/config") + vim.env.XDG_DATA_HOME = M.root(".tests/data") + vim.env.XDG_STATE_HOME = M.root(".tests/state") + vim.env.XDG_CACHE_HOME = M.root(".tests/cache") +end + +M.setup() diff --git a/tests/run b/tests/run new file mode 100755 index 0000000..412d7b5 --- /dev/null +++ b/tests/run @@ -0,0 +1,3 @@ +#!/bin/sh + +nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests {minimal_init = 'tests//init.lua', sequential = true}" From b22614679ed52346e96320bf8e6690d1e028c3a0 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Fri, 6 Oct 2023 22:16:46 +0200 Subject: [PATCH 05/55] Support skip args as command option --- README.md | 28 +++++++++++++++------------- lua/laravel/config.lua | 18 +++++++++--------- lua/laravel/run.lua | 4 +++- lua/laravel/telescope/ui_run.lua | 13 +++++++++++++ 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 1e74296..6d431e6 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ Default configuration }, default_runner = "buffer", commands_runner = { - ["dump-server"] = "persist", - ["queue:listen"] = "persist", - ["serve"] = "persist", - ["websockets"] = "persist", - ["queue:restart"] = "watch", - ["tinker"] = "terminal", - ["db"] = "terminal", + ["dump-server"] = { runner = "persist" }, + ["queue:listen"] = { runner = "persist" }, + ["serve"] = { runner = "persist" }, + ["websockets"] = { runner = "persist" }, + ["queue:restart"] = { runner = "watch" }, + ["tinker"] = { runner = "terminal", skip_args = true }, + ["db"] = { runner = "terminal" }, }, environment = { resolver = require "laravel.environment.resolver"(true, true, nil), @@ -258,12 +258,14 @@ This is to provide the option to you to build what ever you need for you develop The commands have a default runner configure that you can customize ```lua default_runner = "buffer", - commands_runner = { - ["dump-server"] = "persist", - ["queue:listen"] = "persist", - ["serve"] = "persist", - ["websockets"] = "persist", - ["queue:restart"] = "watch", + commands_options = { + ["dump-server"] = { runner = "persist" }, + ["queue:listen"] = { runner = "persist" }, + ["serve"] = { runner = "persist" }, + ["websockets"] = { runner = "persist" }, + ["queue:restart"] = { runner = "watch" }, + ["tinker"] = { runner = "terminal", skip_args = true }, + ["db"] = { runner = "terminal" }, }, ``` diff --git a/lua/laravel/config.lua b/lua/laravel/config.lua index 691b44a..1cb321e 100644 --- a/lua/laravel/config.lua +++ b/lua/laravel/config.lua @@ -16,17 +16,17 @@ M.defaults = { enable = true, position = "right", }, - commands_runner = { - ["dump-server"] = "persist", - ["queue:listen"] = "persist", - ["serve"] = "persist", - ["websockets"] = "persist", - ["queue:restart"] = "watch", - ["tinker"] = "terminal", - ["db"] = "terminal", + commands_options = { + ["dump-server"] = { runner = "persist" }, + ["queue:listen"] = { runner = "persist" }, + ["serve"] = { runner = "persist" }, + ["websockets"] = { runner = "persist" }, + ["queue:restart"] = { runner = "watch" }, + ["tinker"] = { runner = "terminal", skip_args = true }, + ["db"] = { runner = "terminal" }, }, environment = { - resolver = require "laravel.environment.resolver"(true, true, nil), + resolver = require "laravel.environment.resolver" (true, true, nil), environments = { ["local"] = require("laravel.environment.native").setup(), ["sail"] = require("laravel.environment.sail").setup(), diff --git a/lua/laravel/run.lua b/lua/laravel/run.lua index d87b4f1..735f17d 100644 --- a/lua/laravel/run.lua +++ b/lua/laravel/run.lua @@ -10,7 +10,9 @@ return function(name, args, opts) local executable = environment.get_executable(name) local cmd = vim.fn.extend(executable, args) - local runner = opts.runner or config.options.commands_runner[args[1]] or config.options.default_runner + local command_option = config.options.commands_options[args[1]] or {} + + local runner = opts.runner or command_option.runner or config.options.default_runner return runners[runner](cmd, opts) end diff --git a/lua/laravel/telescope/ui_run.lua b/lua/laravel/telescope/ui_run.lua index 358653e..8f8319e 100644 --- a/lua/laravel/telescope/ui_run.lua +++ b/lua/laravel/telescope/ui_run.lua @@ -1,8 +1,10 @@ local application_run = require "laravel.run" local is_resource = require "laravel.resources.is_resource" local create = require "laravel.resources.create" +local config = require "laravel.config" return function(command, ask_options, runner) + local command_options = config.options.commands_options[command.name] or {} local function build_prompt(argument) local prompt = "Argument " .. argument.name .. " " if argument.is_required then @@ -54,6 +56,17 @@ return function(command, ask_options, runner) table.insert(args, argument) end + if command_options.skip_args then + if ask_options then + vim.ui.input({ prompt = "Options" }, function(options) + run({}, options) + end) + return + end + run({}, nil) + return + end + get_arguments(args, function(values) if ask_options then vim.ui.input({ prompt = "Options" }, function(options) From 37aaba7fe6ce26e907f83137a95149e4995b9e68 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Mon, 9 Oct 2023 19:51:40 +0200 Subject: [PATCH 06/55] Skip the setup if the artisan file is not present --- lua/laravel/environment/init.lua | 4 ++++ lua/laravel/init.lua | 5 +---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lua/laravel/environment/init.lua b/lua/laravel/environment/init.lua index 5452e9a..93653f4 100644 --- a/lua/laravel/environment/init.lua +++ b/lua/laravel/environment/init.lua @@ -6,6 +6,10 @@ local M = {} M.environment = {} function M.setup() + if vim.fn.filereadable "artisan" == 0 then + return + end + M.environment = config.options.environment.resolver(config.options.environment.environments) if type(M.environment) == "function" then M.environment = M.environment() diff --git a/lua/laravel/init.lua b/lua/laravel/init.lua index 0742365..43690ce 100644 --- a/lua/laravel/init.lua +++ b/lua/laravel/init.lua @@ -8,10 +8,7 @@ function M.setup(opts) config.setup(opts) autocmds.setup() - - if vim.fn.filereadable "artisan" ~= 0 then - environment.setup() - end + environment.setup() end return M From f1df12607bd870bc001db26f7975da62c6421d45 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 10 Oct 2023 19:48:56 +0200 Subject: [PATCH 07/55] Add devenv --- .envrc | 3 + .gitignore | 11 ++++ devenv.lock | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++ devenv.nix | 25 +++++++++ devenv.yaml | 3 + 5 files changed, 198 insertions(+) create mode 100644 .envrc create mode 100644 devenv.lock create mode 100644 devenv.nix create mode 100644 devenv.yaml diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..6de8a8a --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0=" + +use devenv \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8bdf483..f46de9e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,12 @@ /.tests + +# Devenv +.devenv* +devenv.local.nix + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml + diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 0000000..b83639b --- /dev/null +++ b/devenv.lock @@ -0,0 +1,156 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1696609182, + "narHash": "sha256-PzVHnPnm+aceuQOoE3oExjHSxiLFAEiHFyQb3xXCI1c=", + "owner": "cachix", + "repo": "devenv", + "rev": "bd859ef4b207c2071f5bd3cae2a74f4d3e69c2e2", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1685518550, + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1696757521, + "narHash": "sha256-cfgtLNCBLFx2qOzRLI6DHfqTdfWI+UbvsKYa3b3fvaA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2646b294a146df2781b1ca49092450e8a32814e1", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1696846637, + "narHash": "sha256-0hv4kbXxci2+pxhuXlVgftj/Jq79VSmtAyvfabCCtYk=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "42e1b6095ef80a51f79595d9951eb38e91c4e6ca", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 0000000..d1e8873 --- /dev/null +++ b/devenv.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: + +{ + # https://devenv.sh/basics/ + env.GREET = "devenv"; + + # https://devenv.sh/packages/ + packages = [ pkgs.git ]; + + enterShell = '' + git --version + ''; + + # https://devenv.sh/languages/ + # languages.nix.enable = true; + + # https://devenv.sh/pre-commit-hooks/ + pre-commit.hooks.luacheck.enable = true; + pre-commit.hooks.stylua.enable = true; + + # https://devenv.sh/processes/ + # processes.ping.exec = "ping example.com"; + + # See full reference at https://devenv.sh/reference/options/ +} diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 0000000..c7cb5ce --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + nixpkgs: + url: github:NixOS/nixpkgs/nixpkgs-unstable From 2656bb146514dc8e9715b738a962c5de7e46832b Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 10 Oct 2023 20:35:38 +0200 Subject: [PATCH 08/55] clean test --- tests/command/composer_spec.lua | 16 ++++++++-------- tests/init.lua | 23 ++++++++++++----------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tests/command/composer_spec.lua b/tests/command/composer_spec.lua index c48ebc5..3d6bf7f 100644 --- a/tests/command/composer_spec.lua +++ b/tests/command/composer_spec.lua @@ -1,17 +1,17 @@ -describe("Composer user command", function() - local spy = require('luassert.spy') +local spy = require "luassert.spy" +describe("Composer user command", function() local s = spy.new(function() end) - package.loaded['laravel.run'] = s - require('laravel.user_commands.composer').setup() + package.loaded["laravel.run"] = s + require("laravel.user_commands.composer").setup() - it('require formats the parameter', function() + it("require formats the parameter", function() vim.cmd [[Composer require laravel/folio]] - assert.spy(s).was.called_with('composer', { "require", "laravel/folio" }, {}) + assert.spy(s).was.called_with("composer", { "require", "laravel/folio" }, {}) end) - it('passes the arguments to the install', function() + it("passes the arguments to the install", function() vim.cmd [[Composer install --options]] - assert.spy(s).was.called_with('composer', { "install", "--options" }, {}) + assert.spy(s).was.called_with("composer", { "install", "--options" }, {}) end) end) diff --git a/tests/init.lua b/tests/init.lua index a72b101..599eb61 100644 --- a/tests/init.lua +++ b/tests/init.lua @@ -7,30 +7,31 @@ end ---@param plugin string function M.load(plugin) - local name = plugin:match(".*/(.*)") - local package_root = M.root(".tests/site/pack/deps/start/") + local name = plugin:match ".*/(.*)" + local package_root = M.root ".tests/site/pack/deps/start/" if not vim.loop.fs_stat(package_root .. name) then print("Installing " .. plugin) vim.fn.mkdir(package_root, "p") - vim.fn.system({ + vim.fn.system { "git", "clone", "--depth=1", "https://github.com/" .. plugin .. ".git", package_root .. "/" .. name, - }) + } end end function M.setup() - vim.cmd([[set runtimepath=$VIMRUNTIME]]) + vim.cmd [[set runtimepath=$VIMRUNTIME]] vim.opt.runtimepath:append(M.root()) - vim.opt.packpath = { M.root(".tests/site") } - M.load("nvim-lua/plenary.nvim") - vim.env.XDG_CONFIG_HOME = M.root(".tests/config") - vim.env.XDG_DATA_HOME = M.root(".tests/data") - vim.env.XDG_STATE_HOME = M.root(".tests/state") - vim.env.XDG_CACHE_HOME = M.root(".tests/cache") + vim.opt.packpath = { M.root ".tests/site" } + M.load "nvim-lua/plenary.nvim" + M.load "MunifTanjim/nui.nvim" + vim.env.XDG_CONFIG_HOME = M.root ".tests/config" + vim.env.XDG_DATA_HOME = M.root ".tests/data" + vim.env.XDG_STATE_HOME = M.root ".tests/state" + vim.env.XDG_CACHE_HOME = M.root ".tests/cache" end M.setup() From 8547706214871123b5d49be58bb8952eea2edc11 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 10 Oct 2023 21:30:56 +0200 Subject: [PATCH 09/55] Format and clean --- README.md | 12 ++++----- TODO.md | 15 ++++++++++-- lua/laravel/config.lua | 5 ++-- lua/laravel/runners/buffer.lua | 35 ++++++++++----------------- lua/laravel/runners/init.lua | 20 ++++++--------- lua/laravel/runners/persist.lua | 13 ---------- lua/laravel/runners/popup.lua | 39 ++++++++++++++++++++++++++++++ lua/laravel/runners/split.lua | 29 ++++++++++++++++++++++ tests/command/environment_spec.lua | 20 +++++++++++++++ 9 files changed, 130 insertions(+), 58 deletions(-) delete mode 100644 lua/laravel/runners/persist.lua create mode 100644 lua/laravel/runners/popup.lua create mode 100644 lua/laravel/runners/split.lua create mode 100644 tests/command/environment_spec.lua diff --git a/README.md b/README.md index 6d431e6..1af8650 100644 --- a/README.md +++ b/README.md @@ -290,8 +290,8 @@ local function start() vim.cmd "split new" local bot = vim.api.nvim_get_current_win() - local test_run = require("laravel.application").run('artisan', { "test" }, "watch", { open = false }) - local dump_run = require("laravel.application").run('artisan', { "dump-server" }, "persist", { open = false }) + local test_run = require("laravel.run")('artisan', { "test" }, {runner = "watch", open = false }) + local dump_run = require("laravel.run")('artisan', { "dump-server" }, { runner = "persist", open = false }) vim.api.nvim_win_set_buf(top, test_run.buff) vim.api.nvim_win_set_buf(bot, dump_run.buff) @@ -304,10 +304,10 @@ After that we only need to set the buffer from the commands into the windows and Other example to just run everything ```lua vim.api.nvim_create_user_command("StartMyApp", function () - require('laravel.application').run('artisan', {"serve"}) - require('laravel.application').run('artisan', {"queue:restart"}) - require('laravel.application').run('artisan', {"queue:listen"}) - require('laravel.application').run('yarn', {"dev"}, "persist") + require('laravel.run')('artisan', {"serve"}) + require('laravel.run')('artisan', {"queue:restart"}) + require('laravel.run')('artisan', {"queue:listen"}) + require('laravel.run')('yarn', {"dev"}, {runenr = "persist"}) end, {}) ``` This will create your own command and when run will just call everyone of the commands, and split the windows as it needs and you resize when you want. Remember the `open = false` is an option to not have it display and run in the background. diff --git a/TODO.md b/TODO.md index 925f117..8e5c950 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,16 @@ # Ideas -Con telescope mostrar la lista de rutas y al seleccionar, llegar al controllador y al metodo +Tengo los runners. -- source: artisan list +como se van a ver +Split +Popup + + +watch +buffer +term + +como van a devolver resultado +sync +async diff --git a/lua/laravel/config.lua b/lua/laravel/config.lua index 1cb321e..d6abb67 100644 --- a/lua/laravel/config.lua +++ b/lua/laravel/config.lua @@ -11,7 +11,7 @@ M.defaults = { lsp_server = "phpactor", register_user_commands = true, bind_telescope = true, - default_runner = "buffer", + default_runner = "split", route_info = { enable = true, position = "right", @@ -24,9 +24,10 @@ M.defaults = { ["queue:restart"] = { runner = "watch" }, ["tinker"] = { runner = "terminal", skip_args = true }, ["db"] = { runner = "terminal" }, + ["docs"] = { runner = "popup", skip_args = true }, }, environment = { - resolver = require "laravel.environment.resolver" (true, true, nil), + resolver = require "laravel.environment.resolver"(true, true, nil), environments = { ["local"] = require("laravel.environment.native").setup(), ["sail"] = require("laravel.environment.sail").setup(), diff --git a/lua/laravel/runners/buffer.lua b/lua/laravel/runners/buffer.lua index 4f1ddae..b236059 100644 --- a/lua/laravel/runners/buffer.lua +++ b/lua/laravel/runners/buffer.lua @@ -1,4 +1,3 @@ -local Split = require "nui.split" local notify = require "laravel.notify" local config = require "laravel.config" @@ -59,11 +58,21 @@ return function(cmd, opts) opts = vim.tbl_deep_extend("force", default, opts or {}) - local job_id = 0 + if opts.persist then + opts.listed = true + opts.buf_name = vim.fn.join(cmd, " ") + end - local bufnr = vim.api.nvim_create_buf(opts.listed or false, true) + local job_id = 0 + local bufnr + if opts.bufnr == nil then + bufnr = vim.api.nvim_create_buf(opts.listed or false, true) + else + bufnr = opts.bufnr + end if opts.buf_name then + ---@diagnostic disable-next-line: param-type-mismatch if vim.fn.bufexists(opts.buf_name) == 1 then notify("Buffer Run", { msg = string.format("Buffer with the name `%s` already exists", opts.buf_name), @@ -85,24 +94,6 @@ return function(cmd, opts) vim.fn.chansend(channel_id, lines) end - if opts.open then - if opts.focus then - opts.split.enter = true - end - - local split = Split(opts.split) - - -- mount/open the component - split:mount() - - vim.api.nvim_win_set_buf(split.winid, bufnr) - - vim.api.nvim_win_call(split.winid, function() - -- vim.cmd "stopinsert" - vim.cmd "startinsert" - end) - end - job_id = vim.fn.jobstart(sanetize_cmd(cmd), { stdeout_buffered = true, on_stdout = handle_output, @@ -114,7 +105,7 @@ return function(cmd, opts) end end, pty = true, - width = config.options.split.width, + -- width = config.options.split.width, }) require("laravel._jobs").register(job_id, bufnr) diff --git a/lua/laravel/runners/init.lua b/lua/laravel/runners/init.lua index a290378..2fa17ce 100644 --- a/lua/laravel/runners/init.lua +++ b/lua/laravel/runners/init.lua @@ -1,17 +1,11 @@ -local buffer = require "laravel.runners.buffer" -local sync = require "laravel.runners.sync" -local async = require "laravel.runners.async" -local persist = require "laravel.runners.persist" -local watch = require "laravel.runners.watch" -local terminal = require "laravel.runners.terminal" - local runners = { - buffer = buffer, - sync = sync, - async = async, - persist = persist, - watch = watch, - terminal = terminal, + async = require "laravel.runners.async", + buffer = require "laravel.runners.buffer", + popup = require "laravel.runners.popup", + split = require "laravel.runners.split", + sync = require "laravel.runners.sync", + terminal = require "laravel.runners.terminal", + watch = require "laravel.runners.watch", } return runners diff --git a/lua/laravel/runners/persist.lua b/lua/laravel/runners/persist.lua deleted file mode 100644 index 73beffe..0000000 --- a/lua/laravel/runners/persist.lua +++ /dev/null @@ -1,13 +0,0 @@ -local buffer = require "laravel.runners.buffer" - ---- Runs in a buffers as a job ----@param cmd table ----@param opts table|nil ----@return table, boolean -return function(cmd, opts) - opts = opts or {} - opts.listed = true - opts.buf_name = vim.fn.join(cmd, " ") - - return buffer(cmd, opts) -end diff --git a/lua/laravel/runners/popup.lua b/lua/laravel/runners/popup.lua new file mode 100644 index 0000000..3c69c5a --- /dev/null +++ b/lua/laravel/runners/popup.lua @@ -0,0 +1,39 @@ +local Popup = require "nui.popup" +local event = require("nui.utils.autocmd").event +local buffer_run = require "laravel.runners.buffer" + +--- Runs in a buffers as a job +---@param cmd table +---@param opts table +---@return table, boolean +return function(cmd, opts) + local popup = Popup(vim.tbl_extend("force", { + enter = true, + focusable = true, + border = { + style = "rounded", + }, + position = { + row = "20%", + col = "50%", + }, + size = { + width = "28%", + height = "35%", + }, + }, opts.popup or {})) + + popup:mount() + + popup:on(event.BufLeave, function() + popup:unmount() + end) + + local result, ok = buffer_run(cmd, vim.tbl_extend("force", opts, { bufnr = popup.bufnr })) + if not ok then + popup:unmount() + end + vim.cmd "startinsert" + + return result, ok +end diff --git a/lua/laravel/runners/split.lua b/lua/laravel/runners/split.lua new file mode 100644 index 0000000..ea88505 --- /dev/null +++ b/lua/laravel/runners/split.lua @@ -0,0 +1,29 @@ +local Split = require "nui.split" +local event = require("nui.utils.autocmd").event +local buffer_run = require "laravel.runners.buffer" + +--- Runs in a buffers as a job +---@param cmd table +---@param opts table +---@return table, boolean +return function(cmd, opts) + local split = Split(vim.tbl_extend("force", { + relative = "editor", + position = "right", + size = "20%", + }, opts.split or {})) + + split:mount() + + split:on(event.BufLeave, function() + split:unmount() + end) + + local result, ok = buffer_run(cmd, vim.tbl_extend("force", opts, { bufnr = split.bufnr })) + if not ok then + split:unmount() + end + vim.cmd "startinsert" + + return result, ok +end diff --git a/tests/command/environment_spec.lua b/tests/command/environment_spec.lua new file mode 100644 index 0000000..cbcdd17 --- /dev/null +++ b/tests/command/environment_spec.lua @@ -0,0 +1,20 @@ +describe("environment", function() + it("generates environment", function() + local config = require "laravel.config" + local environment = require "laravel.environment" + local user_commands = require "laravel.user_commands" + local route_info = require "laravel.route_info" + local env = {} + config.setup {} + config.options.environment.resolver = function(environments) + return env + end + local spy = require "luassert.spy" + spy.on(config.options.environment, "resolver") + environment.setup() + assert.spy(config.options.environment.resolver).was.called_with(config.options.environment.environments) + assert.are.same(env, environment.environment) + assert.spy(user_commands.setup).was.called() + assert.spy(route_info.setup).was.called() + end) +end) From 3185bc92626d95926b7478a94911b0aba1a70f47 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 22 Oct 2023 13:21:25 +0200 Subject: [PATCH 10/55] Small updates --- README.md | 5 +---- lua/laravel/config.lua | 8 ++++---- lua/laravel/runners/split.lua | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 1af8650..632489d 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,7 @@ return { }, }, event = { "VeryLazy" }, - config = function() - require("laravel").setup() - require("telescope").load_extension "laravel" - end, + config = true, } ``` diff --git a/lua/laravel/config.lua b/lua/laravel/config.lua index d6abb67..f795cb3 100644 --- a/lua/laravel/config.lua +++ b/lua/laravel/config.lua @@ -17,10 +17,10 @@ M.defaults = { position = "right", }, commands_options = { - ["dump-server"] = { runner = "persist" }, - ["queue:listen"] = { runner = "persist" }, - ["serve"] = { runner = "persist" }, - ["websockets"] = { runner = "persist" }, + ["dump-server"] = { runner = "split" }, + ["queue:listen"] = { runner = "split" }, + ["serve"] = { runner = "split" }, + ["websockets"] = { runner = "split" }, ["queue:restart"] = { runner = "watch" }, ["tinker"] = { runner = "terminal", skip_args = true }, ["db"] = { runner = "terminal" }, diff --git a/lua/laravel/runners/split.lua b/lua/laravel/runners/split.lua index ea88505..f4b3021 100644 --- a/lua/laravel/runners/split.lua +++ b/lua/laravel/runners/split.lua @@ -10,7 +10,7 @@ return function(cmd, opts) local split = Split(vim.tbl_extend("force", { relative = "editor", position = "right", - size = "20%", + size = "33%", }, opts.split or {})) split:mount() From 9ab67e8dd201d186177121d741b4d6b7b638c61f Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 26 Oct 2023 22:15:30 +0200 Subject: [PATCH 11/55] Add status --- lua/laravel/environment/init.lua | 4 +++ lua/laravel/run.lua | 4 +++ lua/laravel/status.lua | 48 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 lua/laravel/status.lua diff --git a/lua/laravel/environment/init.lua b/lua/laravel/environment/init.lua index 93653f4..3fbf964 100644 --- a/lua/laravel/environment/init.lua +++ b/lua/laravel/environment/init.lua @@ -6,6 +6,7 @@ local M = {} M.environment = {} function M.setup() + M.environment = {} if vim.fn.filereadable "artisan" == 0 then return end @@ -24,6 +25,9 @@ end ---@param name string ---@return string[]|nil function M.get_executable(name) + if vim.tbl_isempty(M.environment) then + return nil + end local executable = M.environment.executables[name] if executable == nil then return nil diff --git a/lua/laravel/run.lua b/lua/laravel/run.lua index 735f17d..de90bf1 100644 --- a/lua/laravel/run.lua +++ b/lua/laravel/run.lua @@ -8,6 +8,10 @@ local runners = require "laravel.runners" return function(name, args, opts) opts = opts or {} local executable = environment.get_executable(name) + if not executable then + error(string.format("Executable %s not found", name), vim.log.levels.ERROR) + return + end local cmd = vim.fn.extend(executable, args) local command_option = config.options.commands_options[args[1]] or {} diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua new file mode 100644 index 0000000..4d3093f --- /dev/null +++ b/lua/laravel/status.lua @@ -0,0 +1,48 @@ +local environment = require "laravel.environment" +local run = require "laravel.run" +local M = {} + +local properties = { + php = { + has = function() + return environment.get_executable "php" ~= nil + end, + get = function() + if not environment.get_executable "php" then + return nil + end + local res, _ = run("php", { "-v" }, { runner = "sync" }) + --[[ +PHP 8.1.23 (cli) (built: Aug 30 2023 08:23:26) (NTS) +Copyright (c) The PHP Group +Zend Engine v4.1.23, Copyright (c) Zend Technologies + with Zend OPcache v8.1.23, Copyright (c), by Zend Technologies + --]] + return res.out[1]:match "PHP ([%d%.]+)" + end, + }, + laravel = { + has = function() + return environment.get_executable "artisan" ~= nil + end, + get = function() + if not environment.get_executable "artisan" then + return nil + end + + local res, _ = run("artisan", { "--version" }, { runner = "sync" }) + + return res.out[1]:match "Laravel Framework ([%d%.]+)" + end, + }, +} + +function M.get(property) + return properties[property].get() +end + +function M.has(property) + return properties[property].has() +end + +return M From c18b2743a728bb135be0ce041e5bc8d7e1c01ab4 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 26 Oct 2023 22:41:51 +0200 Subject: [PATCH 12/55] Add cache for getting status --- lua/laravel/status.lua | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua index 4d3093f..c5f69bf 100644 --- a/lua/laravel/status.lua +++ b/lua/laravel/status.lua @@ -2,22 +2,31 @@ local environment = require "laravel.environment" local run = require "laravel.run" local M = {} +local counters = { + php = 0, + laravel = 0, +} + +local values = { + php = nil, + laravel = nil, +} + local properties = { php = { has = function() return environment.get_executable "php" ~= nil end, get = function() + counters.php = counters.php + 1 + if values.php and counters.php < 60 then + return values.php + end + counters.php = 0 if not environment.get_executable "php" then return nil end local res, _ = run("php", { "-v" }, { runner = "sync" }) - --[[ -PHP 8.1.23 (cli) (built: Aug 30 2023 08:23:26) (NTS) -Copyright (c) The PHP Group -Zend Engine v4.1.23, Copyright (c) Zend Technologies - with Zend OPcache v8.1.23, Copyright (c), by Zend Technologies - --]] return res.out[1]:match "PHP ([%d%.]+)" end, }, @@ -26,6 +35,11 @@ Zend Engine v4.1.23, Copyright (c) Zend Technologies return environment.get_executable "artisan" ~= nil end, get = function() + counters.laravel = counters.laravel + 1 + if values.laravel and counters.laravel < 60 then + return values.laravel + end + counters.laravel = 0 if not environment.get_executable "artisan" then return nil end From e5b7ffc1d72f57794feccb5414ec19b0f65a5d6a Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 26 Oct 2023 22:45:55 +0200 Subject: [PATCH 13/55] Save the value in the cache --- lua/laravel/status.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua index c5f69bf..8611f30 100644 --- a/lua/laravel/status.lua +++ b/lua/laravel/status.lua @@ -27,7 +27,9 @@ local properties = { return nil end local res, _ = run("php", { "-v" }, { runner = "sync" }) - return res.out[1]:match "PHP ([%d%.]+)" + values.php = res.out[1]:match "PHP ([%d%.]+)" + + return values.php end, }, laravel = { @@ -46,7 +48,8 @@ local properties = { local res, _ = run("artisan", { "--version" }, { runner = "sync" }) - return res.out[1]:match "Laravel Framework ([%d%.]+)" + values.laravel = res.out[1]:match "Laravel Framework ([%d%.]+)" + return values.laravel end, }, } From cc4f2f05b04272469e9672641c0c6969e719306c Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 29 Oct 2023 10:51:34 +0100 Subject: [PATCH 14/55] Update the tests --- lua/laravel/environment/get_env.lua | 6 +++--- lua/laravel/environment/resolver.lua | 6 +++++- lua/laravel/user_commands/artisan.lua | 7 ++++--- tests/command/artisan_spec.lua | 15 +++++++++++++++ tests/command/environment_spec.lua | 20 -------------------- tests/environment/resolver_spec.lua | 13 +++++++++++++ 6 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 tests/command/artisan_spec.lua delete mode 100644 tests/command/environment_spec.lua create mode 100644 tests/environment/resolver_spec.lua diff --git a/lua/laravel/environment/get_env.lua b/lua/laravel/environment/get_env.lua index 98e4fb2..1e1cd01 100644 --- a/lua/laravel/environment/get_env.lua +++ b/lua/laravel/environment/get_env.lua @@ -1,9 +1,9 @@ return function(var) local envVal - if vim.fn.exists "*DotenvGet" == 1 then - envVal = vim.fn.DotenvGet(var) + if vim.api.nvim_call_function("exists", { "*DotenvGet" }) == 1 then + envVal = vim.api.nvim_call_function("DotenvGet", { var }) else - envVal = vim.fn.eval("$" .. var) + envVal = vim.api.nvim_call_function("eval", { "$" .. var }) end if envVal == "" then diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua index 7da704b..cfde178 100644 --- a/lua/laravel/environment/resolver.lua +++ b/lua/laravel/environment/resolver.lua @@ -30,7 +30,11 @@ return function(env_check, auto_discovery, default) return environments.sail end -- check for docker-compose - if environments["docker-compose"] ~= nil and vim.fn.filereadable "docker-compose.yml" == 1 then + if + environments["docker-compose"] ~= nil + and vim.fn.filereadable "docker-compose.yml" == 1 + and vim.fn.executable "docker" + then return environments["docker-compose"] end -- check for native diff --git a/lua/laravel/user_commands/artisan.lua b/lua/laravel/user_commands/artisan.lua index c35ecb5..2cbfc8d 100644 --- a/lua/laravel/user_commands/artisan.lua +++ b/lua/laravel/user_commands/artisan.lua @@ -1,5 +1,7 @@ local laravel_commands = require "laravel.commands" local config = require "laravel.config" +local is_resource = require "laravel.resources.is_resource" +local resources_create = require "laravel.resources.create" local run = require "laravel.run" local function get_artisan_auto_complete(current_match, full_command) @@ -35,9 +37,8 @@ return { return end - local resources = require "laravel.resources" - if resources.is_resource(args.fargs[1]) then - return resources.create(args.fargs) + if is_resource(args.fargs[1]) then + return resources_create(args.fargs) end return run("artisan", args.fargs, {}) diff --git a/tests/command/artisan_spec.lua b/tests/command/artisan_spec.lua new file mode 100644 index 0000000..e13f743 --- /dev/null +++ b/tests/command/artisan_spec.lua @@ -0,0 +1,15 @@ +local spy = require "luassert.spy" + +describe("Artisan user command", function() + local s = spy.new(function() end) + package.loaded["laravel.run"] = s + package.loaded["laravel.resources.is_resource"] = function() + return false + end + require("laravel.user_commands.artisan").setup() + + it("require formats the parameter", function() + vim.cmd [[Artisan --version]] + assert.spy(s).was.called_with("artisan", { "--version" }, {}) + end) +end) diff --git a/tests/command/environment_spec.lua b/tests/command/environment_spec.lua deleted file mode 100644 index cbcdd17..0000000 --- a/tests/command/environment_spec.lua +++ /dev/null @@ -1,20 +0,0 @@ -describe("environment", function() - it("generates environment", function() - local config = require "laravel.config" - local environment = require "laravel.environment" - local user_commands = require "laravel.user_commands" - local route_info = require "laravel.route_info" - local env = {} - config.setup {} - config.options.environment.resolver = function(environments) - return env - end - local spy = require "luassert.spy" - spy.on(config.options.environment, "resolver") - environment.setup() - assert.spy(config.options.environment.resolver).was.called_with(config.options.environment.environments) - assert.are.same(env, environment.environment) - assert.spy(user_commands.setup).was.called() - assert.spy(route_info.setup).was.called() - end) -end) diff --git a/tests/environment/resolver_spec.lua b/tests/environment/resolver_spec.lua new file mode 100644 index 0000000..35d37b2 --- /dev/null +++ b/tests/environment/resolver_spec.lua @@ -0,0 +1,13 @@ +describe("Environment Resolver test", function() + before_each(function() end) + + it("resolve by the environment variable", function() + package.loaded["laravel.environment.get_env"] = function() + return "test-environment" + end + local resolver = require "laravel.environment.resolver" + local test_resolver = resolver(true, false, nil) + local environment = test_resolver { ["test-environment"] = "test-environment" } + assert.equals("test-environment", environment) + end) +end) From 6c239cd5b0a81f17a7c83103f2841feddbc680f5 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Fri, 3 Nov 2023 21:36:37 +0100 Subject: [PATCH 15/55] feat: Implement api --- lua/laravel/api.lua | 46 ++++++++++ lua/laravel/commands/init.lua | 23 ++--- lua/laravel/resources/create.lua | 11 +-- lua/laravel/routes/init.lua | 19 ++--- lua/laravel/runners/async.lua | 38 --------- lua/laravel/runners/init.lua | 9 +- lua/laravel/runners/sync.lua | 35 -------- lua/laravel/status.lua | 11 +-- lua/laravel/telescope/pickers/commands.lua | 4 +- lua/laravel/telescope/pickers/related.lua | 29 +++---- lua/laravel/user_commands/composer.lua | 10 +-- lua/laravel/user_commands/docker_compose.lua | 88 +++++++++----------- lua/laravel/user_commands/sail.lua | 81 ++++++++---------- 13 files changed, 168 insertions(+), 236 deletions(-) create mode 100644 lua/laravel/api.lua delete mode 100644 lua/laravel/runners/async.lua delete mode 100644 lua/laravel/runners/sync.lua diff --git a/lua/laravel/api.lua b/lua/laravel/api.lua new file mode 100644 index 0000000..baad0cb --- /dev/null +++ b/lua/laravel/api.lua @@ -0,0 +1,46 @@ +local Job = require "plenary.job" +local environment = require "laravel.environment" + +local M = {} + +local function generate_command(name, args) + local executable = environment.get_executable(name) + if not executable then + error(string.format("Executable %s not found", name), vim.log.levels.ERROR) + end + + return vim.fn.extend(executable, args) +end + +function M.sync(program, args) + local cmd = generate_command(program, args) + + local command = table.remove(cmd, 1) + local stderr = {} + local stdout, ret = Job:new({ + command = command, + args = cmd, + on_stderr = function(_, data) + table.insert(stderr, data) + end, + }):sync() + + return { + stdout = stdout, + exit_code = ret, + stderr = stderr, + } +end + +function M.async(program, args, callback) + local cmd = generate_command(program, args) + + local command = table.remove(cmd, 1) + Job:new({ + command = command, + args = cmd, + on_exit = vim.schedule_wrap(callback), + }):start() +end + +return M diff --git a/lua/laravel/commands/init.lua b/lua/laravel/commands/init.lua index c7a9e3a..5da16fe 100644 --- a/lua/laravel/commands/init.lua +++ b/lua/laravel/commands/init.lua @@ -1,26 +1,21 @@ -local run = require "laravel.run" local utils = require "laravel.commands.utils" -local notify = require "laravel.notify" +local api = require "laravel.api" local M = {} M.list = {} function M.load() - local result, ok = run("artisan", { "list", "--format=json" }, { runner = "sync" }) - if not ok or result.exit_code == 1 then - notify("Commands.Load", { - msg = string.format("Failed to get commands %s %s", vim.inspect(result.out), vim.inspect(result.err)), - level = "ERROR", - }) - M.list = {} - - return false + M.list = {} + local result = api.sync("artisan", { "list", "--format=json" }) + if result.exit_code == 1 then + error( + string.format("Failed to get commands %s %s", vim.inspect(result.stdout), vim.inspect(result.stderr)), + vim.log.levels.ERROR + ) end - M.list = utils.from_json(result.out) - - return true + M.list = utils.from_json(result.stdout) end return M diff --git a/lua/laravel/resources/create.lua b/lua/laravel/resources/create.lua index 0812798..fd17383 100644 --- a/lua/laravel/resources/create.lua +++ b/lua/laravel/resources/create.lua @@ -1,7 +1,7 @@ -local run = require "laravel.run" local is_resource = require "laravel.resources.is_resource" local open = require "laravel.resources.open" local notify = require "laravel.notify" +local api = require "laravel.api" return function(command) local resource = command[1] @@ -16,12 +16,9 @@ return function(command) return false end - run("artisan", command, { - runner = "async", - callback = function() - open(resource, name) - end, - }) + api.async("artisan", command, function() + open(resource, name) + end) return true end diff --git a/lua/laravel/routes/init.lua b/lua/laravel/routes/init.lua index 0a6cb78..09329de 100644 --- a/lua/laravel/routes/init.lua +++ b/lua/laravel/routes/init.lua @@ -1,24 +1,21 @@ -local run = require "laravel.run" -local notify = require "laravel.notify" local utils = require "laravel.routes.utils" +local api = require "laravel.api" local M = {} M.list = {} function M.load() - local result, ok = run("artisan", { "route:list", "--json" }, { runner = "sync" }) - if not ok or result.exit_code == 1 then - notify( - "Routes.Load", - { msg = string.format("Failed to get routes %s %s", result.out, result.err), level = "ERROR" } + M.list = {} + local result = api.sync("artisan", { "route:list", "--json" }) + if result.exit_code == 1 then + error( + string.format("Failed to get routes %s %s", vim.inspect(result.stdout), vim.inspect(result.stderr)), + vim.log.levels.ERROR ) - M.list = {} - - return false end - M.list = utils.from_json(result.out) + M.list = utils.from_json(result.stdout) return true end diff --git a/lua/laravel/runners/async.lua b/lua/laravel/runners/async.lua deleted file mode 100644 index ddea87d..0000000 --- a/lua/laravel/runners/async.lua +++ /dev/null @@ -1,38 +0,0 @@ -local Job = require "plenary.job" -local notify = require "laravel.notify" - ---- Runs and returns the command inmediately ----@param cmd table ----@param opts table ----@return table, boolean -return function(cmd, opts) - opts = opts or {} - if type(cmd) ~= "table" then - notify("runner.async", { - msg = "cmd has to be a table", - level = "ERROR", - }) - return { err = { "cmd is not a table" } }, false - end - - if type(opts.callback) ~= "function" then - notify("runner.async", { - msg = "callback not pass", - level = "ERROR", - }) - return { err = { "callback is not a function" } }, false - end - - local command = table.remove(cmd, 1) - local stderr = {} - Job:new({ - command = command, - args = cmd, - on_exit = vim.schedule_wrap(opts.callback), - on_stderr = function(_, data) - table.insert(stderr, data) - end, - }):start() - - return {}, true -end diff --git a/lua/laravel/runners/init.lua b/lua/laravel/runners/init.lua index 2fa17ce..b574c50 100644 --- a/lua/laravel/runners/init.lua +++ b/lua/laravel/runners/init.lua @@ -1,11 +1,16 @@ local runners = { - async = require "laravel.runners.async", buffer = require "laravel.runners.buffer", popup = require "laravel.runners.popup", split = require "laravel.runners.split", - sync = require "laravel.runners.sync", + terminal = require "laravel.runners.terminal", + watch = require "laravel.runners.watch", } +-- sync and async are differente from this +-- The rest are base on how to show in the split +-- want to be able to trace the open terminals in the split +-- can re-use the same, or create a new one if necessary + return runners diff --git a/lua/laravel/runners/sync.lua b/lua/laravel/runners/sync.lua deleted file mode 100644 index f7bb716..0000000 --- a/lua/laravel/runners/sync.lua +++ /dev/null @@ -1,35 +0,0 @@ -local Job = require "plenary.job" -local notify = require "laravel.notify" - ---- Runs and returns the command immediately ----@param cmd table ----@return table, boolean -return function(cmd) - if type(cmd) ~= "table" then - notify("runners.sync", { - msg = "cmd has to be a table", - level = "ERROR", - }) - return { - out = {}, - exit_code = 1, - err = { "cmd is not a table" }, - }, false - end - - local command = table.remove(cmd, 1) - local stderr = {} - local stdout, ret = Job:new({ - command = command, - args = cmd, - on_stderr = function(_, data) - table.insert(stderr, data) - end, - }):sync() - - return { - out = stdout, - exit_code = ret, - err = stderr, - }, true -end diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua index 8611f30..ad5ff1c 100644 --- a/lua/laravel/status.lua +++ b/lua/laravel/status.lua @@ -1,5 +1,6 @@ local environment = require "laravel.environment" -local run = require "laravel.run" +local api = require "laravel.api" + local M = {} local counters = { @@ -26,8 +27,8 @@ local properties = { if not environment.get_executable "php" then return nil end - local res, _ = run("php", { "-v" }, { runner = "sync" }) - values.php = res.out[1]:match "PHP ([%d%.]+)" + local res = api.sync("php", { "-v" }) + values.php = res.stdout[1]:match "PHP ([%d%.]+)" return values.php end, @@ -46,9 +47,9 @@ local properties = { return nil end - local res, _ = run("artisan", { "--version" }, { runner = "sync" }) + local res = api.sync("artisan", { "--version" }) - values.laravel = res.out[1]:match "Laravel Framework ([%d%.]+)" + values.laravel = res.stdout[1]:match "Laravel Framework ([%d%.]+)" return values.laravel end, }, diff --git a/lua/laravel/telescope/pickers/commands.lua b/lua/laravel/telescope/pickers/commands.lua index 84766fe..c2a44fd 100644 --- a/lua/laravel/telescope/pickers/commands.lua +++ b/lua/laravel/telescope/pickers/commands.lua @@ -12,9 +12,7 @@ return function(opts) opts = opts or {} if #commands.list == 0 then - if not commands.load() then - return - end + commands.load() end pickers diff --git a/lua/laravel/telescope/pickers/related.lua b/lua/laravel/telescope/pickers/related.lua index 5131cb1..baaddca 100644 --- a/lua/laravel/telescope/pickers/related.lua +++ b/lua/laravel/telescope/pickers/related.lua @@ -1,12 +1,11 @@ local pickers = require "telescope.pickers" -local run = require "laravel.run" local lsp = require "laravel._lsp" local make_entry = require "laravel.telescope.make_entry" local finders = require "telescope.finders" local conf = require("telescope.config").values local actions = require "telescope.actions" local action_state = require "telescope.actions.state" -local notify = require "laravel.notify" +local api = require "laravel.api" return function(opts) opts = opts or {} @@ -38,30 +37,22 @@ return function(opts) local class = get_model_class_name() if class ~= "" then - local result, ok = run("artisan", { "model:show", class, "--json" }, { runner = "sync" }) - if not ok then - notify("Artisan", { msg = "'php artisan model:show " .. class .. " --json' command failed", level = "ERROR" }) - return nil - end - - if result.exit_code ~= 0 or string.sub(result.out[1], 1, 1) ~= "{" or string.sub(result.out[1], -1) ~= "}" then - notify( - "Artisan", - { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } + local result = api.sync("artisan", { "model:show", class, "--json" }) + if result.exit_code == 1 then + error( + string.format("'php artisan model:show %s --json' failed %s", class, vim.inspect(result.stderr)), + vim.log.levels.ERROR ) - return nil end - local model_info = vim.fn.json_decode(result.out[1]) + local model_info = vim.fn.json_decode(result.stdout[1]) if model_info == nil then - notify( - "Artisan", - { msg = "'php artisan model:show" .. class .. " --json' response could not be decoded", level = "ERROR" } + error( + string.format("'php artisan model:show %s --json' response could not be decoded", class), + vim.log.levels.ERROR ) - return nil end - ---@return ModelRelation|nil local build_relation = function(info, relation_type) if next(info) == nil then return nil diff --git a/lua/laravel/user_commands/composer.lua b/lua/laravel/user_commands/composer.lua index a6b29e8..1364c59 100644 --- a/lua/laravel/user_commands/composer.lua +++ b/lua/laravel/user_commands/composer.lua @@ -1,6 +1,7 @@ local notify = require "laravel.notify" local create_user_command = require "laravel.user_commands.create_user_command" local run = require "laravel.run" +local api = require "laravel.api" local M = {} @@ -32,12 +33,9 @@ function M.setup() end, ["dump-autoload"] = function() - run("composer", { "dump-autoload" }, { - runner = "async", - callback = function() - notify("composer.dump-autoload", { msg = "Completed", level = "INFO" }) - end, - }) + api.async("composer", { "dump-autoload" }, function() + notify("composer.dump-autoload", { msg = "Completed", level = "INFO" }) + end) end, }) end diff --git a/lua/laravel/user_commands/docker_compose.lua b/lua/laravel/user_commands/docker_compose.lua index 10ec7e0..bfb27b0 100644 --- a/lua/laravel/user_commands/docker_compose.lua +++ b/lua/laravel/user_commands/docker_compose.lua @@ -1,7 +1,7 @@ -local run = require "laravel.run" local notify = require "laravel.notify" local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" +local api = require "laravel.api" local M = {} @@ -12,69 +12,57 @@ function M.setup() create_user_command("DockerCompose", "compose", { up = function() - run("compose", { "up", "-d" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify( - "compose.up", - { msg = string.format("Error on Compose up. %s", vim.inspection(j:result())), level = "ERROR" } - ) + api.async("compose", { "up", "-d" }, function(j, exit_code) + if exit_code ~= 0 then + notify( + "compose.up", + { msg = string.format("Error on Compose up. %s", vim.inspection(j:result())), level = "ERROR" } + ) - return - end - notify("compose.up", { msg = "Completed", level = "INFO" }) - end, - }) + return + end + notify("compose.up", { msg = "Completed", level = "INFO" }) + end) end, ps = function() - run("compose", { "ps" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify("compose.ps", { msg = "Failed to run compose up", level = "ERROR" }) + api.async("compose", { "ps" }, function(j, exit_code) + if exit_code ~= 0 then + notify("compose.ps", { msg = "Failed to run compose up", level = "ERROR" }) - return - end - notify("compose.ps", { raw = j:result(), level = "INFO" }) - end, - }) + return + end + notify("compose.ps", { raw = j:result(), level = "INFO" }) + end) end, restart = function() - run("compose", { "restart" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify( - "compose.restart", - { msg = string.format("Failed to restart compose. %s", vim.inspect(j:result())), level = "ERROR" } - ) + api.async("compose", { "restart" }, function(j, exit_code) + if exit_code ~= 0 then + notify( + "compose.restart", + { msg = string.format("Failed to restart compose. %s", vim.inspect(j:result())), level = "ERROR" } + ) - return - end - notify("compose.restart", { msg = "compose restart complete", level = "INFO" }) - end, - }) + return + end + notify("compose.restart", { msg = "compose restart complete", level = "INFO" }) + end) notify("compose.restart", { msg = "compose restart starting", level = "INFO" }) end, down = function() - run("compose", { "down" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify( - "compose.down", - { msg = string.format("Failed to down compose. %s", vim.inspect(j:result())), level = "ERROR" } - ) + api.async("compose", { "down" }, function(j, exit_code) + if exit_code ~= 0 then + notify( + "compose.down", + { msg = string.format("Failed to down compose. %s", vim.inspect(j:result())), level = "ERROR" } + ) - return - end - notify("compose.down", { msg = "compose Down complete", level = "INFO" }) - end, - }) + return + end + notify("compose.down", { msg = "compose Down complete", level = "INFO" }) + end) end, }) end diff --git a/lua/laravel/user_commands/sail.lua b/lua/laravel/user_commands/sail.lua index 898319b..b40d051 100644 --- a/lua/laravel/user_commands/sail.lua +++ b/lua/laravel/user_commands/sail.lua @@ -2,6 +2,7 @@ local run = require "laravel.run" local notify = require "laravel.notify" local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" +local api = require "laravel.api" local M = {} @@ -12,17 +13,14 @@ function M.setup() create_user_command("Sail", "sail", { up = function() - run("sail", { "up", "-d" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify("sail.up", { msg = string.format("Error on Sail up. %s", vim.inspect(j:result())), level = "ERROR" }) + api.async("sail", { "up", "-d" }, function(j, exit_code) + if exit_code ~= 0 then + notify("sail.up", { msg = string.format("Error on Sail up. %s", vim.inspect(j:result())), level = "ERROR" }) - return - end - notify("sail.up", { msg = "Completed", level = "INFO" }) - end, - }) + return + end + notify("sail.up", { msg = "Completed", level = "INFO" }) + end) end, shell = function() @@ -30,52 +28,43 @@ function M.setup() end, ps = function() - run("sail", { "ps" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify("sail.ps", { msg = "Failed to run Sail up", level = "ERROR" }) + api.async("sail", { "ps" }, function(j, exit_code) + if exit_code ~= 0 then + notify("sail.ps", { msg = "Failed to run Sail up", level = "ERROR" }) - return - end - notify("sail.ps", { raw = vim.fn.join(j:result(), "\n"), level = "INFO" }) - end, - }) + return + end + notify("sail.ps", { raw = vim.fn.join(j:result(), "\n"), level = "INFO" }) + end) end, restart = function() - run("sail", { "restart" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify( - "sail.restart", - { msg = string.format("Failed to restart Sail. %s", vim.inspect(j:result())), level = "ERROR" } - ) + api.async("sail", { "restart" }, function(j, exit_code) + if exit_code ~= 0 then + notify( + "sail.restart", + { msg = string.format("Failed to restart Sail. %s", vim.inspect(j:result())), level = "ERROR" } + ) - return - end - notify("sail.restart", { msg = "Sail restart complete", level = "INFO" }) - end, - }) + return + end + notify("sail.restart", { msg = "Sail restart complete", level = "INFO" }) + end) notify("sail.restart", { msg = "Sail restart starting", level = "INFO" }) end, down = function() - run("sail", { "down" }, { - runner = "async", - callback = function(j, exit_code) - if exit_code ~= 0 then - notify( - "sail.down", - { msg = string.format("Failed to down Sail. Error: %s", vim.inspect(j:result())), level = "ERROR" } - ) + api.async("sail", { "down" }, function(j, exit_code) + if exit_code ~= 0 then + notify( + "sail.down", + { msg = string.format("Failed to down Sail. Error: %s", vim.inspect(j:result())), level = "ERROR" } + ) - return - end - notify("sail.down", { msg = "Sail Down complete", level = "INFO" }) - end, - }) + return + end + notify("sail.down", { msg = "Sail Down complete", level = "INFO" }) + end) end, }) end From d6c67e67891cd126e9282175d66d73717831f7be Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 5 Nov 2023 07:50:52 +0100 Subject: [PATCH 16/55] feat: use terminal to run commands --- lua/laravel/config.lua | 81 -------------------------------- lua/laravel/config/init.lua | 36 ++++++++++++++ lua/laravel/config/resources.lua | 35 ++++++++++++++ lua/laravel/config/ui.lua | 34 ++++++++++++++ lua/laravel/resources/create.lua | 8 +--- lua/laravel/run.lua | 21 +++++++-- lua/laravel/runners/popup.lua | 39 --------------- lua/laravel/runners/split.lua | 29 ------------ 8 files changed, 124 insertions(+), 159 deletions(-) delete mode 100644 lua/laravel/config.lua create mode 100644 lua/laravel/config/init.lua create mode 100644 lua/laravel/config/resources.lua create mode 100644 lua/laravel/config/ui.lua delete mode 100644 lua/laravel/runners/popup.lua delete mode 100644 lua/laravel/runners/split.lua diff --git a/lua/laravel/config.lua b/lua/laravel/config.lua deleted file mode 100644 index f795cb3..0000000 --- a/lua/laravel/config.lua +++ /dev/null @@ -1,81 +0,0 @@ -local M = {} - ----@class LaravelOptions -M.defaults = { - split = { - relative = "editor", - position = "right", - size = "30%", - enter = true, - }, - lsp_server = "phpactor", - register_user_commands = true, - bind_telescope = true, - default_runner = "split", - route_info = { - enable = true, - position = "right", - }, - commands_options = { - ["dump-server"] = { runner = "split" }, - ["queue:listen"] = { runner = "split" }, - ["serve"] = { runner = "split" }, - ["websockets"] = { runner = "split" }, - ["queue:restart"] = { runner = "watch" }, - ["tinker"] = { runner = "terminal", skip_args = true }, - ["db"] = { runner = "terminal" }, - ["docs"] = { runner = "popup", skip_args = true }, - }, - environment = { - resolver = require "laravel.environment.resolver"(true, true, nil), - environments = { - ["local"] = require("laravel.environment.native").setup(), - ["sail"] = require("laravel.environment.sail").setup(), - ["docker-compose"] = require("laravel.environment.docker_compose").setup(), - }, - }, - resources = { - ["make:cast"] = "app/Casts", - ["make:channel"] = "app/Broadcasting", - ["make:command"] = "app/Console/Commands", - ["make:component"] = "app/View/Components", - ["make:controller"] = "app/Http/Controllers", - ["make:event"] = "app/Events", - ["make:exception"] = "app/Exceptions", - ["make:factory"] = function(name) - return string.format("database/factories/%sFactory.php", name), nil - end, - ["make:job"] = "app/Jobs", - ["make:listener"] = "app/Listeners", - ["make:mail"] = "app/Mail", - ["make:middleware"] = "app/Http/Middleware", - ["make:migration"] = function(name) - local result = require("laravel.runners").sync { "fd", name .. ".php" } - if result.exit_code == 1 then - return "", result.error - end - - return result.out, nil - end, - ["make:model"] = "app/Models", - ["make:notification"] = "app/Notifications", - ["make:observer"] = "app/Observers", - ["make:policy"] = "app/Policies", - ["make:provider"] = "app/Providers", - ["make:request"] = "app/Http/Requests", - ["make:resource"] = "app/Http/Resources", - ["make:rule"] = "app/Rules", - ["make:scope"] = "app/Models/Scopes", - ["make:seeder"] = "database/seeders", - ["make:test"] = "tests/Feature", - }, -} - ---- @type LaravelOptions -M.options = {} - -function M.setup(options) - M.options = vim.tbl_deep_extend("force", {}, M.defaults, options or {}) -end - -return M diff --git a/lua/laravel/config/init.lua b/lua/laravel/config/init.lua new file mode 100644 index 0000000..088db11 --- /dev/null +++ b/lua/laravel/config/init.lua @@ -0,0 +1,36 @@ +local M = {} + +---@class LaravelOptions +M.defaults = { + ui = require "laravel.config.ui", + lsp_server = "phpactor", + register_user_commands = true, + bind_telescope = true, + route_info = { + enable = true, + position = "right", + }, + commands_options = { + ["queue:restart"] = { watch = true }, + ["tinker"] = { skip_args = true }, + ["docs"] = { ui = "popup", skip_args = true }, + }, + environment = { + resolver = require "laravel.environment.resolver"(true, true, nil), + environments = { + ["local"] = require("laravel.environment.native").setup(), + ["sail"] = require("laravel.environment.sail").setup(), + ["docker-compose"] = require("laravel.environment.docker_compose").setup(), + }, + }, + resources = require "laravel.config.resources", +} + +--- @type LaravelOptions +M.options = {} + +function M.setup(options) + M.options = vim.tbl_deep_extend("force", {}, M.defaults, options or {}) +end + +return M diff --git a/lua/laravel/config/resources.lua b/lua/laravel/config/resources.lua new file mode 100644 index 0000000..15459e7 --- /dev/null +++ b/lua/laravel/config/resources.lua @@ -0,0 +1,35 @@ +return { + ["make:cast"] = "app/Casts", + ["make:channel"] = "app/Broadcasting", + ["make:command"] = "app/Console/Commands", + ["make:component"] = "app/View/Components", + ["make:controller"] = "app/Http/Controllers", + ["make:event"] = "app/Events", + ["make:exception"] = "app/Exceptions", + ["make:factory"] = function(name) + return string.format("database/factories/%sFactory.php", name), nil + end, + ["make:job"] = "app/Jobs", + ["make:listener"] = "app/Listeners", + ["make:mail"] = "app/Mail", + ["make:middleware"] = "app/Http/Middleware", + ["make:migration"] = function(name) + local result = require("laravel.runners").sync { "fd", name .. ".php" } + if result.exit_code == 1 then + return "", result.error + end + + return result.out, nil + end, + ["make:model"] = "app/Models", + ["make:notification"] = "app/Notifications", + ["make:observer"] = "app/Observers", + ["make:policy"] = "app/Policies", + ["make:provider"] = "app/Providers", + ["make:request"] = "app/Http/Requests", + ["make:resource"] = "app/Http/Resources", + ["make:rule"] = "app/Rules", + ["make:scope"] = "app/Models/Scopes", + ["make:seeder"] = "database/seeders", + ["make:test"] = "tests/Feature", +} diff --git a/lua/laravel/config/ui.lua b/lua/laravel/config/ui.lua new file mode 100644 index 0000000..57468b0 --- /dev/null +++ b/lua/laravel/config/ui.lua @@ -0,0 +1,34 @@ +return { + default = "split", + nui_opts = { + split = { + enter = true, + relative = "editor", + position = "right", + size = "33%", + win_options = { + number = false, + relativenumber = false, + }, + }, + popup = { + enter = true, + focusable = true, + border = { + style = "rounded", + }, + position = { + row = "20%", + col = "50%", + }, + size = { + width = "28%", + height = "35%", + }, + win_options = { + number = false, + relativenumber = false, + }, + }, + }, +} diff --git a/lua/laravel/resources/create.lua b/lua/laravel/resources/create.lua index fd17383..e82c074 100644 --- a/lua/laravel/resources/create.lua +++ b/lua/laravel/resources/create.lua @@ -1,6 +1,5 @@ local is_resource = require "laravel.resources.is_resource" local open = require "laravel.resources.open" -local notify = require "laravel.notify" local api = require "laravel.api" return function(command) @@ -8,12 +7,7 @@ return function(command) local name = command[2] if not is_resource(resource) then - notify( - "Resource.Create", - { level = "ERROR", msg = string.format("Command %s is not a resource creation suported", resource) } - ) - - return false + error(string.format("Command %s is not a resource creation suported", resource), vim.log.levels.ERROR) end api.async("artisan", command, function() diff --git a/lua/laravel/run.lua b/lua/laravel/run.lua index de90bf1..4e69ccf 100644 --- a/lua/laravel/run.lua +++ b/lua/laravel/run.lua @@ -1,6 +1,12 @@ local config = require "laravel.config" local environment = require "laravel.environment" -local runners = require "laravel.runners" +local Split = require "nui.split" +local Popup = require "nui.popup" + +local ui_builders = { + split = Split, + popup = Popup, +} ---@param name string ---@param args string[] @@ -16,7 +22,16 @@ return function(name, args, opts) local command_option = config.options.commands_options[args[1]] or {} - local runner = opts.runner or command_option.runner or config.options.default_runner + opts = vim.tbl_extend("force", command_option, opts) + + local selected_ui = opts.ui or config.options.ui.default + + local instance = ui_builders[selected_ui](opts.nui_opts or {}) + + instance:mount() + + -- This returns thhe job id + local _ = vim.fn.termopen(table.concat(cmd, " ")) - return runners[runner](cmd, opts) + vim.cmd "startinsert" end diff --git a/lua/laravel/runners/popup.lua b/lua/laravel/runners/popup.lua deleted file mode 100644 index 3c69c5a..0000000 --- a/lua/laravel/runners/popup.lua +++ /dev/null @@ -1,39 +0,0 @@ -local Popup = require "nui.popup" -local event = require("nui.utils.autocmd").event -local buffer_run = require "laravel.runners.buffer" - ---- Runs in a buffers as a job ----@param cmd table ----@param opts table ----@return table, boolean -return function(cmd, opts) - local popup = Popup(vim.tbl_extend("force", { - enter = true, - focusable = true, - border = { - style = "rounded", - }, - position = { - row = "20%", - col = "50%", - }, - size = { - width = "28%", - height = "35%", - }, - }, opts.popup or {})) - - popup:mount() - - popup:on(event.BufLeave, function() - popup:unmount() - end) - - local result, ok = buffer_run(cmd, vim.tbl_extend("force", opts, { bufnr = popup.bufnr })) - if not ok then - popup:unmount() - end - vim.cmd "startinsert" - - return result, ok -end diff --git a/lua/laravel/runners/split.lua b/lua/laravel/runners/split.lua deleted file mode 100644 index f4b3021..0000000 --- a/lua/laravel/runners/split.lua +++ /dev/null @@ -1,29 +0,0 @@ -local Split = require "nui.split" -local event = require("nui.utils.autocmd").event -local buffer_run = require "laravel.runners.buffer" - ---- Runs in a buffers as a job ----@param cmd table ----@param opts table ----@return table, boolean -return function(cmd, opts) - local split = Split(vim.tbl_extend("force", { - relative = "editor", - position = "right", - size = "33%", - }, opts.split or {})) - - split:mount() - - split:on(event.BufLeave, function() - split:unmount() - end) - - local result, ok = buffer_run(cmd, vim.tbl_extend("force", opts, { bufnr = split.bufnr })) - if not ok then - split:unmount() - end - vim.cmd "startinsert" - - return result, ok -end From 80617a9fa7b90ff66f4b125dbe18b349de49ac59 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 5 Nov 2023 11:59:56 +0100 Subject: [PATCH 17/55] feat: implement command history --- lua/laravel/config/ui.lua | 2 ++ lua/laravel/history.lua | 18 ++++++++++ lua/laravel/run.lua | 9 +++-- lua/laravel/telescope/make_entry.lua | 14 ++++---- lua/laravel/telescope/pickers/commands.lua | 8 ----- lua/laravel/telescope/pickers/history.lua | 40 ++++++++++++++++++++++ lua/laravel/telescope/ui_run.lua | 4 +-- lua/laravel/user_commands/laravel/init.lua | 3 ++ lua/telescope/_extensions/laravel.lua | 1 + 9 files changed, 79 insertions(+), 20 deletions(-) create mode 100644 lua/laravel/history.lua create mode 100644 lua/laravel/telescope/pickers/history.lua diff --git a/lua/laravel/config/ui.lua b/lua/laravel/config/ui.lua index 57468b0..b456ce7 100644 --- a/lua/laravel/config/ui.lua +++ b/lua/laravel/config/ui.lua @@ -6,6 +6,7 @@ return { relative = "editor", position = "right", size = "33%", + buf_options = {}, win_options = { number = false, relativenumber = false, @@ -25,6 +26,7 @@ return { width = "28%", height = "35%", }, + buf_options = {}, win_options = { number = false, relativenumber = false, diff --git a/lua/laravel/history.lua b/lua/laravel/history.lua new file mode 100644 index 0000000..0440306 --- /dev/null +++ b/lua/laravel/history.lua @@ -0,0 +1,18 @@ +local list = {} + +local M = {} + +function M.add(jobId, name, args, opts) + table.insert(list, { + jobId = jobId, + name = name, + args = args, + opts = opts, + }) +end + +function M.all() + return list +end + +return M diff --git a/lua/laravel/run.lua b/lua/laravel/run.lua index 4e69ccf..fd2ecb4 100644 --- a/lua/laravel/run.lua +++ b/lua/laravel/run.lua @@ -1,7 +1,8 @@ local config = require "laravel.config" local environment = require "laravel.environment" -local Split = require "nui.split" +local history = require "laravel.history" local Popup = require "nui.popup" +local Split = require "nui.split" local ui_builders = { split = Split, @@ -26,12 +27,14 @@ return function(name, args, opts) local selected_ui = opts.ui or config.options.ui.default - local instance = ui_builders[selected_ui](opts.nui_opts or {}) + local instance = ui_builders[selected_ui](opts.nui_opts or config.options.ui.nui_opts[selected_ui]) instance:mount() -- This returns thhe job id - local _ = vim.fn.termopen(table.concat(cmd, " ")) + local jobId = vim.fn.termopen(table.concat(cmd, " ")) + + history.add(jobId, name, args, opts) vim.cmd "startinsert" end diff --git a/lua/laravel/telescope/make_entry.lua b/lua/laravel/telescope/make_entry.lua index ea87556..8cd4ddd 100644 --- a/lua/laravel/telescope/make_entry.lua +++ b/lua/laravel/telescope/make_entry.lua @@ -1,6 +1,6 @@ local entry_display = require "telescope.pickers.entry_display" -local make_entry = {} +local M = {} local handle_entry_index = function(opts, t, k) local override = ((opts or {}).entry_index or {})[k] @@ -15,7 +15,7 @@ local handle_entry_index = function(opts, t, k) return val end -make_entry.set_default_entry_mt = function(tbl, opts) +M.set_default_entry_mt = function(tbl, opts) return setmetatable({}, { __index = function(t, k) local override = handle_entry_index(opts, t, k) @@ -34,7 +34,7 @@ make_entry.set_default_entry_mt = function(tbl, opts) }) end -function make_entry.gen_from_laravel_routes(opts) +function M.gen_from_laravel_routes(opts) opts = opts or {} local displayer = entry_display.create { @@ -56,7 +56,7 @@ function make_entry.gen_from_laravel_routes(opts) end return function(route) - return make_entry.set_default_entry_mt({ + return M.set_default_entry_mt({ value = route, ordinal = route.uri, display = make_display, @@ -65,7 +65,7 @@ function make_entry.gen_from_laravel_routes(opts) end end -function make_entry.gen_from_model_relations(opts) +function M.gen_from_model_relations(opts) opts = opts or {} local displayer = entry_display.create { @@ -89,7 +89,7 @@ function make_entry.gen_from_model_relations(opts) return function(relation) local class_parts = vim.split(relation.class, "\\") relation.class_name = class_parts[#class_parts] - return make_entry.set_default_entry_mt({ + return M.set_default_entry_mt({ value = relation, ordinal = relation.class_name, display = make_display, @@ -97,4 +97,4 @@ function make_entry.gen_from_model_relations(opts) end end -return make_entry +return M diff --git a/lua/laravel/telescope/pickers/commands.lua b/lua/laravel/telescope/pickers/commands.lua index c2a44fd..2af606a 100644 --- a/lua/laravel/telescope/pickers/commands.lua +++ b/lua/laravel/telescope/pickers/commands.lua @@ -64,15 +64,7 @@ return function(opts) ui_run(command, true) end) end) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - local command = entry.value - vim.schedule(function() - ui_run(command) - end) - end) return true end, }) diff --git a/lua/laravel/telescope/pickers/history.lua b/lua/laravel/telescope/pickers/history.lua new file mode 100644 index 0000000..9d91f0d --- /dev/null +++ b/lua/laravel/telescope/pickers/history.lua @@ -0,0 +1,40 @@ +local actions = require "telescope.actions" +local action_state = require "telescope.actions.state" +local conf = require("telescope.config").values +local finders = require "telescope.finders" +local history = require "laravel.history" +local pickers = require "telescope.pickers" +local run = require "laravel.run" + +return function(opts) + opts = opts or {} + + pickers + .new(opts, { + prompt_title = "Laravel Command History", + finder = finders.new_table { + results = history.all(), + entry_maker = function(history_entry) + return { + value = history_entry, + display = string.format("%s %s", history_entry.name, vim.fn.join(history_entry.args, " ")), + ordinal = string.format("%s %s", history_entry.name, vim.fn.join(history_entry.args, " ")), + } + end, + }, + previewer = false, + sorter = conf.prefilter_sorter { + sorter = conf.generic_sorter(opts or {}), + }, + attach_mappings = function(_, map) + map("i", "", function(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + run(entry.value.name, entry.value.args, entry.value.opts) + end) + + return true + end, + }) + :find() +end diff --git a/lua/laravel/telescope/ui_run.lua b/lua/laravel/telescope/ui_run.lua index 8f8319e..e67a765 100644 --- a/lua/laravel/telescope/ui_run.lua +++ b/lua/laravel/telescope/ui_run.lua @@ -3,7 +3,7 @@ local is_resource = require "laravel.resources.is_resource" local create = require "laravel.resources.create" local config = require "laravel.config" -return function(command, ask_options, runner) +return function(command, ask_options) local command_options = config.options.commands_options[command.name] or {} local function build_prompt(argument) local prompt = "Argument " .. argument.name .. " " @@ -48,7 +48,7 @@ return function(command, ask_options, runner) return create(cmd) end - application_run("artisan", cmd, { runner = runner }) + application_run("artisan", cmd, {}) end local args = {} diff --git a/lua/laravel/user_commands/laravel/init.lua b/lua/laravel/user_commands/laravel/init.lua index 3b206cf..7040818 100644 --- a/lua/laravel/user_commands/laravel/init.lua +++ b/lua/laravel/user_commands/laravel/init.lua @@ -19,6 +19,9 @@ local commands = { ["related"] = function() return require("telescope").extensions.laravel.related() end, + ["history"] = function() + return require("telescope").extensions.laravel.history() + end, ["info"] = require "laravel.user_commands.laravel.info", } diff --git a/lua/telescope/_extensions/laravel.lua b/lua/telescope/_extensions/laravel.lua index 9ac8b8f..5d35353 100644 --- a/lua/telescope/_extensions/laravel.lua +++ b/lua/telescope/_extensions/laravel.lua @@ -3,5 +3,6 @@ return require("telescope").register_extension { commands = require "laravel.telescope.pickers.commands", routes = require "laravel.telescope.pickers.routes", related = require "laravel.telescope.pickers.related", + history = require "laravel.telescope.pickers.history", }, } From ee6e91eeaefeef0537b64662fefd8cd6f0487013 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 5 Nov 2023 12:09:29 +0100 Subject: [PATCH 18/55] feat: remove bind_telescope --- README.md | 1 - lua/laravel/config/init.lua | 1 - lua/laravel/user_commands/artisan.lua | 12 ++++-------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 632489d..d091854 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,6 @@ Default configuration size = "30%", enter = true, }, - bind_telescope = true, lsp_server = "phpactor", register_user_commands = true, route_info = { diff --git a/lua/laravel/config/init.lua b/lua/laravel/config/init.lua index 088db11..398cbd4 100644 --- a/lua/laravel/config/init.lua +++ b/lua/laravel/config/init.lua @@ -5,7 +5,6 @@ M.defaults = { ui = require "laravel.config.ui", lsp_server = "phpactor", register_user_commands = true, - bind_telescope = true, route_info = { enable = true, position = "right", diff --git a/lua/laravel/user_commands/artisan.lua b/lua/laravel/user_commands/artisan.lua index 2cbfc8d..25d22e0 100644 --- a/lua/laravel/user_commands/artisan.lua +++ b/lua/laravel/user_commands/artisan.lua @@ -1,6 +1,5 @@ -local laravel_commands = require "laravel.commands" -local config = require "laravel.config" local is_resource = require "laravel.resources.is_resource" +local laravel_commands = require "laravel.commands" local resources_create = require "laravel.resources.create" local run = require "laravel.run" @@ -28,13 +27,10 @@ return { setup = function() vim.api.nvim_create_user_command("Artisan", function(args) if args.args == "" then - if config.options.bind_telescope then - local ok, telescope = pcall(require, "telescope") - if ok then - return telescope.extensions.laravel.commands() - end + local ok, telescope = pcall(require, "telescope") + if ok then + return telescope.extensions.laravel.commands() end - return end if is_resource(args.fargs[1]) then From b9d8f9004b04cbf9cc63f54be97fbaaa8b2efeaa Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 5 Nov 2023 12:16:02 +0100 Subject: [PATCH 19/55] fix: proper display error when routes are broken --- lua/laravel/route_info/init.lua | 4 +--- lua/laravel/routes/init.lua | 6 +++++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lua/laravel/route_info/init.lua b/lua/laravel/route_info/init.lua index 11c1cff..88e6a0f 100644 --- a/lua/laravel/route_info/init.lua +++ b/lua/laravel/route_info/init.lua @@ -53,9 +53,7 @@ local function set_route_to_methods(event) vim.diagnostic.reset(namespace, bufnr) if #routes.list == 0 then - if not routes.load() then - return - end + routes.load() end local php_parser = vim.treesitter.get_parser(bufnr, "php") diff --git a/lua/laravel/routes/init.lua b/lua/laravel/routes/init.lua index 09329de..29569b8 100644 --- a/lua/laravel/routes/init.lua +++ b/lua/laravel/routes/init.lua @@ -10,7 +10,11 @@ function M.load() local result = api.sync("artisan", { "route:list", "--json" }) if result.exit_code == 1 then error( - string.format("Failed to get routes %s %s", vim.inspect(result.stdout), vim.inspect(result.stderr)), + string.format( + "Failed to get routes check your code %s %s", + vim.fn.join(result.stdout, "\r\n"), + vim.fn.join(result.stderr, "\r\n") + ), vim.log.levels.ERROR ) end From b1eeda5e1c9a43ac10ffaf5d265b2bb4647f2d2b Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 5 Nov 2023 17:01:09 +0100 Subject: [PATCH 20/55] feat: support view completition --- lua/laravel/config/init.lua | 11 ++++-- lua/laravel/environment/init.lua | 6 +++- lua/laravel/null_ls/views.lua | 62 ++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 lua/laravel/null_ls/views.lua diff --git a/lua/laravel/config/init.lua b/lua/laravel/config/init.lua index 398cbd4..c409140 100644 --- a/lua/laravel/config/init.lua +++ b/lua/laravel/config/init.lua @@ -5,9 +5,14 @@ M.defaults = { ui = require "laravel.config.ui", lsp_server = "phpactor", register_user_commands = true, - route_info = { - enable = true, - position = "right", + features = { + null_ls = { + views = { enable = true }, + }, + route_info = { + enable = true, + position = "right", + }, }, commands_options = { ["queue:restart"] = { watch = true }, diff --git a/lua/laravel/environment/init.lua b/lua/laravel/environment/init.lua index 3fbf964..ad750e1 100644 --- a/lua/laravel/environment/init.lua +++ b/lua/laravel/environment/init.lua @@ -17,9 +17,13 @@ function M.setup() end user_commands.setup() - if config.options.route_info.enable then + if config.options.features.route_info.enable then require("laravel.route_info").setup() end + + if config.options.features.null_ls.views.enable then + require("laravel.null_ls.views").setup() + end end ---@param name string diff --git a/lua/laravel/null_ls/views.lua b/lua/laravel/null_ls/views.lua new file mode 100644 index 0000000..de79e0d --- /dev/null +++ b/lua/laravel/null_ls/views.lua @@ -0,0 +1,62 @@ +local M = {} + +function M.setup() + local ok, null_ls = pcall(require, "null-ls") + if not ok then + error "Completition view requires null ls" + end + + local scan = require "plenary.scandir" + local ts_utils = require "nvim-treesitter.ts_utils" + local api = require "laravel.api" + + null_ls.deregister "Laravel Views" + + local laravel_view = { + name = "Laravel Views", + method = null_ls.methods.COMPLETION, + filetypes = { "php" }, + generator = { + fn = function(params, done) + local node = ts_utils.get_node_at_cursor() + node = node:parent() + while node ~= nil and node.type(node) ~= "function_call_expression" do + node = node:parent() + end + if node == nil then + return + end + if node:child_count() > 0 then + local node_text = vim.treesitter.get_node_text(node:child(0), params.bufnr, {}) + + if node_text ~= "view" then + return + end + end + + local candidates = {} + + local res = api.sync("artisan", { "tinker", "--execute", "echo resource_path('views')" }) + local view_path = res.stdout[1] + local rule = string.format("^%s/(.*).blade.php$", view_path:gsub("-", "%%-")) + local finds = scan.scan_dir(view_path, { hidden = false, depth = 4 }) + for _, value in pairs(finds) do + local name = value:match(rule):gsub("/", ".") + table.insert(candidates, { + label = name, + insertText = string.format('"%s"', name), + kind = vim.lsp.protocol.CompletionItemKind["Value"], + documentation = value, + }) + end + + done { { items = candidates, isIncomplete = false } } + end, + async = true, + }, + } + + null_ls.register(laravel_view) +end + +return M From 23b09cacd5a98c67d576a3893dc8cdb528776f7e Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 5 Nov 2023 17:26:27 +0100 Subject: [PATCH 21/55] fix: change to single quotes --- lua/laravel/null_ls/views.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/laravel/null_ls/views.lua b/lua/laravel/null_ls/views.lua index de79e0d..c3ea373 100644 --- a/lua/laravel/null_ls/views.lua +++ b/lua/laravel/null_ls/views.lua @@ -44,7 +44,7 @@ function M.setup() local name = value:match(rule):gsub("/", ".") table.insert(candidates, { label = name, - insertText = string.format('"%s"', name), + insertText = string.format("'%s'", name), kind = vim.lsp.protocol.CompletionItemKind["Value"], documentation = value, }) From 9cdb84a0afc041f912ccb889d7afb343a57d6b53 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Mon, 6 Nov 2023 23:37:29 +0100 Subject: [PATCH 22/55] fix: route info reading options --- lua/laravel/route_info/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/laravel/route_info/init.lua b/lua/laravel/route_info/init.lua index 88e6a0f..f64c69f 100644 --- a/lua/laravel/route_info/init.lua +++ b/lua/laravel/route_info/init.lua @@ -3,7 +3,7 @@ local routes = require "laravel.routes" local config = require "laravel.config" local get_node_text = vim.treesitter.get_node_text -local options = config.options.route_info +local options = config.options.features.route_info local function is_same_class(action, class) return string.sub(action, 1, string.len(class)) == class From e56f73a85ca397a6a01ef48a4793c568bc765467 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 14 Nov 2023 08:48:11 +0100 Subject: [PATCH 23/55] feat: use system call for fd instead of sync runner --- lua/laravel/config/resources.lua | 7 +- lua/laravel/runners/buffer.lua | 117 ------------------------------- lua/laravel/runners/init.lua | 16 ----- lua/laravel/runners/terminal.lua | 32 --------- lua/laravel/runners/watch.lua | 78 --------------------- 5 files changed, 2 insertions(+), 248 deletions(-) delete mode 100644 lua/laravel/runners/buffer.lua delete mode 100644 lua/laravel/runners/init.lua delete mode 100644 lua/laravel/runners/terminal.lua delete mode 100644 lua/laravel/runners/watch.lua diff --git a/lua/laravel/config/resources.lua b/lua/laravel/config/resources.lua index 15459e7..47c91e1 100644 --- a/lua/laravel/config/resources.lua +++ b/lua/laravel/config/resources.lua @@ -14,12 +14,9 @@ return { ["make:mail"] = "app/Mail", ["make:middleware"] = "app/Http/Middleware", ["make:migration"] = function(name) - local result = require("laravel.runners").sync { "fd", name .. ".php" } - if result.exit_code == 1 then - return "", result.error - end + local files = vim.fn.systemlist(string.format("fd %s.php", name)) - return result.out, nil + return files[1], nil end, ["make:model"] = "app/Models", ["make:notification"] = "app/Notifications", diff --git a/lua/laravel/runners/buffer.lua b/lua/laravel/runners/buffer.lua deleted file mode 100644 index b236059..0000000 --- a/lua/laravel/runners/buffer.lua +++ /dev/null @@ -1,117 +0,0 @@ -local notify = require "laravel.notify" -local config = require "laravel.config" - ----@param cmd table ----@return string -local function sanetize_cmd(cmd) - -- this is to escape namespaces - for index, value in ipairs(cmd) do - cmd[index] = value:gsub("\\", "\\\\") - end - - return vim.fn.join(cmd, " ") -end - -local function splitStrings(strings) - local result = {} - - for _, str in ipairs(strings) do - local parts = {} - local stop - local start = 1 - if str == "" then - table.insert(result, "") - else - while start <= #str do - local index = string.find(str, "\r", start + 1) - - if index then - stop = index - table.insert(parts, string.sub(str, start, stop)) - start = stop + 1 - else - table.insert(parts, string.sub(str, start)) - break - end - end - - for _, part in ipairs(parts) do - table.insert(result, part) - end - end - end - - return result -end - ---- Runs in a buffers as a job ----@param cmd table ----@param opts table ----@return table, boolean -return function(cmd, opts) - local default = { - open = true, - focus = true, - buf_name = nil, - split = config.options.split, - } - - opts = vim.tbl_deep_extend("force", default, opts or {}) - - if opts.persist then - opts.listed = true - opts.buf_name = vim.fn.join(cmd, " ") - end - - local job_id = 0 - local bufnr - if opts.bufnr == nil then - bufnr = vim.api.nvim_create_buf(opts.listed or false, true) - else - bufnr = opts.bufnr - end - - if opts.buf_name then - ---@diagnostic disable-next-line: param-type-mismatch - if vim.fn.bufexists(opts.buf_name) == 1 then - notify("Buffer Run", { - msg = string.format("Buffer with the name `%s` already exists", opts.buf_name), - level = "ERROR", - }) - return {}, false - end - vim.api.nvim_buf_set_name(bufnr, opts.buf_name) - end - - local channel_id = vim.api.nvim_open_term(bufnr, { - on_input = function(_, _, _, data) - vim.api.nvim_chan_send(job_id, data) - end, - }) - - local function handle_output(_, data) - local lines = splitStrings(data) - vim.fn.chansend(channel_id, lines) - end - - job_id = vim.fn.jobstart(sanetize_cmd(cmd), { - stdeout_buffered = true, - on_stdout = handle_output, - on_exit = function(id) - require("laravel._jobs").unregister(id) - vim.fn.chanclose(channel_id) - if opts.on_exit ~= nil then - opts.on_exit() - end - end, - pty = true, - -- width = config.options.split.width, - }) - - require("laravel._jobs").register(job_id, bufnr) - - return { - job = job_id, - buff = bufnr, - }, true -end diff --git a/lua/laravel/runners/init.lua b/lua/laravel/runners/init.lua deleted file mode 100644 index b574c50..0000000 --- a/lua/laravel/runners/init.lua +++ /dev/null @@ -1,16 +0,0 @@ -local runners = { - buffer = require "laravel.runners.buffer", - popup = require "laravel.runners.popup", - split = require "laravel.runners.split", - - terminal = require "laravel.runners.terminal", - - watch = require "laravel.runners.watch", -} - --- sync and async are differente from this --- The rest are base on how to show in the split --- want to be able to trace the open terminals in the split --- can re-use the same, or create a new one if necessary - -return runners diff --git a/lua/laravel/runners/terminal.lua b/lua/laravel/runners/terminal.lua deleted file mode 100644 index b7284f1..0000000 --- a/lua/laravel/runners/terminal.lua +++ /dev/null @@ -1,32 +0,0 @@ -local config = require "laravel.config" ---- Runs in a new terminal and can operate in the terminal ----@param cmd table ----@param opts table ----@return table, boolean -return function(cmd, opts) - local default = { - focus = true, - split = { - cmd = config.options.split.cmd, - }, - } - - local cur_window = vim.api.nvim_get_current_win() - - opts = vim.tbl_deep_extend("force", default, opts or {}) - vim.cmd(string.format("vertical new term://%s", table.concat(cmd, " "))) - vim.cmd "startinsert" - - local buff = vim.api.nvim_get_current_buf() - local term_id = vim.b.terminal_job_id - - if not opts.focus then - vim.api.nvim_set_current_win(cur_window) - vim.cmd "stopinsert" - end - - return { - buff = buff, - term_id = term_id, - }, true -end diff --git a/lua/laravel/runners/watch.lua b/lua/laravel/runners/watch.lua deleted file mode 100644 index 915fec3..0000000 --- a/lua/laravel/runners/watch.lua +++ /dev/null @@ -1,78 +0,0 @@ ----@param cmd table ----@param opts table ----@return table, boolean -return function(cmd, opts) - opts = opts or {} - local options = require("laravel.application").get_options() - local default = { - open = true, - split = { - cmd = options.split.cmd, - width = options.split.width, - }, - } - - opts = vim.tbl_deep_extend("force", default, opts or {}) - - local pattern = opts.pattern or { "*.php" } - local buf_name = opts.buf_name or ("[Watched] " .. vim.fn.join(cmd, " ")) - - local bufnr = vim.api.nvim_create_buf(true, true) - vim.api.nvim_buf_set_name(bufnr, buf_name) - - if opts.open then - vim.cmd "vertical new" - local new_window = vim.api.nvim_get_current_win() - vim.api.nvim_win_set_width(new_window, 85) - vim.api.nvim_win_set_buf(new_window, bufnr) - end - - local run = function() - local windows = vim.fn.win_findbuf(bufnr) - local new_window = windows[1] - - local channel_id = vim.api.nvim_open_term(bufnr, {}) - if new_window ~= nil then - vim.api.nvim_win_set_cursor(new_window, { 1, 0 }) - end - - vim.fn.jobstart(vim.fn.join(cmd, " "), { - stdeout_buffered = true, - on_stdout = function(_, data) - vim.fn.chansend(channel_id, data) - end, - on_exit = function() - if new_window ~= nil then - local row = vim.api.nvim_buf_line_count(bufnr) - vim.api.nvim_win_set_cursor(new_window, { row, 0 }) - end - end, - pty = true, - width = options.split.width, - }) - end - - run() - - local group = vim.api.nvim_create_augroup("laravel.watch", {}) - - local au_cmd_id = vim.api.nvim_create_autocmd({ "BufWritePost" }, { - pattern = pattern, - group = group, - callback = function() - run() - end, - }) - - vim.api.nvim_create_autocmd({ "BufDelete" }, { - buffer = bufnr, - group = group, - callback = function() - vim.api.nvim_del_autocmd(au_cmd_id) - end, - }) - - return { - buff = bufnr, - }, true -end From 5db249e9b865724315b1f20ae6e669d59d437096 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Fri, 17 Nov 2023 20:54:14 +0100 Subject: [PATCH 24/55] feat: support default options per command --- lua/laravel/config/init.lua | 1 + lua/laravel/telescope/ui_run.lua | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lua/laravel/config/init.lua b/lua/laravel/config/init.lua index c409140..01751c2 100644 --- a/lua/laravel/config/init.lua +++ b/lua/laravel/config/init.lua @@ -18,6 +18,7 @@ M.defaults = { ["queue:restart"] = { watch = true }, ["tinker"] = { skip_args = true }, ["docs"] = { ui = "popup", skip_args = true }, + ["make:model"] = { options = { "-mf" } }, }, environment = { resolver = require "laravel.environment.resolver"(true, true, nil), diff --git a/lua/laravel/telescope/ui_run.lua b/lua/laravel/telescope/ui_run.lua index e67a765..c0db747 100644 --- a/lua/laravel/telescope/ui_run.lua +++ b/lua/laravel/telescope/ui_run.lua @@ -39,8 +39,12 @@ return function(command, ask_options) end if options ~= nil and options ~= "" then - for _, value in pairs(vim.fn.split(options, " ")) do - table.insert(cmd, value) + if type(options) == "string" then + for _, value in pairs(vim.fn.split(options, " ")) do + table.insert(cmd, value) + end + elseif type(options) == "table" then + cmd = vim.fn.extend(cmd, options) end end @@ -74,7 +78,7 @@ return function(command, ask_options) end) return end - run(values, nil) + run(values, command_options.options) end, {}) return true From cfaa291c5a658d1961d5bdc0ba2a99fb721de68e Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Fri, 17 Nov 2023 21:13:42 +0100 Subject: [PATCH 25/55] feat: support create cli when empty for require parameter --- lua/laravel/telescope/ui_run.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lua/laravel/telescope/ui_run.lua b/lua/laravel/telescope/ui_run.lua index c0db747..f496b09 100644 --- a/lua/laravel/telescope/ui_run.lua +++ b/lua/laravel/telescope/ui_run.lua @@ -2,6 +2,7 @@ local application_run = require "laravel.run" local is_resource = require "laravel.resources.is_resource" local create = require "laravel.resources.create" local config = require "laravel.config" +local laravel_run = require "laravel.run" return function(command, ask_options) local command_options = config.options.commands_options[command.name] or {} @@ -23,9 +24,17 @@ return function(command, ask_options) end vim.ui.input({ prompt = build_prompt(args[1]) }, function(value) + -- esc value is nil + if value == nil and args[1].is_required then + return + end + -- enter value is "" if value == "" and args[1].is_required then + print(vim.inspect(command)) + laravel_run("artisan", { command.name }, { ui = "popup" }) return end + table.insert(values, value) table.remove(args, 1) get_arguments(args, callback, values) From 1a57661f856c3ae54180e9f2bac1d35103c224e0 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Fri, 17 Nov 2023 23:04:59 +0100 Subject: [PATCH 26/55] feat: completion add support for routes --- lua/laravel/config/init.lua | 2 +- lua/laravel/environment/init.lua | 4 +- lua/laravel/null_ls/completion/init.lua | 48 ++++++++++++++++++ lua/laravel/null_ls/completion/route.lua | 18 +++++++ lua/laravel/null_ls/completion/view.lua | 22 +++++++++ lua/laravel/null_ls/init.lua | 7 +++ lua/laravel/null_ls/views.lua | 62 ------------------------ 7 files changed, 98 insertions(+), 65 deletions(-) create mode 100644 lua/laravel/null_ls/completion/init.lua create mode 100644 lua/laravel/null_ls/completion/route.lua create mode 100644 lua/laravel/null_ls/completion/view.lua create mode 100644 lua/laravel/null_ls/init.lua delete mode 100644 lua/laravel/null_ls/views.lua diff --git a/lua/laravel/config/init.lua b/lua/laravel/config/init.lua index 01751c2..1303d5b 100644 --- a/lua/laravel/config/init.lua +++ b/lua/laravel/config/init.lua @@ -7,7 +7,7 @@ M.defaults = { register_user_commands = true, features = { null_ls = { - views = { enable = true }, + enable = true, }, route_info = { enable = true, diff --git a/lua/laravel/environment/init.lua b/lua/laravel/environment/init.lua index ad750e1..919cf03 100644 --- a/lua/laravel/environment/init.lua +++ b/lua/laravel/environment/init.lua @@ -21,8 +21,8 @@ function M.setup() require("laravel.route_info").setup() end - if config.options.features.null_ls.views.enable then - require("laravel.null_ls.views").setup() + if config.options.features.null_ls.enable then + require("laravel.null_ls").setup() end end diff --git a/lua/laravel/null_ls/completion/init.lua b/lua/laravel/null_ls/completion/init.lua new file mode 100644 index 0000000..84aed50 --- /dev/null +++ b/lua/laravel/null_ls/completion/init.lua @@ -0,0 +1,48 @@ +local M = {} + +local completions = { + view = require "laravel.null_ls.completion.view", + route = require "laravel.null_ls.completion.route", +} + +function M.setup() + local ok, null_ls = pcall(require, "null-ls") + if not ok then + error "Completition requires null ls" + end + + null_ls.deregister "Laravel" + + local laravel = { + name = "Laravel", + method = null_ls.methods.COMPLETION, + filetypes = { "php" }, + generator = { + fn = function(params, done) + local ts_utils = require "nvim-treesitter.ts_utils" + local node = ts_utils.get_node_at_cursor() + node = node:parent() + while node ~= nil and node.type(node) ~= "function_call_expression" do + node = node:parent() + end + if node == nil then + return + end + if node:child_count() > 0 then + local node_text = vim.treesitter.get_node_text(node:child(0), params.bufnr, {}) + + local completion = completions[node_text] + if not completion then + return + end + completion(done) + end + end, + async = true, + }, + } + + null_ls.register(laravel) +end + +return M diff --git a/lua/laravel/null_ls/completion/route.lua b/lua/laravel/null_ls/completion/route.lua new file mode 100644 index 0000000..d94891b --- /dev/null +++ b/lua/laravel/null_ls/completion/route.lua @@ -0,0 +1,18 @@ +return function(done) + local routes = require "laravel.routes" + + local candidates = {} + + for _, route in pairs(routes.list) do + if route.name then + table.insert(candidates, { + label = string.format("%s (route)", route.name), + insertText = string.format("'%s'", route.name), + kind = vim.lsp.protocol.CompletionItemKind["Value"], + documentation = string.format("[%s] %s", route.name, route.uri), + }) + end + end + + done { { items = candidates, isIncomplete = false } } +end diff --git a/lua/laravel/null_ls/completion/view.lua b/lua/laravel/null_ls/completion/view.lua new file mode 100644 index 0000000..ded114c --- /dev/null +++ b/lua/laravel/null_ls/completion/view.lua @@ -0,0 +1,22 @@ +return function(done) + local scan = require "plenary.scandir" + local api = require "laravel.api" + + local candidates = {} + + local res = api.sync("artisan", { "tinker", "--execute", "echo resource_path('views')" }) + local view_path = res.stdout[1] + local rule = string.format("^%s/(.*).blade.php$", view_path:gsub("-", "%%-")) + local finds = scan.scan_dir(view_path, { hidden = false, depth = 4 }) + for _, value in pairs(finds) do + local name = value:match(rule):gsub("/", ".") + table.insert(candidates, { + label = string.format("%s (view)", name), + insertText = string.format("'%s'", name), + kind = vim.lsp.protocol.CompletionItemKind["Value"], + documentation = value, + }) + end + + done { { items = candidates, isIncomplete = false } } +end diff --git a/lua/laravel/null_ls/init.lua b/lua/laravel/null_ls/init.lua new file mode 100644 index 0000000..808a4b1 --- /dev/null +++ b/lua/laravel/null_ls/init.lua @@ -0,0 +1,7 @@ +local M = {} + +function M.setup() + require("laravel.null_ls.completion").setup() +end + +return M diff --git a/lua/laravel/null_ls/views.lua b/lua/laravel/null_ls/views.lua deleted file mode 100644 index c3ea373..0000000 --- a/lua/laravel/null_ls/views.lua +++ /dev/null @@ -1,62 +0,0 @@ -local M = {} - -function M.setup() - local ok, null_ls = pcall(require, "null-ls") - if not ok then - error "Completition view requires null ls" - end - - local scan = require "plenary.scandir" - local ts_utils = require "nvim-treesitter.ts_utils" - local api = require "laravel.api" - - null_ls.deregister "Laravel Views" - - local laravel_view = { - name = "Laravel Views", - method = null_ls.methods.COMPLETION, - filetypes = { "php" }, - generator = { - fn = function(params, done) - local node = ts_utils.get_node_at_cursor() - node = node:parent() - while node ~= nil and node.type(node) ~= "function_call_expression" do - node = node:parent() - end - if node == nil then - return - end - if node:child_count() > 0 then - local node_text = vim.treesitter.get_node_text(node:child(0), params.bufnr, {}) - - if node_text ~= "view" then - return - end - end - - local candidates = {} - - local res = api.sync("artisan", { "tinker", "--execute", "echo resource_path('views')" }) - local view_path = res.stdout[1] - local rule = string.format("^%s/(.*).blade.php$", view_path:gsub("-", "%%-")) - local finds = scan.scan_dir(view_path, { hidden = false, depth = 4 }) - for _, value in pairs(finds) do - local name = value:match(rule):gsub("/", ".") - table.insert(candidates, { - label = name, - insertText = string.format("'%s'", name), - kind = vim.lsp.protocol.CompletionItemKind["Value"], - documentation = value, - }) - end - - done { { items = candidates, isIncomplete = false } } - end, - async = true, - }, - } - - null_ls.register(laravel_view) -end - -return M From eb1d184795dbe5c254da2d74392ee60cb0e0de69 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 16:08:11 +0100 Subject: [PATCH 27/55] feat: add checkhealth --- lua/laravel/health.lua | 71 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 lua/laravel/health.lua diff --git a/lua/laravel/health.lua b/lua/laravel/health.lua new file mode 100644 index 0000000..3284183 --- /dev/null +++ b/lua/laravel/health.lua @@ -0,0 +1,71 @@ +local environment = require "laravel.environment" +local api = require "laravel.api" +local M = {} + +M.check = function() + vim.health.report_start "Laravel" + + if vim.fn.executable "fd" == 1 then + vim.health.report_ok "fd installed" + else + vim.health.report_warn( + "fd is missing, is required for opening the migration", + { "Installed from your package manager or source https://github.com/sharkdp/fd" } + ) + end + + if vim.tbl_isempty(environment.environment) then + vim.health.report_error( + "Environment not configure for this directory, no more checks", + { "Check project is laravel, current directory `:pwd` is the root of laravel project" } + ) + return + end + vim.health.report_ok "Environment setup complete" + + vim.health.report_start "Environment" + + if vim.tbl_isempty(environment.environment.executables) then + vim.health.report_error "No executables found in the environment, check the environment config" + return + end + + for name, command in pairs(environment.environment.executables) do + if vim.fn.executable(command[1]) == 1 then + vim.health.report_ok(string.format("%s: executable %s exists", name, command[1])) + else + vim.health.report_error(string.format("%s: executable %s does not exists", name, command[1])) + end + end + + if not environment.get_executable "composer" then + vim.health.report_error "Composer executable not found can't check dependencies" + end + + local composer_dependencies = { + { + name = "doctrine/dbal", + messages = "This is required for model:show, related model picker and autocomplete", + }, + { + name = "laravel/tinker", + messages = "This is required for tinker repl", + }, + } + + vim.health.report_start "Composer dependencies" + + for _, dependency in pairs(composer_dependencies) do + local res = api.sync("composer", { "info", dependency.name }) + if res.exit_code == 0 then + vim.health.report_ok(string.format("Composer dependency `%s` is installed", dependency.name)) + else + vim.health.report_warn( + string.format("Composer dependency `%s` is not installed", dependency.name), + { dependency.messages } + ) + end + end +end + +return M From fa2165c9b29cdd57a75973c8efb2837ee8c55854 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 16:24:35 +0100 Subject: [PATCH 28/55] feat: check doctrine dbal before running --- lua/laravel/telescope/pickers/related.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lua/laravel/telescope/pickers/related.lua b/lua/laravel/telescope/pickers/related.lua index baaddca..384a838 100644 --- a/lua/laravel/telescope/pickers/related.lua +++ b/lua/laravel/telescope/pickers/related.lua @@ -16,6 +16,11 @@ return function(opts) return false end + local res = api.sync("composer", { "info", "doctrine/dbal" }) + if res.exit_code ~= 0 then + error "doctrine dbal not install this picker depends on it" + end + local get_model_class_name = function() local query = vim.treesitter.query.parse( lang, @@ -38,7 +43,7 @@ return function(opts) local class = get_model_class_name() if class ~= "" then local result = api.sync("artisan", { "model:show", class, "--json" }) - if result.exit_code == 1 then + if result.exit_code ~= 0 then error( string.format("'php artisan model:show %s --json' failed %s", class, vim.inspect(result.stderr)), vim.log.levels.ERROR From 7cb289b8ad1e87c8b81179f9bc0a21c2b8dfdac9 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 19:03:24 +0100 Subject: [PATCH 29/55] fix: update the way of checking route list --- lua/laravel/routes/init.lua | 2 +- lua/laravel/telescope/pickers/routes.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/laravel/routes/init.lua b/lua/laravel/routes/init.lua index 29569b8..e586c44 100644 --- a/lua/laravel/routes/init.lua +++ b/lua/laravel/routes/init.lua @@ -8,7 +8,7 @@ M.list = {} function M.load() M.list = {} local result = api.sync("artisan", { "route:list", "--json" }) - if result.exit_code == 1 then + if result.exit_code ~= 0 then error( string.format( "Failed to get routes check your code %s %s", diff --git a/lua/laravel/telescope/pickers/routes.lua b/lua/laravel/telescope/pickers/routes.lua index d1b84fc..671bb88 100644 --- a/lua/laravel/telescope/pickers/routes.lua +++ b/lua/laravel/telescope/pickers/routes.lua @@ -12,7 +12,7 @@ local go = require "laravel.routes.go" return function(opts) opts = opts or {} - if #routes.list == 0 then + if vim.tbl_isempty(routes.list) then if not routes.load() then return end From eb17a8bf4b27dbcbe3e8bcf1da0b33d1e2a4bb30 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 19:06:02 +0100 Subject: [PATCH 30/55] fix: load the route list if empty on completion --- lua/laravel/null_ls/completion/route.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lua/laravel/null_ls/completion/route.lua b/lua/laravel/null_ls/completion/route.lua index d94891b..bc70353 100644 --- a/lua/laravel/null_ls/completion/route.lua +++ b/lua/laravel/null_ls/completion/route.lua @@ -3,6 +3,12 @@ return function(done) local candidates = {} + if vim.tbl_isempty(routes.list) then + if not routes.load() then + return + end + end + for _, route in pairs(routes.list) do if route.name then table.insert(candidates, { From b5d919a4f31c3ed00138c6e0f13efc9d1678f67f Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 19:11:00 +0100 Subject: [PATCH 31/55] fix: silent fail if load does not work --- lua/laravel/null_ls/completion/route.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/laravel/null_ls/completion/route.lua b/lua/laravel/null_ls/completion/route.lua index bc70353..31bd25b 100644 --- a/lua/laravel/null_ls/completion/route.lua +++ b/lua/laravel/null_ls/completion/route.lua @@ -4,7 +4,8 @@ return function(done) local candidates = {} if vim.tbl_isempty(routes.list) then - if not routes.load() then + local ok, res = pcall(routes.load) + if not ok or not res then return end end From 68345112fa0063760d6e84354dcfef3a67e53769 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 21:00:42 +0100 Subject: [PATCH 32/55] fix: how routes are check in completion and update how verions are retrieve --- lua/laravel/null_ls/completion/route.lua | 8 +++++ lua/laravel/status.lua | 46 ++++++++++-------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lua/laravel/null_ls/completion/route.lua b/lua/laravel/null_ls/completion/route.lua index 31bd25b..46e4b34 100644 --- a/lua/laravel/null_ls/completion/route.lua +++ b/lua/laravel/null_ls/completion/route.lua @@ -1,14 +1,22 @@ +local failed_last_time = false + return function(done) local routes = require "laravel.routes" local candidates = {} if vim.tbl_isempty(routes.list) then + if failed_last_time then + return + end + local ok, res = pcall(routes.load) if not ok or not res then + failed_last_time = true return end end + failed_last_time = false for _, route in pairs(routes.list) do if route.name then diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua index ad5ff1c..a1250b8 100644 --- a/lua/laravel/status.lua +++ b/lua/laravel/status.lua @@ -1,35 +1,38 @@ local environment = require "laravel.environment" local api = require "laravel.api" +local last_check = nil + local M = {} -local counters = { - php = 0, - laravel = 0, -} +local frequency = 120 local values = { php = nil, laravel = nil, } +local function get_values() + if last_check and (last_check + frequency > os.time()) then + return + end + if environment.get_executable "php" then + local res = api.sync("php", { "-v" }) + values.php = res.stdout[1]:match "PHP ([%d%.]+)" + end + if environment.get_executable "artisan" then + local res = api.sync("artisan", { "--version" }) + values.laravel = res.stdout[1]:match "Laravel Framework ([%d%.]+)" + end + last_check = os.time() +end + local properties = { php = { has = function() return environment.get_executable "php" ~= nil end, get = function() - counters.php = counters.php + 1 - if values.php and counters.php < 60 then - return values.php - end - counters.php = 0 - if not environment.get_executable "php" then - return nil - end - local res = api.sync("php", { "-v" }) - values.php = res.stdout[1]:match "PHP ([%d%.]+)" - return values.php end, }, @@ -38,24 +41,13 @@ local properties = { return environment.get_executable "artisan" ~= nil end, get = function() - counters.laravel = counters.laravel + 1 - if values.laravel and counters.laravel < 60 then - return values.laravel - end - counters.laravel = 0 - if not environment.get_executable "artisan" then - return nil - end - - local res = api.sync("artisan", { "--version" }) - - values.laravel = res.stdout[1]:match "Laravel Framework ([%d%.]+)" return values.laravel end, }, } function M.get(property) + get_values() return properties[property].get() end From a1fc6b30bd52de4a6e5563bcc8d93edd2988bcb6 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 21:30:38 +0100 Subject: [PATCH 33/55] feature: support quotes for completion --- lua/laravel/null_ls/completion/init.lua | 41 +++++++++++++++++------- lua/laravel/null_ls/completion/route.lua | 8 +++-- lua/laravel/null_ls/completion/view.lua | 9 ++++-- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/lua/laravel/null_ls/completion/init.lua b/lua/laravel/null_ls/completion/init.lua index 84aed50..4123a76 100644 --- a/lua/laravel/null_ls/completion/init.lua +++ b/lua/laravel/null_ls/completion/init.lua @@ -5,6 +5,15 @@ local completions = { route = require "laravel.null_ls.completion.route", } +local function get_function_node(param_node) + local node = param_node + while node ~= nil and node.type(node) ~= "function_call_expression" do + node = node:parent() + end + + return node +end + function M.setup() local ok, null_ls = pcall(require, "null-ls") if not ok then @@ -21,21 +30,29 @@ function M.setup() fn = function(params, done) local ts_utils = require "nvim-treesitter.ts_utils" local node = ts_utils.get_node_at_cursor() - node = node:parent() - while node ~= nil and node.type(node) ~= "function_call_expression" do - node = node:parent() - end - if node == nil then + if node.type(node) == "member_call_expression" then + -- print("memeber property") + -- to add support for model fields return - end - if node:child_count() > 0 then - local node_text = vim.treesitter.get_node_text(node:child(0), params.bufnr, {}) - - local completion = completions[node_text] - if not completion then + else + local func_node = get_function_node(node) + if not func_node then return end - completion(done) + + if func_node:child_count() > 0 then + local node_text = vim.treesitter.get_node_text(func_node:child(0), params.bufnr, {}) + + -- encapsed_string initial node it means is in double quotes + -- string initial node it means single quotes + -- arguments does not have quotes + local have_quotes = node.type(node) == "encapsed_string" or node.type(node) == "string" + local completion = completions[node_text] + if not completion then + return + end + completion(done, not have_quotes) + end end end, async = true, diff --git a/lua/laravel/null_ls/completion/route.lua b/lua/laravel/null_ls/completion/route.lua index 46e4b34..bef3b4a 100644 --- a/lua/laravel/null_ls/completion/route.lua +++ b/lua/laravel/null_ls/completion/route.lua @@ -1,6 +1,6 @@ local failed_last_time = false -return function(done) +return function(done, should_quote) local routes = require "laravel.routes" local candidates = {} @@ -20,9 +20,13 @@ return function(done) for _, route in pairs(routes.list) do if route.name then + local insert = route.name + if should_quote then + insert = string.format("'%s'", route.name) + end table.insert(candidates, { label = string.format("%s (route)", route.name), - insertText = string.format("'%s'", route.name), + insertText = insert, kind = vim.lsp.protocol.CompletionItemKind["Value"], documentation = string.format("[%s] %s", route.name, route.uri), }) diff --git a/lua/laravel/null_ls/completion/view.lua b/lua/laravel/null_ls/completion/view.lua index ded114c..b0e7549 100644 --- a/lua/laravel/null_ls/completion/view.lua +++ b/lua/laravel/null_ls/completion/view.lua @@ -1,4 +1,4 @@ -return function(done) +return function(done, should_quote) local scan = require "plenary.scandir" local api = require "laravel.api" @@ -10,9 +10,14 @@ return function(done) local finds = scan.scan_dir(view_path, { hidden = false, depth = 4 }) for _, value in pairs(finds) do local name = value:match(rule):gsub("/", ".") + + local insert = name + if should_quote then + insert = string.format("'%s'", name) + end table.insert(candidates, { label = string.format("%s (view)", name), - insertText = string.format("'%s'", name), + insertText = insert, kind = vim.lsp.protocol.CompletionItemKind["Value"], documentation = value, }) From d0531fee489a5cb6aef86bb2c650f974cdb3d041 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 18 Nov 2023 23:31:21 +0100 Subject: [PATCH 34/55] feat: support model properties completion --- lua/laravel/null_ls/completion/init.lua | 65 ++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/lua/laravel/null_ls/completion/init.lua b/lua/laravel/null_ls/completion/init.lua index 4123a76..c4d9f3a 100644 --- a/lua/laravel/null_ls/completion/init.lua +++ b/lua/laravel/null_ls/completion/init.lua @@ -28,11 +28,72 @@ function M.setup() filetypes = { "php" }, generator = { fn = function(params, done) - local ts_utils = require "nvim-treesitter.ts_utils" - local node = ts_utils.get_node_at_cursor() + local api = require "laravel.api" + + local node = vim.treesitter.get_node() + if not node then + return + end if node.type(node) == "member_call_expression" then + local object_node = node:child(0) + local row, col = vim.treesitter.get_node_range(object_node) + local param = vim.lsp.util.make_position_params() + param.position.line = row + param.position.character = col + + vim.lsp.buf_request(0, "textDocument/typeDefinition", param, function(error, result) + if error then + return + end + local bufnr = vim.uri_to_bufnr(result.uri) + + vim.fn.bufload(bufnr) + + local query = vim.treesitter.query.parse( + "php", + [[ (namespace_definition name: (namespace_name) @namespace) + (class_declaration name: (name) @class) ]] + ) + local tree = vim.treesitter.get_parser(bufnr):parse()[1]:root() + local class = "" + for id, in_node, _ in query:iter_captures(tree, bufnr, tree:start(), tree:end_()) do + if query.captures[id] == "class" then + class = class .. "\\" .. vim.treesitter.get_node_text(in_node, bufnr) + elseif query.captures[id] == "namespace" then + class = vim.treesitter.get_node_text(in_node, bufnr) .. class + end + end + if class == "" then + return + end + + local related_res = api.sync("artisan", { "model:show", class, "--json" }) + if related_res.exit_code ~= 0 then + return + end + + local model_info = vim.fn.json_decode(related_res.stdout[1]) + if not model_info then + return + end + + local candidates = {} + for _, attr in pairs(model_info.attributes) do + table.insert(candidates, { + label = attr.name, + insertText = attr.name, + kind = vim.lsp.protocol.CompletionItemKind["Property"], + documentation = string.format("Database property %s. Type: %s", attr.name, attr.type), + }) + end + done { { items = candidates, isIncomplete = false } } + end) + + -- print(vim.inspect(param)) + -- local object = vim.treesitter.get_node_text(node:child(0), params.bufnr, {}) -- print("memeber property") -- to add support for model fields + -- get the node of the property return else local func_node = get_function_node(node) From e3096fe2374f3bb340fcea19ffd2945db79255a6 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 19 Nov 2023 19:29:20 +0100 Subject: [PATCH 35/55] update todo --- TODO.md | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/TODO.md b/TODO.md index 8e5c950..f8b73a5 100644 --- a/TODO.md +++ b/TODO.md @@ -1,16 +1,83 @@ # Ideas -Tengo los runners. +## To implement +```lua +- [X] implement api +- [X] implement ui +- [X] implements a command history +- [X] remove bind telescope +- [X] Fix error when route list breaks it slows the heck out of the editor +- [X] order of arguments running command from telescope +- [X] completion for none-ls view('<"">') get all *.balde.php files. +- [X] implement default args | implement as options on the command options +- [X] escape on required args cancel it +- [X] when calling make commands without arguments run it in a popup +- [X] fix bug with `fd` switch from `sync` to proper use +- [X] How to implement checkhealth +- [X] completion route +- [X] detect library use by model show (command -precheck- on picker) +- [X] completion for routes when broken not loading to many making slow the editor +- [X] change the way of versions are being poll +- [X] maybe command for make only where only list commands of make principal laravel ones and open in a popup or how to configure from the command pallete +- [X] completion detect or not quotes +- [X] completion for model fields +- [ ] clean completion for models +- [ ] tinker interface +- [ ] implement watch +- [ ] re-write the readme and translate (not forget fd as dependency) the counter does not work as I expect +- [ ] virtual text info ??? -como se van a ver -Split -Popup +Somethign like thinkerwell +read the buffer and send to tinker ?? -watch -buffer -term +```lua +local res = api.sync("artisan", {"tinker", "--execute", "$a = view('welcome'); dump($a)"}) +``` +since php does not car of breake lines I could do something like this +read the buffer -como van a devolver resultado -sync -async +If I want colors needs to use jobstart I think +```lua +vim.fn.jobstart({ "php", "artisan", "tinker", "--execute", vim.fn.join(lines, "") }, { + stdeout_buffered = true, + on_stdout = function(_, data) + vim.fn.chansend(chan, data) + end, + pty = true, +}) +``` + +To have autocomplete need to have the file in the project folder. +or start the server for the specific buffer + +`tinker.php` could be created on the root when starting the mode + +delete it when it's done, or persist it. + +create temporary buffer and use vim.lsp.buf_attach_client() to attach it to the current php actor client + +should start the buffer with the first line ` attach it to current lsp server for php +TinkerOutput -> render the output per save + +Autocommand for TinkerEditor to save and run the hole buffer content into the api sync command. + +Action Start Tinker +Open side for output. +Create buffer or look for buffer of tinker +On Close Leave tinkerEditor buffer but close the output + + + +Completion of model fields +- check that we are trying to complete property for variable. +- check that variable is of model (lsp) +- get model name +if for the variable use type definition can get the document for the variable. +can I get the name of it ? +should be in the location +What can I get from location ?? From e11ca2596fa4fb257719020b25e98ecbd1135ddd Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sun, 19 Nov 2023 21:44:50 +0100 Subject: [PATCH 36/55] feat: expose generate command, remove model completion --- lua/laravel/api.lua | 6 +- lua/laravel/null_ls/completion/init.lua | 90 ++++--------------------- 2 files changed, 16 insertions(+), 80 deletions(-) diff --git a/lua/laravel/api.lua b/lua/laravel/api.lua index baad0cb..872fa94 100644 --- a/lua/laravel/api.lua +++ b/lua/laravel/api.lua @@ -3,7 +3,7 @@ local environment = require "laravel.environment" local M = {} -local function generate_command(name, args) +function M.generate_command(name, args) local executable = environment.get_executable(name) if not executable then error(string.format("Executable %s not found", name), vim.log.levels.ERROR) @@ -13,7 +13,7 @@ local function generate_command(name, args) end function M.sync(program, args) - local cmd = generate_command(program, args) + local cmd = M.generate_command(program, args) local command = table.remove(cmd, 1) local stderr = {} @@ -33,7 +33,7 @@ function M.sync(program, args) end function M.async(program, args, callback) - local cmd = generate_command(program, args) + local cmd = M.generate_command(program, args) local command = table.remove(cmd, 1) Job:new({ diff --git a/lua/laravel/null_ls/completion/init.lua b/lua/laravel/null_ls/completion/init.lua index c4d9f3a..a674337 100644 --- a/lua/laravel/null_ls/completion/init.lua +++ b/lua/laravel/null_ls/completion/init.lua @@ -28,92 +28,28 @@ function M.setup() filetypes = { "php" }, generator = { fn = function(params, done) - local api = require "laravel.api" - local node = vim.treesitter.get_node() if not node then return end - if node.type(node) == "member_call_expression" then - local object_node = node:child(0) - local row, col = vim.treesitter.get_node_range(object_node) - local param = vim.lsp.util.make_position_params() - param.position.line = row - param.position.character = col - - vim.lsp.buf_request(0, "textDocument/typeDefinition", param, function(error, result) - if error then - return - end - local bufnr = vim.uri_to_bufnr(result.uri) - - vim.fn.bufload(bufnr) - - local query = vim.treesitter.query.parse( - "php", - [[ (namespace_definition name: (namespace_name) @namespace) - (class_declaration name: (name) @class) ]] - ) - local tree = vim.treesitter.get_parser(bufnr):parse()[1]:root() - local class = "" - for id, in_node, _ in query:iter_captures(tree, bufnr, tree:start(), tree:end_()) do - if query.captures[id] == "class" then - class = class .. "\\" .. vim.treesitter.get_node_text(in_node, bufnr) - elseif query.captures[id] == "namespace" then - class = vim.treesitter.get_node_text(in_node, bufnr) .. class - end - end - if class == "" then - return - end - - local related_res = api.sync("artisan", { "model:show", class, "--json" }) - if related_res.exit_code ~= 0 then - return - end - - local model_info = vim.fn.json_decode(related_res.stdout[1]) - if not model_info then - return - end - local candidates = {} - for _, attr in pairs(model_info.attributes) do - table.insert(candidates, { - label = attr.name, - insertText = attr.name, - kind = vim.lsp.protocol.CompletionItemKind["Property"], - documentation = string.format("Database property %s. Type: %s", attr.name, attr.type), - }) - end - done { { items = candidates, isIncomplete = false } } - end) - - -- print(vim.inspect(param)) - -- local object = vim.treesitter.get_node_text(node:child(0), params.bufnr, {}) - -- print("memeber property") - -- to add support for model fields - -- get the node of the property + local func_node = get_function_node(node) + if not func_node then return - else - local func_node = get_function_node(node) - if not func_node then - return - end + end - if func_node:child_count() > 0 then - local node_text = vim.treesitter.get_node_text(func_node:child(0), params.bufnr, {}) + if func_node:child_count() > 0 then + local node_text = vim.treesitter.get_node_text(func_node:child(0), params.bufnr, {}) - -- encapsed_string initial node it means is in double quotes - -- string initial node it means single quotes - -- arguments does not have quotes - local have_quotes = node.type(node) == "encapsed_string" or node.type(node) == "string" - local completion = completions[node_text] - if not completion then - return - end - completion(done, not have_quotes) + -- encapsed_string initial node it means is in double quotes + -- string initial node it means single quotes + -- arguments does not have quotes + local have_quotes = node.type(node) == "encapsed_string" or node.type(node) == "string" + local completion = completions[node_text] + if not completion then + return end + completion(done, not have_quotes) end end, async = true, From 3959cbfb21a467c1abee109260c76001907242a1 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Fri, 24 Nov 2023 22:39:00 +0100 Subject: [PATCH 37/55] feat: show action name in telescope help --- TODO.md | 9 ++-- lua/laravel/telescope/actions.lua | 53 ++++++++++++++++++++++ lua/laravel/telescope/pickers/commands.lua | 24 ++-------- lua/laravel/telescope/pickers/history.lua | 10 +--- lua/laravel/telescope/pickers/related.lua | 13 +----- lua/laravel/telescope/pickers/routes.lua | 12 +---- 6 files changed, 68 insertions(+), 53 deletions(-) create mode 100644 lua/laravel/telescope/actions.lua diff --git a/TODO.md b/TODO.md index f8b73a5..4db2933 100644 --- a/TODO.md +++ b/TODO.md @@ -21,11 +21,14 @@ - [X] maybe command for make only where only list commands of make principal laravel ones and open in a popup or how to configure from the command pallete - [X] completion detect or not quotes - [X] completion for model fields -- [ ] clean completion for models -- [ ] tinker interface +- [X] remove completion for models +- [ ] replace anonymous function from mapping with dedicated functions to have descriptions +- [ ] recipes for ide-helper models and eloquent +- [ ] using the get_type in completion is dangerus. better to replace it with ide-helper - [ ] implement watch -- [ ] re-write the readme and translate (not forget fd as dependency) the counter does not work as I expect +- [ ] tinker interface - [ ] virtual text info ??? +- [ ] re-write the readme and translate (not forget fd as dependency) the counter does not work as I expect Somethign like thinkerwell diff --git a/lua/laravel/telescope/actions.lua b/lua/laravel/telescope/actions.lua new file mode 100644 index 0000000..72711a3 --- /dev/null +++ b/lua/laravel/telescope/actions.lua @@ -0,0 +1,53 @@ +local actions = require "telescope.actions" +local action_state = require "telescope.actions.state" +local ui_run = require "laravel.telescope.ui_run" +local go = require "laravel.routes.go" +local run = require "laravel.run" +local lsp = require "laravel._lsp" + +local M = {} + +function M.run(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + local command = entry.value + + vim.schedule(function() + ui_run(command) + end) +end + +function M.run_asking_options(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + local command = entry.value + + vim.schedule(function() + ui_run(command, true) + end) +end + +function M.open_route(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + vim.schedule(function() + go(entry.value) + end) +end + +function M.re_run_command(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + run(entry.value.name, entry.value.args, entry.value.opts) +end + +function M.open_relation(prompt_bufnr) + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + vim.schedule(function() + local action = vim.fn.split(entry.value.class, "@") + lsp.go_to(action[1], action[2]) + end) +end + +return M diff --git a/lua/laravel/telescope/pickers/commands.lua b/lua/laravel/telescope/pickers/commands.lua index 2af606a..3f112ed 100644 --- a/lua/laravel/telescope/pickers/commands.lua +++ b/lua/laravel/telescope/pickers/commands.lua @@ -1,12 +1,10 @@ -local actions = require "telescope.actions" -local action_state = require "telescope.actions.state" local conf = require("telescope.config").values local finders = require "telescope.finders" local pickers = require "telescope.pickers" local previewers = require "telescope.previewers" local preview = require "laravel.telescope.preview" local commands = require "laravel.commands" -local ui_run = require "laravel.telescope.ui_run" +local actions = require "laravel.telescope.actions" return function(opts) opts = opts or {} @@ -46,24 +44,8 @@ return function(opts) }, 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 - - vim.schedule(function() - ui_run(command) - end) - end) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - local command = entry.value - - vim.schedule(function() - ui_run(command, true) - end) - end) + map("i", "", actions.run) + map("i", "", actions.run_asking_options) return true end, diff --git a/lua/laravel/telescope/pickers/history.lua b/lua/laravel/telescope/pickers/history.lua index 9d91f0d..5b65967 100644 --- a/lua/laravel/telescope/pickers/history.lua +++ b/lua/laravel/telescope/pickers/history.lua @@ -1,10 +1,8 @@ -local actions = require "telescope.actions" -local action_state = require "telescope.actions.state" local conf = require("telescope.config").values local finders = require "telescope.finders" local history = require "laravel.history" local pickers = require "telescope.pickers" -local run = require "laravel.run" +local actions = require "laravel.telescope.actions" return function(opts) opts = opts or {} @@ -27,11 +25,7 @@ return function(opts) sorter = conf.generic_sorter(opts or {}), }, attach_mappings = function(_, map) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - run(entry.value.name, entry.value.args, entry.value.opts) - end) + map("i", "", actions.re_run_command) return true end, diff --git a/lua/laravel/telescope/pickers/related.lua b/lua/laravel/telescope/pickers/related.lua index 384a838..f113591 100644 --- a/lua/laravel/telescope/pickers/related.lua +++ b/lua/laravel/telescope/pickers/related.lua @@ -1,11 +1,9 @@ local pickers = require "telescope.pickers" -local lsp = require "laravel._lsp" local make_entry = require "laravel.telescope.make_entry" local finders = require "telescope.finders" local conf = require("telescope.config").values -local actions = require "telescope.actions" -local action_state = require "telescope.actions.state" local api = require "laravel.api" +local actions = require "laravel.telescope.actions" return function(opts) opts = opts or {} @@ -115,14 +113,7 @@ return function(opts) sorter = conf.generic_sorter(opts or {}), }, attach_mappings = function(_, map) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - vim.schedule(function() - local action = vim.fn.split(entry.value.class, "@") - lsp.go_to(action[1], action[2]) - end) - end) + map("i", "", actions.open_relation) return true end, diff --git a/lua/laravel/telescope/pickers/routes.lua b/lua/laravel/telescope/pickers/routes.lua index 671bb88..e7ac901 100644 --- a/lua/laravel/telescope/pickers/routes.lua +++ b/lua/laravel/telescope/pickers/routes.lua @@ -1,5 +1,3 @@ -local actions = require "telescope.actions" -local action_state = require "telescope.actions.state" local conf = require("telescope.config").values local finders = require "telescope.finders" local pickers = require "telescope.pickers" @@ -7,7 +5,7 @@ local previewers = require "telescope.previewers" local preview = require "laravel.telescope.preview" local make_entry = require "laravel.telescope.make_entry" local routes = require "laravel.routes" -local go = require "laravel.routes.go" +local actions = require "laravel.telescope.actions" return function(opts) opts = opts or {} @@ -46,13 +44,7 @@ return function(opts) sorter = conf.generic_sorter(opts or {}), }, attach_mappings = function(_, map) - map("i", "", function(prompt_bufnr) - actions.close(prompt_bufnr) - local entry = action_state.get_selected_entry() - vim.schedule(function() - go(entry.value) - end) - end) + map("i", "", actions.open_route) return true end, From ccce12e5401e26e8047b4d9017462bae514ada75 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Sat, 25 Nov 2023 10:21:59 +0100 Subject: [PATCH 38/55] feat: add doc file --- doc/laravel.txt | 9 +++++++++ doc/tags | 3 +++ 2 files changed, 12 insertions(+) create mode 100644 doc/laravel.txt create mode 100644 doc/tags diff --git a/doc/laravel.txt b/doc/laravel.txt new file mode 100644 index 0000000..c0a34d8 --- /dev/null +++ b/doc/laravel.txt @@ -0,0 +1,9 @@ +*laravel.txt* Plugin to work with Laravel Framework + +Author: Ariel D'Alessandro +Repo: https://github.com/adalessa/laravel.nvim +License: Same terms as Vim itself (see |license|) + +Usage *laravel* *:Artisan* + + vim:tw=78:et:ft=help:norl: diff --git a/doc/tags b/doc/tags new file mode 100644 index 0000000..c9714c2 --- /dev/null +++ b/doc/tags @@ -0,0 +1,3 @@ +:Artisan laravel.txt /*:Artisan* +laravel laravel.txt /*laravel* +laravel.txt laravel.txt /*laravel.txt* From 7091842ca605a2ba2733a1c9d2dfc1a82e12811a Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Fri, 15 Dec 2023 20:38:55 +0100 Subject: [PATCH 39/55] feat: improve healt, add support for make:view --- lua/laravel/api.lua | 8 ++++++-- lua/laravel/config/resources.lua | 12 ++++++++---- lua/laravel/health.lua | 5 ++--- lua/laravel/resources/open.lua | 8 +------- lua/laravel/telescope/pickers/related.lua | 3 +-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lua/laravel/api.lua b/lua/laravel/api.lua index 872fa94..76666b6 100644 --- a/lua/laravel/api.lua +++ b/lua/laravel/api.lua @@ -14,9 +14,9 @@ end function M.sync(program, args) local cmd = M.generate_command(program, args) - local command = table.remove(cmd, 1) local stderr = {} + local stdout, ret = Job:new({ command = command, args = cmd, @@ -34,8 +34,8 @@ end function M.async(program, args, callback) local cmd = M.generate_command(program, args) - local command = table.remove(cmd, 1) + Job:new({ command = command, args = cmd, @@ -43,4 +43,8 @@ function M.async(program, args, callback) }):start() end +function M.is_composer_package_install(package) + return M.sync("composer", { "info", package }).exit_code == 0 +end + return M diff --git a/lua/laravel/config/resources.lua b/lua/laravel/config/resources.lua index 47c91e1..549a09b 100644 --- a/lua/laravel/config/resources.lua +++ b/lua/laravel/config/resources.lua @@ -1,3 +1,6 @@ +-- each element represent a command that after execution should open a file +-- if the return is a string is use as directory to search file. +-- if the return is a function will call and expects the result to be an string return { ["make:cast"] = "app/Casts", ["make:channel"] = "app/Broadcasting", @@ -7,16 +10,14 @@ return { ["make:event"] = "app/Events", ["make:exception"] = "app/Exceptions", ["make:factory"] = function(name) - return string.format("database/factories/%sFactory.php", name), nil + return string.format("database/factories/%sFactory.php", name) end, ["make:job"] = "app/Jobs", ["make:listener"] = "app/Listeners", ["make:mail"] = "app/Mail", ["make:middleware"] = "app/Http/Middleware", ["make:migration"] = function(name) - local files = vim.fn.systemlist(string.format("fd %s.php", name)) - - return files[1], nil + return vim.fn.systemlist(string.format("fd %s.php", name))[1] end, ["make:model"] = "app/Models", ["make:notification"] = "app/Notifications", @@ -29,4 +30,7 @@ return { ["make:scope"] = "app/Models/Scopes", ["make:seeder"] = "database/seeders", ["make:test"] = "tests/Feature", + ["make:view"] = function(name) + return "resources/views/" .. name:gsub("%.", "/") .. ".blade.php" + end, } diff --git a/lua/laravel/health.lua b/lua/laravel/health.lua index 3284183..923a752 100644 --- a/lua/laravel/health.lua +++ b/lua/laravel/health.lua @@ -45,7 +45,7 @@ M.check = function() local composer_dependencies = { { name = "doctrine/dbal", - messages = "This is required for model:show, related model picker and autocomplete", + messages = "This is required for model:show, related model picker", }, { name = "laravel/tinker", @@ -56,8 +56,7 @@ M.check = function() vim.health.report_start "Composer dependencies" for _, dependency in pairs(composer_dependencies) do - local res = api.sync("composer", { "info", dependency.name }) - if res.exit_code == 0 then + if api.is_composer_package_install(dependency.name) then vim.health.report_ok(string.format("Composer dependency `%s` is installed", dependency.name)) else vim.health.report_warn( diff --git a/lua/laravel/resources/open.lua b/lua/laravel/resources/open.lua index 62d8cfa..6c4042f 100644 --- a/lua/laravel/resources/open.lua +++ b/lua/laravel/resources/open.lua @@ -5,13 +5,7 @@ return function(resource, name) local directory = config.options.resources[resource] local filename = "" if type(directory) == "function" then - local err - filename, err = directory(name) - if err ~= nil then - notify("Resource.Open", { level = "ERROR", msg = "Error getting the name" }) - return - end - filename = filename[1] + filename = directory(name) elseif type(directory) == "string" then filename = string.format("%s/%s.php", directory, name) end diff --git a/lua/laravel/telescope/pickers/related.lua b/lua/laravel/telescope/pickers/related.lua index f113591..83c709b 100644 --- a/lua/laravel/telescope/pickers/related.lua +++ b/lua/laravel/telescope/pickers/related.lua @@ -14,8 +14,7 @@ return function(opts) return false end - local res = api.sync("composer", { "info", "doctrine/dbal" }) - if res.exit_code ~= 0 then + if not api.is_composer_package_install "doctrine/dbal" then error "doctrine dbal not install this picker depends on it" end From d4a5eaa48e3dbe6ad0e822aa3b3831a182ef71fb Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 26 Dec 2023 15:38:15 +0100 Subject: [PATCH 40/55] feat: introduce laravel recipes --- lua/laravel/recipes/ide-helper.lua | 35 ++++++++++++++++++++++ lua/laravel/recipes/init.lua | 18 +++++++++++ lua/laravel/user_commands/laravel/init.lua | 32 +++++++++----------- 3 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 lua/laravel/recipes/ide-helper.lua create mode 100644 lua/laravel/recipes/init.lua diff --git a/lua/laravel/recipes/ide-helper.lua b/lua/laravel/recipes/ide-helper.lua new file mode 100644 index 0000000..cecec7e --- /dev/null +++ b/lua/laravel/recipes/ide-helper.lua @@ -0,0 +1,35 @@ +local api = require "laravel.api" + +local M = {} + +local function writeModels() + api.async("artisan", { "ide-helper:models", "-n", "-W", "-M" }, function(_, exit_code) + local level = vim.log.levels.INFO + if exit_code ~= 0 then + level = vim.log.levels.ERROR + end + vim.notify("Ide Helper Models Complete", level) + end) +end + +local function installIdeHelperAndWrite() + api.async("composer", { "require", "--dev", "barryvdh/laravel-ide-helper" }, function(_, exit_code) + if exit_code ~= 0 then + error("Cant install ide-helper", vim.log.levels.ERROR) + end + require("laravel.commands").list = {} + + writeModels() + end) +end + +function M.run() + if not api.is_composer_package_install "barryvdh/laravel-ide-helper" then + writeModels() + return + end + + installIdeHelperAndWrite() +end + +return M diff --git a/lua/laravel/recipes/init.lua b/lua/laravel/recipes/init.lua new file mode 100644 index 0000000..66bc6c6 --- /dev/null +++ b/lua/laravel/recipes/init.lua @@ -0,0 +1,18 @@ +local recipes = { + ["ide-helper"] = require "laravel.recipes.ide-helper", +} + +local M = {} + +function M.run() + vim.ui.select(vim.tbl_keys(recipes), { prompt = "Recipe to run:" }, function(recipeName) + local recipe = recipes[recipeName] + if recipe == nil then + error(string.format("Recipe %s not found", recipeName), vim.log.levels.ERROR) + end + + recipe.run() + end) +end + +return M diff --git a/lua/laravel/user_commands/laravel/init.lua b/lua/laravel/user_commands/laravel/init.lua index 7040818..7fa2cc0 100644 --- a/lua/laravel/user_commands/laravel/init.lua +++ b/lua/laravel/user_commands/laravel/init.lua @@ -1,5 +1,4 @@ local notify = require "laravel.notify" -local run = require "laravel.run" local commands = { ["cache:clean"] = function() @@ -7,21 +6,14 @@ local commands = { require("laravel.routes").list = {} notify("laravel.cache:clean", { msg = "Cache cleaned", level = "INFO" }) end, - ["routes"] = function() - return require("telescope").extensions.laravel.routes() - end, - ["artisan"] = function() - return require("telescope").extensions.laravel.commands() - end, - ["test:watch"] = function() - return run("artisan", { "test" }, { runner = "watch" }) - end, - ["related"] = function() - return require("telescope").extensions.laravel.related() - end, - ["history"] = function() - return require("telescope").extensions.laravel.history() - end, + ["routes"] = require("telescope").extensions.laravel.routes, + ["artisan"] = require("telescope").extensions.laravel.commands, + -- ["test:watch"] = function() + -- return run("artisan", { "test" }, { runner = "watch" }) + -- end, + ["related"] = require("telescope").extensions.laravel.related, + ["history"] = require("telescope").extensions.laravel.history, + ["recipes"] = require("laravel.recipes").run, ["info"] = require "laravel.user_commands.laravel.info", } @@ -34,9 +26,13 @@ return { return commands[command](unpack(args.fargs)) end - notify("laravel", { msg = "Unkown command", level = "ERROR" }) + vim.ui.select(vim.tbl_keys(commands), { prompt = "Laravel Plugin:" }, function(action) + if commands[action] ~= nil then + commands[action]() + end + end) end, { - nargs = "+", + nargs = "*", complete = function() return vim.tbl_keys(commands) end, From 0fbb4d9c79854bef3244cebc2c3d32f028ca50f6 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 26 Dec 2023 16:21:27 +0100 Subject: [PATCH 41/55] fix: calls with nil --- lua/laravel/recipes/init.lua | 4 ++++ lua/laravel/user_commands/laravel/init.lua | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lua/laravel/recipes/init.lua b/lua/laravel/recipes/init.lua index 66bc6c6..2a73897 100644 --- a/lua/laravel/recipes/init.lua +++ b/lua/laravel/recipes/init.lua @@ -6,6 +6,10 @@ local M = {} function M.run() vim.ui.select(vim.tbl_keys(recipes), { prompt = "Recipe to run:" }, function(recipeName) + if not recipeName then + return + end + local recipe = recipes[recipeName] if recipe == nil then error(string.format("Recipe %s not found", recipeName), vim.log.levels.ERROR) diff --git a/lua/laravel/user_commands/laravel/init.lua b/lua/laravel/user_commands/laravel/init.lua index 7fa2cc0..9c8fdb5 100644 --- a/lua/laravel/user_commands/laravel/init.lua +++ b/lua/laravel/user_commands/laravel/init.lua @@ -26,7 +26,10 @@ return { return commands[command](unpack(args.fargs)) end - vim.ui.select(vim.tbl_keys(commands), { prompt = "Laravel Plugin:" }, function(action) + vim.ui.select(vim.fn.sort(vim.tbl_keys(commands)), { prompt = "Laravel Plugin:" }, function(action) + if not action then + return + end if commands[action] ~= nil then commands[action]() end From fb108aaedbb44339e99583de07c51dd1e6b88209 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 26 Dec 2023 17:06:26 +0100 Subject: [PATCH 42/55] feat: add watch --- lua/laravel/user_commands/laravel/init.lua | 6 +-- lua/laravel/watch.lua | 58 ++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 lua/laravel/watch.lua diff --git a/lua/laravel/user_commands/laravel/init.lua b/lua/laravel/user_commands/laravel/init.lua index 9c8fdb5..c61c8c8 100644 --- a/lua/laravel/user_commands/laravel/init.lua +++ b/lua/laravel/user_commands/laravel/init.lua @@ -8,9 +8,9 @@ local commands = { end, ["routes"] = require("telescope").extensions.laravel.routes, ["artisan"] = require("telescope").extensions.laravel.commands, - -- ["test:watch"] = function() - -- return run("artisan", { "test" }, { runner = "watch" }) - -- end, + ["test:watch"] = function() + require "laravel.watch"("artisan", { "test" }) + end, ["related"] = require("telescope").extensions.laravel.related, ["history"] = require("telescope").extensions.laravel.history, ["recipes"] = require("laravel.recipes").run, diff --git a/lua/laravel/watch.lua b/lua/laravel/watch.lua new file mode 100644 index 0000000..87c2015 --- /dev/null +++ b/lua/laravel/watch.lua @@ -0,0 +1,58 @@ +local config = require "laravel.config" +local environment = require "laravel.environment" +local Split = require "nui.split" +local event = require("nui.utils.autocmd").event + +---@param name string +---@param args string[] +---@param opts table|nil +return function(name, args, opts) + opts = opts or {} + local executable = environment.get_executable(name) + if not executable then + error(string.format("Executable %s not found", name), vim.log.levels.ERROR) + return + end + local cmd = vim.fn.extend(executable, args) + + local command_option = config.options.commands_options[args[1]] or {} + + opts = vim.tbl_extend("force", command_option, opts) + + local nui_opts = opts.nui_opts or config.options.ui.nui_opts.split + nui_opts.enter = false + local instance = Split(nui_opts) + + instance:mount() + + local bufnr = instance.bufnr + + local run = function() + local chan_id = vim.api.nvim_open_term(bufnr, {}) + vim.fn.jobstart(table.concat(cmd, " "), { + stdeout_buffered = true, + on_stdout = function(_, data) + vim.fn.chansend(chan_id, data) + local row = vim.api.nvim_buf_line_count(bufnr) + vim.api.nvim_win_set_cursor(instance.winid, { row, 0 }) + end, + pty = true, + }) + end + run() + + local group = vim.api.nvim_create_augroup("laravel.watch", {}) + + local au_cmd_id = vim.api.nvim_create_autocmd({ "BufWritePost" }, { + pattern = opts.pattern or { "*.php" }, + group = group, + callback = function() + run() + end, + }) + + instance:on(event.BufHidden, function() + vim.api.nvim_del_autocmd(au_cmd_id) + vim.notify("AutoCmd for watch deleted", vim.log.levels.INFO, {}) + end) +end From 975fa4dc9ca9b95f2db5610af11f0b3362f440a7 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Tue, 26 Dec 2023 18:23:30 +0100 Subject: [PATCH 43/55] feat: support go to view from file --- lua/laravel/views.lua | 99 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 lua/laravel/views.lua diff --git a/lua/laravel/views.lua b/lua/laravel/views.lua new file mode 100644 index 0000000..1f2136f --- /dev/null +++ b/lua/laravel/views.lua @@ -0,0 +1,99 @@ +local notify = require "laravel.notify" +local get_node_text = vim.treesitter.get_node_text +local run = require "laravel.run" +local api = require "laravel.api" + +local M = {} +-- In the current buffer get run a treesitter query to get the frist argument for `view()` and `response()->view()`. +-- Present them in a ui select if more than one +-- From selected or unique, look for file. if does not exists ask to be created, open buffer or use artisan command + +local function gotoView(view) + local res = api.sync("artisan", { "tinker", "--execute", "echo resource_path('views')" }) + local view_path = res.stdout[1] + + local file_path = string.format("%s/%s.blade.php", view_path, string.gsub(view, "%.", "/")) + + if vim.fn.findfile(file_path) then + vim.cmd("edit " .. file_path) + return + end + -- It creates the view if does not exists and user want it + if vim.fn.confirm("View does not exists, Should create it?", "&Yes\n&No") == 1 then + run("artisan", { "make:view", view }) + end +end + +local function php_run() + local bufnr = vim.api.nvim_get_current_buf() + local php_parser = vim.treesitter.get_parser(bufnr, "php") + local tree = php_parser:parse()[1] + if tree == nil then + notify("laravel.views", { msg = "Could not retrive syntax tree", level = "WARN" }) + return + end + + local query = vim.treesitter.query.get("php", "laravel_views") + + if true or query == nil then + vim.treesitter.query.set( + "php", + "laravel_views", + [[ + (function_call_expression + (name) @function_name (#eq? @function_name "view") + (arguments (argument (string (string_value) @view))) + ) + ]] + ) + + query = vim.treesitter.query.get("php", "laravel_views") + end + if not query then + notify("laravel.views", { msg = "Could not get proper query", level = "WARN" }) + return + end + + local views = {} + for id, node in query:iter_captures(tree:root(), bufnr, 0, -1) do + if query.captures[id] == "view" then + table.insert(views, get_node_text(node, bufnr)) + end + end + + if #views == 0 then + notify("laravel.views", { msg = "No views found in file", level = "WARN" }) + return + end + + if #views > 1 then + vim.ui.select(vim.fn.sort(views), { prompt = "Which view:" }, function(selected) + if not selected then + return + end + gotoView(selected) + end) + return + end + gotoView(views[1]) +end + +local function blade_run() + -- get the filename + -- TODO: from filename get the name of view in dot format + -- grep the app directory looking for that with view("" + -- not close it for posibility of arguments, any quotes + -- more than one show select + -- open file and position in line +end + +function M.run() + local ft = vim.o.filetype + if ft == "php" then + php_run() + elseif ft == "blade" then + blade_run() + end +end + +return M From f4968b7785ded2c5b9312f606ff131767acee6eb Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Wed, 27 Dec 2023 12:12:06 +0100 Subject: [PATCH 44/55] feat: view_finder --- lua/laravel/api.lua | 4 + lua/laravel/null_ls/completion/view.lua | 10 +-- lua/laravel/paths.lua | 23 ++++++ lua/laravel/utils.lua | 24 ++++++ lua/laravel/view_finder.lua | 98 +++++++++++++++++++++++++ lua/laravel/views.lua | 87 ++-------------------- 6 files changed, 160 insertions(+), 86 deletions(-) create mode 100644 lua/laravel/paths.lua create mode 100644 lua/laravel/utils.lua create mode 100644 lua/laravel/view_finder.lua diff --git a/lua/laravel/api.lua b/lua/laravel/api.lua index 76666b6..489bc8b 100644 --- a/lua/laravel/api.lua +++ b/lua/laravel/api.lua @@ -47,4 +47,8 @@ function M.is_composer_package_install(package) return M.sync("composer", { "info", package }).exit_code == 0 end +function M.php_execute(code) + return M.sync("artisan", { "tinker", "--execute", "echo " .. code }) +end + return M diff --git a/lua/laravel/null_ls/completion/view.lua b/lua/laravel/null_ls/completion/view.lua index b0e7549..7320ee8 100644 --- a/lua/laravel/null_ls/completion/view.lua +++ b/lua/laravel/null_ls/completion/view.lua @@ -1,11 +1,9 @@ -return function(done, should_quote) - local scan = require "plenary.scandir" - local api = require "laravel.api" +local paths = require "laravel.paths" +local scan = require "plenary.scandir" +return function(done, should_quote) local candidates = {} - - local res = api.sync("artisan", { "tinker", "--execute", "echo resource_path('views')" }) - local view_path = res.stdout[1] + local view_path = paths.resource_path "views" local rule = string.format("^%s/(.*).blade.php$", view_path:gsub("-", "%%-")) local finds = scan.scan_dir(view_path, { hidden = false, depth = 4 }) for _, value in pairs(finds) do diff --git a/lua/laravel/paths.lua b/lua/laravel/paths.lua new file mode 100644 index 0000000..86d5c77 --- /dev/null +++ b/lua/laravel/paths.lua @@ -0,0 +1,23 @@ +local api = require "laravel.api" + +local M = {} + +local function get_cwd() + return vim.fn.getcwd() +end + +local function get_base_path() + return api.php_execute("base_path()").stdout[1] +end + +local function map_path(path) + return path:gsub(get_base_path():gsub("-", "%%-"), get_cwd()) +end + +function M.resource_path(resource) + local path = api.php_execute(string.format("resource_path('%s')", resource)).stdout[1] + + return map_path(path) +end + +return M diff --git a/lua/laravel/utils.lua b/lua/laravel/utils.lua new file mode 100644 index 0000000..3a3fec4 --- /dev/null +++ b/lua/laravel/utils.lua @@ -0,0 +1,24 @@ +local M = {} + +function M.runRipgrep(pattern) + -- Build the ripgrep command + local rg_command = string.format('rg --vimgrep "%s"', pattern) + + -- Run the command and capture the output + local result = vim.fn.systemlist(rg_command) + + -- Process the result + local matches = {} + for _, line in ipairs(result) do + local parts = vim.fn.split(line, ":", true) + local file = parts[1] + local line_number = parts[2] + local text = parts[3] + + table.insert(matches, { file = file, line_number = line_number, text = text }) + end + + return matches +end + +return M diff --git a/lua/laravel/view_finder.lua b/lua/laravel/view_finder.lua new file mode 100644 index 0000000..c2a7e35 --- /dev/null +++ b/lua/laravel/view_finder.lua @@ -0,0 +1,98 @@ +local views = require "laravel.views" +local utils = require "laravel.utils" +local notify = require "laravel.notify" + +local M = {} + +-- Should be use from blades to find where is being use +function M.go_to_usage() + local fname = vim.uri_to_fname(vim.uri_from_bufnr(vim.api.nvim_get_current_buf())) + local view = views.name_from_fname(fname) + + local matches = utils.runRipgrep(string.format("view\\(['\\\"]%s['\\\"]", view)) + + if #matches == 0 then + notify("laravel.views", { msg = "No usage of this view found", level = "WARN" }) + elseif #matches == 1 then + vim.cmd("edit " .. matches[1].file) + else + vim.ui.select( + vim.fn.sort(vim.tbl_map(function(item) + return item.file + end, matches)), + { prompt = "File: " }, + function(value) + if not value then + return + end + vim.cmd("edit " .. value) + end + ) + end +end + +-- should be use in files to find the views +function M.go_to_definition() + local bufnr = vim.api.nvim_get_current_buf() + local php_parser = vim.treesitter.get_parser(bufnr, "php") + local tree = php_parser:parse()[1] + if tree == nil then + notify("laravel.views", { msg = "Could not retrive syntax tree", level = "WARN" }) + return + end + + local query = vim.treesitter.query.get("php", "laravel_views") + + if true or query == nil then + vim.treesitter.query.set( + "php", + "laravel_views", + [[ + (function_call_expression + (name) @function_name (#eq? @function_name "view") + (arguments (argument (string (string_value) @view))) + ) + ]] + ) + + query = vim.treesitter.query.get("php", "laravel_views") + end + if not query then + notify("laravel.views", { msg = "Could not get proper query", level = "WARN" }) + return + end + + local founds = {} + for id, node in query:iter_captures(tree:root(), bufnr, 0, -1) do + if query.captures[id] == "view" then + table.insert(founds, vim.treesitter.get_node_text(node, bufnr)) + end + end + + if #founds == 0 then + notify("laravel.views", { msg = "No views found in file", level = "WARN" }) + return + end + + if #founds > 1 then + vim.ui.select(vim.fn.sort(founds), { prompt = "Which view:" }, function(selected) + if not selected then + return + end + views.open(selected) + end) + return + end + views.open(founds[1]) +end + +function M.auto() + local ft = vim.o.filetype + if ft == "php" then + return M.go_to_definition() + elseif ft == "blade" then + return M.go_to_usage() + end +end + +return M diff --git a/lua/laravel/views.lua b/lua/laravel/views.lua index 1f2136f..f4fe99d 100644 --- a/lua/laravel/views.lua +++ b/lua/laravel/views.lua @@ -1,18 +1,12 @@ -local notify = require "laravel.notify" -local get_node_text = vim.treesitter.get_node_text local run = require "laravel.run" -local api = require "laravel.api" +local paths = require "laravel.paths" local M = {} --- In the current buffer get run a treesitter query to get the frist argument for `view()` and `response()->view()`. --- Present them in a ui select if more than one --- From selected or unique, look for file. if does not exists ask to be created, open buffer or use artisan command -local function gotoView(view) - local res = api.sync("artisan", { "tinker", "--execute", "echo resource_path('views')" }) - local view_path = res.stdout[1] +function M.open(view) + local views_directory = paths.resource_path "views" - local file_path = string.format("%s/%s.blade.php", view_path, string.gsub(view, "%.", "/")) + local file_path = string.format("%s/%s.blade.php", views_directory, string.gsub(view, "%.", "/")) if vim.fn.findfile(file_path) then vim.cmd("edit " .. file_path) @@ -24,76 +18,9 @@ local function gotoView(view) end end -local function php_run() - local bufnr = vim.api.nvim_get_current_buf() - local php_parser = vim.treesitter.get_parser(bufnr, "php") - local tree = php_parser:parse()[1] - if tree == nil then - notify("laravel.views", { msg = "Could not retrive syntax tree", level = "WARN" }) - return - end - - local query = vim.treesitter.query.get("php", "laravel_views") - - if true or query == nil then - vim.treesitter.query.set( - "php", - "laravel_views", - [[ - (function_call_expression - (name) @function_name (#eq? @function_name "view") - (arguments (argument (string (string_value) @view))) - ) - ]] - ) - - query = vim.treesitter.query.get("php", "laravel_views") - end - if not query then - notify("laravel.views", { msg = "Could not get proper query", level = "WARN" }) - return - end - - local views = {} - for id, node in query:iter_captures(tree:root(), bufnr, 0, -1) do - if query.captures[id] == "view" then - table.insert(views, get_node_text(node, bufnr)) - end - end - - if #views == 0 then - notify("laravel.views", { msg = "No views found in file", level = "WARN" }) - return - end - - if #views > 1 then - vim.ui.select(vim.fn.sort(views), { prompt = "Which view:" }, function(selected) - if not selected then - return - end - gotoView(selected) - end) - return - end - gotoView(views[1]) -end - -local function blade_run() - -- get the filename - -- TODO: from filename get the name of view in dot format - -- grep the app directory looking for that with view("" - -- not close it for posibility of arguments, any quotes - -- more than one show select - -- open file and position in line -end - -function M.run() - local ft = vim.o.filetype - if ft == "php" then - php_run() - elseif ft == "blade" then - blade_run() - end +function M.name_from_fname(fname) + local views_directory = paths.resource_path "views" .. "/" + return fname:gsub(views_directory:gsub("-", "%%-"), ""):gsub("%.blade%.php", ""):gsub("/", ".") end return M From c5e0071529ecfe098aec5354135f9e3b0b132137 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Wed, 27 Dec 2023 12:18:06 +0100 Subject: [PATCH 45/55] feat: add command to laravel --- lua/laravel/user_commands/laravel/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/laravel/user_commands/laravel/init.lua b/lua/laravel/user_commands/laravel/init.lua index c61c8c8..7c09efa 100644 --- a/lua/laravel/user_commands/laravel/init.lua +++ b/lua/laravel/user_commands/laravel/init.lua @@ -14,6 +14,7 @@ local commands = { ["related"] = require("telescope").extensions.laravel.related, ["history"] = require("telescope").extensions.laravel.history, ["recipes"] = require("laravel.recipes").run, + ["view-finder"] = require("laravel.view_finder").auto, ["info"] = require "laravel.user_commands.laravel.info", } From dd2abe76c6e83fd9a3fbae3c32fcc018efb3ee66 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Wed, 27 Dec 2023 12:29:24 +0100 Subject: [PATCH 46/55] feat: add cache for command in paths --- lua/laravel/paths.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lua/laravel/paths.lua b/lua/laravel/paths.lua index 86d5c77..41e81df 100644 --- a/lua/laravel/paths.lua +++ b/lua/laravel/paths.lua @@ -1,13 +1,22 @@ local api = require "laravel.api" +local cache = {} + local M = {} +local function exec(cmd) + if not cache[cmd] then + cache[cmd] = api.php_execute(cmd) + end + return cache[cmd] +end + local function get_cwd() return vim.fn.getcwd() end local function get_base_path() - return api.php_execute("base_path()").stdout[1] + return exec("base_path()").stdout[1] end local function map_path(path) @@ -15,7 +24,7 @@ local function map_path(path) end function M.resource_path(resource) - local path = api.php_execute(string.format("resource_path('%s')", resource)).stdout[1] + local path = exec(string.format("resource_path('%s')", resource)).stdout[1] return map_path(path) end From 76b677ce533ea1be711d16926f9c46266984c629 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Wed, 27 Dec 2023 13:28:09 +0100 Subject: [PATCH 47/55] feat: add doctrine-dbal recipe --- lua/laravel/recipes/doctrine-dbal.lua | 18 ++++++++++++++++++ lua/laravel/recipes/init.lua | 1 + 2 files changed, 19 insertions(+) create mode 100644 lua/laravel/recipes/doctrine-dbal.lua diff --git a/lua/laravel/recipes/doctrine-dbal.lua b/lua/laravel/recipes/doctrine-dbal.lua new file mode 100644 index 0000000..fe13bcc --- /dev/null +++ b/lua/laravel/recipes/doctrine-dbal.lua @@ -0,0 +1,18 @@ +local api = require "laravel.api" + +local M = {} + +function M.run() + if not api.is_composer_package_install "doctrine/dbal" then + api.async("composer", { "require", "--dev", "doctrine/dbal" }, function(_, exit_code) + if exit_code ~= 0 then + error("Cant install doctrine/dbal", vim.log.levels.ERROR) + end + vim.notify("Installation completed", vim.log.levels.INFO) + end) + else + vim.notify("Already Installed", vim.log.levels.INFO) + end +end + +return M diff --git a/lua/laravel/recipes/init.lua b/lua/laravel/recipes/init.lua index 2a73897..1ac1280 100644 --- a/lua/laravel/recipes/init.lua +++ b/lua/laravel/recipes/init.lua @@ -1,5 +1,6 @@ local recipes = { ["ide-helper"] = require "laravel.recipes.ide-helper", + ["doctrine-dbal"] = require "laravel.recipes.doctrine-dbal", } local M = {} From 1a8770222b2607665a6f8a44bf54b0df4e045c49 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Wed, 27 Dec 2023 14:52:19 +0100 Subject: [PATCH 48/55] fix: remove unused script --- lua/laravel/_jobs.lua | 47 ------------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 lua/laravel/_jobs.lua diff --git a/lua/laravel/_jobs.lua b/lua/laravel/_jobs.lua deleted file mode 100644 index 884c3ae..0000000 --- a/lua/laravel/_jobs.lua +++ /dev/null @@ -1,47 +0,0 @@ -local M = {} - -local cleanup_autocmd -local all_channels = {} - -local keys = vim.api.nvim_replace_termcodes("", true, false, true) -local function terminate(job_id) - vim.api.nvim_chan_send(job_id, keys) - vim.fn.jobstop(job_id) -end - ----@param job_id number ----@param bufnr number -M.register = function(job_id, bufnr) - if not cleanup_autocmd then - cleanup_autocmd = vim.api.nvim_create_autocmd("VimLeavePre", { - desc = "Clean up running overseer tasks on exit", - callback = function() - local job_ids = vim.tbl_keys(all_channels) - for _, j in ipairs(job_ids) do - terminate(j) - end - end, - }) - end - all_channels[job_id] = true - - vim.api.nvim_create_autocmd({ "BufUnload" }, { - buffer = bufnr, - callback = function() - M.terminate(job_id) - end, - }) -end - -M.unregister = function(job_id) - all_channels[job_id] = nil -end - -M.terminate = function(job_id) - if all_channels[job_id] ~= nil then - terminate(job_id) - all_channels[job_id] = nil - end -end - -return M From 4fd54281b2b459d0d07b9117c104f98a62eba3df Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Wed, 27 Dec 2023 20:11:25 +0100 Subject: [PATCH 49/55] feat: remove notify function --- TODO.md | 69 ++--------------- lua/laravel/_lsp/init.lua | 8 +- lua/laravel/_lsp/intelephense.lua | 12 +-- lua/laravel/_lsp/phpactor.lua | 14 ++-- lua/laravel/{api.lua => api/init.lua} | 21 ++++-- lua/laravel/api/response.lua | 68 +++++++++++++++++ lua/laravel/commands/init.lua | 7 +- lua/laravel/environment/resolver.lua | 19 ++--- lua/laravel/notify.lua | 13 ---- lua/laravel/paths.lua | 6 +- lua/laravel/recipes/doctrine-dbal.lua | 15 ++-- lua/laravel/recipes/ide-helper.lua | 36 +++++---- lua/laravel/resources/create.lua | 16 ++-- lua/laravel/resources/open.lua | 6 +- lua/laravel/route_info/init.lua | 4 +- lua/laravel/routes/go.lua | 3 +- lua/laravel/routes/init.lua | 11 +-- lua/laravel/status.lua | 2 +- lua/laravel/telescope/pickers/related.lua | 12 +-- lua/laravel/tinker/init.lua | 4 +- lua/laravel/user_commands/composer.lua | 6 +- lua/laravel/user_commands/docker_compose.lua | 79 ++++++++++---------- lua/laravel/user_commands/laravel/init.lua | 4 +- lua/laravel/user_commands/sail.lua | 76 ++++++++++--------- lua/laravel/view_finder.lua | 13 ++-- 25 files changed, 259 insertions(+), 265 deletions(-) rename lua/laravel/{api.lua => api/init.lua} (67%) create mode 100644 lua/laravel/api/response.lua delete mode 100644 lua/laravel/notify.lua diff --git a/TODO.md b/TODO.md index 4db2933..71eec98 100644 --- a/TODO.md +++ b/TODO.md @@ -22,65 +22,10 @@ - [X] completion detect or not quotes - [X] completion for model fields - [X] remove completion for models -- [ ] replace anonymous function from mapping with dedicated functions to have descriptions -- [ ] recipes for ide-helper models and eloquent -- [ ] using the get_type in completion is dangerus. better to replace it with ide-helper -- [ ] implement watch -- [ ] tinker interface -- [ ] virtual text info ??? -- [ ] re-write the readme and translate (not forget fd as dependency) the counter does not work as I expect - - -Somethign like thinkerwell -read the buffer and send to tinker ?? - -```lua -local res = api.sync("artisan", {"tinker", "--execute", "$a = view('welcome'); dump($a)"}) -``` -since php does not car of breake lines I could do something like this -read the buffer - -If I want colors needs to use jobstart I think -```lua -vim.fn.jobstart({ "php", "artisan", "tinker", "--execute", vim.fn.join(lines, "") }, { - stdeout_buffered = true, - on_stdout = function(_, data) - vim.fn.chansend(chan, data) - end, - pty = true, -}) -``` - -To have autocomplete need to have the file in the project folder. -or start the server for the specific buffer - -`tinker.php` could be created on the root when starting the mode - -delete it when it's done, or persist it. - -create temporary buffer and use vim.lsp.buf_attach_client() to attach it to the current php actor client - -should start the buffer with the first line ` attach it to current lsp server for php -TinkerOutput -> render the output per save - -Autocommand for TinkerEditor to save and run the hole buffer content into the api sync command. - -Action Start Tinker -Open side for output. -Create buffer or look for buffer of tinker -On Close Leave tinkerEditor buffer but close the output - - - -Completion of model fields -- check that we are trying to complete property for variable. -- check that variable is of model (lsp) -- get model name -if for the variable use type definition can get the document for the variable. -can I get the name of it ? -should be in the location -What can I get from location ?? +- [X] replace anonymous function from mapping with dedicated functions to have descriptions +- [X] using the get_type in completion is dangerus. better to replace it with ide-helper +- [X] recipes for ide-helper models and eloquent +- [X] implement watch +- [X] implement alternate file for livewire components `:A` +- [X] extend api .sync and .async with better respons object. maybe create a new object with method for example `.successful()` and `.failed()` +- [ ] re-write the readme and translate (not forget fd as dependency) move all info from readme to doc diff --git a/lua/laravel/_lsp/init.lua b/lua/laravel/_lsp/init.lua index ff7c30e..5d764a4 100644 --- a/lua/laravel/_lsp/init.lua +++ b/lua/laravel/_lsp/init.lua @@ -1,6 +1,5 @@ local phpactor = require "laravel._lsp.phpactor" local intelephense = require "laravel._lsp.intelephense" -local notify = require "laravel.notify" local config = require "laravel.config" local servers = { @@ -18,6 +17,9 @@ local get_client = function(server_name) if not client then local server = require("lspconfig")[server_name] local client_id = vim.lsp.start(server.make_config(vim.fn.getcwd())) + if not client_id then + error "Could not start lsp client" + end client = vim.lsp.get_client_by_id(client_id) new_instance = true end @@ -32,14 +34,14 @@ local go_to = function(full_class, method) local server = servers[server_name] if server == nil then - notify("Route open", { msg = "No server name " .. server_name, level = "WARN" }) + vim.notify(string.format("No server with name %s found", server_name), vim.log.levels.WARN) return end local client, is_new_instance = get_client(server_name) if not client then - notify("Route open", { msg = "Can't get lsp client", level = "WARN" }) + vim.notify("Can't get lsp client", vim.log.levels.WARN) return end diff --git a/lua/laravel/_lsp/intelephense.lua b/lua/laravel/_lsp/intelephense.lua index a8e5de9..ea8c63b 100644 --- a/lua/laravel/_lsp/intelephense.lua +++ b/lua/laravel/_lsp/intelephense.lua @@ -1,5 +1,4 @@ local lsp_utils = require "laravel._lsp.utils" -local notify = require "laravel.notify" ---@param client table ---@param is_new_instance boolean @@ -25,7 +24,7 @@ local function go_to(client, is_new_instance, full_class, method) end if class_location == nil then - notify("Route Open", { msg = "Could not find class for : " .. full_class, level = "WARN" }) + vim.notify("Could not find the class " .. full_class, vim.log.levels.WARN) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -41,7 +40,7 @@ local function go_to(client, is_new_instance, full_class, method) vim.lsp.buf_request(0, "textDocument/documentSymbol", params, function(method_err, method_server_result, _, _) if method_err then - notify("Route Open", { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" }) + vim.notify("Error when finding workspace symbols " .. method_err.message, vim.log.levels.WARN) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -50,10 +49,7 @@ local function go_to(client, is_new_instance, full_class, method) local method_locations = vim.lsp.util.symbols_to_items(method_server_result or {}, 0) or {} if vim.tbl_isempty(method_locations) then - lsp_utils.notify( - "Route open", - { msg = string.format("empty response looking for method: %s", method or "__invoke"), level = "WARN" } - ) + vim.notify(string.format("empty response looking for method: %s", method or "__invoke"), vim.log.levels.WARN) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -81,7 +77,7 @@ local function go_to(client, is_new_instance, full_class, method) if row and col then local ok, err_msg = pcall(vim.api.nvim_win_set_cursor, 0, { row, col }) if not ok then - lsp_utils.notify("Route Open", { msg = "Erro setting row and col " .. err_msg, level = "WARN" }) + vim.notify(string.format("Error setting row and col %s", err_msg), vim.log.levels.WARN) end vim.cmd "normal zt" end diff --git a/lua/laravel/_lsp/phpactor.lua b/lua/laravel/_lsp/phpactor.lua index 37f3516..e5f3818 100644 --- a/lua/laravel/_lsp/phpactor.lua +++ b/lua/laravel/_lsp/phpactor.lua @@ -1,5 +1,4 @@ local lsp_utils = require "laravel._lsp.utils" -local notify = require "laravel.notify" ---@param client table ---@param is_new_instance boolean @@ -14,7 +13,7 @@ local function go_to(client, is_new_instance, full_class, method) local locations = vim.lsp.util.symbols_to_items(resp.result or {}, nil) or {} if vim.tbl_isempty(locations) then - notify("Route Open", { msg = "Empty response looking for class: " .. full_class, level = "WARN" }) + vim.notify("Could not find the class " .. full_class, vim.log.levels.WARN) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -30,7 +29,7 @@ local function go_to(client, is_new_instance, full_class, method) end if class_location == nil then - notify("Route Open", { msg = "Could not find class for : " .. full_class, level = "WARN" }) + vim.notify("Could not find the class " .. full_class, vim.log.levels.WARN) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -46,7 +45,7 @@ local function go_to(client, is_new_instance, full_class, method) vim.lsp.buf_request(0, "textDocument/documentSymbol", params, function(method_err, method_server_result, _, _) if method_err then - notify("Route Open", { msg = "Error when finding workspace symbols: " .. method_err.message, level = "WARN" }) + vim.notify("Error when finding workspace symbols " .. method_err.message, vim.log.levels.WARN) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -55,10 +54,7 @@ local function go_to(client, is_new_instance, full_class, method) local method_locations = vim.lsp.util.symbols_to_items(method_server_result or {}, 0) or {} if vim.tbl_isempty(method_locations) then - lsp_utils.notify( - "Route open", - { msg = string.format("empty response looking for method: %s", method or "__invoke"), level = "WARN" } - ) + vim.notify(string.format("empty response looking for method: %s", method or "__invoke"), vim.log.levels.WARN) if is_new_instance then vim.lsp.stop_client(client.id) end @@ -86,7 +82,7 @@ local function go_to(client, is_new_instance, full_class, method) if row and col then local ok, err_msg = pcall(vim.api.nvim_win_set_cursor, 0, { row, col }) if not ok then - lsp_utils.notify("Route Open", { msg = "Erro setting row and col " .. err_msg, level = "WARN" }) + vim.notify(string.format("Error setting row and col %s", err_msg), vim.log.levels.WARN) end vim.cmd "normal zt" end diff --git a/lua/laravel/api.lua b/lua/laravel/api/init.lua similarity index 67% rename from lua/laravel/api.lua rename to lua/laravel/api/init.lua index 489bc8b..1ea95a6 100644 --- a/lua/laravel/api.lua +++ b/lua/laravel/api/init.lua @@ -1,5 +1,6 @@ local Job = require "plenary.job" local environment = require "laravel.environment" +local ApiResponse = require "laravel.api.response" local M = {} @@ -12,6 +13,10 @@ function M.generate_command(name, args) return vim.fn.extend(executable, args) end +--- Run the command sync +---@param program string +---@param args string[] +---@return ApiResponse function M.sync(program, args) local cmd = M.generate_command(program, args) local command = table.remove(cmd, 1) @@ -25,13 +30,13 @@ function M.sync(program, args) end, }):sync() - return { - stdout = stdout, - exit_code = ret, - stderr = stderr, - } + return ApiResponse:new(stdout, ret, stderr) end +--- Run the command async +---@param program string +---@param args string[] +---@param callback function function M.async(program, args, callback) local cmd = M.generate_command(program, args) local command = table.remove(cmd, 1) @@ -39,12 +44,14 @@ function M.async(program, args, callback) Job:new({ command = command, args = cmd, - on_exit = vim.schedule_wrap(callback), + on_exit = vim.schedule_wrap(function(j, exit_code) + callback(ApiResponse:new(j:result(), exit_code, j:stderr_result())) + end), }):start() end function M.is_composer_package_install(package) - return M.sync("composer", { "info", package }).exit_code == 0 + return M.sync("composer", { "info", package }):successful() end function M.php_execute(code) diff --git a/lua/laravel/api/response.lua b/lua/laravel/api/response.lua new file mode 100644 index 0000000..0d0b0fe --- /dev/null +++ b/lua/laravel/api/response.lua @@ -0,0 +1,68 @@ +--- ApiResponse class represents the result of a command execution. +---@class ApiResponse +---@field stdout string[] The standard output of the command execution. +---@field exit_code number The exit code indicating how the command ended (0 for success, non-zero for failure). +---@field stderror string[] The standard error output in case of errors during command execution. +local ApiResponse = {} + +---@param stdout string[] +---@param exit_code number +---@param stderror string[] +---@return ApiResponse +function ApiResponse:new(stdout, exit_code, stderror) + local obj = { + stdout = stdout, + exit_code = exit_code, + stderror = stderror, + } + + setmetatable(obj, self) + self.__index = self + + return obj +end + +---@return boolean +function ApiResponse:successful() + return self.exit_code == 0 +end + +---@return boolean +function ApiResponse:failed() + return not self:successful() +end + +--- Returns the content +---@return string[] +function ApiResponse:content() + return self.stdout +end + +---@return string +function ApiResponse:prettyContent() + return vim.inspect(self:content()) +end + +---@return string|nil +function ApiResponse:first() + if self:failed() then + return nil + end + + return self.stdout[1] +end + +---@return string[]|nil +function ApiResponse:errors() + if self:failed() then + return nil + end + + if not vim.tbl_isempty(self.stderror) then + return self.stderror + end + + return self:content() +end + +return ApiResponse diff --git a/lua/laravel/commands/init.lua b/lua/laravel/commands/init.lua index 5da16fe..931a0cd 100644 --- a/lua/laravel/commands/init.lua +++ b/lua/laravel/commands/init.lua @@ -8,11 +8,8 @@ M.list = {} function M.load() M.list = {} local result = api.sync("artisan", { "list", "--format=json" }) - if result.exit_code == 1 then - error( - string.format("Failed to get commands %s %s", vim.inspect(result.stdout), vim.inspect(result.stderr)), - vim.log.levels.ERROR - ) + if result:failed() then + error(result:failed(), vim.log.levels.ERROR) end M.list = utils.from_json(result.stdout) diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua index cfde178..bafce1f 100644 --- a/lua/laravel/environment/resolver.lua +++ b/lua/laravel/environment/resolver.lua @@ -1,4 +1,3 @@ -local notify = require "laravel.notify" local get_env = require "laravel.environment.get_env" ---@param env_check boolean @@ -10,10 +9,10 @@ return function(env_check, auto_discovery, default) if env_check and env_name ~= nil then local environment = environments[env_name] if environment == nil then - notify("Environment resolver", { - msg = "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", - level = "ERROR", - }) + vim.notify( + "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", + vim.log.levels.ERROR + ) return nil else return environment @@ -46,20 +45,14 @@ return function(env_check, auto_discovery, default) if default then local environment = environments[default] if environment == nil then - notify( - "Environment resolver", - { msg = "Default define as " .. default .. " but there is no environment define", level = "ERROR" } - ) + vim.notify("Default define as " .. default .. " but there is no environment define", vim.log.levels.ERROR) return nil else return environment end end - notify( - "Environment resolver", - { msg = "Could not resolve any environment please check your configuration", level = "ERROR" } - ) + vim.notify("Could not resolve any environment please check your configuration", vim.log.levels.ERROR) return nil end end diff --git a/lua/laravel/notify.lua b/lua/laravel/notify.lua deleted file mode 100644 index e110fd9..0000000 --- a/lua/laravel/notify.lua +++ /dev/null @@ -1,13 +0,0 @@ -return function(funname, opts) - local level = vim.log.levels[opts.level] - if not level then - error("Invalid error level", 2) - end - local body = string.format("[laravel.%s]: %s", funname, opts.msg) - if opts.raw ~= nil then - body = opts.raw - end - vim.notify(body, level, { - title = "Laravel.nvim", - }) -end diff --git a/lua/laravel/paths.lua b/lua/laravel/paths.lua index 41e81df..3fa1d78 100644 --- a/lua/laravel/paths.lua +++ b/lua/laravel/paths.lua @@ -4,10 +4,12 @@ local cache = {} local M = {} +---@return ApiResponse local function exec(cmd) if not cache[cmd] then cache[cmd] = api.php_execute(cmd) end + return cache[cmd] end @@ -16,7 +18,7 @@ local function get_cwd() end local function get_base_path() - return exec("base_path()").stdout[1] + return exec("base_path()"):first() end local function map_path(path) @@ -24,7 +26,7 @@ local function map_path(path) end function M.resource_path(resource) - local path = exec(string.format("resource_path('%s')", resource)).stdout[1] + local path = exec(string.format("resource_path('%s')", resource)):first() return map_path(path) end diff --git a/lua/laravel/recipes/doctrine-dbal.lua b/lua/laravel/recipes/doctrine-dbal.lua index fe13bcc..109dce3 100644 --- a/lua/laravel/recipes/doctrine-dbal.lua +++ b/lua/laravel/recipes/doctrine-dbal.lua @@ -4,12 +4,17 @@ local M = {} function M.run() if not api.is_composer_package_install "doctrine/dbal" then - api.async("composer", { "require", "--dev", "doctrine/dbal" }, function(_, exit_code) - if exit_code ~= 0 then - error("Cant install doctrine/dbal", vim.log.levels.ERROR) + api.async( + "composer", + { "require", "--dev", "doctrine/dbal" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error({ "Cant install doctrine/dbal", response:errors() }, vim.log.levels.ERROR) + end + vim.notify("Installation completed", vim.log.levels.INFO) end - vim.notify("Installation completed", vim.log.levels.INFO) - end) + ) else vim.notify("Already Installed", vim.log.levels.INFO) end diff --git a/lua/laravel/recipes/ide-helper.lua b/lua/laravel/recipes/ide-helper.lua index cecec7e..29271c6 100644 --- a/lua/laravel/recipes/ide-helper.lua +++ b/lua/laravel/recipes/ide-helper.lua @@ -3,24 +3,34 @@ local api = require "laravel.api" local M = {} local function writeModels() - api.async("artisan", { "ide-helper:models", "-n", "-W", "-M" }, function(_, exit_code) - local level = vim.log.levels.INFO - if exit_code ~= 0 then - level = vim.log.levels.ERROR + api.async( + "artisan", + { "ide-helper:models", "-n", "-W", "-M" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + + vim.notify("Ide Helper Models Complete", vim.log.levels.INFO) end - vim.notify("Ide Helper Models Complete", level) - end) + ) end local function installIdeHelperAndWrite() - api.async("composer", { "require", "--dev", "barryvdh/laravel-ide-helper" }, function(_, exit_code) - if exit_code ~= 0 then - error("Cant install ide-helper", vim.log.levels.ERROR) - end - require("laravel.commands").list = {} + api.async( + "composer", + { "require", "--dev", "barryvdh/laravel-ide-helper" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error({ "Cant install ide-helper", response:errors() }, vim.log.levels.ERROR) + end - writeModels() - end) + require("laravel.commands").list = {} + writeModels() + end + ) end function M.run() diff --git a/lua/laravel/resources/create.lua b/lua/laravel/resources/create.lua index e82c074..34da053 100644 --- a/lua/laravel/resources/create.lua +++ b/lua/laravel/resources/create.lua @@ -10,9 +10,15 @@ return function(command) error(string.format("Command %s is not a resource creation suported", resource), vim.log.levels.ERROR) end - api.async("artisan", command, function() - open(resource, name) - end) - - return true + api.async( + "artisan", + command, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + open(resource, name) + end + ) end diff --git a/lua/laravel/resources/open.lua b/lua/laravel/resources/open.lua index 6c4042f..82829a1 100644 --- a/lua/laravel/resources/open.lua +++ b/lua/laravel/resources/open.lua @@ -1,5 +1,4 @@ local config = require "laravel.config" -local notify = require "laravel.notify" return function(resource, name) local directory = config.options.resources[resource] @@ -18,8 +17,5 @@ return function(resource, name) return end - notify("Resource.Open", { - msg = string.format("Can't find resource %s", filename), - level = "INFO", - }) + vim.notify(string.format("Can't find resource %s", filename), vim.log.levels.INFO) end diff --git a/lua/laravel/route_info/init.lua b/lua/laravel/route_info/init.lua index f64c69f..38bcb9a 100644 --- a/lua/laravel/route_info/init.lua +++ b/lua/laravel/route_info/init.lua @@ -1,4 +1,3 @@ -local notify = require "laravel.notify" local routes = require "laravel.routes" local config = require "laravel.config" @@ -59,8 +58,7 @@ local function set_route_to_methods(event) local php_parser = vim.treesitter.get_parser(bufnr, "php") local tree = php_parser:parse()[1] if tree == nil then - notify("route_info.set_route_to_methods", { msg = "Could not retrive syntax tree", level = "WARN" }) - return + error("Could not retrieve syntx tree", vim.log.levels.ERROR) end local query = vim.treesitter.query.get("php", "laravel_route_info") diff --git a/lua/laravel/routes/go.lua b/lua/laravel/routes/go.lua index 5d3e0f4..18975bd 100644 --- a/lua/laravel/routes/go.lua +++ b/lua/laravel/routes/go.lua @@ -1,4 +1,3 @@ -local notify = require "laravel.notify" local lsp = require "laravel._lsp" return function(route) @@ -14,7 +13,7 @@ return function(route) vim.fn.search("/" .. route.uri) end else - notify("Route", { msg = "Could not open the route location", level = "WARN" }) + vim.notify("Could not open the route location", vim.log.levels.WARN) return end diff --git a/lua/laravel/routes/init.lua b/lua/laravel/routes/init.lua index e586c44..2348854 100644 --- a/lua/laravel/routes/init.lua +++ b/lua/laravel/routes/init.lua @@ -8,15 +8,8 @@ M.list = {} function M.load() M.list = {} local result = api.sync("artisan", { "route:list", "--json" }) - if result.exit_code ~= 0 then - error( - string.format( - "Failed to get routes check your code %s %s", - vim.fn.join(result.stdout, "\r\n"), - vim.fn.join(result.stderr, "\r\n") - ), - vim.log.levels.ERROR - ) + if result:failed() then + error(result:errors(), vim.log.levels.ERROR) end M.list = utils.from_json(result.stdout) diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua index a1250b8..0b8f2f9 100644 --- a/lua/laravel/status.lua +++ b/lua/laravel/status.lua @@ -22,7 +22,7 @@ local function get_values() end if environment.get_executable "artisan" then local res = api.sync("artisan", { "--version" }) - values.laravel = res.stdout[1]:match "Laravel Framework ([%d%.]+)" + values.laravel = res:first():match "Laravel Framework ([%d%.]+)" end last_check = os.time() end diff --git a/lua/laravel/telescope/pickers/related.lua b/lua/laravel/telescope/pickers/related.lua index 83c709b..1d4044d 100644 --- a/lua/laravel/telescope/pickers/related.lua +++ b/lua/laravel/telescope/pickers/related.lua @@ -40,19 +40,13 @@ return function(opts) local class = get_model_class_name() if class ~= "" then local result = api.sync("artisan", { "model:show", class, "--json" }) - if result.exit_code ~= 0 then - error( - string.format("'php artisan model:show %s --json' failed %s", class, vim.inspect(result.stderr)), - vim.log.levels.ERROR - ) + if result:failed() then + error(result:errors(), vim.log.levels.ERROR) end local model_info = vim.fn.json_decode(result.stdout[1]) if model_info == nil then - error( - string.format("'php artisan model:show %s --json' response could not be decoded", class), - vim.log.levels.ERROR - ) + error(string.format("'artisan model:show %s --json' response could not be decoded", class), vim.log.levels.ERROR) end local build_relation = function(info, relation_type) diff --git a/lua/laravel/tinker/init.lua b/lua/laravel/tinker/init.lua index 8d06bf2..6489dba 100644 --- a/lua/laravel/tinker/init.lua +++ b/lua/laravel/tinker/init.lua @@ -1,4 +1,3 @@ -local notify = require "laravel.notify" local run = require "laravel.run" local get_selection = require "laravel.tinker.get_selection" @@ -15,8 +14,7 @@ function M.send_to_tinker() if nil == M.current_terminal then run("artisan", { "tinker" }, { focus = false }) if nil == M.current_terminal then - notify("Send To Tinker", { msg = "Tinker terminal id not found and could create it", level = "ERROR" }) - return + error("Tinker terminal id not found and could create it", vim.log.levels.ERROR) end end diff --git a/lua/laravel/user_commands/composer.lua b/lua/laravel/user_commands/composer.lua index 1364c59..11e38f8 100644 --- a/lua/laravel/user_commands/composer.lua +++ b/lua/laravel/user_commands/composer.lua @@ -1,4 +1,3 @@ -local notify = require "laravel.notify" local create_user_command = require "laravel.user_commands.create_user_command" local run = require "laravel.run" local api = require "laravel.api" @@ -25,8 +24,7 @@ function M.setup() remove = function(cmd) if #cmd == 0 then - notify("composer.remove", { msg = "Need arguement for composer remove", level = "ERROR" }) - return + error("Needs argument for composer remove", vim.log.levels.ERROR) end table.insert(cmd, 1, "remove") run("composer", cmd, {}) @@ -34,7 +32,7 @@ function M.setup() ["dump-autoload"] = function() api.async("composer", { "dump-autoload" }, function() - notify("composer.dump-autoload", { msg = "Completed", level = "INFO" }) + vim.notify("Composer Dump autoload Completed", vim.log.levels.INFO) end) end, }) diff --git a/lua/laravel/user_commands/docker_compose.lua b/lua/laravel/user_commands/docker_compose.lua index bfb27b0..fca5f3b 100644 --- a/lua/laravel/user_commands/docker_compose.lua +++ b/lua/laravel/user_commands/docker_compose.lua @@ -1,4 +1,3 @@ -local notify = require "laravel.notify" local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" local api = require "laravel.api" @@ -12,57 +11,61 @@ function M.setup() create_user_command("DockerCompose", "compose", { up = function() - api.async("compose", { "up", "-d" }, function(j, exit_code) - if exit_code ~= 0 then - notify( - "compose.up", - { msg = string.format("Error on Compose up. %s", vim.inspection(j:result())), level = "ERROR" } - ) - - return + api.async( + "compose", + { "up", "-d" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + vim.notify("Compose Up Completed", vim.log.levels.INFO) end - notify("compose.up", { msg = "Completed", level = "INFO" }) - end) + ) end, ps = function() - api.async("compose", { "ps" }, function(j, exit_code) - if exit_code ~= 0 then - notify("compose.ps", { msg = "Failed to run compose up", level = "ERROR" }) - - return + api.async( + "compose", + { "ps" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + vim.notify(response:prettyContent(), vim.log.levels.INFO) end - notify("compose.ps", { raw = j:result(), level = "INFO" }) - end) + ) end, restart = function() - api.async("compose", { "restart" }, function(j, exit_code) - if exit_code ~= 0 then - notify( - "compose.restart", - { msg = string.format("Failed to restart compose. %s", vim.inspect(j:result())), level = "ERROR" } - ) + api.async( + "compose", + { "restart" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end - return + vim.notify("Compose restart complete", vim.log.levels.INFO) end - notify("compose.restart", { msg = "compose restart complete", level = "INFO" }) - end) - notify("compose.restart", { msg = "compose restart starting", level = "INFO" }) + ) + vim.notify("Compose restart starting", vim.log.levels.INFO) end, down = function() - api.async("compose", { "down" }, function(j, exit_code) - if exit_code ~= 0 then - notify( - "compose.down", - { msg = string.format("Failed to down compose. %s", vim.inspect(j:result())), level = "ERROR" } - ) - - return + api.async( + "compose", + { "down" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + vim.notify("Compose Down complete", vim.log.levels.INFO) end - notify("compose.down", { msg = "compose Down complete", level = "INFO" }) - end) + ) end, }) end diff --git a/lua/laravel/user_commands/laravel/init.lua b/lua/laravel/user_commands/laravel/init.lua index 7c09efa..f30eb7a 100644 --- a/lua/laravel/user_commands/laravel/init.lua +++ b/lua/laravel/user_commands/laravel/init.lua @@ -1,10 +1,8 @@ -local notify = require "laravel.notify" - local commands = { ["cache:clean"] = function() require("laravel.commands").list = {} require("laravel.routes").list = {} - notify("laravel.cache:clean", { msg = "Cache cleaned", level = "INFO" }) + vim.notify("Laravel plugin cache cleaned", vim.log.levels.INFO) end, ["routes"] = require("telescope").extensions.laravel.routes, ["artisan"] = require("telescope").extensions.laravel.commands, diff --git a/lua/laravel/user_commands/sail.lua b/lua/laravel/user_commands/sail.lua index b40d051..6665640 100644 --- a/lua/laravel/user_commands/sail.lua +++ b/lua/laravel/user_commands/sail.lua @@ -1,5 +1,4 @@ local run = require "laravel.run" -local notify = require "laravel.notify" local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" local api = require "laravel.api" @@ -13,14 +12,18 @@ function M.setup() create_user_command("Sail", "sail", { up = function() - api.async("sail", { "up", "-d" }, function(j, exit_code) - if exit_code ~= 0 then - notify("sail.up", { msg = string.format("Error on Sail up. %s", vim.inspect(j:result())), level = "ERROR" }) + api.async( + "sail", + { "up", "-d" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:content(), vim.log.levels.ERROR) + end - return + vim.notify("Sail up completed", vim.log.levels.INFO) end - notify("sail.up", { msg = "Completed", level = "INFO" }) - end) + ) end, shell = function() @@ -28,43 +31,46 @@ function M.setup() end, ps = function() - api.async("sail", { "ps" }, function(j, exit_code) - if exit_code ~= 0 then - notify("sail.ps", { msg = "Failed to run Sail up", level = "ERROR" }) - - return + api.async( + "sail", + { "ps" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + vim.notify(response:prettyContent(), vim.log.levels.INFO) end - notify("sail.ps", { raw = vim.fn.join(j:result(), "\n"), level = "INFO" }) - end) + ) end, restart = function() - api.async("sail", { "restart" }, function(j, exit_code) - if exit_code ~= 0 then - notify( - "sail.restart", - { msg = string.format("Failed to restart Sail. %s", vim.inspect(j:result())), level = "ERROR" } - ) - - return + api.async( + "sail", + { "restart" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + vim.notify("Sail restart complete", vim.log.levels.INFO) end - notify("sail.restart", { msg = "Sail restart complete", level = "INFO" }) - end) - notify("sail.restart", { msg = "Sail restart starting", level = "INFO" }) + ) + vim.notify("Sail restart starting", vim.log.levels.INFO) end, down = function() - api.async("sail", { "down" }, function(j, exit_code) - if exit_code ~= 0 then - notify( - "sail.down", - { msg = string.format("Failed to down Sail. Error: %s", vim.inspect(j:result())), level = "ERROR" } - ) - - return + api.async( + "sail", + { "down" }, + ---@param response ApiResponse + function(response) + if response:failed() then + error(response:errors(), vim.log.levels.ERROR) + end + vim.notify("Sail Down complete", vim.log.levels.INFO) end - notify("sail.down", { msg = "Sail Down complete", level = "INFO" }) - end) + ) end, }) end diff --git a/lua/laravel/view_finder.lua b/lua/laravel/view_finder.lua index c2a7e35..510b7bd 100644 --- a/lua/laravel/view_finder.lua +++ b/lua/laravel/view_finder.lua @@ -1,6 +1,5 @@ local views = require "laravel.views" local utils = require "laravel.utils" -local notify = require "laravel.notify" local M = {} @@ -12,7 +11,7 @@ function M.go_to_usage() local matches = utils.runRipgrep(string.format("view\\(['\\\"]%s['\\\"]", view)) if #matches == 0 then - notify("laravel.views", { msg = "No usage of this view found", level = "WARN" }) + vim.notify("No usage of this view found", vim.log.levels.WARN) elseif #matches == 1 then vim.cmd("edit " .. matches[1].file) else @@ -37,13 +36,12 @@ function M.go_to_definition() local php_parser = vim.treesitter.get_parser(bufnr, "php") local tree = php_parser:parse()[1] if tree == nil then - notify("laravel.views", { msg = "Could not retrive syntax tree", level = "WARN" }) - return + error("Could not retrive syntax tree", vim.log.levels.ERROR) end local query = vim.treesitter.query.get("php", "laravel_views") - if true or query == nil then + if query == nil then vim.treesitter.query.set( "php", "laravel_views", @@ -58,8 +56,7 @@ function M.go_to_definition() query = vim.treesitter.query.get("php", "laravel_views") end if not query then - notify("laravel.views", { msg = "Could not get proper query", level = "WARN" }) - return + error("Could not get treesitter query", vim.log.levels.ERROR) end local founds = {} @@ -70,7 +67,7 @@ function M.go_to_definition() end if #founds == 0 then - notify("laravel.views", { msg = "No views found in file", level = "WARN" }) + vim.notify("No usage of this view found", vim.log.levels.WARN) return end From a251ca372fa260a95725ced1ada9eb935b545810 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 28 Dec 2023 12:37:21 +0100 Subject: [PATCH 50/55] feat: rework environment --- TODO.md | 29 ++++- lua/laravel/config/environments.lua | 43 +++++++ lua/laravel/config/init.lua | 9 +- lua/laravel/environment/docker_compose.lua | 34 ------ lua/laravel/environment/environment.lua | 107 ++++++++++++++++++ lua/laravel/environment/get_env.lua | 14 --- lua/laravel/environment/init.lua | 54 +++++++-- lua/laravel/environment/native.lua | 24 ---- lua/laravel/environment/resolver.lua | 58 ---------- lua/laravel/environment/sail.lua | 30 ----- lua/laravel/health.lua | 35 +++--- .../{laravel/init.lua => laravel.lua} | 4 +- lua/laravel/user_commands/laravel/info.lua | 35 ------ lua/laravel/utils.lua | 17 +++ 14 files changed, 262 insertions(+), 231 deletions(-) create mode 100644 lua/laravel/config/environments.lua delete mode 100644 lua/laravel/environment/docker_compose.lua create mode 100644 lua/laravel/environment/environment.lua delete mode 100644 lua/laravel/environment/get_env.lua delete mode 100644 lua/laravel/environment/native.lua delete mode 100644 lua/laravel/environment/resolver.lua delete mode 100644 lua/laravel/environment/sail.lua rename lua/laravel/user_commands/{laravel/init.lua => laravel.lua} (94%) delete mode 100644 lua/laravel/user_commands/laravel/info.lua diff --git a/TODO.md b/TODO.md index 71eec98..76fd509 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,6 @@ # Ideas ## To implement -```lua - [X] implement api - [X] implement ui - [X] implements a command history @@ -28,4 +27,32 @@ - [X] implement watch - [X] implement alternate file for livewire components `:A` - [X] extend api .sync and .async with better respons object. maybe create a new object with method for example `.successful()` and `.failed()` +- [ ] rework environment - [ ] re-write the readme and translate (not forget fd as dependency) move all info from readme to doc + +## Environment +How I want the environment + +I have environments, resolver and executables +In environment only have `executables` +I need to get from the configuration per project the executables + +I want it to be set on the configuration + +So do I need the resolver ? +Is not clear ? +I already have the `environment` term so it's hard to tink into ahother + +So I have diferent environments +Executables not found should use try to look for it +```lua +local environments = { + local = { + executables = { + artisan = {"php", "artisan"}, + composer = {"composer"}, + npm = {"npm"}, + } + } +} +``` diff --git a/lua/laravel/config/environments.lua b/lua/laravel/config/environments.lua new file mode 100644 index 0000000..893e3bb --- /dev/null +++ b/lua/laravel/config/environments.lua @@ -0,0 +1,43 @@ +return { + env_variable = "NVIM_LARAVEL_ENV", + auto_dicover = true, + default = "local", + definitions = { + ["sail"] = { + condition = { + file_exists = { "vendor/bin/sail", "docker-compose.yml" }, + }, + commands = { + sail = { "vendor/bin/sail" }, + { + commands = { "php", "composer", "npm", "yarn" }, + prefix = { "vendor/bin/sail" }, + }, + }, + }, + ["docker-compose"] = { + condition = { + file_exists = { "docker-compose.yml" }, + executable = { "docker" }, + }, + commands = { + compose = { "docker", "compose" }, + { + commands = { "php", "composer", "npm" }, + docker = { + container = { + env = "APP_SERVICE", + default = "app", + }, + exec = { "docker", "compose", "exec", "-it" }, + }, + }, + }, + }, + ["local"] = { + condition = { + executable = { "php" }, + }, + }, + }, +} diff --git a/lua/laravel/config/init.lua b/lua/laravel/config/init.lua index 1303d5b..cf13280 100644 --- a/lua/laravel/config/init.lua +++ b/lua/laravel/config/init.lua @@ -20,14 +20,7 @@ M.defaults = { ["docs"] = { ui = "popup", skip_args = true }, ["make:model"] = { options = { "-mf" } }, }, - environment = { - resolver = require "laravel.environment.resolver"(true, true, nil), - environments = { - ["local"] = require("laravel.environment.native").setup(), - ["sail"] = require("laravel.environment.sail").setup(), - ["docker-compose"] = require("laravel.environment.docker_compose").setup(), - }, - }, + environments = require "laravel.config.environments", resources = require "laravel.config.resources", } diff --git a/lua/laravel/environment/docker_compose.lua b/lua/laravel/environment/docker_compose.lua deleted file mode 100644 index b7bb3b8..0000000 --- a/lua/laravel/environment/docker_compose.lua +++ /dev/null @@ -1,34 +0,0 @@ -local get_env = require "laravel.environment.get_env" - -local M = {} - ----@param opts table|nil ----@return function -M.setup = function(opts) - return function() - opts = opts or {} - - local container = get_env "APP_SERVICE" or opts.container_name or "app" - - local cmd = opts.cmd or { "docker", "compose", "exec", "-it", container } - - local function get_cmd(args) - return vim.fn.extend(cmd, args) - end - - local executables = { - artisan = opts.artisan or get_cmd { "php", "artisan" }, - composer = opts.composer or get_cmd { "composer" }, - npm = opts.npm or get_cmd { "npm" }, - yarn = opts.yarn or get_cmd { "yarn" }, - php = opts.php or get_cmd { "php" }, - compose = opts.compose or { "docker", "compose" }, - } - - return { - executables = vim.tbl_deep_extend("force", executables, opts.executables or {}), - } - end -end - -return M diff --git a/lua/laravel/environment/environment.lua b/lua/laravel/environment/environment.lua new file mode 100644 index 0000000..4f96f9b --- /dev/null +++ b/lua/laravel/environment/environment.lua @@ -0,0 +1,107 @@ +local get_env = require("laravel.utils").get_env + +---@class Environment +---@field name string +---@field condition table|nil +---@field commands table +local Environment = {} + +local cache = {} + +---@param env table +---@return Environment +function Environment:new(name, env) + local obj = { + name = name, + condition = env.condition or nil, + commands = env.commands or {}, + } + + setmetatable(obj, self) + self.__index = self + + return obj +end + +---@return boolean +function Environment:check() + if not self.condition then + return true + end + + for _, file in pairs(self.condition.file_exists or {}) do + if vim.fn.filereadable(file) ~= 1 then + return false + end + end + + for _, exec in pairs(self.condition.executable or {}) do + if vim.fn.executable(exec) == 0 then + return false + end + end + + return true +end + +---@param name string +---@return table|nil +function Environment:executable(name) + if cache[name] then + return cache[name] + end + + -- check commands directly by name + if self.commands[name] then + cache[name] = self.commands[name] + return cache[name] + end + + for _, value in pairs(self.commands) do + if vim.tbl_contains(value.commands or {}, name) then + -- is on the list have to process it + if value.docker then + -- is set to run from docker + if not value.docker.container then + error( + "Configuration indicates docker but there is no container information, check the configuration", + vim.log.levels.ERROR + ) + end + + local container = value.docker.container.default + if value.docker.container.env and get_env(value.docker.container.env) then + container = get_env(value.docker.container.env) + end + + if not container then + error("Could not resolve container name check the configuration", vim.log.levels.ERROR) + end + + if not value.docker.exec then + error("Need to define a docker exec command", vim.log.levels.ERROR) + end + + cache[name] = vim.fn.extend(value.docker.exec, { container, name }) + + return cache[name] + end + + if value.prefix then + cache[name] = vim.fn.extend(value.prefix, { name }) + + return cache[name] + end + end + end + + -- if is not define look for the executable in the system + if vim.fn.executable(name) == 1 then + cache[name] = { name } + return { name } + end + + return nil +end + +return Environment diff --git a/lua/laravel/environment/get_env.lua b/lua/laravel/environment/get_env.lua deleted file mode 100644 index 1e1cd01..0000000 --- a/lua/laravel/environment/get_env.lua +++ /dev/null @@ -1,14 +0,0 @@ -return function(var) - local envVal - if vim.api.nvim_call_function("exists", { "*DotenvGet" }) == 1 then - envVal = vim.api.nvim_call_function("DotenvGet", { var }) - else - envVal = vim.api.nvim_call_function("eval", { "$" .. var }) - end - - if envVal == "" then - return nil - end - - return envVal -end diff --git a/lua/laravel/environment/init.lua b/lua/laravel/environment/init.lua index 919cf03..20777e5 100644 --- a/lua/laravel/environment/init.lua +++ b/lua/laravel/environment/init.lua @@ -1,22 +1,55 @@ local config = require "laravel.config" local user_commands = require "laravel.user_commands" +local get_env = require("laravel.utils").get_env +local Environment = require "laravel.environment.environment" local M = {} -M.environment = {} +M.environment = nil + +---@return Environment|nil +local function resolve() + local opts = config.options.environments + + if opts.env_variable then + local env_name = get_env(opts.env_variable) + if env_name and opts.definitions[env_name] then + return Environment:new(env_name, opts.definitions[env_name]) + end + end + + if opts.auto_dicover then + for name, opt in pairs(opts.definitions) do + local env = Environment:new(name, opt) + if env:check() then + return env + end + end + end + + if opts.default then + if opts.definitions[opts.default] then + return Environment:new(opts.default, opts.definitions[opts.default]) + end + end + + return nil +end function M.setup() - M.environment = {} + M.environment = nil if vim.fn.filereadable "artisan" == 0 then return end - M.environment = config.options.environment.resolver(config.options.environment.environments) - if type(M.environment) == "function" then - M.environment = M.environment() + M.environment = resolve() + + if not M.environment then + return end user_commands.setup() + if config.options.features.route_info.enable then require("laravel.route_info").setup() end @@ -29,14 +62,15 @@ end ---@param name string ---@return string[]|nil function M.get_executable(name) - if vim.tbl_isempty(M.environment) then + if not M.environment then return nil end - local executable = M.environment.executables[name] - if executable == nil then - return nil + + if name == "artisan" then + return vim.fn.extend(M.environment:executable "php", { "artisan" }) end - return executable + + return M.environment:executable(name) end return M diff --git a/lua/laravel/environment/native.lua b/lua/laravel/environment/native.lua deleted file mode 100644 index e803679..0000000 --- a/lua/laravel/environment/native.lua +++ /dev/null @@ -1,24 +0,0 @@ -local M = {} - ----@param opts table|nil ----@return function -M.setup = function(opts) - return function() - opts = opts or {} - - local executables = { - artisan = opts.artisan or { "php", "artisan" }, - composer = opts.composer or { "composer" }, - npm = opts.npm or { "npm" }, - bun = opts.bun or { "bun" }, - yarn = opts.yarn or { "yarn" }, - php = opts.php or { "php" }, - } - - return { - executables = vim.tbl_deep_extend("force", executables, opts.executables or {}), - } - end -end - -return M diff --git a/lua/laravel/environment/resolver.lua b/lua/laravel/environment/resolver.lua deleted file mode 100644 index bafce1f..0000000 --- a/lua/laravel/environment/resolver.lua +++ /dev/null @@ -1,58 +0,0 @@ -local get_env = require "laravel.environment.get_env" - ----@param env_check boolean ----@param auto_discovery boolean ----@param default string|nil -return function(env_check, auto_discovery, default) - return function(environments) - local env_name = get_env "NVIM_LARAVEL_ENV" - if env_check and env_name ~= nil then - local environment = environments[env_name] - if environment == nil then - vim.notify( - "NVIM_LARAVEL_ENV defined as " .. env_name .. " but there is no such environment defined", - vim.log.levels.ERROR - ) - return nil - else - return environment - end - end - - if auto_discovery then - -- check for sail - if - environments.sail ~= nil - and vim.fn.filereadable "vendor/bin/sail" == 1 - and vim.fn.filereadable "docker-compose.yml" == 1 - then - return environments.sail - end - -- check for docker-compose - if - environments["docker-compose"] ~= nil - and vim.fn.filereadable "docker-compose.yml" == 1 - and vim.fn.executable "docker" - then - return environments["docker-compose"] - end - -- check for native - if environments["local"] ~= nil and vim.fn.executable "php" then - return environments["local"] - end - end - - if default then - local environment = environments[default] - if environment == nil then - vim.notify("Default define as " .. default .. " but there is no environment define", vim.log.levels.ERROR) - return nil - else - return environment - end - end - - vim.notify("Could not resolve any environment please check your configuration", vim.log.levels.ERROR) - return nil - end -end diff --git a/lua/laravel/environment/sail.lua b/lua/laravel/environment/sail.lua deleted file mode 100644 index 00ce7dd..0000000 --- a/lua/laravel/environment/sail.lua +++ /dev/null @@ -1,30 +0,0 @@ -local M = {} - ----@param opts table|nil ----@return function -M.setup = function(opts) - return function() - opts = opts or {} - - local cmd = opts.cmd or { "vendor/bin/sail" } - - local function get_cmd(args) - return vim.fn.extend(cmd, args) - end - - local executables = { - artisan = opts.artisan or get_cmd { "artisan" }, - composer = opts.composer or get_cmd { "composer" }, - npm = opts.npm or get_cmd { "npm" }, - yarn = opts.yarn or get_cmd { "yarn" }, - sail = opts.sail or cmd, - php = opts.php or get_cmd { "php" }, - } - - return { - executables = vim.tbl_deep_extend("force", executables, opts.executables or {}), - } - end -end - -return M diff --git a/lua/laravel/health.lua b/lua/laravel/health.lua index 923a752..61407e6 100644 --- a/lua/laravel/health.lua +++ b/lua/laravel/health.lua @@ -14,29 +14,34 @@ M.check = function() ) end - if vim.tbl_isempty(environment.environment) then + if vim.fn.executable "rg" == 1 then + vim.health.report_ok "rg installed" + else + vim.health.report_warn( + "ripgrep is missing, is required for finding view usage", + { "Installed from your package manager" } + ) + end + + vim.health.report_start "Environment" + + if not environment.environment then vim.health.report_error( "Environment not configure for this directory, no more checks", { "Check project is laravel, current directory `:pwd` is the root of laravel project" } ) return end - vim.health.report_ok "Environment setup complete" - vim.health.report_start "Environment" + vim.health.report_ok "Environment setup successful" - if vim.tbl_isempty(environment.environment.executables) then - vim.health.report_error "No executables found in the environment, check the environment config" - return - end + vim.health.report_info("Name: " .. environment.environment.name) + vim.health.report_info "Condition: " + vim.health.report_info(vim.inspect(environment.environment.condition)) + vim.health.report_info "Commands: " + vim.health.report_info(vim.inspect(environment.environment.commands)) - for name, command in pairs(environment.environment.executables) do - if vim.fn.executable(command[1]) == 1 then - vim.health.report_ok(string.format("%s: executable %s exists", name, command[1])) - else - vim.health.report_error(string.format("%s: executable %s does not exists", name, command[1])) - end - end + vim.health.report_start "Composer Dependencies" if not environment.get_executable "composer" then vim.health.report_error "Composer executable not found can't check dependencies" @@ -53,8 +58,6 @@ M.check = function() }, } - vim.health.report_start "Composer dependencies" - for _, dependency in pairs(composer_dependencies) do if api.is_composer_package_install(dependency.name) then vim.health.report_ok(string.format("Composer dependency `%s` is installed", dependency.name)) diff --git a/lua/laravel/user_commands/laravel/init.lua b/lua/laravel/user_commands/laravel.lua similarity index 94% rename from lua/laravel/user_commands/laravel/init.lua rename to lua/laravel/user_commands/laravel.lua index f30eb7a..2fbea12 100644 --- a/lua/laravel/user_commands/laravel/init.lua +++ b/lua/laravel/user_commands/laravel.lua @@ -13,7 +13,9 @@ local commands = { ["history"] = require("telescope").extensions.laravel.history, ["recipes"] = require("laravel.recipes").run, ["view-finder"] = require("laravel.view_finder").auto, - ["info"] = require "laravel.user_commands.laravel.info", + ["health"] = function() + vim.cmd [[checkhealth laravel]] + end, } return { diff --git a/lua/laravel/user_commands/laravel/info.lua b/lua/laravel/user_commands/laravel/info.lua deleted file mode 100644 index 47ec245..0000000 --- a/lua/laravel/user_commands/laravel/info.lua +++ /dev/null @@ -1,35 +0,0 @@ -local Popup = require "nui.popup" -local event = require("nui.utils.autocmd").event -local environment = require "laravel.environment" -local config = require "laravel.config" - -return function() - local popup = Popup { - enter = true, - focusable = true, - border = { - style = "rounded", - }, - position = "50%", - size = { - width = "80%", - height = "60%", - }, - } - - -- mount/open the component - popup:mount() - - -- unmount component when cursor leaves buffer - popup:on(event.BufLeave, function() - popup:unmount() - end) - - vim.api.nvim_buf_set_lines( - popup.bufnr, - 0, - 1, - false, - vim.fn.split(vim.inspect { environment = environment.environment, options = config.options }, "\n") - ) -end diff --git a/lua/laravel/utils.lua b/lua/laravel/utils.lua index 3a3fec4..61632a1 100644 --- a/lua/laravel/utils.lua +++ b/lua/laravel/utils.lua @@ -21,4 +21,21 @@ function M.runRipgrep(pattern) return matches end +---@param var string +---@return string|nil +function M.get_env(var) + local envVal + if vim.api.nvim_call_function("exists", { "*DotenvGet" }) == 1 then + envVal = vim.api.nvim_call_function("DotenvGet", { var }) + else + envVal = vim.api.nvim_call_function("eval", { "$" .. var }) + end + + if envVal == "" then + return nil + end + + return envVal +end + return M From 174374a6766c9577d19186e9a804ad9bb49abc6f Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 28 Dec 2023 15:22:11 +0100 Subject: [PATCH 51/55] fix: get of the status --- lua/laravel/status.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua index 0b8f2f9..3dfc4fe 100644 --- a/lua/laravel/status.lua +++ b/lua/laravel/status.lua @@ -18,11 +18,19 @@ local function get_values() end if environment.get_executable "php" then local res = api.sync("php", { "-v" }) - values.php = res.stdout[1]:match "PHP ([%d%.]+)" + if res:failed() then + values.php = "" + else + values.php = res:first():match "PHP ([%d%.]+)" + end end if environment.get_executable "artisan" then local res = api.sync("artisan", { "--version" }) - values.laravel = res:first():match "Laravel Framework ([%d%.]+)" + if res:failed() then + values.laravel = "" + else + values.laravel = res:first():match "Laravel Framework ([%d%.]+)" + end end last_check = os.time() end From 51f8a033e85c4dc4970d6b3b4d2815f572bec4d5 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 28 Dec 2023 15:44:14 +0100 Subject: [PATCH 52/55] fix: status commands and use of error function --- lua/laravel/api/response.lua | 13 ++++++++++-- lua/laravel/recipes/doctrine-dbal.lua | 5 +++-- lua/laravel/recipes/ide-helper.lua | 14 ++++++------- lua/laravel/resources/create.lua | 9 ++++++--- lua/laravel/user_commands/docker_compose.lua | 21 +++++++++++--------- lua/laravel/user_commands/sail.lua | 21 +++++++++++--------- 6 files changed, 51 insertions(+), 32 deletions(-) diff --git a/lua/laravel/api/response.lua b/lua/laravel/api/response.lua index 0d0b0fe..fbcbf85 100644 --- a/lua/laravel/api/response.lua +++ b/lua/laravel/api/response.lua @@ -40,7 +40,7 @@ end ---@return string function ApiResponse:prettyContent() - return vim.inspect(self:content()) + return table.concat(self:content(), "\r\n") end ---@return string|nil @@ -54,7 +54,7 @@ end ---@return string[]|nil function ApiResponse:errors() - if self:failed() then + if self:successful() then return nil end @@ -65,4 +65,13 @@ function ApiResponse:errors() return self:content() end +function ApiResponse:prettyErrors() + local errors = self:errors() + if not errors then + return "" + end + + return table.concat(errors, "\r\n") +end + return ApiResponse diff --git a/lua/laravel/recipes/doctrine-dbal.lua b/lua/laravel/recipes/doctrine-dbal.lua index 109dce3..f91deef 100644 --- a/lua/laravel/recipes/doctrine-dbal.lua +++ b/lua/laravel/recipes/doctrine-dbal.lua @@ -10,9 +10,10 @@ function M.run() ---@param response ApiResponse function(response) if response:failed() then - error({ "Cant install doctrine/dbal", response:errors() }, vim.log.levels.ERROR) + vim.notify("Cant install doctrine/dbal\n\r" .. response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Installation completed", vim.log.levels.INFO) end - vim.notify("Installation completed", vim.log.levels.INFO) end ) else diff --git a/lua/laravel/recipes/ide-helper.lua b/lua/laravel/recipes/ide-helper.lua index 29271c6..96dc6d2 100644 --- a/lua/laravel/recipes/ide-helper.lua +++ b/lua/laravel/recipes/ide-helper.lua @@ -9,10 +9,10 @@ local function writeModels() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Ide Helper Models Complete", vim.log.levels.INFO) end - - vim.notify("Ide Helper Models Complete", vim.log.levels.INFO) end ) end @@ -24,11 +24,11 @@ local function installIdeHelperAndWrite() ---@param response ApiResponse function(response) if response:failed() then - error({ "Cant install ide-helper", response:errors() }, vim.log.levels.ERROR) + vim.notify("Cant install ide-helper\n\r" .. response:prettyErrors(), vim.log.levels.ERROR) + else + require("laravel.commands").list = {} + writeModels() end - - require("laravel.commands").list = {} - writeModels() end ) end diff --git a/lua/laravel/resources/create.lua b/lua/laravel/resources/create.lua index 34da053..d48f92d 100644 --- a/lua/laravel/resources/create.lua +++ b/lua/laravel/resources/create.lua @@ -7,7 +7,9 @@ return function(command) local name = command[2] if not is_resource(resource) then - error(string.format("Command %s is not a resource creation suported", resource), vim.log.levels.ERROR) + vim.notify(string.format("Command %s is not a resource creation suported", resource), vim.log.levels.ERROR) + + return end api.async( @@ -16,9 +18,10 @@ return function(command) ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + open(resource, name) end - open(resource, name) end ) end diff --git a/lua/laravel/user_commands/docker_compose.lua b/lua/laravel/user_commands/docker_compose.lua index fca5f3b..7d527ad 100644 --- a/lua/laravel/user_commands/docker_compose.lua +++ b/lua/laravel/user_commands/docker_compose.lua @@ -17,9 +17,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Compose Up Completed", vim.log.levels.INFO) end - vim.notify("Compose Up Completed", vim.log.levels.INFO) end ) end, @@ -31,9 +32,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify(response:prettyContent(), vim.log.levels.INFO) end - vim.notify(response:prettyContent(), vim.log.levels.INFO) end ) end, @@ -45,10 +47,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Compose restart complete", vim.log.levels.INFO) end - - vim.notify("Compose restart complete", vim.log.levels.INFO) end ) vim.notify("Compose restart starting", vim.log.levels.INFO) @@ -61,9 +63,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Compose Down complete", vim.log.levels.INFO) end - vim.notify("Compose Down complete", vim.log.levels.INFO) end ) end, diff --git a/lua/laravel/user_commands/sail.lua b/lua/laravel/user_commands/sail.lua index 6665640..430054f 100644 --- a/lua/laravel/user_commands/sail.lua +++ b/lua/laravel/user_commands/sail.lua @@ -18,10 +18,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:content(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Sail up completed", vim.log.levels.INFO) end - - vim.notify("Sail up completed", vim.log.levels.INFO) end ) end, @@ -37,9 +37,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify(response:prettyContent(), vim.log.levels.INFO) end - vim.notify(response:prettyContent(), vim.log.levels.INFO) end ) end, @@ -51,9 +52,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Sail restart complete", vim.log.levels.INFO) end - vim.notify("Sail restart complete", vim.log.levels.INFO) end ) vim.notify("Sail restart starting", vim.log.levels.INFO) @@ -66,9 +68,10 @@ function M.setup() ---@param response ApiResponse function(response) if response:failed() then - error(response:errors(), vim.log.levels.ERROR) + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Sail Down complete", vim.log.levels.INFO) end - vim.notify("Sail Down complete", vim.log.levels.INFO) end ) end, From b2ba0a6670d7b09c854c66d7d06fa77f27ceea08 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 28 Dec 2023 15:54:09 +0100 Subject: [PATCH 53/55] fix: use async for getting the status values --- lua/laravel/status.lua | 36 +++++++++++++------- lua/laravel/user_commands/docker_compose.lua | 2 ++ lua/laravel/user_commands/sail.lua | 2 ++ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/lua/laravel/status.lua b/lua/laravel/status.lua index 3dfc4fe..baee57a 100644 --- a/lua/laravel/status.lua +++ b/lua/laravel/status.lua @@ -17,20 +17,28 @@ local function get_values() return end if environment.get_executable "php" then - local res = api.sync("php", { "-v" }) - if res:failed() then - values.php = "" - else - values.php = res:first():match "PHP ([%d%.]+)" - end + api.async( + "php", + { "-v" }, + ---@param response ApiResponse + function(response) + if response:successful() then + values.php = response:first():match "PHP ([%d%.]+)" + end + end + ) end if environment.get_executable "artisan" then - local res = api.sync("artisan", { "--version" }) - if res:failed() then - values.laravel = "" - else - values.laravel = res:first():match "Laravel Framework ([%d%.]+)" - end + api.async( + "artisan", + { "--version" }, + ---@param response ApiResponse + function(response) + if response:successful() then + values.laravel = response:first():match "Laravel Framework ([%d%.]+)" + end + end + ) end last_check = os.time() end @@ -63,4 +71,8 @@ function M.has(property) return properties[property].has() end +function M.refresh() + last_check = nil +end + return M diff --git a/lua/laravel/user_commands/docker_compose.lua b/lua/laravel/user_commands/docker_compose.lua index 7d527ad..99c5064 100644 --- a/lua/laravel/user_commands/docker_compose.lua +++ b/lua/laravel/user_commands/docker_compose.lua @@ -1,6 +1,7 @@ local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" local api = require "laravel.api" +local status = require "laravel.status" local M = {} @@ -20,6 +21,7 @@ function M.setup() vim.notify(response:prettyErrors(), vim.log.levels.ERROR) else vim.notify("Compose Up Completed", vim.log.levels.INFO) + status.refresh() end end ) diff --git a/lua/laravel/user_commands/sail.lua b/lua/laravel/user_commands/sail.lua index 430054f..5925667 100644 --- a/lua/laravel/user_commands/sail.lua +++ b/lua/laravel/user_commands/sail.lua @@ -2,6 +2,7 @@ local run = require "laravel.run" local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" local api = require "laravel.api" +local status = require "laravel.status" local M = {} @@ -21,6 +22,7 @@ function M.setup() vim.notify(response:prettyErrors(), vim.log.levels.ERROR) else vim.notify("Sail up completed", vim.log.levels.INFO) + status.refresh() end end ) From 60d73f96c5f6b4f1691473cc8307f91826537134 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 28 Dec 2023 16:13:08 +0100 Subject: [PATCH 54/55] feature: add dinamicaly the sail and docker compose commands to laravel one --- .../user_commands/create_user_command.lua | 26 +++- lua/laravel/user_commands/docker_compose.lua | 5 - lua/laravel/user_commands/laravel.lua | 33 ++--- lua/laravel/user_commands/sail.lua | 133 +++++++++--------- 4 files changed, 100 insertions(+), 97 deletions(-) diff --git a/lua/laravel/user_commands/create_user_command.lua b/lua/laravel/user_commands/create_user_command.lua index 0282a80..2d1ecb0 100644 --- a/lua/laravel/user_commands/create_user_command.lua +++ b/lua/laravel/user_commands/create_user_command.lua @@ -1,6 +1,13 @@ local run = require "laravel.run" +local environment = require "laravel.environment" return function(name, executable, commands, opts) + if executable then + if not environment.get_executable(executable) then + return + end + end + vim.api.nvim_create_user_command( name, function(args) @@ -10,10 +17,25 @@ return function(name, executable, commands, opts) return commands[command](args.fargs) end - return run(executable, args.fargs, {}) + if not command then + vim.ui.select(vim.fn.sort(vim.tbl_keys(commands)), { prompt = name }, function(action) + if not action then + return + end + if commands[action] ~= nil then + commands[action]() + end + end) + + return + end + + if executable then + return run(executable, args.fargs, {}) + end end, vim.tbl_deep_extend("force", { - nargs = "+", + nargs = "*", complete = function() return vim.tbl_keys(commands) end, diff --git a/lua/laravel/user_commands/docker_compose.lua b/lua/laravel/user_commands/docker_compose.lua index 99c5064..110447e 100644 --- a/lua/laravel/user_commands/docker_compose.lua +++ b/lua/laravel/user_commands/docker_compose.lua @@ -1,4 +1,3 @@ -local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" local api = require "laravel.api" local status = require "laravel.status" @@ -6,10 +5,6 @@ local status = require "laravel.status" local M = {} function M.setup() - if environment.get_executable "compose" == nil then - return - end - create_user_command("DockerCompose", "compose", { up = function() api.async( diff --git a/lua/laravel/user_commands/laravel.lua b/lua/laravel/user_commands/laravel.lua index 2fbea12..29ea360 100644 --- a/lua/laravel/user_commands/laravel.lua +++ b/lua/laravel/user_commands/laravel.lua @@ -1,3 +1,6 @@ +local create_user_command = require "laravel.user_commands.create_user_command" +local environment = require "laravel.environment" + local commands = { ["cache:clean"] = function() require("laravel.commands").list = {} @@ -20,26 +23,16 @@ local commands = { return { setup = function() - vim.api.nvim_create_user_command("Laravel", function(args) - local command = args.fargs[1] - if commands[command] ~= nil then - table.remove(args.fargs, 1) - return commands[command](unpack(args.fargs)) + if environment.get_executable "sail" then + commands["sail"] = function() + vim.cmd [[Sail]] end - - vim.ui.select(vim.fn.sort(vim.tbl_keys(commands)), { prompt = "Laravel Plugin:" }, function(action) - if not action then - return - end - if commands[action] ~= nil then - commands[action]() - end - end) - end, { - nargs = "*", - complete = function() - return vim.tbl_keys(commands) - end, - }) + end + if environment.get_executable "compose" then + commands["docker-compose"] = function() + vim.cmd [[DockerCompose]] + end + end + create_user_command("Laravel", nil, commands) end, } diff --git a/lua/laravel/user_commands/sail.lua b/lua/laravel/user_commands/sail.lua index 5925667..0f4e46d 100644 --- a/lua/laravel/user_commands/sail.lua +++ b/lua/laravel/user_commands/sail.lua @@ -1,83 +1,76 @@ local run = require "laravel.run" -local environment = require "laravel.environment" local create_user_command = require "laravel.user_commands.create_user_command" local api = require "laravel.api" local status = require "laravel.status" -local M = {} - -function M.setup() - if environment.get_executable "sail" == nil then - return - end - - create_user_command("Sail", "sail", { - up = function() - api.async( - "sail", - { "up", "-d" }, - ---@param response ApiResponse - function(response) - if response:failed() then - vim.notify(response:prettyErrors(), vim.log.levels.ERROR) - else - vim.notify("Sail up completed", vim.log.levels.INFO) - status.refresh() +return { + setup = function() + create_user_command("Sail", "sail", { + up = function() + api.async( + "sail", + { "up", "-d" }, + ---@param response ApiResponse + function(response) + if response:failed() then + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Sail up completed", vim.log.levels.INFO) + status.refresh() + end end - end - ) - end, + ) + end, - shell = function() - run("sail", { "shell" }, {}) - end, + shell = function() + run("sail", { "shell" }, {}) + end, - ps = function() - api.async( - "sail", - { "ps" }, - ---@param response ApiResponse - function(response) - if response:failed() then - vim.notify(response:prettyErrors(), vim.log.levels.ERROR) - else - vim.notify(response:prettyContent(), vim.log.levels.INFO) + ps = function() + api.async( + "sail", + { "ps" }, + ---@param response ApiResponse + function(response) + if response:failed() then + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify(response:prettyContent(), vim.log.levels.INFO) + end end - end - ) - end, + ) + end, - restart = function() - api.async( - "sail", - { "restart" }, - ---@param response ApiResponse - function(response) - if response:failed() then - vim.notify(response:prettyErrors(), vim.log.levels.ERROR) - else - vim.notify("Sail restart complete", vim.log.levels.INFO) + restart = function() + api.async( + "sail", + { "restart" }, + ---@param response ApiResponse + function(response) + if response:failed() then + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Sail restart complete", vim.log.levels.INFO) + end end - end - ) - vim.notify("Sail restart starting", vim.log.levels.INFO) - end, + ) + vim.notify("Sail restart starting", vim.log.levels.INFO) + end, - down = function() - api.async( - "sail", - { "down" }, - ---@param response ApiResponse - function(response) - if response:failed() then - vim.notify(response:prettyErrors(), vim.log.levels.ERROR) - else - vim.notify("Sail Down complete", vim.log.levels.INFO) + down = function() + api.async( + "sail", + { "down" }, + ---@param response ApiResponse + function(response) + if response:failed() then + vim.notify(response:prettyErrors(), vim.log.levels.ERROR) + else + vim.notify("Sail Down complete", vim.log.levels.INFO) + end end - end - ) - end, - }) -end - -return M + ) + end, + }) + end, +} From 6c4f8818b8c75d554f3907501cd21c23c6aa31e6 Mon Sep 17 00:00:00 2001 From: Ariel D'Alessandro Date: Thu, 28 Dec 2023 21:34:52 +0100 Subject: [PATCH 55/55] feat: improve readme --- README.md | 295 ++++++------------------- TODO.md | 31 +-- lua/laravel/config/command_options.lua | 4 + lua/laravel/config/default.lua | 17 ++ lua/laravel/config/init.lua | 23 +- lua/laravel/config/ui.lua | 1 + 6 files changed, 97 insertions(+), 274 deletions(-) create mode 100644 lua/laravel/config/command_options.lua create mode 100644 lua/laravel/config/default.lua diff --git a/README.md b/README.md index d091854..fde347e 100644 --- a/README.md +++ b/README.md @@ -4,15 +4,17 @@ Plugin for Neovim to enhance the development experience of Laravel projects Quick executing of artisan commands, list and navigate to routes. Information about the routes. Robust API to allow you to run any command in the way that you need. -# Preview +## Preview ![](./images/telescope_commands.png) ![](./images/telescope_routes.png) ![](./images/route_info.png) -# Requirements +## Requirements Treesitter, LSP Server (I use and recommend [phpactor](https://github.com/phpactor/phpactor)) +`fd` to look for files as migrations when are created +`rg` ripgrep to look usage of views -# Installation +## Installation Lazy ```lua return { @@ -27,23 +29,15 @@ return { { "la", ":Laravel artisan" }, { "lr", ":Laravel routes" }, { "lm", ":Laravel related" }, - { - "lt", - function() - require("laravel.tinker").send_to_tinker() - end, - mode = "v", - desc = "Laravel Application Routes", - }, }, event = { "VeryLazy" }, config = true, } ``` - Dotenv is use to read environment variables from the `.env` file -For nicer notifications use `rcarriga/nvim-notify` +For nicer notifications I recommend `rcarriga/nvim-notify` + My lazy configuration for notify is ```lua return { @@ -58,120 +52,58 @@ return { } ``` -Default configuration -```lua -{ - split = { - relative = "editor", - position = "right", - size = "30%", - enter = true, - }, - lsp_server = "phpactor", - register_user_commands = true, - route_info = { - enable = true, - position = "right", - }, - default_runner = "buffer", - commands_runner = { - ["dump-server"] = { runner = "persist" }, - ["queue:listen"] = { runner = "persist" }, - ["serve"] = { runner = "persist" }, - ["websockets"] = { runner = "persist" }, - ["queue:restart"] = { runner = "watch" }, - ["tinker"] = { runner = "terminal", skip_args = true }, - ["db"] = { runner = "terminal" }, - }, - environment = { - resolver = require "laravel.environment.resolver"(true, true, nil), - environments = { - ["local"] = require("laravel.environment.native").setup(), - ["sail"] = require("laravel.environment.sail").setup(), - ["docker-compose"] = require("laravel.environment.docker_compose").setup(), - }, - }, - resources = { - ["make:cast"] = "app/Casts", - ["make:channel"] = "app/Broadcasting", - ["make:command"] = "app/Console/Commands", - ["make:component"] = "app/View/Components", - ["make:controller"] = "app/Http/Controllers", - ["make:event"] = "app/Events", - ["make:exception"] = "app/Exceptions", - ["make:factory"] = function(name) - return string.format("database/factories/%sFactory.php", name), nil - end, - ["make:job"] = "app/Jobs", - ["make:listener"] = "app/Listeners", - ["make:mail"] = "app/Mail", - ["make:middleware"] = "app/Http/Middleware", - ["make:migration"] = function(name) - local result = require("laravel.runners").sync { "fd", name .. ".php" } - if result.exit_code == 1 then - return "", result.error - end - - return result.out, nil - end, - ["make:model"] = "app/Models", - ["make:notification"] = "app/Notifications", - ["make:observer"] = "app/Observers", - ["make:policy"] = "app/Policies", - ["make:provider"] = "app/Providers", - ["make:request"] = "app/Http/Requests", - ["make:resource"] = "app/Http/Resources", - ["make:rule"] = "app/Rules", - ["make:scope"] = "app/Models/Scopes", - ["make:seeder"] = "database/seeders", - ["make:test"] = "tests/Feature", - } -} -``` +## Config -## Environments -There are many ways to run your laravel application, could be natively in you computer, using docker-compose, using sail, or others. -Even using docker-compose you could have differences from project to project. -In order to support this there is an `environment` configuration. Here you can set 2 properties. -`resolver` takes care of determining which environment to use. -The resolver will return the environment to use. The resolver will first look for an environment variable `NVIM_LARAVEL_ENV` which should correspond to configured environment name. -If is not set it will be ignored, if it is set but could not be found an error will be thrown. -Next is the auto auto-discovery this will look for docker-compose file and Sail file in the vendor directory. If they are present Sail will be used. -If only docker-compose.yml file is present docker-compose environment will be used. -If both checks fail will check if the php is executable and then local environment will be used. -The third part is try to use the provided default. -You can configure the resolver by passing parameters -```lua ----@param env_check boolean ----@param auto_discovery boolean ----@param default string|nil -return function(env_check, auto_discovery, default) -``` -Resolver can be configured to ignore environment variable, ignore auto-discovery and just use the default -```lua - resolver = require "laravel.environment.resolver"(false, false, "sail"), -``` +Default [config]("./lua/laravel/config/default.lua"), this can be set on the `setup` function +In this config there are several secitions, like `lsp_server` which is use to interact with neovim lsp client to look for classes by the name. +Currently support `phpactor` and `intelephense` as far as I know there are no other php lsp sever. + +By default the plugin register several commands like `Artisan` `Composer` `Npm` `Sail` `DockerCompose` `Yarn` and `Bun` if you don't want them you can use +`register_user_commands` and set it as `false`. -The environment needs to return a function that returns a list of executables in format of a table. This will be used when running the `run` method on the application `require('laravel.application').run('', {"args"}, {options})` -Let say you want to modify the Sail command, you can do it by calling the setup method on the environment Sail with options cmd -```lua - ["sail"] = require("laravel.environment.sail").setup({cmd = {"my-sail-binary"}}), -``` -You can set different commands for normal executables, or completely replace all the executables. -If you add your executable you can call it using -`require('laravel.application).run('executable', args, options)` -Changing the container name for docker compose +## Features +In adition to the selector for the commands, routes and api, you can use some extras features *Route Info* *Views Completion* *Routes Completion* +Route info can be seen in the above screenshots, this allows to see in the controller the route associated to it, and in case that is missing will +add a diagnostic error which indicate which method is missing. +![](./images/route_info.png) +This also will show error if a route is defined but the method is not defined +![](./images/missing_method.png) + +> Note: using lazy is likely that you will not see at first since the plugin will not load until you call one of the commands, after that it is just picked up + +The completions uses `none-ls` which was previusly know as `null-ls`. +Views and Routes completion works as providing the list of the respective in the php files for the function `view` and `route`. + +## UI +An important part of the plugin is how to show the results of the commands, for this I decide to use `nui` this allow to easily interact with split and popup +You can customize from the size and options. examples can be seen in the default [here](./lua/laravel/config/ui.lua) + +## Command Options +Of course not all the commands want to be run in the same way. you can specify for example which `ui` to use, if should `skip_args`. +Can also set `nui_opts` to define how the ui should display. +Also can define options this is usefull for example for `make:model` you may want to always use the flags `-mf` ```lua - require("laravel").setup({ - environment = { - environments = { - ["docker-compose"] = require("laravel.environment.docker_compose").setup({container_name = "testing"}), - } - } - }) + ["make:model"] = { options = { "-mf" } }, ``` +## Resources +A main part when creating resources like controllers, models, etc you most likely want to open it. Since the laravel commands does not return what was created +I base on the type and and provided name to look for the file here is the list that can also be customize to add in case you have custom or from a plugin that +you use [resources](./lua/laravel/config/resources.lua) + + + +# Environments +Running your laravel app has many forms, you can use something like *Laravel Herd* *Laravel Sail* *Docker Compose* or just the good `php artisan serve` this presents +a challange, a fundamental aspect you want to run the command where it should with sail, with in your docker or simple the php native executable. +In order to support this there is this [configuration](./lua/laravel/config/environments.lua) + +Since you may not want the same configuration for all you projects you can use the env variable `NVIM_LARAVEL_ENV` define it in your `.env` file in your project. +If you don't se it by default will use auto_discover this will go over each definition and test base on the conditions, if they are meant will use that. +In case no configuration matches will try to use the default one. + +For the docker compose one also you can use an env variable to define which container will be use to run the commands. ## Artisan To run Artisan commands you can use `:Artisan` which will autocomplete with the available @@ -195,122 +127,39 @@ You can run `shell` as tinker will open a new terminal `Laravel commands` shows the list of artisan commands and executes it. `Laravel routes` show the list of routes and goes to the implementation. `Laravel related` show the list of model related classes, includes observers, policy and relations and goes to the implementation. -`Laravel test` runs the application tests `Laravel test:watch` runs the application tests and keep monitoring the changes - -# Route Info -I want to have more information in the controller, I want to have the route information directly in the controller so I build route info, this will show the -![](./images/route_info.png) -This also will show error if a route is defined but the method is not defined -![](./images/missing_method.png) - -> Note: using lazy is likely that you will not see at first since the plugin will not load until you call one of the commands, after that it is just picked up +`Laravel history` each command is recorded in case you want to run the same again +`Laravel view-finder` This will look for the views that are use in the file and if only one will go to it, in case of more will show a select, in the view will look for the class that uses it +`Laravel recipes` There are some recipes like installing ide helper and running the model and eloquent command. and to install doctrine dbal +`Laravel health` trigger the neovim command `:checkhealth laravel` ## Lua API -As developer I want to enable other to extend this plugin to cover all your needs. For this I tried to have a good API. +### Telescope +One of the things you may want to change are actions or styles or something related to telescope +The picker is `require("telescope").extensions.laravel.routes` so you can call it and pass the arguments as usual for telescope +the same for `commands`, `related` and `history` -To run artisan commands you can execute +### Run commands +You may want to run commands of course you can use `:Artisan my-command args` but you may want to pass nui options and more for that you can use ```lua -require('laravel.application').run('artisan', {'your-command'}, {}) +local run = require "laravel.run" +run("artisan", {"my-command"}, {}) ``` -That is great but what about how to get the results not all commands behave in the same way. -Currently there are several runners: - -| Runner | Description | -| -------- | ---------------------------------------------------------------- | -| buffer | This opens an split and shows the results in a new buffer. This uses the `vim.fn.jobstart` to run the command | -| sync | This is more for api since the result of the command will be directly return to work with | -| async | Similar to `sync` but it takes a callback and will call it once the data is loaded, usefull for long process and to not block the editor | -| persist | One thing with buffers is that are temprary once you close the buffer the job is terminated, for some process you don't want that like, npm dev or other | -| watch | This is usefull for commands that needs to be retrigger one files are modifed, like queues restart, or tests | -| terminal | This runner uses the invocation of the `:term ` this provide a fully experience in a terminal, but it can't escape arguments in the command to execute | +This will be run in the nui, but you may want to do more plugins like and do something with the output +for that you can call the `api` -So you can run commands like ```lua -require('laravel.application').run('artisan', {'your-command'}, {runner = 'persist'}) +local api = require "laravel.api" ``` -Each runner returns different values since it have different behave. +Here you can use the methods `sync` and `async` I recommend the use of async that will not block the editor but there are cases that you may want to use sync. +have in consideration that to avoid hanging the editor there is the default timeout from plenary +The response and the value for callback is [ApiResponse](./lua/laravel/api/response.lua) +If you will use them I recommend peek into the code sync I use them a lot as building block for the plugin. -| Runner | Output | -| -- | -- | -| buffer | {buff, job} | -| sync | {out, exit_code, err } | -| async | {} | -| persist | {buff, job} | -| watch | {buff, job} | -| terminal | {buff, term_id} | - - -These runners are available for the following commands -- artisan -- composer -- sail -- npm -- yarn - -This is to provide the option to you to build what ever you need for you development experience. - -The commands have a default runner configure that you can customize -```lua - default_runner = "buffer", - commands_options = { - ["dump-server"] = { runner = "persist" }, - ["queue:listen"] = { runner = "persist" }, - ["serve"] = { runner = "persist" }, - ["websockets"] = { runner = "persist" }, - ["queue:restart"] = { runner = "watch" }, - ["tinker"] = { runner = "terminal", skip_args = true }, - ["db"] = { runner = "terminal" }, - }, -``` - - -## Send to Tinker -Working with laravel tinker is a great tool so after thinking how can improve my flow with it I decide that selecting lines and have them send to tinker it was a good idea -So that is exactly what I did with the function `require("laravel.tinker").send_to_tinker()` which will grab the selected lines and send them to the open tinker or open a new one if is not already. -If you copy my keybindings from lazy or you can assign to your like is great. - - - -### Improve your flow. -Is normal that working with a project you have several things that you would like to start automatically. -Lets say for example that you would like to have two windows, one with the test running with every change of file and other with the dump server -we can write this -```lua -local function start() - vim.cmd "vsplit new" - local top = vim.api.nvim_get_current_win() - local width = vim.api.nvim_win_get_width(0) - vim.api.nvim_win_set_width(0, vim.fn.round(width * 2 / 3)) - vim.cmd "split new" - local bot = vim.api.nvim_get_current_win() - - local test_run = require("laravel.run")('artisan', { "test" }, {runner = "watch", open = false }) - local dump_run = require("laravel.run")('artisan', { "dump-server" }, { runner = "persist", open = false }) - - vim.api.nvim_win_set_buf(top, test_run.buff) - vim.api.nvim_win_set_buf(bot, dump_run.buff) -end -``` -The function will create an split, and resize it, split again and with these 2 windows will call the commands that want. Since in this case we want to set the position our self we send the option to not open. -After that we only need to set the buffer from the commands into the windows and ready. - - -Other example to just run everything -```lua -vim.api.nvim_create_user_command("StartMyApp", function () - require('laravel.run')('artisan', {"serve"}) - require('laravel.run')('artisan', {"queue:restart"}) - require('laravel.run')('artisan', {"queue:listen"}) - require('laravel.run')('yarn', {"dev"}, {runenr = "persist"}) -end, {}) -``` -This will create your own command and when run will just call everyone of the commands, and split the windows as it needs and you resize when you want. Remember the `open = false` is an option to not have it display and run in the background. # Self promotion I am Ariel I am a developer and also content creator (mostly in Spanish) if you would like to show some love leave a start into the plugin and subscribe to my [Youtube](https://youtube.com/@Alpha_Dev) if you want to show even more love you can support becoming a member on Youtube. But just leaving a like or letting me know that you like and enjoy the plugin is appreciated. - # Collaboration I am open to review pr if you have ideas or ways to improve the plugin would be great. diff --git a/TODO.md b/TODO.md index 76fd509..9fb8524 100644 --- a/TODO.md +++ b/TODO.md @@ -27,32 +27,5 @@ - [X] implement watch - [X] implement alternate file for livewire components `:A` - [X] extend api .sync and .async with better respons object. maybe create a new object with method for example `.successful()` and `.failed()` -- [ ] rework environment -- [ ] re-write the readme and translate (not forget fd as dependency) move all info from readme to doc - -## Environment -How I want the environment - -I have environments, resolver and executables -In environment only have `executables` -I need to get from the configuration per project the executables - -I want it to be set on the configuration - -So do I need the resolver ? -Is not clear ? -I already have the `environment` term so it's hard to tink into ahother - -So I have diferent environments -Executables not found should use try to look for it -```lua -local environments = { - local = { - executables = { - artisan = {"php", "artisan"}, - composer = {"composer"}, - npm = {"npm"}, - } - } -} -``` +- [X] rework environment +- [X] re-write the readme and translate (not forget fd as dependency) move all info from readme to doc diff --git a/lua/laravel/config/command_options.lua b/lua/laravel/config/command_options.lua new file mode 100644 index 0000000..51f4775 --- /dev/null +++ b/lua/laravel/config/command_options.lua @@ -0,0 +1,4 @@ +return { + ["tinker"] = { skip_args = true }, + ["docs"] = { ui = "popup", skip_args = true }, +} diff --git a/lua/laravel/config/default.lua b/lua/laravel/config/default.lua new file mode 100644 index 0000000..f9ccf06 --- /dev/null +++ b/lua/laravel/config/default.lua @@ -0,0 +1,17 @@ +return { + lsp_server = "phpactor", + register_user_commands = true, + features = { + null_ls = { + enable = true, + }, + route_info = { + enable = true, + position = "right", + }, + }, + ui = require "laravel.config.ui", + commands_options = require "laravel.config.command_options", + environments = require "laravel.config.environments", + resources = require "laravel.config.resources", +} diff --git a/lua/laravel/config/init.lua b/lua/laravel/config/init.lua index cf13280..aaa6fc3 100644 --- a/lua/laravel/config/init.lua +++ b/lua/laravel/config/init.lua @@ -1,28 +1,7 @@ local M = {} ---@class LaravelOptions -M.defaults = { - ui = require "laravel.config.ui", - lsp_server = "phpactor", - register_user_commands = true, - features = { - null_ls = { - enable = true, - }, - route_info = { - enable = true, - position = "right", - }, - }, - commands_options = { - ["queue:restart"] = { watch = true }, - ["tinker"] = { skip_args = true }, - ["docs"] = { ui = "popup", skip_args = true }, - ["make:model"] = { options = { "-mf" } }, - }, - environments = require "laravel.config.environments", - resources = require "laravel.config.resources", -} +M.defaults = require "laravel.config.default" --- @type LaravelOptions M.options = {} diff --git a/lua/laravel/config/ui.lua b/lua/laravel/config/ui.lua index b456ce7..d8bc1f8 100644 --- a/lua/laravel/config/ui.lua +++ b/lua/laravel/config/ui.lua @@ -15,6 +15,7 @@ return { popup = { enter = true, focusable = true, + relative = "editor", border = { style = "rounded", },