Skip to content

Commit

Permalink
Merge pull request #112 from Bleksak/main
Browse files Browse the repository at this point in the history
Add fzf-lua as a picker
  • Loading branch information
adalessa authored Nov 5, 2024
2 parents b6964a1 + ccb462c commit c458110
Show file tree
Hide file tree
Showing 23 changed files with 637 additions and 106 deletions.
3 changes: 2 additions & 1 deletion lua/laravel/options/default.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

---@class PickersFeature
---@field enable boolean
---@field provider 'telescope'|'ui.select'
---@field provider 'telescope'|'ui.select'|'fzf-lua'

---@class LaravelFeatures
---@field route_info RouteInfoFeature
Expand Down Expand Up @@ -57,6 +57,7 @@ return {
require("laravel.providers.route_info_provider"),
require("laravel.providers.tinker_provider"),
require("laravel.providers.telescope_provider"),
require("laravel.providers.fzf_lua_provider"),
require("laravel.providers.ui_select_provider"),
require("laravel.providers.user_command_provider"),
require("laravel.providers.status_provider"),
Expand Down
4 changes: 2 additions & 2 deletions lua/laravel/pickers/common/actions.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-- local ui_run = require("laravel.pickers.ui_select.ui_run")
local lsp = require("laravel._lsp")
local app = require("laravel").app
local ui_run = require("laravel.pickers.common.ui_run")

local M = {}

Expand Down Expand Up @@ -29,7 +29,7 @@ local function go(route)
lsp.go_to(action[1], action[2])
end

function M.run(command, ui_run)
function M.run(command)
vim.schedule(function()
ui_run(command)
end)
Expand Down
File renamed without changes.
97 changes: 67 additions & 30 deletions lua/laravel/pickers/common/ui_run.lua
Original file line number Diff line number Diff line change
@@ -1,42 +1,74 @@
local Layout = require("nui.layout")
local Popup = require("nui.popup")
local Input = require("nui.input")
local app = require("laravel").app
local event = require("nui.utils.autocmd").event
local preview = require("laravel.pickers.common.preview")

---@class UIPopups
---@field entry_popup NuiPopup
---@field help_popup ?NuiPopup

local M = {}
local function scroll_fn(popup, direction)
return function()
local scroll = vim.api.nvim_get_option_value("scroll", { win = popup.winid })
vim.api.nvim_win_call(popup.winid, function()
vim.cmd("normal! " .. scroll .. direction)
end)
end
end

function M.entry_popup()
return Popup({
enter = true,
return function(command)
local entry_popup = Input({
focusable = true,
border = {
style = "rounded",
text = {
top = "Artisan",
top_align = "center",
},
},
buf_options = {
buftype = "prompt",
},
win_options = {
winhighlight = "Normal:LaravelPrompt",
},
}, {
prompt = "$ artisan " .. command.name .. " ",
on_submit = function(input)
local args = vim.fn.split(input, " ", false)
table.insert(args, 1, command.name)

app("runner"):run("artisan", args)
end,
})
end

---@param popups UIPopups
function M.ui_run(command, popups)
local boxes = {
Layout.Box(popups.entry_popup, { size = 3 }), -- 3 because of borders to be 1 row
}
local help_popup = Popup({
border = {
style = "rounded",
text = {
top = "Help (<c-c> to cancel)",
top_align = "center",
},
},
win_options = {
winhighlight = "Normal:LaravelHelp",
},
})

local command_preview = preview.command(command)

if popups.help_popup then
table.insert(boxes, Layout.Box(popups.help_popup, { grow = 1 }))
vim.api.nvim_buf_set_lines(help_popup.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(help_popup.bufnr, hl, value[1], value[2], value[3], value[4])
end

entry_popup:map("i", "<c-d>", scroll_fn(help_popup, "j"))
entry_popup:map("n", "<c-d>", scroll_fn(help_popup, "j"))
entry_popup:map("i", "<c-u>", scroll_fn(help_popup, "k"))
entry_popup:map("n", "<c-u>", scroll_fn(help_popup, "k"))

local boxes = {
Layout.Box(entry_popup, { size = 3 }), -- 3 because of borders to be 1 row
Layout.Box(help_popup, { grow = 1 }),
}

local layout = Layout({
position = "50%",
size = {
Expand All @@ -46,25 +78,30 @@ function M.ui_run(command, popups)
relative = "editor",
}, Layout.Box(boxes, { dir = "col" }))

popups.entry_popup:map("i", "<c-c>", function()
entry_popup:map("i", "<c-c>", function()
layout:unmount()
end)
popups.entry_popup:map("n", "<c-c>", function()

entry_popup:map("n", "<c-c>", function()
layout:unmount()
end)

local prompt = "$ artisan " .. command.name .. " "
vim.fn.prompt_setprompt(popups.entry_popup.bufnr, prompt)
vim.fn.prompt_setcallback(popups.entry_popup.bufnr, function(input)
entry_popup:map("n", "<Esc>", function()
layout:unmount()
local args = vim.fn.split(input, " ", false)
table.insert(args, 1, command.name)
end)

app("runner"):run("artisan", args)
entry_popup:map("i", "<Esc>", function()
layout:unmount()
end)

entry_popup:on(event.BufLeave, function()
layout:unmount()
end)

layout:mount()
vim.cmd([[startinsert]])
end

return M
-- hack for starting in insert mode
vim.defer_fn(function()
vim.api.nvim_command("startinsert!")
end, 20)
end
83 changes: 83 additions & 0 deletions lua/laravel/pickers/fzf_lua/format_entry.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
local M = {}

function M.gen_from_artisan(commands)
local string_names = vim
.iter(commands)
:map(function(command)
return command.name
end)
:totable()

local command_hash = {}
for _, command in ipairs(commands) do
command_hash[command.name] = command
end

return string_names, command_hash
end

function M.gen_from_commands(commands)
local string_names = vim
.iter(commands)
:map(function(command)
return command.display
end)
:totable()

local command_hash = {}
for _, command in ipairs(commands) do
command_hash[command.display] = command
end

return string_names, command_hash
end

function M.gen_from_history(history)
local string_names = vim
.iter(history)
:map(function(command)
return command.name
end)
:totable()

local history_hash = {}
for _, command in ipairs(history) do
history_hash[command.name] = command
end

return string_names, history_hash
end

function M.gen_from_related(relations)
local string_names = vim
.iter(relations)
:map(function(relation)
return relation.class .. " " .. relation.type .. " " .. relation.extra_information
end)
:totable()

local relation_hash = {}
for _, relation in ipairs(relations) do
relation_hash[relation.class .. " " .. relation.type .. " " .. relation.extra_information] = relation
end

return string_names, relation_hash
end

function M.gen_from_routes(routes)
local string_names = vim
.iter(routes)
:map(function(route)
return route.uri .. " " .. (route.name or "")
end)
:totable()

local route_hash = {}
for _, route in ipairs(routes) do
route_hash[route.uri .. " " .. (route.name or "")] = route
end

return string_names, route_hash
end

return M
44 changes: 44 additions & 0 deletions lua/laravel/pickers/fzf_lua/pickers/artisan.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
local format_entry = require("laravel.pickers.fzf_lua.format_entry").gen_from_artisan
local actions = require("laravel.pickers.common.actions")
local fzf_exec = require("fzf-lua").fzf_exec
local CommandPreviewer = require("laravel.pickers.fzf_lua.previewer").CommandPreviewer

---@class LaravelFzfLuaArtisanPicker
---@field commands_repository CommandsRepository
local ui_artisan_picker = {}

function ui_artisan_picker:new(cache_commands_repository)
local instance = {
commands_repository = cache_commands_repository,
}
setmetatable(instance, self)
self.__index = self

return instance
end

function ui_artisan_picker:run(opts)
opts = opts or {}

return self.commands_repository:all():thenCall(function(commands)
local command_names, command_table = format_entry(commands)

fzf_exec(command_names, {
actions = {
["default"] = function(selected)
local command = command_table[selected[1]]
actions.run(command)
end,
},
prompt = "Artisan > ",
previewer = CommandPreviewer(command_table),
fzf_opts = {
["--preview-window"] = "nohidden,70%",
},
})
end, function(error)
vim.api.nvim_err_writeln(error)
end)
end

return ui_artisan_picker
61 changes: 61 additions & 0 deletions lua/laravel/pickers/fzf_lua/pickers/commands.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
local format_entry = require("laravel.pickers.fzf_lua.format_entry").gen_from_commands
local fzf_exec = require("fzf-lua").fzf_exec

local commands_picker = {}

function commands_picker:new(runner, options)
local instance = {
runner = runner,
options = options,
}
setmetatable(instance, self)
self.__index = self

return instance
end

function commands_picker:run(opts)
opts = opts or {}

local commands = {}

for command_name, group_commands in pairs(self.options:get().user_commands) do
for name, details in pairs(group_commands) do
table.insert(commands, {
executable = command_name,
name = name,
display = string.format("[%s] %s", command_name, name),
cmd = details.cmd,
desc = details.desc,
opts = details.opts or {},
})
end
end

if vim.tbl_isempty(commands) then
vim.notify("No user command defined in the config", vim.log.levels.WARN, {})
return
end

local command_names, command_table = format_entry(commands)

fzf_exec(command_names, {
actions = {
["default"] = function(selected)
local command = command_table[selected[1]]
self.runner:run(command.executable, command.cmd, command.opts)
end,
},
prompt = "User Commands > ",
fzf_opts = {
["--preview-window"] = "nohidden,70%",
["--preview"] = function(selected)
local command = command_table[selected[1]]

return command.desc
end
},
})
end

return commands_picker
33 changes: 33 additions & 0 deletions lua/laravel/pickers/fzf_lua/pickers/history.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
local fzf_exec = require("fzf-lua").fzf_exec
local format_entry = require("laravel.pickers.fzf_lua.format_entry").gen_from_history
local app = require("laravel").app

local history_picker = {}

function history_picker:new(history)
local instance = {
history_provider = history,
}
setmetatable(instance, self)
self.__index = self
return instance
end

function history_picker:run(opts)
opts = opts or {}

local history = self.history_provider:get()
local history_names, history_table = format_entry(history)

fzf_exec(history_names, {
actions = {
["default"] = function(selected)
local command = history_table[selected[1]]
app("runner"):run(command.name, command.args, command.opts)
end,
},
prompt = "History > ",
})
end

return history_picker
Loading

0 comments on commit c458110

Please sign in to comment.