Skip to content

Commit

Permalink
Playing with async and telescope
Browse files Browse the repository at this point in the history
  • Loading branch information
Kim Gert Nielsen committed Aug 29, 2024
1 parent 71c43d6 commit d4732be
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 36 deletions.
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@

`greyjoy.nvim` is a pluggable pattern/file based launcher.

![Demo of greyjoy](doc/greyjoy.gif?raw=true "Demo of greyjoy")
![Demo of greyjoy](doc/greyjoy.mp4?raw=true "Demo of greyjoy")

greyjoy uses vim.ui.select so the settings from (telescope, dressing etc.) menu will reflect it. The above example uses telescope.
Greyjoy per default uses vim.ui.select so the settings from (telescope, dressing etc.) menu will reflect it. But there is also a telescope only version that uses async which makes the UI feel faster.

Integration with [toggleterm](/~https://github.com/akinsho/toggleterm.nvim) is also provided.

## Requirements

Neovim 0.9+ is required
Neovim 0.10+ is required
[Toggleterm](/~https://github.com/akinsho/toggleterm.nvim) (Optional)
[Telescope](/~https://github.com/nvim-telescope/telescope.nvim) + [Plenary](/~https://github.com/nvim-lua/plenary.nvim) (Optional but UI is more responsive)

## Default settings

Expand All @@ -29,6 +31,12 @@ Neovim 0.9+ is required
-- greyjoy.nvim it will be dependent on the user configured size for toggle
-- term.
size = nil,
},
telescope = {
keys = {
select = "<CR>", -- enter
edit = "<C-e>", -- CTRL-e
},
}
},
toggleterm = {
Expand Down Expand Up @@ -180,11 +188,14 @@ Using lazy
"desdic/greyjoy.nvim",
keys = {
{ "<Leader>gr", "<cmd>Greyjoy<CR>", desc = "[G]reyjoy [r]un" },
{ "<Leader>gt", "<cmd>GreyjoyTelescope<CR>", desc = "[G]reyjoy [t]elescope" },
{ "<Leader>gg", "<cmd>Greyjoy fast<CR>", desc = "[G]reyjoy fast [g]roup" },
{ "<Leader>ge", "<cmd>Greyedit<CR>", desc = "[G]reyjoy [r]un" },
},
dependencies = {
{ "akinsho/toggleterm.nvim" },
{ "akinsho/toggleterm.nvim" }, -- Optional
{ "nvim-lua/plenary.nvim" }, -- Optional
{ "nvim-telescope/telescope.nvim" }, -- Optional
},
cmd = "Greyjoy",
config = function()
Expand Down Expand Up @@ -244,7 +255,7 @@ Using lazy
}
```

Once installed and reloaded you can use `:Greyjoy` to run it or `Greyjoy <pluginname or group name>`. If you need to edit a command (like adding a variable or option) you can use `:Greyedit` (Works with group and plugins as parameter too).
Once installed and reloaded you can use `:Greyjoy` or `:GreyjoyTelescope` to run it or `Greyjoy/GreyjoyTelescope <pluginname or group name>`. If you need to edit a command (like adding a variable or option) you can use `:Greyedit` (Works with group and plugins as parameter too).

So in the above example its possible to run the generic and makefile plugin by running `:Greyjoy fast` or if you only wanted to run the makefile plugin you could do `:Greyjoy makefile`

Expand Down
Binary file added doc/greyjoy.mp4
Binary file not shown.
6 changes: 6 additions & 0 deletions lua/greyjoy/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ local defaults = {
-- term.
size = nil,
},
telescope = {
keys = {
select = "<CR>", -- enter
edit = "<C-e>", -- CTRL-e
},
},
},
toggleterm = {
-- default_group_id can be a number or a function that takes a string as parameter.
Expand Down
13 changes: 8 additions & 5 deletions lua/greyjoy/health.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ local M = {}
M.check = function()
health.start("Checking for optional plugins")

local ok, _ = pcall(require, "toggleterm")
if not ok then
health.warn("`toggleterm` not installed")
else
health.ok("`toggleterm` installed")
local optional = { "toggleterm", "telescope", "plenary" }
for _, plugin in pairs(optional) do
local ok, _ = pcall(require, plugin)
if not ok then
health.warn("`" .. plugin .. "` not installed")
else
health.ok("`" .. plugin .. "` installed")
end
end

health.start("===== Installed extensions =====")
Expand Down
36 changes: 14 additions & 22 deletions lua/greyjoy/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ greyjoy.to_toggleterm = function(command)
end
end

-- TermExec cmd=

local commandstr = table.concat(command.command, " ")
local exec_command = "dir='"
.. command.path
Expand All @@ -199,6 +201,9 @@ greyjoy.to_toggleterm = function(command)
.. " "
.. exec_command
end

-- vim.cmd([[TermExec cmd='ls']])

toggleterm.exec_command(exec_command, count)
end

Expand Down Expand Up @@ -272,30 +277,10 @@ greyjoy.run = function(arg, method)
return
end

local filetype = vim.bo.filetype
local fullname = vim.api.nvim_buf_get_name(0)
local filename = vim.fs.basename(fullname)
local filepath = vim.fs.dirname(fullname)
local pluginname = arg or ""
local uv = vim.uv

filepath = utils.if_nil(filepath, "")
if filepath == "" then
filepath = uv.cwd()
end

local rootdir =
vim.fs.dirname(vim.fs.find(greyjoy.patterns, { upward = true })[1])
rootdir = utils.if_nil(rootdir, filepath)

local fileobj = {
filetype = filetype,
fullname = fullname,
filename = filename,
filepath = filepath,
rootdir = rootdir,
}

local fileobj = utils.new_file_obj(greyjoy.patterns)
local rootdir = fileobj.rootdir
local elements = {}

for p, v in pairs(greyjoy.extensions) do
Expand Down Expand Up @@ -343,4 +328,11 @@ vim.api.nvim_create_user_command("Greyedit", function(args)
greyjoy.run(args.args, "edit")
end, { nargs = "*", desc = "Edit greyjoy" })

local has_telescope, _ = pcall(require, "telescope")
if has_telescope then
vim.api.nvim_create_user_command("GreyjoyTelescope", function(args)
require("greyjoy.telescope").run(args.args)
end, { nargs = "*", desc = "Run greyjoy via telescope" })
end

return greyjoy
201 changes: 201 additions & 0 deletions lua/greyjoy/telescope.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
local has_telescope, _ = pcall(require, "telescope")
if not has_telescope then
vim.notify(
"This plugin requires telescope and plenary (/~https://github.com/nvim-telescope/telescope.nvim)",
vim.log.levels.ERROR,
{ title = "Plugin error" }
)
return
end

local greytelescope = {}

local last_choice = ""

local greyjoy = require("greyjoy")
local utils = require("greyjoy.utils")
local async = require("plenary.async")
local pickers = require("telescope.pickers")
local finders = require("telescope.finders")
local sorters = require("telescope.sorters")
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")

local translate = function(obj)
local orig_command = nil
local commandinput = table.concat(obj.command, " ")
if greyjoy.overrides[commandinput] then
orig_command = obj.command
obj.command = utils.str_to_array(greyjoy.overrides[commandinput])
obj.name = greyjoy.overrides[commandinput]
end
obj.orig_command = orig_command
return obj
end

local collect_output = function(output, on_item_collected)
if type(output) == "table" then
for _, x in pairs(output) do
local newx = translate(x)
on_item_collected({
name = newx.name,
value = newx,
})
async.util.sleep(1) -- TODO: find out why this improves performance (Or makes it more responsive)
end
end
end

greytelescope.run_async = function(arg, on_item_collected, on_complete)
local fileobj = utils.new_file_obj(greyjoy.patterns)
local rootdir = fileobj.rootdir

local pluginname = arg or ""

async.run(function()
-- TODO: do generically
for p, v in pairs(greyjoy.extensions) do
if
pluginname == ""
or pluginname == p
or greyjoy.__in_group(pluginname, p)
then
if v.type == "global" then
local output = v.parse(fileobj)
collect_output(output, on_item_collected)

-- Do file based extensions
elseif v.type == "file" then
if rootdir then
for _, file in pairs(v.files) do
if utils.file_exists(rootdir .. "/" .. file) then
local fileinfo = {
filename = file,
filepath = rootdir,
}
local output = v.parse(fileinfo)
collect_output(output, on_item_collected)
end
end
end
end
end
end

on_complete()
end)
end

greytelescope.run = function(arg)
if not has_telescope then
vim.notify(
"This function requires telescope.nvim (/~https://github.com/nvim-telescope/telescope.nvim)",
vim.log.levels.ERROR,
{ title = "Plugin error" }
)
return
end

local items = {}

local get_selection_index = function()
for index, data in pairs(items) do
if data.name == last_choice then
return index
end
end
return #items
end

local generate_finder = function()
return finders.new_table({
results = items,
entry_maker = function(entry)
return {
value = entry,
ordinal = entry.name,
display = entry.name,
}
end,
})
end

local picker = pickers.new({}, {
prompt_title = "Runners",
finder = generate_finder(),
sorter = sorters.get_generic_fuzzy_sorter(),
attach_mappings = function(_, map)
map("i", greyjoy.ui.telescope.keys.select, function(prompt_bufnr)
local selection = action_state.get_selected_entry()

last_choice = selection.value.value.name

actions.close(prompt_bufnr)
greyjoy.execute(selection.value.value)
end)
map("i", greyjoy.ui.telescope.keys.edit, function(prompt_bufnr)
local current_picker =
action_state.get_current_picker(prompt_bufnr)
local selection = current_picker:get_selection()

local obj = selection.value.value
local commandinput = table.concat(obj.command, " ")

vim.ui.input({
prompt = "Edit before running: ",
default = obj.name,
}, function(newname)
if newname then
if obj.orig_command then
local tmp = table.concat(obj.orig_command, " ")
greyjoy.overrides[tmp] = newname
else
greyjoy.overrides[commandinput] = newname
end

obj.command = utils.str_to_array(newname)
last_choice = newname

actions.close(prompt_bufnr)
greyjoy.execute(obj)
end
end)
end)
return true
end,
})

picker:find()

-- On every new item we insert and refresh picker
local function on_item_collected(item)
table.insert(items, item)

vim.schedule(function()
picker:refresh(finders.new_table({
results = items,
entry_maker = function(entry)
return {
value = entry,
display = entry.name,
ordinal = entry.name,
}
end,
}))
end)
end

-- Once all plugins are done we need to set selection
local function on_complete()
local index = get_selection_index()
picker:set_selection(picker:get_index(index))
vim.schedule(function()
print("All plugins processed!")
end)
end

-- Start the asynchronous collection and processing
greytelescope.run_async(arg, on_item_collected, on_complete)
end

return greytelescope
23 changes: 23 additions & 0 deletions lua/greyjoy/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,27 @@ M.str_to_array = function(str)
return words
end

M.new_file_obj = function(patterns)
local filetype = vim.bo.filetype
local fullname = vim.api.nvim_buf_get_name(0)
local filename = vim.fs.basename(fullname)
local filepath = vim.fs.dirname(fullname)

filepath = M.if_nil(filepath, "")
if filepath == "" then
filepath = vim.uv.cwd()
end

local rootdir = vim.fs.dirname(vim.fs.find(patterns, { upward = true })[1])
rootdir = M.if_nil(rootdir, filepath)

return {
filetype = filetype,
fullname = fullname,
filename = filename,
filepath = filepath,
rootdir = rootdir,
}
end

return M
4 changes: 2 additions & 2 deletions lua/tests/automated/generic_spec.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
local utils = require("greyjoy.utils")
local eq = assert.are.same

describe("makefile extension", function()
it("runs make", function()
describe("generic extension", function()
it("reads config", function()
local generic = require("greyjoy._extensions.generic")

eq(generic.exports, utils.if_nil(generic.exports, false))
Expand Down
Loading

0 comments on commit d4732be

Please sign in to comment.