Update check_dir_and_ask: async for vim.ui.select

vim.ui.select is meant to be used as an asynchronous operation,
in order to do this, it receives a callback as a third argument.

This commit adjusts check_dir_and_ask to leverage the asynchronous
usage of vim.ui.select, as a side effect to make this work, I also
refactored the code that depends on the function in order to leverage
the asynchronous operations.

References:
- https://github.com/stevearc/dressing.nvim/issues/80#issuecomment-1380734202
- https://github.com/stevearc/dressing.nvim
- https://github.com/neovim/neovim/pull/15771

Fixes:
- https://github.com/renerocksai/telekasten.nvim/issues/266

One reason this bug can sneak into the codebase is because the
default unmodified behavior of vim.ui.select is to use the
:Messages section of neovim to ask for input and this UI is
a synchronous blocking operation. However, this is not the
intended usage of vim.ui.select as presented above.
This commit is contained in:
Sleepful
2023-07-06 14:21:23 -06:00
parent b6ff784fbb
commit 2576725041

View File

@@ -183,7 +183,7 @@ local function generate_note_filename(uuid, title)
end
end
local function check_dir_and_ask(dir, purpose)
local function check_dir_and_ask(dir, purpose, callback)
local ret = false
if dir ~= nil and Path:new(dir):exists() == false then
vim.ui.select({ "No (default)", "Yes" }, {
@@ -201,34 +201,44 @@ local function check_dir_and_ask(dir, purpose)
vim.cmd('echomsg " "')
vim.cmd('echomsg "' .. dir .. ' created"')
ret = true
callback(ret)
else
-- unreachable: plenary.Path:mkdir() will error out
tkutils.print_error("Could not create directory " .. dir)
ret = false
callback(ret)
end
end
end)
else
ret = true
if callback ~= nil then
callback(ret)
end
return ret
end
end
local function global_dir_check()
local function global_dir_check(callback)
local ret
if M.Cfg.home == nil then
tkutils.print_error("Telekasten.nvim: home is not configured!")
ret = false
else
ret = check_dir_and_ask(M.Cfg.home, "home")
callback(ret)
end
ret = ret and check_dir_and_ask(M.Cfg.dailies, "dailies")
ret = ret and check_dir_and_ask(M.Cfg.weeklies, "weeklies")
ret = ret and check_dir_and_ask(M.Cfg.templates, "templates")
ret = ret and check_dir_and_ask(M.Cfg.image_subdir, "images")
return ret
local check = check_dir_and_ask
-- nested callbacks to handle asynchronous vim.ui.select
-- looks a little confusing but execution is sequential from top to bottom
check(M.Cfg.home, "home", function()
check(M.Cfg.dailies, "dailies", function()
check(M.Cfg.weeklies, "weeklies", function()
check(M.Cfg.templates, "templates", function()
-- Note the `callback` in this last function call
check(M.Cfg.image_subdir, "images", callback)
end)
end)
end)
end)
end
local function make_config_path_absolute(path)
@@ -245,7 +255,8 @@ local function make_config_path_absolute(path)
end
local function recursive_substitution(dir, old, new)
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -275,6 +286,7 @@ local function recursive_substitution(dir, old, new)
.. new
.. "\\2|g' >/dev/null 2>&1"
os.execute(replace_cmd)
end)
end
local function save_all_mod_buffers()
@@ -341,7 +353,8 @@ local function make_relative_path(bufferpath, imagepath, sep)
end
local function imgFromClipboard()
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -428,6 +441,7 @@ local function imgFromClipboard()
else
vim.api.nvim_err_writeln("Unable to write image " .. png)
end
end)
end
-- end of image stuff
@@ -437,7 +451,8 @@ local function create_note_from_template(
uuid,
filepath,
templatefn,
calendar_info
calendar_info,
callback
)
-- first, read the template file
local lines = {}
@@ -448,11 +463,12 @@ local function create_note_from_template(
end
-- now write the output file, substituting vars line by line
local filedir = title:match("(.*/)") or ""
local dir_succeed = check_dir_and_ask(filedir, filedir)
local file_dir = filepath:match("(.*/)") or ""
check_dir_and_ask(file_dir, file_dir, function(dir_succeed)
if dir_succeed == false then
return
end
local ofile = io.open(filepath, "a")
for _, line in pairs(lines) do
@@ -469,6 +485,8 @@ local function create_note_from_template(
ofile:flush()
ofile:close()
callback()
end)
end
--- Pinfo
@@ -716,10 +734,6 @@ function Pinfo:resolve_link(title, opts)
-- final round, there still can be a subdir mess-up
if not Path:new(self.filepath):parent():exists() then
print("Path " .. self.filepath .. " is invalid!")
-- local fname_only = Path:new(self.filename):_split()
-- fname_only = fname_only[#fname_only]
-- self.filepath = opts.home .. "/" .. fname_only
self.filepath = ""
end
end
@@ -1119,13 +1133,34 @@ local function FindDailyNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
local today = os.date(dateutils.dateformats.date)
local fname = M.Cfg.dailies .. "/" .. today .. M.Cfg.extension
local fexists = fileutils.file_exists(fname)
local function picker()
find_files_sorted({
prompt_title = "Find daily note",
cwd = M.Cfg.dailies,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(
picker_actions.select_default
)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
sort = M.Cfg.sort,
})
end
if
(fexists ~= true)
and (
@@ -1137,28 +1172,17 @@ local function FindDailyNotes(opts)
today,
nil,
fname,
M.note_type_templates.daily
)
M.note_type_templates.daily,
function()
opts.erase = true
opts.erase_file = fname
picker()
end
find_files_sorted({
prompt_title = "Find daily note",
cwd = M.Cfg.dailies,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(picker_actions.select_default)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
sort = M.Cfg.sort,
})
)
return
end
picker()
end)
end
--
@@ -1174,13 +1198,36 @@ local function FindWeeklyNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
local title = os.date(dateutils.dateformats.isoweek)
local fname = M.Cfg.weeklies .. "/" .. title .. M.Cfg.extension
local fexists = fileutils.file_exists(fname)
local function picker()
find_files_sorted({
prompt_title = "Find weekly note",
cwd = M.Cfg.weeklies,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(
picker_actions.select_default
)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
sort = M.Cfg.sort,
})
end
if
(fexists ~= true)
and (
@@ -1192,28 +1239,17 @@ local function FindWeeklyNotes(opts)
title,
nil,
fname,
M.note_type_templates.weekly
)
M.note_type_templates.weekly,
function()
opts.erase = true
opts.erase_file = fname
picker()
end
find_files_sorted({
prompt_title = "Find weekly note",
cwd = M.Cfg.weeklies,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(picker_actions.select_default)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
sort = M.Cfg.sort,
})
)
return
end
picker()
end)
end
--
@@ -1230,7 +1266,8 @@ local function InsertLink(opts)
or M.Cfg.close_after_yanking
opts.subdirs_in_links = opts.subdirs_in_links or M.Cfg.subdirs_in_links
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1245,7 +1282,12 @@ local function InsertLink(opts)
filepath = selection.filename or selection.value,
opts,
})
vim.api.nvim_put({ "[[" .. pinfo.title .. "]]" }, "", false, true)
vim.api.nvim_put(
{ "[[" .. pinfo.title .. "]]" },
"",
false,
true
)
if opts.i then
vim.api.nvim_feedkeys("a", "m", false)
end
@@ -1276,6 +1318,7 @@ local function InsertLink(opts)
sort = sort,
})
end
end)
end
-- local function check_for_link_or_tag()
@@ -1325,7 +1368,8 @@ local function PreviewImg(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1371,6 +1415,7 @@ local function PreviewImg(opts)
else
print("File not found: " .. M.Cfg.home .. "/" .. fname)
end
end)
end
--
@@ -1386,7 +1431,8 @@ local function BrowseImg(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1418,6 +1464,7 @@ local function BrowseImg(opts)
end,
sort = M.Cfg.sort,
})
end)
end
--
@@ -1433,7 +1480,8 @@ local function FindFriends(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1461,6 +1509,7 @@ local function FindFriends(opts)
return true
end,
})
end)
end
--
@@ -1477,6 +1526,31 @@ local function YankLink()
print("yanked " .. title)
end
local function rename_update_links(oldfile, newname)
if M.Cfg.rename_update_links == true then
-- Only look for the first part of the link, so we do not touch to #heading or #^paragraph
-- Should use regex instead to ensure it is a proper link
local oldlink = "[[" .. oldfile.title
local newlink = "[[" .. newname
-- Save open buffers before looking for links to replace
if #(vim.fn.getbufinfo({ bufmodified = 1 })) > 1 then
vim.ui.select({ "Yes (default)", "No" }, {
prompt = "Telekasten.nvim: "
.. "Save all modified buffers before updating links?",
}, function(answer)
if answer ~= "No" then
save_all_mod_buffers()
end
end)
end
recursive_substitution(M.Cfg.home, oldlink, newlink)
recursive_substitution(M.Cfg.dailies, oldlink, newlink)
recursive_substitution(M.Cfg.weeklies, oldlink, newlink)
end
end
--
-- RenameNote:
-- -----------
@@ -1508,7 +1582,8 @@ local function RenameNote()
-- Savas newfile, delete buffer of old one and remove old file
if newname ~= "" and newname ~= oldfile.title then
if not (check_dir_and_ask(newpath, "Renamed file")) then
check_dir_and_ask(newpath, "Renamed file", function(success)
if not success then
return
end
@@ -1520,29 +1595,10 @@ local function RenameNote()
os.execute(
"rm " .. M.Cfg.home .. "/" .. oldTitle .. M.Cfg.extension
)
end
if M.Cfg.rename_update_links == true then
-- Only look for the first part of the link, so we do not touch to #heading or #^paragraph
-- Should use regex instead to ensure it is a proper link
local oldlink = "[[" .. oldfile.title
local newlink = "[[" .. newname
-- Save open buffers before looking for links to replace
if #(vim.fn.getbufinfo({ bufmodified = 1 })) > 1 then
vim.ui.select({ "Yes (default)", "No" }, {
prompt = "Telekasten.nvim: "
.. "Save all modified buffers before updating links?",
}, function(answer)
if answer ~= "No" then
save_all_mod_buffers()
end
rename_update_links(oldfile, newname)
end)
end
recursive_substitution(M.Cfg.home, oldlink, newlink)
recursive_substitution(M.Cfg.dailies, oldlink, newlink)
recursive_substitution(M.Cfg.weeklies, oldlink, newlink)
else
rename_update_links(oldfile, newname)
end
end)
end
@@ -1568,24 +1624,7 @@ local function GotoDate(opts)
local fname = M.Cfg.dailies .. "/" .. word .. M.Cfg.extension
local fexists = fileutils.file_exists(fname)
if
(fexists ~= true)
and (
(opts.dailies_create_nonexisting == true)
or M.Cfg.dailies_create_nonexisting == true
)
then
create_note_from_template(
word,
nil,
fname,
M.note_type_templates.daily,
opts.dates
)
opts.erase = true
opts.erase_file = fname
end
local function picker()
if opts.journal_auto_open then
vim.cmd("e " .. fname)
else
@@ -1615,6 +1654,31 @@ local function GotoDate(opts)
end,
})
end
end
if
(fexists ~= true)
and (
(opts.dailies_create_nonexisting == true)
or M.Cfg.dailies_create_nonexisting == true
)
then
create_note_from_template(
word,
nil,
fname,
M.note_type_templates.daily,
opts.dates,
function()
opts.erase = true
opts.erase_file = fname
picker()
end
)
return
end
picker()
end
--
@@ -1626,7 +1690,8 @@ end
local function GotoToday(opts)
opts = opts or {}
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1635,6 +1700,7 @@ local function GotoToday(opts)
opts.date = today
opts.dailies_create_nonexisting = true -- Always use template for GotoToday
GotoDate(opts)
end)
end
--
@@ -1650,7 +1716,8 @@ local function FindNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1687,6 +1754,7 @@ local function FindNotes(opts)
sort = sort,
})
end
end)
end
--
@@ -1698,7 +1766,8 @@ end
local function InsertImgLink(opts)
opts = opts or {}
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1737,6 +1806,7 @@ local function InsertImgLink(opts)
end,
sort = M.Cfg.sort,
})
end)
end
--
@@ -1752,7 +1822,8 @@ local function SearchNotes(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1773,6 +1844,7 @@ local function SearchNotes(opts)
return true
end,
})
end)
end
--
@@ -1788,11 +1860,13 @@ local function ShowBacklinks(opts)
opts.close_after_yanking = opts.close_after_yanking
or M.Cfg.close_after_yanking
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
local title = Pinfo:new({ filepath = vim.fn.expand("%:p"), M.Cfg }).title
local title =
Pinfo:new({ filepath = vim.fn.expand("%:p"), M.Cfg }).title
-- or vim.api.nvim_buf_get_name(0)
builtin.live_grep({
results_title = "Backlinks to " .. title,
@@ -1812,6 +1886,7 @@ local function ShowBacklinks(opts)
return true
end,
})
end)
end
--
@@ -1863,11 +1938,13 @@ local function on_create_with_template(opts, title)
uuid,
fname,
template,
pinfo.calendar_info
)
pinfo.calendar_info,
function()
-- open the new note
vim.cmd("e " .. fname)
picker_actions.post_open()
end
)
end)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
@@ -1881,13 +1958,15 @@ end
local function CreateNoteSelectTemplate(opts)
opts = opts or {}
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
fileutils.prompt_title(M.Cfg.extension, nil, function(title)
on_create_with_template(opts, title)
end)
end)
end
--
@@ -1917,19 +1996,7 @@ local function on_create(opts, title)
})
local fname = pinfo.filepath
if pinfo.fexists ~= true then
-- TODO: pass in the calendar_info returned in pinfo
create_note_from_template(
title,
uuid,
fname,
pinfo.template,
pinfo.calendar_info
)
opts.erase = true
opts.erase_file = fname
end
local function picker()
find_files_sorted({
prompt_title = "Created note...",
cwd = pinfo.root_dir,
@@ -1946,12 +2013,32 @@ local function on_create(opts, title)
return true
end,
})
end
if pinfo.fexists ~= true then
-- TODO: pass in the calendar_info returned in pinfo
create_note_from_template(
title,
uuid,
fname,
pinfo.template,
pinfo.calendar_info,
function()
opts.erase = true
opts.erase_file = fname
picker()
end
)
return
end
picker()
end
local function CreateNote(opts)
opts = opts or {}
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -1962,6 +2049,7 @@ local function CreateNote(opts)
fileutils.prompt_title(M.Cfg.extension, nil, function(title)
on_create(opts, title)
end)
end)
end
--
@@ -1981,7 +2069,8 @@ local function FollowLink(opts)
opts.new_note_location = opts.new_note_location or M.Cfg.new_note_location
local uuid_type = opts.uuid_type or M.Cfg.uuid_type
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -2060,10 +2149,31 @@ local function FollowLink(opts)
-- check if subdir exists
local filepath = title:match("(.*/)") or ""
filepath = M.Cfg.home .. "/" .. filepath
check_dir_and_ask(filepath, "")
check_dir_and_ask(filepath, "", function()
-- check if fname exists anywhere
local pinfo = Pinfo:new({ title = title })
local function picker()
find_files_sorted({
prompt_title = "Follow link to note...",
cwd = pinfo.root_dir,
default_text = title,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(
picker_actions.select_default
)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
sort = M.Cfg.sort,
})
end
if
(pinfo.fexists ~= true)
and (
@@ -2082,30 +2192,19 @@ local function FollowLink(opts)
uuid,
pinfo.filepath,
pinfo.template,
pinfo.calendar_info
)
pinfo.calendar_info,
function()
opts.erase = true
opts.erase_file = pinfo.filepath
opts.erase_file = fname
picker()
end
)
return
end
end
find_files_sorted({
prompt_title = "Follow link to note...",
cwd = pinfo.root_dir,
default_text = title,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(picker_actions.select_default)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
sort = M.Cfg.sort,
})
picker()
end)
end
if search_mode ~= "files" then
@@ -2130,7 +2229,8 @@ local function FollowLink(opts)
local display =
utils.transform_path(display_opts, display_entry.value)
display_entry.filn = display_entry.filn or display:gsub(":.*", "")
display_entry.filn = display_entry.filn
or display:gsub(":.*", "")
display, hl_group =
utils.transform_devicons(display_entry.filn, display, false)
@@ -2269,7 +2369,8 @@ local function FollowLink(opts)
if Path:new(t.filename):is_absolute() then
return t.filename, false
else
return Path:new({ t.cwd, t.filename }):absolute(), false
return Path:new({ t.cwd, t.filename }):absolute(),
false
end
end,
filename = function(t)
@@ -2391,7 +2492,9 @@ local function FollowLink(opts)
previewer = conf.grep_previewer(opts),
sorter = sorters.highlighter_only(opts),
attach_mappings = function(_, map)
actions.select_default:replace(picker_actions.select_default)
actions.select_default:replace(
picker_actions.select_default
)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
@@ -2403,6 +2506,7 @@ local function FollowLink(opts)
})
picker:find()
end
end)
end
--
@@ -2419,7 +2523,8 @@ local function GotoThisWeek(opts)
or M.Cfg.close_after_yanking
opts.journal_auto_open = opts.journal_auto_open or M.Cfg.journal_auto_open
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -2428,6 +2533,31 @@ local function GotoThisWeek(opts)
local title = dinfo.isoweek
local fname = M.Cfg.weeklies .. "/" .. title .. M.Cfg.extension
local fexists = fileutils.file_exists(fname)
local function picker()
if opts.journal_auto_open then
vim.cmd("e " .. fname)
else
find_files_sorted({
prompt_title = "Goto this week:",
cwd = M.Cfg.weeklies,
default_text = title,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(
picker_actions.select_default
)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
})
end
end
if
(fexists ~= true)
and (
@@ -2439,32 +2569,18 @@ local function GotoThisWeek(opts)
title,
nil,
fname,
M.note_type_templates.weekly
)
M.note_type_templates.weekly,
function()
opts.erase = true
opts.erase_file = fname
picker()
end
)
return
end
if opts.journal_auto_open then
vim.cmd("e " .. fname)
else
find_files_sorted({
prompt_title = "Goto this week:",
cwd = M.Cfg.weeklies,
default_text = title,
find_command = M.Cfg.find_command,
attach_mappings = function(_, map)
actions.select_default:replace(picker_actions.select_default)
map("i", "<c-y>", picker_actions.yank_link(opts))
map("i", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-y>", picker_actions.yank_link(opts))
map("n", "<c-i>", picker_actions.paste_link(opts))
map("n", "<c-c>", picker_actions.close(opts))
map("n", "<esc>", picker_actions.close(opts))
return true
end,
})
end
picker()
end)
end
--
@@ -2619,7 +2735,8 @@ local function FindAllTags(opts)
opts.templateDir = templateDir
opts.rg_pcre = M.Cfg.rg_pcre
if not global_dir_check() then
global_dir_check(function(dir_check)
if not dir_check then
return
end
@@ -2703,6 +2820,7 @@ local function FindAllTags(opts)
end,
})
:find()
end)
end
-- Setup(cfg)