mirror of
https://github.com/kristoferssolo/solorice.git
synced 2026-03-18 08:09:40 +00:00
Update 2024-07-16
This commit is contained in:
993
.config/yazi/plugins/augment-command.yazi/init.lua
Normal file
993
.config/yazi/plugins/augment-command.yazi/init.lua
Normal file
@@ -0,0 +1,993 @@
|
||||
-- Plugin to make some Yazi commands smarter
|
||||
-- Written in Lua 5.4
|
||||
|
||||
-- The enum for which group of items to operate on
|
||||
local ItemGroup = {
|
||||
Hovered = "hovered",
|
||||
Selected = "selected",
|
||||
None = "none",
|
||||
Prompt = "prompt",
|
||||
}
|
||||
|
||||
-- The enum for the archive extraction behaviour
|
||||
local ExtractBehaviour = {
|
||||
Overwrite = "overwrite",
|
||||
Rename = "rename",
|
||||
Skip = "skip",
|
||||
}
|
||||
|
||||
-- The enum for the flags for the archive extraction behaviour
|
||||
local ExtractBehaviourFlags = {
|
||||
[ExtractBehaviour.Overwrite] = "-f",
|
||||
[ExtractBehaviour.Rename] = "-r",
|
||||
[ExtractBehaviour.Skip] = "-s",
|
||||
}
|
||||
|
||||
-- The enum for the supported commands
|
||||
local Commands = {
|
||||
Open = "open",
|
||||
Enter = "enter",
|
||||
Leave = "leave",
|
||||
Rename = "rename",
|
||||
Remove = "remove",
|
||||
Paste = "paste",
|
||||
Arrow = "arrow",
|
||||
ParentArrow = "parent-arrow",
|
||||
Editor = "editor",
|
||||
Pager = "pager",
|
||||
}
|
||||
|
||||
-- The default configuration for the plugin
|
||||
local DEFAULT_CONFIG = {
|
||||
prompt = false,
|
||||
default_item_group_for_prompt = ItemGroup.Hovered,
|
||||
smart_enter = true,
|
||||
smart_paste = false,
|
||||
enter_archives = true,
|
||||
extract_behaviour = ExtractBehaviour.Skip,
|
||||
must_have_hovered_item = true,
|
||||
skip_single_subdirectory_on_enter = true,
|
||||
skip_single_subdirectory_on_leave = true,
|
||||
ignore_hidden_items = false,
|
||||
wraparound_file_navigation = false,
|
||||
}
|
||||
|
||||
-- The default notification options for this plugin
|
||||
local DEFAULT_NOTIFICATION_OPTIONS = {
|
||||
title = "Augment Command Plugin",
|
||||
timeout = 5.0
|
||||
}
|
||||
|
||||
-- The default input options for this plugin
|
||||
local DEFAULT_INPUT_OPTIONS = {
|
||||
position = { "top-center", y = 2, w = 50 }
|
||||
}
|
||||
|
||||
-- The table of input options for the prompt
|
||||
local INPUT_OPTIONS_TABLE = {
|
||||
[ItemGroup.Hovered] = "(H/s)",
|
||||
[ItemGroup.Selected] = "(h/S)",
|
||||
[ItemGroup.None] = "(h/s)",
|
||||
}
|
||||
|
||||
-- The list of archive mime types
|
||||
local ARCHIVE_MIME_TYPES = {
|
||||
"application/zip",
|
||||
"application/gzip",
|
||||
"application/x-tar",
|
||||
"application/x-bzip",
|
||||
"application/x-bzip2",
|
||||
"application/x-7z-compressed",
|
||||
"application/x-rar",
|
||||
"application/x-xz",
|
||||
}
|
||||
|
||||
-- The pattern to get the double dash from the front of the argument
|
||||
local double_dash_pattern = "^%-%-"
|
||||
|
||||
-- The pattern to get the parent directory of the current directory
|
||||
local get_parent_directory_pattern = "(.*)/.*"
|
||||
|
||||
-- The pattern to get if a file path is a directory
|
||||
local is_directory_pattern = "(.*)/$"
|
||||
|
||||
-- The pattern to get the filename of a file
|
||||
local get_filename_pattern = "(.*)%.[^%.]+$"
|
||||
|
||||
|
||||
-- Function to merge tables.
|
||||
-- The tables given later in the argument list WILL OVERRIDE
|
||||
-- the tables given earlier in the argument list.
|
||||
local function merge_tables(...)
|
||||
|
||||
-- Initialise a new table
|
||||
local new_table = {}
|
||||
|
||||
-- Iterates over the tables given
|
||||
for _, table in ipairs({...}) do
|
||||
|
||||
-- Iterate over all of the keys and values
|
||||
for key, value in pairs(table) do
|
||||
|
||||
-- Set the key in the new table to the value given
|
||||
new_table[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
-- Return the new table
|
||||
return new_table
|
||||
end
|
||||
|
||||
|
||||
-- Function to check if a list contains a given value
|
||||
local function list_contains(list, value)
|
||||
|
||||
-- Iterate over all of the items in the list
|
||||
for _, item in ipairs(list) do
|
||||
|
||||
-- If the item is equal to the given value,
|
||||
-- then return true
|
||||
if item == value then return true end
|
||||
end
|
||||
|
||||
-- Otherwise, return false if the item isn't in the list
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- Function to split a string into a list
|
||||
local function string_split(given_string, separator)
|
||||
|
||||
-- If the separator isn't given, set it to the whitespace character
|
||||
if separator == nil then
|
||||
separator = "%s"
|
||||
end
|
||||
|
||||
-- Initialise the list of splitted strings
|
||||
local splitted_strings = {}
|
||||
|
||||
-- Iterate over all of the strings found by pattern
|
||||
for string in string.gmatch(given_string, "([^" .. separator .. "]+)") do
|
||||
|
||||
-- Add the string to the list of splitted strings
|
||||
table.insert(splitted_strings, string)
|
||||
end
|
||||
|
||||
-- Return the list of splitted strings
|
||||
return splitted_strings
|
||||
end
|
||||
|
||||
|
||||
-- Function to parse the arguments given.
|
||||
-- This function takes the arguments passed to the entry function
|
||||
local function parse_args(args)
|
||||
|
||||
-- The table of options to pass to ya.manager_emit
|
||||
local options = {}
|
||||
|
||||
-- Iterates over the arguments given
|
||||
for index, argument in ipairs(args) do
|
||||
|
||||
-- If the index isn't 1,
|
||||
-- which means it is the arguments to the command given
|
||||
if index ~= 1 then
|
||||
|
||||
-- If the argument doesn't start with a double dash
|
||||
if not argument:match(double_dash_pattern) then
|
||||
|
||||
-- Try to convert the argument to a number
|
||||
local number_argument = tonumber(argument)
|
||||
|
||||
-- Add the argument to the list of options
|
||||
table.insert(
|
||||
options,
|
||||
number_argument and number_argument or argument
|
||||
)
|
||||
|
||||
-- Continue the loop
|
||||
goto continue
|
||||
end
|
||||
|
||||
-- Otherwise, remove the double dash from the front of the argument
|
||||
local cleaned_argument =
|
||||
argument:gsub(double_dash_pattern, "")
|
||||
|
||||
-- Replace all of the dashes with underscores
|
||||
cleaned_argument = cleaned_argument:gsub("%-", "_")
|
||||
|
||||
-- Split the arguments at the = character
|
||||
local arg_name, arg_value = table.unpack(
|
||||
string_split(cleaned_argument, "=")
|
||||
)
|
||||
|
||||
-- If the argument value is nil
|
||||
if arg_value == nil then
|
||||
|
||||
-- Set the argument name to the cleaned argument
|
||||
arg_name = cleaned_argument
|
||||
|
||||
-- Set the argument value to true
|
||||
arg_value = true
|
||||
|
||||
-- Otherwise
|
||||
else
|
||||
|
||||
-- Try to convert the argument value to a number
|
||||
local number_arg_value = tonumber(arg_value)
|
||||
|
||||
-- Set the argument value to the number
|
||||
-- if the the argument value can be converted to a number
|
||||
arg_value = number_arg_value and number_arg_value or arg_value
|
||||
end
|
||||
|
||||
-- Add the argument name and value to the options
|
||||
options[arg_name] = arg_value
|
||||
end
|
||||
|
||||
-- The label to continue the loop
|
||||
::continue::
|
||||
end
|
||||
|
||||
-- Return the table of options
|
||||
return options
|
||||
end
|
||||
|
||||
|
||||
-- Function to initialise the configuration
|
||||
local initialise_config = ya.sync(function(state, opts)
|
||||
|
||||
-- Merge the default configuration with the given one
|
||||
-- and set it to the state.
|
||||
state.config = merge_tables(DEFAULT_CONFIG, opts)
|
||||
|
||||
-- Return the configuration object for async functions
|
||||
return state.config
|
||||
end)
|
||||
|
||||
|
||||
-- Function to get the configuration from an async function
|
||||
local get_config = ya.sync(function(state)
|
||||
|
||||
-- Returns the configuration object
|
||||
return state.config
|
||||
end)
|
||||
|
||||
|
||||
-- Function to get the current working directory
|
||||
local get_current_directory = ya.sync(function(_)
|
||||
return tostring(cx.active.current.cwd)
|
||||
end)
|
||||
|
||||
|
||||
-- Function to get the parent working directory
|
||||
local get_parent_directory = ya.sync(function(_)
|
||||
|
||||
-- Get the parent directory
|
||||
local parent_directory = cx.active.parent
|
||||
|
||||
-- If the parent directory doesn't exist,
|
||||
-- return nil
|
||||
if not parent_directory then return nil end
|
||||
|
||||
-- Otherwise, return the path of the parent directory
|
||||
return tostring(parent_directory.cwd)
|
||||
end)
|
||||
|
||||
|
||||
-- Function to get the hovered item path
|
||||
local get_hovered_item_path = ya.sync(function(_)
|
||||
|
||||
-- Get the hovered item
|
||||
local hovered_item = cx.active.current.hovered
|
||||
|
||||
-- If the hovered item exists
|
||||
if hovered_item then
|
||||
|
||||
-- Return the path of the hovered item
|
||||
return tostring(cx.active.current.hovered.url)
|
||||
|
||||
-- Otherwise, return nil
|
||||
else return nil end
|
||||
end)
|
||||
|
||||
|
||||
-- Function to get if the hovered item is a directory
|
||||
local hovered_item_is_dir = ya.sync(function(_)
|
||||
|
||||
-- Get the hovered item
|
||||
local hovered_item = cx.active.current.hovered
|
||||
|
||||
-- Return if the hovered item exists and is a directory
|
||||
return hovered_item and hovered_item.cha.is_dir
|
||||
end)
|
||||
|
||||
|
||||
-- Function to get if the hovered item is an archive
|
||||
local hovered_item_is_archive = ya.sync(function(_)
|
||||
|
||||
-- Get the hovered item
|
||||
local hovered_item = cx.active.current.hovered
|
||||
|
||||
-- Return if the hovered item exists and is an archive
|
||||
return hovered_item and list_contains(
|
||||
ARCHIVE_MIME_TYPES, hovered_item:mime()
|
||||
)
|
||||
end)
|
||||
|
||||
|
||||
-- Function to choose which group of items to operate on.
|
||||
-- It returns ItemGroup.Hovered for the hovered item,
|
||||
-- ItemGroup.Selected for the selected items,
|
||||
-- and ItemGroup.Prompt to tell the calling function
|
||||
-- to prompt the user.
|
||||
local get_item_group_from_state = ya.sync(function(state)
|
||||
|
||||
-- Get the hovered item
|
||||
local hovered_item = cx.active.current.hovered
|
||||
|
||||
-- The boolean representing that there are no selected items
|
||||
local no_selected_items = #cx.active.selected == 0
|
||||
|
||||
-- If there is no hovered item
|
||||
if not hovered_item then
|
||||
|
||||
-- If there are no selected items, exit the function
|
||||
if no_selected_items then return
|
||||
|
||||
-- Otherwise, if the configuration is set to have a hovered item,
|
||||
-- exit the function
|
||||
elseif state.config.must_have_hovered_item then return
|
||||
|
||||
-- Otherwise, return the enum for the selected items
|
||||
else return ItemGroup.Selected end
|
||||
|
||||
-- Otherwise, there is a hovered item
|
||||
-- and if there are no selected items,
|
||||
-- return the enum for the hovered item.
|
||||
elseif no_selected_items then return ItemGroup.Hovered
|
||||
|
||||
-- Otherwise if there are selected items and the user wants a prompt,
|
||||
-- then tells the calling function to prompt them
|
||||
elseif state.config.prompt then
|
||||
return ItemGroup.Prompt
|
||||
|
||||
-- Otherwise, if the hovered item is selected,
|
||||
-- then return the enum for the selected items
|
||||
elseif hovered_item:is_selected() then return ItemGroup.Selected
|
||||
|
||||
-- Otherwise, return the enum for the hovered item
|
||||
else return ItemGroup.Hovered end
|
||||
end)
|
||||
|
||||
|
||||
-- Function to prompt the user for their desired item group
|
||||
local function prompt_for_desired_item_group()
|
||||
|
||||
-- Get the configuration
|
||||
local config = get_config()
|
||||
|
||||
-- Get the default item group
|
||||
local default_item_group = config.default_item_group_for_prompt
|
||||
|
||||
-- Get the input options
|
||||
local input_options = INPUT_OPTIONS_TABLE[default_item_group]
|
||||
|
||||
-- If the default item group is None, then set it to nil
|
||||
if default_item_group == ItemGroup.None then
|
||||
default_item_group = nil
|
||||
end
|
||||
|
||||
-- Prompt the user for their input
|
||||
local user_input, event = ya.input(merge_tables(DEFAULT_INPUT_OPTIONS, {
|
||||
title = "Operate on hovered or selected items? " .. input_options
|
||||
}))
|
||||
|
||||
-- Lowercase the user's input
|
||||
user_input = user_input:lower()
|
||||
|
||||
-- If the user did not confirm the input, exit the function
|
||||
if event ~= 1 then return
|
||||
|
||||
-- Otherwise, if the user's input starts with "h",
|
||||
-- return the item group representing the hovered item
|
||||
elseif user_input:find("^h") then return ItemGroup.Hovered
|
||||
|
||||
-- Otherwise, if the user's input starts with "s",
|
||||
-- return the item group representing the selected items
|
||||
elseif user_input:find("^s") then return ItemGroup.Selected
|
||||
|
||||
-- Otherwise, return the default item group
|
||||
else return default_item_group end
|
||||
end
|
||||
|
||||
|
||||
-- Function to get the item group
|
||||
local function get_item_group()
|
||||
|
||||
-- Get the item group from the state
|
||||
local item_group = get_item_group_from_state()
|
||||
|
||||
-- If the item group isn't the prompt one,
|
||||
-- then return the item group immediately
|
||||
if item_group ~= ItemGroup.Prompt then return item_group
|
||||
|
||||
-- Otherwise, prompt the user for the desired item group
|
||||
else return prompt_for_desired_item_group() end
|
||||
end
|
||||
|
||||
|
||||
-- The ls command to get the items in the directory
|
||||
local function ls_command(directory, ignore_hidden_items)
|
||||
return Command("ls")
|
||||
:args({
|
||||
directory,
|
||||
ignore_hidden_items and "-1p" or "-1pA",
|
||||
"--group-directories-first",
|
||||
})
|
||||
:stdout(Command.PIPED)
|
||||
:stderr(Command.PIPED)
|
||||
:output()
|
||||
end
|
||||
|
||||
|
||||
-- Function to skip child directories with only one directory
|
||||
local function skip_single_child_directories(args, config, initial_directory)
|
||||
|
||||
-- If the user doesn't want to skip single subdirectories on enter,
|
||||
-- or one of the arguments passed is no skip,
|
||||
-- then exit the function
|
||||
if not config.skip_single_subdirectory_on_enter or args.no_skip then
|
||||
return
|
||||
end
|
||||
|
||||
-- Initialise the directory variable to the initial directory given
|
||||
local directory = initial_directory
|
||||
|
||||
-- Start an infinite loop
|
||||
while true do
|
||||
|
||||
-- Run the ls command to get the items in the directory
|
||||
local output, _ = ls_command(directory, config.ignore_hidden_items)
|
||||
|
||||
-- If there is no output, then break out of the loop
|
||||
if not output then break end
|
||||
|
||||
-- Get the list of items in the directory
|
||||
local directory_items = string_split(output.stdout, "\n")
|
||||
|
||||
-- If the number of directory items is not 1,
|
||||
-- then break out of the loop
|
||||
if #directory_items ~= 1 then break end
|
||||
|
||||
-- Otherwise, get the item in the directory
|
||||
local directory_item = table.unpack(directory_items)
|
||||
|
||||
-- Match the directory item against the pattern to
|
||||
-- check if it is a directory
|
||||
directory_item = directory_item:match(is_directory_pattern)
|
||||
|
||||
-- If the directory item isn't a directory, break the loop
|
||||
if directory_item == nil then break end
|
||||
|
||||
-- Otherwise, set the directory to the inner directory
|
||||
directory = directory .. "/" .. directory_item
|
||||
end
|
||||
|
||||
-- Emit the change directory command to change to the directory variable
|
||||
ya.manager_emit("cd", { directory })
|
||||
end
|
||||
|
||||
|
||||
-- Function to handle the open command
|
||||
local function handle_open(args, config, command_table)
|
||||
|
||||
-- Call the function to get the item group
|
||||
local item_group = get_item_group()
|
||||
|
||||
-- If no item group is returned, exit the function
|
||||
if not item_group then return end
|
||||
|
||||
-- If the item group is the selected items,
|
||||
-- then execute the command and exit the function
|
||||
if item_group == ItemGroup.Selected then
|
||||
|
||||
-- Emit the command and exit the function
|
||||
return ya.manager_emit("open", args)
|
||||
end
|
||||
|
||||
-- Otherwise, the item group is the hovered item.
|
||||
-- Get the function to handle the enter command.
|
||||
local enter_command = command_table[Commands.Enter]
|
||||
|
||||
-- If the hovered item is a directory
|
||||
if hovered_item_is_dir() then
|
||||
|
||||
-- If smart enter is wanted,
|
||||
-- calls the function to enter the directory
|
||||
-- and exit the function
|
||||
if config.smart_enter then
|
||||
return enter_command(args, config, command_table)
|
||||
|
||||
-- Otherwise, just exit the function
|
||||
else return end
|
||||
end
|
||||
|
||||
-- Otherwise, if the hovered item is not an archive,
|
||||
-- or entering archives isn't wanted
|
||||
if not hovered_item_is_archive() or not config.enter_archives then
|
||||
|
||||
-- Simply emit the open command and exit the function
|
||||
return ya.manager_emit("open", args)
|
||||
end
|
||||
|
||||
-- Otherwise, the hovered item is an archive
|
||||
-- and entering archives is wanted,
|
||||
-- so get the path of the hovered item
|
||||
local archive_path = get_hovered_item_path()
|
||||
|
||||
-- If the archive path somehow doesn't exist, then exit the function
|
||||
if not archive_path then return end
|
||||
|
||||
-- Run the command to extract the archive
|
||||
local output, err = Command("unar")
|
||||
:args({
|
||||
"-d",
|
||||
ExtractBehaviourFlags[config.extract_behaviour],
|
||||
archive_path
|
||||
})
|
||||
:stdout(Command.PIPED)
|
||||
:stderr(Command.PIPED)
|
||||
:output()
|
||||
|
||||
-- If the command isn't successful, notify the user
|
||||
if not output then
|
||||
return ya.notify(merge_tables(DEFAULT_NOTIFICATION_OPTIONS, {
|
||||
content = "Failed to extract archive at: "
|
||||
.. archive_path
|
||||
.. "\nError code: "
|
||||
.. tostring(err),
|
||||
level = "error"
|
||||
}))
|
||||
end
|
||||
|
||||
-- Get the filename of the archive
|
||||
local archive_filename = archive_path:match(get_filename_pattern)
|
||||
|
||||
-- Enter the archive directory
|
||||
ya.manager_emit("cd", { archive_filename })
|
||||
|
||||
-- Calls the function to skip child directories
|
||||
-- with only a single directory inside
|
||||
skip_single_child_directories(args, config, archive_filename)
|
||||
end
|
||||
|
||||
|
||||
-- Function to handle the enter command
|
||||
local function handle_enter(args, config, command_table)
|
||||
|
||||
-- Get the function for the open command
|
||||
local open_command = command_table[Commands.Open]
|
||||
|
||||
-- If the hovered item is not a directory
|
||||
if not hovered_item_is_dir() and config.smart_enter then
|
||||
|
||||
-- If smart enter is wanted,
|
||||
-- call the function for the open command
|
||||
-- and exit the function
|
||||
if config.smart_enter then
|
||||
return open_command(args, config, command_table)
|
||||
|
||||
-- Otherwise, just exit the function
|
||||
else return end
|
||||
end
|
||||
|
||||
-- Otherwise, always emit the enter command,
|
||||
ya.manager_emit("enter", args)
|
||||
|
||||
-- Calls the function to skip child directories
|
||||
-- with only a single directory inside
|
||||
skip_single_child_directories(args, config, get_current_directory())
|
||||
end
|
||||
|
||||
|
||||
-- Function to handle the leave command
|
||||
local function handle_leave(args, config)
|
||||
|
||||
-- Always emit the leave command
|
||||
ya.manager_emit("leave", args)
|
||||
|
||||
-- If the user doesn't want to skip single subdirectories on leave,
|
||||
-- or one of the arguments passed is no skip,
|
||||
-- then exit the function
|
||||
if not config.skip_single_subdirectory_on_leave or args.no_skip then
|
||||
return
|
||||
end
|
||||
|
||||
-- Otherwise, initialise the directory to the current directory
|
||||
local directory = get_current_directory()
|
||||
|
||||
-- Otherwise, start an infinite loop
|
||||
while true do
|
||||
|
||||
-- Run the ls command to get the items in the directory
|
||||
local output, _ = ls_command(directory, config.ignore_hidden_items)
|
||||
|
||||
-- If there is no output, then break out of the loop
|
||||
if not output then break end
|
||||
|
||||
-- Get the list of items in the directory
|
||||
local directory_items = string_split(output.stdout, "\n")
|
||||
|
||||
-- If the number of directory items is not 1,
|
||||
-- then break out of the loop
|
||||
if #directory_items ~= 1 then break end
|
||||
|
||||
-- Otherwise, set the new directory
|
||||
-- to the parent of the current directory
|
||||
directory = directory:match(get_parent_directory_pattern)
|
||||
end
|
||||
|
||||
-- Emit the change directory command to change to the directory variable
|
||||
ya.manager_emit("cd", { directory })
|
||||
end
|
||||
|
||||
|
||||
-- Function to handle the a command
|
||||
local function handle_command(command, args)
|
||||
|
||||
-- Call the function to get the item group
|
||||
local item_group = get_item_group()
|
||||
|
||||
-- If no item group is returned, exit the function
|
||||
if not item_group then return end
|
||||
|
||||
-- If the item group is the selected items
|
||||
if item_group == ItemGroup.Selected then
|
||||
|
||||
-- Emit the command to operate on the selected items
|
||||
ya.manager_emit(command, args)
|
||||
|
||||
-- If the item group is the hovered item
|
||||
elseif item_group == ItemGroup.Hovered then
|
||||
|
||||
-- Emit the command with the hovered option
|
||||
ya.manager_emit(command, merge_tables(args, { hovered = true }))
|
||||
|
||||
-- Otherwise, exit the function
|
||||
else return end
|
||||
end
|
||||
|
||||
|
||||
-- Function to handle a shell command
|
||||
local function handle_shell_command(command, args)
|
||||
|
||||
-- Call the function to get the item group
|
||||
local item_group = get_item_group()
|
||||
|
||||
-- If no item group is returned, exit the function
|
||||
if not item_group then return end
|
||||
|
||||
-- If the item group is the selected items
|
||||
if item_group == ItemGroup.Selected then
|
||||
|
||||
-- Merge the arguments for the shell command with additional ones
|
||||
args = merge_tables({
|
||||
command .. " $@",
|
||||
confirm = true,
|
||||
block = true,
|
||||
}, args)
|
||||
|
||||
-- Emit the command to operate the selected items
|
||||
ya.manager_emit("shell", args)
|
||||
|
||||
-- If the item group is the hovered item
|
||||
elseif item_group == ItemGroup.Hovered then
|
||||
|
||||
-- Merge the arguments for the shell command with additional ones
|
||||
args = merge_tables({
|
||||
command .. " $0",
|
||||
confirm = true,
|
||||
block = true,
|
||||
}, args)
|
||||
|
||||
-- Emit the command to operate on the hovered item
|
||||
ya.manager_emit("shell", args)
|
||||
|
||||
-- Otherwise, exit the function
|
||||
else return end
|
||||
end
|
||||
|
||||
|
||||
-- Function to handle the paste command
|
||||
local function handle_paste(args, config)
|
||||
|
||||
-- If the hovered item is a directory and smart paste is wanted
|
||||
if hovered_item_is_dir() and (config.smart_paste or args.smart) then
|
||||
|
||||
-- Enter the directory
|
||||
ya.manager_emit("enter", {})
|
||||
|
||||
-- Paste the items inside the directory
|
||||
ya.manager_emit("paste", args)
|
||||
|
||||
-- Leave the directory
|
||||
ya.manager_emit("leave", {})
|
||||
|
||||
-- Otherwise, just paste the items inside the current directory
|
||||
else
|
||||
ya.manager_emit("paste", args)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Function to do the wraparound for the arrow command
|
||||
local wraparound_arrow = ya.sync(function(_, args)
|
||||
|
||||
-- Get the current tab
|
||||
local current_tab = cx.active.current
|
||||
|
||||
-- Get the step from the arguments given
|
||||
local step = table.remove(args, 1)
|
||||
|
||||
-- Get the number of files in the current tab
|
||||
local number_of_files = #current_tab.files
|
||||
|
||||
-- If there are no files in the current tab, exit the function
|
||||
if number_of_files == 0 then return end
|
||||
|
||||
-- Get the new cursor index,
|
||||
-- which is the current cursor position plus the step given
|
||||
-- to the arrow function, modulus the number of files in
|
||||
-- the current tab
|
||||
local new_cursor_index = (current_tab.cursor + step) % number_of_files
|
||||
|
||||
-- Emit the arrow function with the new cursor index minus
|
||||
-- the current cursor index to determine how to move the cursor
|
||||
ya.manager_emit("arrow", merge_tables(
|
||||
args,
|
||||
{ new_cursor_index - current_tab.cursor }
|
||||
))
|
||||
end)
|
||||
|
||||
|
||||
-- Function to handle the arrow command
|
||||
local function handle_arrow(args, config)
|
||||
|
||||
-- If wraparound file navigation isn't wanted,
|
||||
-- then execute the arrow command
|
||||
if not config.wraparound_file_navigation then
|
||||
ya.manager_emit("arrow", args)
|
||||
|
||||
-- Otherwise, call the wraparound arrow function
|
||||
else wraparound_arrow(args) end
|
||||
end
|
||||
|
||||
|
||||
-- Function to execute the parent arrow command
|
||||
local execute_parent_arrow_command = ya.sync(
|
||||
function(state, args, number_of_directories)
|
||||
|
||||
-- Gets the parent directory
|
||||
local parent_directory = cx.active.parent
|
||||
|
||||
-- If the parent directory doesn't exist,
|
||||
-- then exit the function
|
||||
if not parent_directory then return end
|
||||
|
||||
-- Get the step from the arguments given
|
||||
local step = table.remove(args, 1)
|
||||
|
||||
-- Initialise the new cursor index
|
||||
-- to the current parent cursor index
|
||||
local new_cursor_index = parent_directory.cursor
|
||||
|
||||
-- Otherwise, if wraparound file navigation is wanted
|
||||
-- and the number of directories is given and isn't 0
|
||||
if
|
||||
state.config.wraparound_file_navigation
|
||||
and number_of_directories
|
||||
and number_of_directories ~= 0
|
||||
then
|
||||
|
||||
-- Get the new cursor index by adding the step,
|
||||
-- and modding the whole thing by the number of
|
||||
-- directories given.
|
||||
new_cursor_index = (parent_directory.cursor + step)
|
||||
% number_of_directories
|
||||
else
|
||||
|
||||
-- Otherwise, get the new cursor index normally.
|
||||
new_cursor_index = parent_directory.cursor + step
|
||||
end
|
||||
|
||||
-- Increment the cursor index by 1.
|
||||
-- The cursor index needs to be increased by 1
|
||||
-- as the cursor index is 0-based, while Lua
|
||||
-- tables are 1-based.
|
||||
new_cursor_index = new_cursor_index + 1
|
||||
|
||||
-- Get the target directory
|
||||
local target_directory = parent_directory.files[new_cursor_index]
|
||||
|
||||
-- If the target directory exists and is a directory
|
||||
if target_directory and target_directory.cha.is_dir then
|
||||
|
||||
-- Emit the command to change directory
|
||||
-- to the target directory
|
||||
ya.manager_emit("cd", { target_directory.url })
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
-- Function to handle the parent arrow command
|
||||
local function handle_parent_arrow(args, config)
|
||||
|
||||
-- If wraparound file navigation isn't wanted,
|
||||
-- then execute the parent arrow command and exit the function
|
||||
if not config.wraparound_file_navigation then
|
||||
return execute_parent_arrow_command(args)
|
||||
end
|
||||
|
||||
-- Otherwise, get the path of the parent directory
|
||||
local parent_directory_path = get_parent_directory()
|
||||
|
||||
-- If there is no parent directory, exit the function
|
||||
if not parent_directory_path then return end
|
||||
|
||||
-- Call the ls command to get the number of directories
|
||||
local output, _ = ls_command(
|
||||
parent_directory_path,
|
||||
config.ignore_hidden_items
|
||||
)
|
||||
|
||||
-- If there is no output, exit the function
|
||||
if not output then return end
|
||||
|
||||
-- Get the item in the parent directory
|
||||
local directory_items = string_split(output.stdout, "\n")
|
||||
|
||||
-- Initialise the number of directories
|
||||
local number_of_directories = 0
|
||||
|
||||
-- Iterate over the directory items
|
||||
for _, item in ipairs(directory_items) do
|
||||
|
||||
-- If the item is a directory
|
||||
if item:match(is_directory_pattern) then
|
||||
|
||||
-- Increment the number of directories by 1
|
||||
number_of_directories = number_of_directories + 1
|
||||
|
||||
-- Otherwise, break out of the loop,
|
||||
-- as the directories are grouped together
|
||||
else break end
|
||||
end
|
||||
|
||||
-- Call the function to execute the parent arrow command
|
||||
execute_parent_arrow_command(args, number_of_directories)
|
||||
end
|
||||
|
||||
|
||||
-- Function to handle the pager command
|
||||
local function handle_pager(args)
|
||||
|
||||
-- Call the function to get the item group
|
||||
local item_group = get_item_group()
|
||||
|
||||
-- If no item group is returned, exit the function
|
||||
if not item_group then return end
|
||||
|
||||
-- If the item group is the selected items,
|
||||
-- then execute the command and exit the function
|
||||
if item_group == ItemGroup.Selected then
|
||||
|
||||
-- Combine the arguments with additional ones
|
||||
args = merge_tables({
|
||||
"$PAGER $@",
|
||||
confirm = true,
|
||||
block = true
|
||||
}, args)
|
||||
|
||||
-- Emit the command and exit the function
|
||||
return ya.manager_emit("shell", args)
|
||||
end
|
||||
|
||||
-- Otherwise, the item group is the hovered item,
|
||||
-- and if the hovered item is a directory, exit the function
|
||||
if hovered_item_is_dir() then return
|
||||
|
||||
-- Otherwise
|
||||
else
|
||||
|
||||
-- Combine the arguments with additional ones
|
||||
args = merge_tables({
|
||||
"$PAGER $0",
|
||||
confirm = true,
|
||||
block = true
|
||||
}, args)
|
||||
|
||||
-- Emit the command and exit the function
|
||||
return ya.manager_emit("shell", args)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Function to run the commands given
|
||||
local function run_command_func(command, args, config)
|
||||
|
||||
-- The command table
|
||||
local command_table = {
|
||||
[Commands.Open] = handle_open,
|
||||
[Commands.Enter] = handle_enter,
|
||||
[Commands.Leave] = handle_leave,
|
||||
[Commands.Rename] = function(_)
|
||||
handle_command("rename", args)
|
||||
end,
|
||||
[Commands.Remove] = function(_)
|
||||
handle_command("remove", args)
|
||||
end,
|
||||
[Commands.Paste] = handle_paste,
|
||||
[Commands.Arrow] = handle_arrow,
|
||||
[Commands.ParentArrow] = handle_parent_arrow,
|
||||
[Commands.Editor] = function(_)
|
||||
handle_shell_command("$EDITOR", args)
|
||||
end,
|
||||
[Commands.Pager] = handle_pager,
|
||||
}
|
||||
|
||||
-- Get the function for the command
|
||||
local command_func = command_table[command]
|
||||
|
||||
-- If the function isn't found, notify the user and exit the function
|
||||
if not command_func then
|
||||
return ya.notify(
|
||||
merge_tables(DEFAULT_NOTIFICATION_OPTIONS, {
|
||||
content = "Unknown command: " .. command,
|
||||
level = "error"
|
||||
})
|
||||
)
|
||||
end
|
||||
|
||||
-- Parse the arguments and set it to the args variable
|
||||
args = parse_args(args)
|
||||
|
||||
-- Otherwise, call the function for the command
|
||||
command_func(args, config, command_table)
|
||||
end
|
||||
|
||||
-- The setup function to setup the plugin
|
||||
local function setup(_, opts)
|
||||
|
||||
-- Initialise the configuration with the default configuration
|
||||
initialise_config(opts)
|
||||
end
|
||||
|
||||
|
||||
-- The function to be called to use the plugin
|
||||
local function entry(_, args)
|
||||
|
||||
-- Gets the command passed to the plugin
|
||||
local command = args[1]
|
||||
|
||||
-- If the command isn't given, exit the function
|
||||
if not command then return end
|
||||
|
||||
-- Gets the configuration object
|
||||
local config = get_config()
|
||||
|
||||
-- If the configuration hasn't been initialised,
|
||||
-- then initialise the configuration
|
||||
if not config then
|
||||
config = initialise_config()
|
||||
end
|
||||
|
||||
-- Call the function to handle the commands
|
||||
run_command_func(command, args, config)
|
||||
end
|
||||
|
||||
-- Returns the table required for Yazi to run the plugin
|
||||
return {
|
||||
setup = setup,
|
||||
entry = entry,
|
||||
}
|
||||
Reference in New Issue
Block a user