yazi plugin refactor

This commit is contained in:
Matt Nish-Lapidus 2025-04-04 15:38:54 -04:00
parent 38f162562e
commit a00af3e849
39 changed files with 92 additions and 4880 deletions

View file

@ -1,44 +1,113 @@
{ inputs, pkgs, ... }:
{ inputs, pkgs, lib, ... }:
{
programs.yazi = {
enable = true;
enableFishIntegration = true;
package = inputs.yazi.packages.x86_64-linux.default;
initLua = ./yazi/init.lua;
plugins = let
officialPluginsNames = [
"chmod"
"diff"
"smart-filter"
"git"
"mount"
];
officialPluginsSrc = pkgs.fetchgit {
url = "https://github.com/yazi-rs/plugins.git";
sparseCheckout = map (p: "${p}.yazi") officialPluginsNames;
rev = "HEAD";
hash = "sha256-3F44uFeFBX7PNXo2/maiAzkA/OfweyN4nbDhftna+CI=";
};
officialPlugins =
lib.lists.fold (
a: b:
{
${a} = "${officialPluginsSrc}/${a}.yazi";
}
// b
)
{}
officialPluginsNames;
in
officialPlugins // {
yatline = pkgs.fetchFromGitHub {
owner = "imsi32";
repo = "yatline.yazi";
rev = "HEAD";
sha256 = "sha256-JiUik4umi+ujsJmHliUbLsIj7ZTKayrWAAM8HmRdjwk=";
};
starship = pkgs.fetchFromGitHub {
owner = "Rolv-Apneseth";
repo = "starship.yazi";
rev = "HEAD";
sha256 = "sha256-bhLUziCDnF4QDCyysRn7Az35RAy8ibZIVUzoPgyEO1A=";
};
restore = pkgs.fetchFromGitHub {
owner = "boydaihungst";
repo = "restore.yazi";
rev = "HEAD";
sha256 = "sha256-OJJPgpSaUHYz8a9opVLCds+VZsK1B6T+pSRJyVgYNy8=";
};
lazygit = pkgs.fetchFromGitHub {
owner = "Lil-Dank";
repo = "lazygit.yazi";
rev = "HEAD";
sha256 = "sha256-OJJPgpSaUHYz8a9opVLCds+VZsK1B6T+pSRJyVgYNy8=";
};
ouch = pkgs.fetchFromGitHub {
owner = "ndtoan96";
repo = "ouch.yazi";
rev = "HEAD";
sha256 = "sha256-7X8uAiJ8vBXYBXOgyKhVVikOnTBGrdCcXOJemjQNolI=";
};
dir-rules = ./yazi/plugins/dir-rules.yazi;
smart-tab = ./yazi/plugins/smart-tab.yazi;
};
keymap = {
manager.prepend_keymap = [
{ on = "!"; run = "shell '$SHELL' --block"; desc = "Open shell here"; }
{ on = ["c" "d"]; run = "shell 'ripdrag \"$@\" -x 2>/dev/null &' --confirm"; desc = "Drag selection";}
{ on = ["c" "c"]; run = "yank"; desc = "Copy file"; }
{ on = "y"; run = ["shell 'for path in \"$@\"; do echo \"file://$path\"; done | wl-copy -t text/uri-list'\n" "yank"]; }
{ on = ["g" "r"]; run = "shell 'ya emit cd \"$(git rev-parse --show-toplevel)\"'\n"; desc = "Go to top of git repo"; }
{ on = ["g" "p"]; run = "cd ~/Projects"; desc = "Go to ~/Projects"; }
{ on = ["g" "l"]; run = "plugin lazygit"; desc = "lazygit"; }
{ on = ["t" "p"]; run = "plugin toggle-view parent"; desc = "Toggle parent"; }
{ on = ["t" "c"]; run = "plugin toggle-view current"; desc = "Toggle current"; }
{ on = ["t" "r"]; run = "plugin toggle-view preview"; desc = "Toggle preview"; }
{ on = "<C-t>"; run ="tab_create"; }
{ on = "<C-w>"; run ="tab_close"; }
{ on = "<C-A-right>"; run ="tab_switch 1 --relative"; }
{ on = "<C-A-left>"; run ="tab_switch -1 --relative"; }
{ on = "<Tab>"; run = "spot"; desc = "Spot hovered file"; }
{ on = "M"; run = "plugin mount"; }
{ on = "p"; run = "plugin smart-paste"; desc = "Paste into the hovered directory or CWD"; }
{ on = ["g" "l"]; run = "plugin lazygit"; desc = "lazygit"; }
# { on = "k"; run = "arrow -1"; desc = "up"; }
# { on = "j"; run = "arrow 1"; desc = "down"; }
# { on = "<Up>"; run = "arrow -1"; desc = "up"; }
# { on = "<Down>"; run = "arrow 1"; desc = "down"; }
{ on = "C"; run = "plugin ouch zip"; }
{ on = "T"; run = "plugin smart-tab"; desc = "Create a tab and enter the hovered directory"; }
{ on = "<Backspace>"; run = "remove"; }
{ on = [ "t" "s" ]; run = "plugin what-size"; desc = "Calc size of selection or cwd"; }
{ on = ["d" "u"]; run = "plugin restore"; desc = "Restore last deleted files/folders"; }
{ on = ["d" "d"]; run = "remove"; desc = "Delete files/folders"; }
{ on = ["d" "u"]; run = "plugin restore"; desc = "Restore last deleted files/folders"; }
{ on = "f"; run = "plugin smart-filter"; desc = "Find file"; }
{ on = "F"; run = "find --smart"; desc = "Find file"; }
{ on = "f"; run = "find --smart"; desc = "Find file"; }
{ on = "F"; run = "filter --smart"; desc = "Find file"; }
];
};
settings = {
@ -90,12 +159,12 @@
{ name = "*"; run = "file-extra-metadata"; }
];
prepend_fetchers = [
{
id = "mime";
name = "*";
run = "mime-ext";
prio = "high";
}
# {
# id = "mime";
# name = "*";
# run = "mime-ext";
# prio = "high";
# }
# {
# id = "git";
# name = "*";
@ -113,5 +182,5 @@
xdg.configFile."yazi/theme.toml".source = ./yazi/theme.toml;
xdg.configFile."yazi/flavors".source = ./yazi/flavors;
xdg.configFile."yazi/plugins".source = ./yazi/plugins;
# xdg.configFile."yazi/plugins".source = ./yazi/plugins;
}

View file

@ -1,15 +1,10 @@
require("git"):setup()
require("yatline-symlink"):setup()
-- require("git"):setup()
require("dir-rules"):setup()
require("starship"):setup {
config_file = "~/.config/starship.toml",
}
require("fg"):setup({
default_action = "menu",
})
require("yatline"):setup({
--theme = my_theme,
section_separator = { open = "", close = "" },

View file

@ -2,9 +2,9 @@ local function setup()
ps.sub("cd", function()
local cwd = cx.active.current.cwd
if cwd:ends_with("Downloads") then
ya.manager_emit("sort", { "mtime", reverse = true, dir_first = false })
ya.mgr_emit("sort", { "mtime", reverse = true, dir_first = false })
else
ya.manager_emit("sort", { "alphabetical", reverse = false })
ya.mgr_emit("sort", { "alphabetical", reverse = false, dir_first = true })
end
end)
end

View file

@ -1,274 +0,0 @@
local toggle_ui = ya.sync(function(self)
if self.children then
Modal:children_remove(self.children)
self.children = nil
else
self.children = Modal:children_add(self, 10)
end
ya.render()
end)
local init_ui_data = ya.sync(function(self,file_url)
self.opt = {"nvim", "jump"}
self.title = "fg"
self.title_color = "#82ab3a"
self.cursor = 0
self.file_url = file_url and file_url or ""
ya.render()
end)
local set_option = ya.sync(function(self,enable)
if enable then
self.active_opt = self.opt[self.cursor+1]
else
self.active_opt = nil
end
end)
local get_option = ya.sync(function(self)
return self.active_opt
end)
local get_default_action = ya.sync(function(self)
return self.default_action
end)
local update_cursor = ya.sync(function(self, cursor)
self.cursor = ya.clamp(0, self.cursor + cursor, 1)
ya.render()
end)
local M = {
keys = {
{ on = "q", run = "quit" },
{ on = "<Esc>", run = "quit" },
{ on = "<Enter>", run = "select" },
{ on = "k", run = "up" },
{ on = "j", run = "down" },
{ on = "<Up>", run = "up" },
{ on = "<Down>", run = "down" },
},
}
function M:new(area)
self:layout(area)
return self
end
function M:layout(area)
local chunks = ui.Layout()
:constraints({
ui.Constraint.Percentage(10),
ui.Constraint.Percentage(80),
ui.Constraint.Percentage(10),
})
:split(area)
local chunks = ui.Layout()
:direction(ui.Layout.HORIZONTAL)
:constraints({
ui.Constraint.Percentage(10),
ui.Constraint.Percentage(80),
ui.Constraint.Percentage(10),
})
:split(chunks[2])
self._area = chunks[2]
end
local function splitAndGetNth(inputstr, sep, index)
if sep == nil then
sep = "%s"
end
local count = 0
local start = 1
while true do
local sepStart, sepEnd = string.find(inputstr, sep, start)
if not sepStart then
break
end
count = count + 1
if count == index then
return string.sub(inputstr, start, sepStart - 1)
end
start = sepEnd + 1
end
if index == 1 then
return inputstr
end
return nil -- 如果没有足够的分割部分返回nil
end
local state = ya.sync(function() return tostring(cx.active.current.cwd) end)
local function fail(s, ...) ya.notify { title = "Fzf", content = string.format(s, ...), timeout = 5, level = "error" } end
function M:entry(job)
local args = job.args
local _permit = ya.hide()
local cwd = state()
local shell_value = ya.target_family() == "windows" and "nu" or os.getenv("SHELL"):match(".*/(.*)")
local cmd_args = ""
local preview_cmd = [===[line={2} && begin=$( if [[ $line -lt 7 ]]; then echo $((line-1)); else echo 6; fi ) && bat --highlight-line={2} --color=always --line-range $((line-begin)):$((line+10)) {1}]===]
if ya.target_family() == "windows" then
preview_cmd = [[bat --highlight-line={2} --color=always --line-range {2}: {1}]]
elseif shell_value == "fish" then
preview_cmd = [[set line {2} && set begin ( test $line -lt 7 && echo (math "$line-1") || echo 6 ) && bat --highlight-line={2} --color=always --line-range (math "$line-$begin"):(math "$line+10") {1}]]
elseif shell_value == "nu" then
preview_cmd = [[let line = ({2} | into int); let begin = if $line < 7 { $line - 1 } else { 6 }; bat --highlight-line={2} --color=always --line-range $'($line - $begin):($line + 10)' {1}]]
end
if ya.target_family() == "windows" and args[1] == "fzf" then
cmd_args = [[fzf --preview="bat --color=always {}"]]
elseif ya.target_family() == "windows" and args[1] == "rg" then
local rg_prefix = [[rg --colors "path:fg:blue" --colors "line:fg:red" --colors "column:fg:yellow" --column --line-number --no-heading --color=always --smart-case ]]
cmd_args = [[fzf --ansi --disabled --bind "start:reload:]]
.. rg_prefix
.. [[{q}" --bind "change:reload:]]
.. rg_prefix
.. [[{q}" --delimiter ":" --preview "]]
.. preview_cmd
.. [[" --preview-window "up,60%" --nth "3.."]]
elseif ya.target_family() == "windows" then
cmd_args = [[rg --color=always --line-number --no-heading --smart-case "" | fzf --ansi --preview="]] .. preview_cmd .. [[" --delimiter=":" --preview-window="up:60%" --nth="3.."]]
elseif args[1] == "fzf" then
cmd_args = [[fzf --preview="bat --color=always {}"]]
elseif args[1] == "rg" and shell_value == "fish" then
cmd_args = [[
RG_PREFIX="rg --colors 'path:fg:blue' --colors 'line:fg:red' --colors 'column:fg:yellow' --column --line-number --no-heading --color=always --smart-case " \
fzf --ansi --disabled \
--bind "start:reload:$RG_PREFIX {q}" \
--bind "change:reload:sleep 0.1; $RG_PREFIX {q} || true" \
--delimiter : \
--preview ']] .. preview_cmd .. [[' \
--preview-window 'up,60%' \
--nth '3..'
]]
elseif args[1] == "rg" and (shell_value == "bash" or shell_value == "zsh") then
cmd_args = [[
RG_PREFIX="rg --colors 'path:fg:blue' --colors 'line:fg:red' --colors 'column:fg:yellow' --column --line-number --no-heading --color=always --smart-case "
fzf --ansi --disabled \
--bind "start:reload:$RG_PREFIX {q}" \
--bind "change:reload:sleep 0.1; $RG_PREFIX {q} || true" \
--delimiter : \
--preview ']] .. preview_cmd .. [[' \
--preview-window 'up,60%' \
--nth '3..'
]]
elseif args[1] == "rg" and shell_value == "nu" then
local rg_prefix = "rg --colors 'path:fg:blue' --colors 'line:fg:red' --colors 'column:fg:yellow' --column --line-number --no-heading --color=always --smart-case "
cmd_args = [[fzf --ansi --disabled --bind "start:reload:]]
.. rg_prefix
.. [[{q}" --bind "change:reload:sleep 100ms; try { ]]
.. rg_prefix
.. [[{q} }" --delimiter : --preview ']]
.. preview_cmd
.. [[' --preview-window 'up,60%' --nth '3..']]
else
cmd_args = [[rg --color=always --line-number --no-heading --smart-case '' | fzf --ansi --preview=']] .. preview_cmd .. [[' --delimiter=':' --preview-window='up:60%' --nth='3..']]
end
local child, err =
Command(shell_value):args({"-c", cmd_args}):cwd(cwd):stdin(Command.INHERIT):stdout(Command.PIPED):stderr(Command.INHERIT):spawn()
if not child then
return fail("Spawn `rfzf` failed with error code %s. Do you have it installed?", err)
end
local output, err = child:wait_with_output()
if not output then
return fail("Cannot read `fzf` output, error code %s", err)
elseif not output.status.success and output.status.code ~= 130 then
return fail("`fzf` exited with error code %s", output.status.code)
end
if output.stdout == "" then
return
end
local target = output.stdout:gsub("\n$", "")
local file_url = splitAndGetNth(target,":",1)
local line_number = splitAndGetNth(target,":",2)
line_number = line_number and line_number or 1
init_ui_data(cwd.."/"..file_url)
local default_action = get_default_action()
if (default_action == "menu" or default_action == nil) and args[1] ~= "fzf" then
_permit:drop()
toggle_ui()
while true do
local cand = self.keys[ya.which { cands = self.keys, silent = true }]
if cand then
if cand.run == "quit" then
set_option(false)
toggle_ui()
break
elseif cand.run == "select" then
set_option(true)
toggle_ui()
break
elseif cand.run == "down" then
update_cursor(1)
elseif cand.run == "up" then
update_cursor(-1)
end
end
end
_permit = ya.hide()
end
if (default_action == "nvim" or get_option() == "nvim" ) and args[1] ~= "fzf" then
os.execute("nvim +"..line_number.." -n "..file_url)
elseif (default_action == "jump" or get_option() == "jump" or args[1] == "fzf") and file_url ~= "" then
ya.manager_emit(file_url:match("[/\\]$") and "cd" or "reveal", { file_url })
else
return
end
end
function M:reflow() return { self } end
function M:redraw()
local rows = {}
rows[1] = ui.Row { "open with nvim" }
rows[2] = ui.Row { "reach at yazi" }
return {
ui.Clear(self._area),
ui.Border(ui.Border.ALL)
:area(self._area)
:type(ui.Border.ROUNDED)
:style(ui.Style():fg("#82ab3a"))
:title(ui.Line(self.title):align(ui.Line.CENTER):fg(self.title_color)),
ui.Table(rows)
:area(self._area:pad(ui.Pad(1, 2, 1, 2)))
:header(ui.Row({ "Action for:"..self.file_url }):style(ui.Style():bold():fg("#e73c80")))
:row(self.cursor)
:row_style(ui.Style():fg("#82ab3a"):underline()),
}
end
function M.fail(s, ...)
ya.manager_emit("plugin", {"mount", args = "refresh" })
ya.notify { title = "fg", content = string.format(s, ...), timeout = 10, level = "error" }
end
function M:click() end
function M:scroll() end
function M:touch() end
function M:setup(config)
self.default_action = (config and config.default_action) and config.default_action or "menu"
end
return M

View file

@ -1,19 +0,0 @@
Copyright (c) 2024 boydaihungst
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,102 +0,0 @@
# file-extra-metadata
<!--toc:start-->
- [file-extra-metadata](#file-extra-metadata)
- [Preview](#preview)
- [Before:](#before)
- [After:](#after)
- [Requirements](#requirements)
- [Installation](#installation)
- [For developer](#for-developer)
<!--toc:end-->
This is a Yazi plugin that replaces the default file previewer and spotter with extra information.
## Preview
### Before:
- Previewer
![Before preview](statics/2024-11-17-12-06-24.png)
- Spotter (yazi >= v0.4 after 21/11/2024)
![Before spot](statics/2024-11-21-04-19-01.png)
### After:
- Previewer
![After previewer](statics/2024-11-21-05-27-48.png)
- Spotter (yazi >= v0.4 after 21/11/2024)
![After spotter](statics/2024-11-21-05-29-50.png)
## Requirements
- [yazi >=0.4](https://github.com/sxyazi/yazi)
- Tested on Linux. For MacOS, Windows: some fields will shows empty values.
## Installation
Install the plugin:
```sh
ya pack -a boydaihungst/file-extra-metadata
```
Add spotter keybind, makes sure not conflict with other `<Tab>` keybind in
`manager` section:
```toml
[manager]
keymap = [
# ...
# Spotting
{ on = "<Tab>", run = "spot", desc = "Spot hovered file" },
]
```
Create `~/.config/yazi/yazi.toml` and add:
```toml
[plugin]
append_previewers = [
{ name = "*", run = "file-extra-metadata" },
]
# yazi v0.4 after 21/11/2024
# Setup keybind for spotter: https://github.com/sxyazi/yazi/pull/1802
append_spotters = [
{ name = "*", run = "file-extra-metadata" },
]
```
or
```toml
[plugin]
previewers = [
# ... the rest
# disable default file plugin { name = "*", run = "file" },
{ name = "*", run = "file-extra-metadata" },
]
# yazi v0.4 after 21/11/2024
# Setup keybind for spotter: https://github.com/sxyazi/yazi/pull/1802
spotters = [
# ... the rest
# Fallback
# { name = "*", run = "file" },
{ name = "*", run = "file-extra-metadata" },
]
```
## For developer
If you want to compile this with other spotter/previewer:
```lua
require("file-extra-metadata"):render_table(job, { show_plugins_section = true })
```

View file

@ -1,489 +0,0 @@
local M = {}
local function permission(file)
local h = file
if not h then
return ""
end
local perm = h.cha:perm()
if not perm then
return ""
end
local spans = ""
for i = 1, #perm do
local c = perm:sub(i, i)
spans = spans .. c
end
return spans
end
local function link_count(file)
local h = file
if h == nil or ya.target_family() ~= "unix" then
return ""
end
return h.cha.nlink
end
local function owner_group(file)
local h = file
if h == nil or ya.target_family() ~= "unix" then
return ""
end
return (ya.user_name(h.cha.uid) or tostring(h.cha.uid)) .. "/" .. (ya.group_name(h.cha.gid) or tostring(h.cha.gid))
end
local file_size_and_folder_childs = function(file)
local h = file
if not h or h.cha.is_link then
return ""
end
return h.cha.len and ya.readable_size(h.cha.len) or ""
end
--- get file timestamp
---@param file any
---@param type "mtime" | "atime" | "btime"
---@return any
local function fileTimestamp(file, type)
local h = file
if not h or h.cha.is_link then
return ""
end
local time = math.floor(h.cha[type] or 0)
if time == 0 then
return ""
else
return os.date("%Y-%m-%d %H:%M", time)
end
end
-- Function to split a string by spaces (considering multiple spaces as one delimiter)
local function split_by_whitespace(input)
local result = {}
for word in string.gmatch(input, "%S+") do
table.insert(result, word)
end
return result
end
local function get_filesystem_extra(file)
local result = {
filesystem = "",
device = "",
type = "",
used_space = "",
avail_space = "",
total_space = "",
used_space_percent = "",
avail_space_percent = "",
error = nil,
}
local h = file
local file_url = tostring(h.url)
if not h or ya.target_family() ~= "unix" then
return result
end
local output, _ = Command("tail")
:args({ "-n", "-1" })
:stdin(Command("df"):args({ "-P", "-T", "-h", file_url }):stdout(Command.PIPED):spawn():take_stdout())
:stdout(Command.PIPED)
:output()
if output then
-- Splitting the data
local parts = split_by_whitespace(output.stdout)
-- Display the result
for i, part in ipairs(parts) do
if i == 1 then
result.filesystem = part
elseif i == 2 then
result.device = part
elseif i == 3 then
result.total_space = part
elseif i == 4 then
result.used_space = part
elseif i == 5 then
result.avail_space = part
elseif i == 6 then
result.used_space_percent = part
result.avail_space_percent = 100 - tonumber((string.match(part, "%d+") or "0"))
elseif i == 7 then
result.type = part
end
end
else
result.error = "tail, df are installed?"
end
return result
end
local function attributes(file)
local h = file
local file_url = tostring(h.url)
if not h or ya.target_family() ~= "unix" then
return ""
end
local output, _ = Command("lsattr"):args({ "-d", file_url }):stdout(Command.PIPED):output()
if output then
-- Splitting the data
local parts = split_by_whitespace(output.stdout)
-- Display the result
for i, part in ipairs(parts) do
if i == 1 then
return part
end
end
return ""
else
return "lsattr is installed?"
end
end
---shorten string
---@param _s string string
---@param _t string tail
---@param _w number max characters
---@return string
local shorten = function(_s, _t, _w)
local s = _s or utf8.len(_s)
local t = _t or ""
local ellipsis = "" .. t
local w = _w < utf8.len(ellipsis) and utf8.len(ellipsis) or _w
local n_ellipsis = utf8.len(ellipsis) or 0
if utf8.len(s) > w then
return s:sub(1, (utf8.offset(s, w - n_ellipsis + 1) or 2) - 1) .. ellipsis
end
return s
end
local is_supported_table = type(ui.Table) ~= "nil" and type(ui.Row) ~= "nil"
local styles = {
header = ui.Style():fg("green"),
row_label = ui.Style():fg("reset"),
row_value = ui.Style():fg("blue"),
row_value_spot_hovered = ui.Style():fg("blue"):reverse(),
}
function M:render_table(job, opts)
local filesystem_extra = get_filesystem_extra(job.file)
local prefix = " "
local label_lines, value_lines, rows = {}, {}, {}
local label_max_length = 15
local file_name_extension = job.file.cha.is_dir and "" or ("." .. (job.file.url.ext(job.file.url) or ""))
local row = function(key, value)
local h = type(value) == "table" and #value or 1
rows[#rows + 1] = ui.Row({ ui.Line(key):style(styles.row_label), ui.Line(value):style(styles.row_value) })
:height(h)
end
local file_name = shorten(
job.file.name,
file_name_extension,
math.floor(job.area.w - label_max_length - utf8.len(file_name_extension))
)
local location =
shorten(tostring(job.file.url:parent()), "", math.floor(job.area.w - label_max_length - utf8.len(prefix)))
local filesystem_error = filesystem_extra.error
and shorten(filesystem_extra.error, "", math.floor(job.area.w - label_max_length - utf8.len(prefix)))
or nil
local filesystem =
shorten(filesystem_extra.filesystem, "", math.floor(job.area.w - label_max_length - utf8.len(prefix)))
if not is_supported_table then
table.insert(
label_lines,
ui.Line({
ui.Span("Metadata:"),
}):style(styles.header)
)
table.insert(
value_lines,
ui.Line({
ui.Span(""),
})
)
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("File:"),
}):style(styles.row_label)
)
table.insert(
value_lines,
ui.Line({
ui.Span(file_name),
}):style(styles.row_value)
)
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Mimetype: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(job._mime or job.mime)):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Location: "),
}):style(styles.row_label)
)
table.insert(
value_lines,
ui.Line({
ui.Span(location),
}):style(styles.row_value)
)
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Mode: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(permission(job.file)):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Attributes: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(attributes(job.file))):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Links: "),
}):style(styles.row_label)
)
table.insert(
value_lines,
ui.Line({
ui.Span(tostring(link_count(job.file))),
}):style(styles.row_value)
)
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Owner: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(owner_group(job.file))):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Size: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(file_size_and_folder_childs(job.file))):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Created: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(fileTimestamp(job.file, "btime"))):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Modified: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(fileTimestamp(job.file, "mtime"))):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Accessed: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(fileTimestamp(job.file, "atime"))):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Filesystem: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(filesystem_error or filesystem)):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Device: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(filesystem_error or filesystem_extra.device)):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Type: "),
}):style(styles.row_label)
)
table.insert(value_lines, ui.Line(ui.Span(filesystem_error or filesystem_extra.type)):style(styles.row_value))
table.insert(
label_lines,
ui.Line({
ui.Span(prefix),
ui.Span("Free space: "),
}):style(styles.row_label)
)
table.insert(
value_lines,
ui.Line(
ui.Span(
filesystem_extra.error
or (
filesystem_extra.avail_space
.. " / "
.. filesystem_extra.total_space
.. " ("
.. filesystem_extra.avail_space_percent
.. "%)"
)
)
):style(styles.row_value)
)
else
rows[#rows + 1] = ui.Row({ "Metadata", "" }):style(styles.header)
row(prefix .. "File:", file_name)
row(prefix .. "Mimetype:", job.mime)
row(prefix .. "Location:", location)
row(prefix .. "Mode:", permission(job.file))
row(prefix .. "Attributes:", attributes(job.file))
row(prefix .. "Links:", tostring(link_count(job.file)))
row(prefix .. "Owner:", owner_group(job.file))
row(prefix .. "Size:", file_size_and_folder_childs(job.file))
row(prefix .. "Created:", fileTimestamp(job.file, "btime"))
row(prefix .. "Modified:", fileTimestamp(job.file, "mtime"))
row(prefix .. "Accessed:", fileTimestamp(job.file, "atime"))
row(prefix .. "Filesystem:", filesystem_error or filesystem)
row(prefix .. "Device:", filesystem_error or filesystem_extra.device)
row(prefix .. "Type:", filesystem_error or filesystem_extra.type)
row(
prefix .. "Free space:",
filesystem_error
or (
(
filesystem_extra.avail_space
and filesystem_extra.total_space
and filesystem_extra.avail_space_percent
)
and (filesystem_extra.avail_space .. " / " .. filesystem_extra.total_space .. " (" .. filesystem_extra.avail_space_percent .. "%)")
or ""
)
)
if opts and opts.show_plugins_section and PLUGIN then
local spotter = PLUGIN.spotter(job.file.url, job.mime)
local previewer = PLUGIN.previewer(job.file.url, job.mime)
local fetchers = PLUGIN.fetchers(job.file, job.mime)
local preloaders = PLUGIN.preloaders(job.file.url, job.mime)
for i, v in ipairs(fetchers) do
fetchers[i] = v.cmd
end
for i, v in ipairs(preloaders) do
preloaders[i] = v.cmd
end
rows[#rows + 1] = ui.Row({ { "", "Plugins" }, "" }):height(2):style(styles.header)
row(prefix .. "Spotter:", spotter and spotter.cmd or "")
row(prefix .. "Previewer:", previewer and previewer.cmd or "")
row(prefix .. "Fetchers:", #fetchers ~= 0 and fetchers or "")
row(prefix .. "Preloaders:", #preloaders ~= 0 and preloaders or "")
end
end
if not is_supported_table then
local areas = ui.Layout()
:direction(ui.Layout.HORIZONTAL)
:constraints({ ui.Constraint.Length(label_max_length), ui.Constraint.Fill(1) })
:split(job.area)
local label_area = areas[1]
local value_area = areas[2]
return {
ui.Text(label_lines):area(label_area):align(ui.Text.LEFT):wrap(ui.Text.WRAP_NO),
ui.Text(value_lines):area(value_area):align(ui.Text.LEFT):wrap(ui.Text.WRAP_NO),
}
else
return {
ui.Table(rows):area(job.area):row(1):col(1):col_style(styles.row_value):widths({
ui.Constraint.Length(label_max_length),
ui.Constraint.Fill(1),
}),
}
end
end
function M:peek(job)
local start, cache = os.clock(), ya.file_cache(job)
if not cache or self:preload(job) ~= 1 then
return 1
end
ya.sleep(math.max(0, PREVIEW.image_delay / 1000 + start - os.clock()))
ya.preview_widgets(job, self:render_table(job))
end
function M:seek(job)
local h = cx.active.current.hovered
if h and h.url == job.file.url then
local step = math.floor(job.units * job.area.h / 10)
ya.manager_emit("peek", {
tostring(math.max(0, cx.active.preview.skip + step)),
only_if = tostring(job.file.url),
})
end
end
function M:preload(job)
local cache = ya.file_cache(job)
if not cache or fs.cha(cache) then
return 1
end
return 1
end
function M:spot(job)
job.area = ui.Pos({ "center", w = 80, h = 25 })
ya.spot_table(
job,
self:render_table(job, { show_plugins_section = true })[1]:cell_style(styles.row_value_spot_hovered)
)
end
return M

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 Darius
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,29 +0,0 @@
# lazygit.yazi
Plugin for [Yazi](https://github.com/sxyazi/yazi) to manage git repos with [lazygit](https://github.com/jesseduffield/lazygit)
## Dependencies
Make sure [lazygit](https://github.com/jesseduffield/lazygit) is installed and in your `PATH`.
## Installation
### Using `ya pack`
```
ya pack -a Lil-Dank/lazygit
```
### Manual
**Linux/macOS**
```
git clone https://github.com/Lil-Dank/lazygit.yazi.git ~/.config/yazi/plugins/lazygit.yazi
```
**Windows**
```
git clone https://github.com/Lil-Dank/lazygit.yazi.git %AppData%\yazi\config\plugins\lazygit.yazi
```
## Configuration
add this to your **keymap.toml** file
```toml
[[manager.prepend_keymap]]
on = [ "g", "i" ]
run = "plugin lazygit"
desc = "run lazygit"
```
you can customize the keybinding however you like. Please refer to the [keymap.toml](https://yazi-rs.github.io/docs/configuration/keymap) documentation

View file

@ -1,31 +0,0 @@
return {
entry = function()
local output = Command("git"):arg("status"):stderr(Command.PIPED):output()
if output.stderr ~= "" then
ya.notify({
title = "lazygit",
content = "Not in a git directory",
level = "warn",
timeout = 5,
})
else
permit = ya.hide()
local output, err_code = Command("lazygit"):stderr(Command.PIPED):output()
if err_code ~= nil then
ya.notify({
title = "Failed to run lazygit command",
content = "Status: " .. err_code,
level = "error",
timeout = 5,
})
elseif not output.status.success then
ya.notify({
title = "lazygit in" .. cwd .. "failed, exit code " .. output.status.code,
content = output.stderr,
level = "error",
timeout = 5,
})
end
end
end,
}

View file

@ -1,19 +0,0 @@
Copyright (c) 2024 Lauri Niskanen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,26 +0,0 @@
> [!NOTE]
> Please use **boydaihungst**'s fork for the latest version of this plugin:
> https://github.com/boydaihungst/mediainfo.yazi
# mediainfo.yazi
This is a Yazi plugin for previewing media files. The preview shows thumbnail
using `ffmpegthumbnailer` if available and media metadata using `mediainfo`.
## Installation
Install the plugin:
```
ya pack -a Ape/mediainfo
```
Create `~/.config/yazi/yazi.toml` and add:
```
[plugin]
prepend_previewers = [
{ mime = "{image,audio,video}/*", run = "mediainfo"},
{ mime = "application/x-subrip", run = "mediainfo"},
]
```

View file

@ -1,111 +0,0 @@
local skip_labels = {
["Complete name"] = true,
["CompleteName_Last"] = true,
["Unique ID"] = true,
["File size"] = true,
["Format/Info"] = true,
["Codec ID/Info"] = true,
["MD5 of the unencoded content"] = true,
}
local M = {}
function M:peek()
local image_height = 0
if self:preload() == 1 then
local cache = ya.file_cache(self)
if cache and fs.cha(cache).length > 0 then
image_height = ya.image_show(cache, self.area).h
end
end
local cmd = "mediainfo"
local output, code = Command(cmd)
:args({ tostring(self.file.url) })
:stdout(Command.PIPED)
:output()
local lines = {}
if output then
local i = 0
for str in output.stdout:gmatch("[^\n]*") do
local label, value = str:match("(.*[^ ]) +: (.*)")
local line
if label then
if not skip_labels[label] then
line = ui.Line({
ui.Span(label .. ": "):bold(),
ui.Span(value),
})
end
elseif str ~= "General" then
line = ui.Line({ ui.Span(str):underline() })
end
if line then
if i >= self.skip then
table.insert(lines, line)
end
local max_width = math.max(1, self.area.w - 3)
i = i + math.max(1, math.ceil(line:width() / max_width))
end
end
else
local error = string.format("Spawn `%s` command returns %s", cmd, code)
table.insert(lines, ui.Line(error))
end
ya.preview_widgets(self, {
ui.Paragraph(
ui.Rect({
x = self.area.x,
y = self.area.y + image_height,
w = self.area.w,
h = self.area.h - image_height,
}),
lines
):wrap(ui.Paragraph.WRAP),
})
end
function M:seek(units)
local h = cx.active.current.hovered
if h and h.url == self.file.url then
local step = math.floor(units * self.area.h / 10)
ya.manager_emit("peek", {
math.max(0, cx.active.preview.skip + step),
only_if = self.file.url,
})
end
end
function M:preload()
local cache = ya.file_cache(self)
if not cache or fs.cha(cache) then
return 1
end
local cmd = "ffmpegthumbnailer"
local child, code = Command(cmd):args({
"-q", "6",
"-c", "jpeg",
"-i", tostring(self.file.url),
"-o", tostring(cache),
"-t", "5",
"-s", tostring(PREVIEW.max_width),
}):spawn()
if not child then
ya.err(string.format("spawn `%s` command returns %s", cmd, code))
return 0
end
local status = child:wait()
return status and status.success and 1 or 2
end
return M

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2023 yazi-rs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,56 +0,0 @@
# mime-ext.yazi
A mime-type provider based on a file extension database, replacing the [builtin `file(1)`](https://github.com/sxyazi/yazi/blob/main/yazi-plugin/preset/plugins/mime.lua) to speed up mime-type retrieval at the expense of accuracy.
See https://yazi-rs.github.io/docs/tips#make-yazi-even-faster for more information.
## Installation
```sh
ya pack -a yazi-rs/plugins:mime-ext
```
## Usage
Add this to your `~/.config/yazi/yazi.toml`:
```toml
[[plugin.prepend_fetchers]]
id = "mime"
name = "*"
run = "mime-ext"
prio = "high"
```
## Advanced
You can also customize it in your `~/.config/yazi/init.lua` with:
```lua
require("mime-ext"):setup {
-- Expand the existing filename database (lowercase), for example:
with_files = {
makefile = "text/makefile",
-- ...
},
-- Expand the existing extension database (lowercase), for example:
with_exts = {
mk = "text/makefile",
-- ...
},
-- If the mime-type is not in both filename and extension databases,
-- then fallback to Yazi's preset `mime` plugin, which uses `file(1)`
fallback_file1 = false,
}
```
## TODO
- Add more file types (PRs welcome!).
- Compress mime-type tables.
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

File diff suppressed because it is too large Load diff

View file

@ -1,20 +0,0 @@
return {
entry = function(_, job)
local block = job.args[1] and job.args[1] == "block"
local value, event = ya.input({
title = block and "Open with (block):" or "Open with:",
position = { "hovered", y = 1, w = 50 },
})
if event == 1 then
local s = ya.target_family() == "windows" and " %*" or ' "$@"'
ya.manager_emit("shell", {
value .. s,
block = block,
orphan = true,
confirm = true,
})
end
end,
}

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 ndtoan96
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,83 +0,0 @@
# ouch.yazi
[ouch](https://github.com/ouch-org/ouch) plugin for [Yazi](https://github.com/sxyazi/yazi).
![ouch.yazi](https://github.com/ndtoan96/ouch.yazi/assets/33489972/946397ec-b37b-4bf4-93f1-c676fc8e59f2)
## Features
- Archive preview
- Compression
## Installation
If you use Yazi from latest main branch
```bash
# Linux/macOS
git clone https://github.com/ndtoan96/ouch.yazi.git ~/.config/yazi/plugins/ouch.yazi
# Windows with cmd
git clone https://github.com/ndtoan96/ouch.yazi.git %AppData%\yazi\config\plugins\ouch.yazi
# Windows with powershell
git clone https://github.com/ndtoan96/ouch.yazi.git "$($env:APPDATA)\yazi\config\plugins\ouch.yazi"
```
If you use Yazi < 0.4.3
```bash
# Linux/macOS
git clone --branch v0.4.0 --single-branch https://github.com/ndtoan96/ouch.yazi.git ~/.config/yazi/plugins/ouch.yazi
# Windows with cmd
git clone --branch v0.4.0 --single-branch https://github.com/ndtoan96/ouch.yazi.git %AppData%\yazi\config\plugins\ouch.yazi
# Windows with powershell
git clone --branch v0.4.0 --single-branch https://github.com/ndtoan96/ouch.yazi.git "$($env:APPDATA)\yazi\config\plugins\ouch.yazi"
```
Make sure you have [ouch](https://github.com/ouch-org/ouch) installed and in your `PATH`.
## Usage
### Preview
For archive preview, add this to your `yazi.toml`:
```toml
[plugin]
prepend_previewers = [
# Archive previewer
{ mime = "application/*zip", run = "ouch" },
{ mime = "application/x-tar", run = "ouch" },
{ mime = "application/x-bzip2", run = "ouch" },
{ mime = "application/x-7z-compressed", run = "ouch" },
{ mime = "application/x-rar", run = "ouch" },
{ mime = "application/x-xz", run = "ouch" },
]
```
Now go to an archive on Yazi, you should see the archive's content in the preview pane. You can use `J` and `K` to roll up and down the preview.
If you want to change the icon or the style of text, you can modify the `peek` function in `init.lua` file (all of them are stored in the `lines` variable).
### Compression
For compession, add this to your `keymap.toml`:
```toml
[[manager.prepend_keymap]]
on = ["C"]
run = "plugin ouch --args=zip"
desc = "Compress with ouch"
```
The `--args=zip` part tells the plugin that default format is `zip`. You can change that to whatever format you want.
### Decompression
This plugin does not provide a decompression feature because it already is supported by Yazi.
To decompress with `ouch`, configure the opener in `yazi.toml`.
```toml
[opener]
extract = [
{ run = 'ouch d -y "%*"', desc = "Extract here with ouch", for = "windows" },
{ run = 'ouch d -y "$@"', desc = "Extract here with ouch", for = "unix" },
]
```

View file

@ -1,145 +0,0 @@
local M = {}
function M:peek(job)
local child = Command("ouch")
:args({ "l", "-t", "-y", tostring(job.file.url) })
:stdout(Command.PIPED)
:stderr(Command.PIPED)
:spawn()
local limit = job.area.h
local file_name = string.match(tostring(job.file.url), ".*[/\\](.*)")
local lines = string.format("📁 \x1b[2m%s\x1b[0m\n", file_name)
local num_lines = 1
local num_skip = 0
repeat
local line, event = child:read_line()
if event == 1 then
ya.err(tostring(event))
elseif event ~= 0 then
break
end
if line:find('Archive', 1, true) ~= 1 and line:find('[INFO]', 1, true) ~= 1 then
if num_skip >= job.skip then
lines = lines .. line
num_lines = num_lines + 1
else
num_skip = num_skip + 1
end
end
until num_lines >= limit
child:start_kill()
if job.skip > 0 and num_lines < limit then
ya.manager_emit(
"peek",
{ tostring(math.max(0, job.skip - (limit - num_lines))), only_if = tostring(job.file.url), upper_bound = "" }
)
else
ya.preview_widgets(job, { ui.Text(lines):area(job.area) })
end
end
function M:seek(job)
local h = cx.active.current.hovered
if h and h.url == job.file.url then
local step = math.floor(job.units * job.area.h / 10)
ya.manager_emit("peek", {
math.max(0, cx.active.preview.skip + step),
only_if = tostring(job.file.url),
})
end
end
-- Check if file exists
local function file_exists(name)
local f = io.open(name, "r")
if f ~= nil then
io.close(f)
return true
else
return false
end
end
-- Get the files that need to be compressed and infer a default archive name
local get_compression_target = ya.sync(function()
local tab = cx.active
local default_name
local paths = {}
if #tab.selected == 0 then
if tab.current.hovered then
local name = tab.current.hovered.name
default_name = name
table.insert(paths, name)
else
return
end
else
default_name = tab.current.cwd:name()
for _, url in pairs(tab.selected) do
table.insert(paths, tostring(url))
end
-- The compression targets are aquired, now unselect them
ya.manager_emit("escape", {})
end
return paths, default_name
end)
local function invoke_compress_command(paths, name)
local cmd_output, err_code = Command("ouch")
:args({ "c", "-y" })
:args(paths)
:arg(name)
:stderr(Command.PIPED)
:output()
if err_code ~= nil then
ya.notify({
title = "Failed to run ouch command",
content = "Status: " .. err_code,
timeout = 5.0,
level = "error",
})
elseif not cmd_output.status.success then
ya.notify({
title = "Compression failed: status code " .. cmd_output.status.code,
content = cmd_output.stderr,
timeout = 5.0,
level = "error",
})
end
end
function M:entry(job)
local default_fmt = job.args[1]
ya.manager_emit("escape", { visual = true })
-- Get the files that need to be compressed and infer a default archive name
local paths, default_name = get_compression_target()
-- Get archive name from user
local output_name, name_event = ya.input({
title = "Create archive:",
value = default_name .. "." .. default_fmt,
position = { "top-center", y = 3, w = 40 },
})
if name_event ~= 1 then
return
end
-- Get confirmation if file exists
if file_exists(output_name) then
local confirm, confirm_event = ya.input({
title = "Overwrite " .. output_name .. "? (y/N)",
position = { "top-center", y = 3, w = 40 },
})
if not (confirm_event == 1 and confirm:lower() == "y") then
return
end
end
invoke_compress_command(paths, output_name)
end
return M

View file

@ -1,280 +0,0 @@
--- @since 25.2.7
local M = {}
local shell = os.getenv("SHELL") or ""
local PackageName = "Restore"
local function success(s, ...)
ya.notify({ title = PackageName, content = string.format(s, ...), timeout = 5, level = "info" })
end
local function fail(s, ...)
ya.notify({ title = PackageName, content = string.format(s, ...), timeout = 5, level = "error" })
end
---@enum STATE
local STATE = {
POSITION = "position",
SHOW_CONFIRM = "show_confirm",
THEME = "theme",
}
local set_state = ya.sync(function(state, key, value)
if state then
state[key] = value
else
state = {}
state[key] = value
end
end)
local get_state = ya.sync(function(state, key)
if state then
return state[key]
else
return nil
end
end)
---@enum File_Type
local File_Type = {
File = "file",
Dir = "dir_all",
None_Exist = "unknown",
}
---@alias TRASHED_ITEM {trash_index: number, trashed_date_time: string, trashed_path: string, type: File_Type} Item in trash list
function get_basename(filepath)
return filepath:match("^.+/(.+)$") or filepath
end
local get_cwd = ya.sync(function()
return tostring(cx.active.current.cwd)
end)
local function path_quote(path)
local result = "'" .. string.gsub(path, "'", "'\\''") .. "'"
return result
end
local function get_file_type(path)
local cha, _ = fs.cha(Url(path))
if cha then
return cha.is_dir and File_Type.Dir or File_Type.File
else
return File_Type.None_Exist
end
end
local function get_trash_volume()
local cwd = get_cwd()
local trash_volumes_stream, cmr_err =
Command("trash-list"):args({ "--volumes" }):stdout(Command.PIPED):stderr(Command.PIPED):output()
local matched_vol_path = nil
if trash_volumes_stream then
local matched_vol_length = 0
for vol in trash_volumes_stream.stdout:gmatch("[^\r\n]+") do
local vol_length = utf8.len(vol) or 0
if cwd:sub(1, vol_length) == vol and vol_length > matched_vol_length then
matched_vol_path = vol
matched_vol_length = vol_length
end
end
if not matched_vol_path then
fail("Can't get trash directory")
end
else
fail("Failed to start `trash-list` with error: `%s`. Do you have `trash-cli` installed?", cmr_err)
end
return matched_vol_path
end
---get list of latest files/folders trashed
---@param curr_working_volume currently working volume
---@return TRASHED_ITEM[]|nil
local function get_latest_trashed_items(curr_working_volume)
---@type TRASHED_ITEM[]
local restorable_items = {}
local fake_enter = Command("printf"):stderr(Command.PIPED):stdout(Command.PIPED):spawn():take_stdout()
local trash_list_stream, err_cmd = Command(shell)
:args({ "-c", "trash-restore " .. path_quote(curr_working_volume) })
:stdin(fake_enter)
:stdout(Command.PIPED)
:stderr(Command.PIPED)
:output()
if trash_list_stream then
---@type TRASHED_ITEM[]
local trash_list = {}
for line in trash_list_stream.stdout:gmatch("[^\r\n]+") do
-- remove leading spaces
line = line:match("^%s*(.+)$")
local trash_index, item_date, item_path = line:match("^(%d+) (%S+ %S+) (.+)$")
if item_date and item_path and trash_index ~= nil then
table.insert(trash_list, {
trash_index = tonumber(trash_index),
trashed_date_time = item_date,
trashed_path = item_path,
type = File_Type.None_Exist,
})
end
end
if #trash_list == 0 then
success("Nothing left to restore")
return
end
local last_item_datetime = trash_list[#trash_list].trashed_date_time
for _, trash_item in ipairs(trash_list) do
if trash_item then
if trash_item.trashed_date_time == last_item_datetime then
trash_item.type = get_file_type(trash_item.trashed_path)
table.insert(restorable_items, trash_item)
end
end
end
else
fail("Failed to start `trash-restore` with error: `%s`. Do you have `trash-cli` installed?", err_cmd)
return
end
return restorable_items
-- return newest_trashed_items
end
---@param trash_list TRASHED_ITEM[]
local function filter_none_exised_paths(trash_list)
---@type TRASHED_ITEM[]
local existed_trash_items = {}
for _, v in ipairs(trash_list) do
if v.type ~= File_Type.None_Exist then
table.insert(existed_trash_items, v)
end
end
return existed_trash_items
end
local function restore_files(curr_working_volume, start_index, end_index)
if type(start_index) ~= "number" or type(end_index) ~= "number" or start_index < 0 or end_index < 0 then
fail("Failed to restore file(s): out of range")
return
end
ya.manager_emit("shell", {
"echo " .. ya.quote(start_index .. "-" .. end_index) .. " | trash-restore --overwrite " .. path_quote(
curr_working_volume
),
confirm = true,
})
local file_to_restore_count = end_index - start_index + 1
success("Restored " .. tostring(file_to_restore_count) .. " file" .. (file_to_restore_count > 1 and "s" or ""))
end
function M:setup(opts)
if opts and opts.position and type(opts.position) == "table" then
set_state(STATE.POSITION, opts.position)
else
set_state(STATE.POSITION, { "center", w = 70, h = 40 })
end
if opts and opts.show_confirm then
set_state(STATE.SHOW_CONFIRM, opts.show_confirm)
else
set_state(STATE.SHOW_CONFIRM, false)
end
if opts and opts.theme and type(opts.theme) == "table" then
set_state(STATE.THEME, opts.theme)
else
set_state(STATE.THEME, {})
end
end
---@param trash_list TRASHED_ITEM[]
local function get_components(trash_list)
local theme = get_state(STATE.THEME) or {}
theme.list_item = theme.list_item or {
odd = "blue",
even = "blue",
}
local trashed_items_components = {}
for idx, item in pairs(trash_list) do
local fg_color = theme.list_item.odd or "blue"
if idx % 2 == 0 then
fg_color = theme.list_item.even or "blue"
end
table.insert(
trashed_items_components,
ui.Line({
ui.Span(" "),
ui.Span(item.trashed_path):fg(fg_color),
}):align(ui.Line.LEFT)
)
end
return trashed_items_components
end
function M:entry()
local curr_working_volume = get_trash_volume()
if not curr_working_volume then
return
end
local trashed_items = get_latest_trashed_items(curr_working_volume)
if trashed_items == nil then
return
end
local collided_items = filter_none_exised_paths(trashed_items)
local overwrite_confirmed = true
local show_confirm = get_state(STATE.SHOW_CONFIRM)
local pos = get_state(STATE.POSITION)
pos = pos or { "center", w = 70, h = 40 }
local theme = get_state(STATE.THEME) or {}
theme.title = theme.title or "blue"
theme.header = theme.header or "green"
theme.header_warning = theme.header_warning or "yellow"
if ya.confirm and show_confirm then
local continue_restore = ya.confirm({
title = ui.Line("Restore files/folders"):fg(theme.title):bold(),
content = ui.Text({
ui.Line(""),
ui.Line("The following files and folders are going to be restored:"):fg(theme.header),
ui.Line(""),
table.unpack(get_components(trashed_items)),
})
:align(ui.Text.LEFT)
:wrap(ui.Text.WRAP),
--TODO: still wating for API :/
-- list = ui.List({
-- table.unpack(get_components(trashed_items)),
-- }),
pos = pos,
})
-- stopping
if not continue_restore then
return
end
end
-- show Confirm dialog with list of collided items
if #collided_items > 0 then
overwrite_confirmed = ya.confirm({
title = ui.Line("Restore files/folders"):fg(theme.title):bold(),
content = ui.Text({
ui.Line(""),
ui.Line("The following files and folders are existed, overwrite?"):fg(theme.header_warning),
ui.Line(""),
table.unpack(get_components(collided_items)),
})
:align(ui.Text.LEFT)
:wrap(ui.Text.WRAP),
pos = pos,
})
end
if overwrite_confirmed then
restore_files(curr_working_volume, trashed_items[1].trash_index, trashed_items[#trashed_items].trash_index)
end
end
return M

View file

@ -1,53 +0,0 @@
local M = {}
function M:peek(job)
local child = Command("rich")
:args({
"-j",
"--left",
"--line-numbers",
"--force-terminal",
"--panel=rounded",
"--guides",
"--max-width",
tostring(job.area.w),
tostring(job.file.url),
})
:stdout(Command.PIPED)
:stderr(Command.PIPED)
:spawn()
if not child then
return require("code"):peek(job)
end
local limit = job.area.h
local i, lines = 0, ""
repeat
local next, event = child:read_line()
if event == 1 then
return require("code"):peek(job)
elseif event ~= 0 then
break
end
i = i + 1
if i > job.skip then
lines = lines .. next
end
until i >= job.skip + limit
child:start_kill()
if job.skip > 0 and i < job.skip + limit then
ya.manager_emit("peek", { math.max(0, i - limit), only_if = job.file.url, upper_bound = true })
else
lines = lines:gsub("\t", string.rep(" ", PREVIEW.tab_size))
ya.preview_widgets(job, { ui.Text.parse(lines):area(job.area) })
end
end
function M:seek(job)
require("code"):seek(job)
end
return M

View file

@ -1,13 +0,0 @@
--- @sync entry
return {
entry = function()
local h = cx.active.current.hovered
if h and h.cha.is_dir then
ya.manager_emit("enter", {})
ya.manager_emit("paste", {})
ya.manager_emit("leave", {})
else
ya.manager_emit("paste", {})
end
end,
}

View file

@ -2,6 +2,6 @@
return {
entry = function()
local h = cx.active.current.hovered
ya.manager_emit("tab_create", h and h.cha.is_dir and { h.url } or { current = true })
ya.mgr_emit("tab_create", h and h.cha.is_dir and { h.url } or { current = true })
end,
}

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 Rolv Apneseth
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,109 +0,0 @@
# starship.yazi
Starship prompt plugin for [Yazi](https://github.com/sxyazi/yazi)
<https://github.com/Rolv-Apneseth/starship.yazi/assets/69486699/f7314687-5cb1-4d66-8d9d-cca960ba6716>
## Requirements
- [Yazi](https://github.com/sxyazi/yazi)
- [starship](https://github.com/starship/starship)
## Installation
```bash
ya pack -a Rolv-Apneseth/starship
```
### Manual
```sh
# Linux / MacOS
git clone https://github.com/Rolv-Apneseth/starship.yazi.git ~/.config/yazi/plugins/starship.yazi
# Windows
git clone https://github.com/Rolv-Apneseth/starship.yazi.git %AppData%\yazi\config\plugins\starship.yazi
```
## Usage
Add this to `~/.config/yazi/init.lua`:
```lua
require("starship"):setup()
```
Make sure you have [starship](https://github.com/starship/starship) installed and in your `PATH`.
## Config
Here is an example with all available config options:
```lua
require("starship"):setup({
-- Hide flags (such as filter, find and search). This is recommended for starship themes which
-- are intended to go across the entire width of the terminal.
hide_flags = false, -- Default: false
-- Whether to place flags after the starship prompt. False means the flags will be placed before the prompt.
flags_after_prompt = true, -- Default: true
-- Custom starship configuration file to use
config_file = "~/.config/starship_full.toml", -- Default: nil
})
```
## Extra
If you use a `starship` theme with a background colour, it might look a bit to cramped on just the one line `Yazi` gives the header by default. To fix this, you can add this to your `init.lua`:
<details>
<summary>Click to expand</summary>
```lua
local old_build = Tab.build
Tab.build = function(self, ...)
local bar = function(c, x, y)
if x <= 0 or x == self._area.w - 1 then
return ui.Bar(ui.Bar.TOP):area(ui.Rect.default)
end
return ui.Bar(ui.Bar.TOP)
:area(ui.Rect({
x = x,
y = math.max(0, y),
w = ya.clamp(0, self._area.w - x, 1),
h = math.min(1, self._area.h),
}))
:symbol(c)
end
local c = self._chunks
self._chunks = {
c[1]:padding(ui.Padding.y(1)),
c[2]:padding(ui.Padding(c[1].w > 0 and 0 or 1, c[3].w > 0 and 0 or 1, 1, 1)),
c[3]:padding(ui.Padding.y(1)),
}
local style = THEME.manager.border_style
self._base = ya.list_merge(self._base or {}, {
ui.Border(ui.Border.ALL):area(self._area):type(ui.Border.ROUNDED):style(style),
ui.Bar(ui.Bar.RIGHT):area(self._chunks[1]):style(style),
ui.Bar(ui.Bar.LEFT):area(self._chunks[1]):style(style),
bar("┬", c[1].right - 1, c[1].y),
bar("┴", c[1].right - 1, c[1].bottom - 1),
bar("┬", c[2].right, c[2].y),
bar("┴", c[2].right, c[2].bottom - 1),
})
old_build(self, ...)
end
```
</details>
> [!NOTE]
> This works by overriding your `Tab.build` function so make sure this is the only place you're doing that in your config. For example, this would be incompatible with the [full-border plugin](https://github.com/yazi-rs/plugins/tree/main/full-border.yazi)
## Thanks
- [sxyazi](https://github.com/sxyazi) for providing the code for this plugin and the demo video [in this comment](https://github.com/sxyazi/yazi/issues/767#issuecomment-1977082834)

View file

@ -1,136 +0,0 @@
--- @since 25.2.7
-- For development
--[[ local function notify(message) ]]
--[[ ya.notify({ title = "Starship", content = message, timeout = 3 }) ]]
--[[ end ]]
local save = ya.sync(function(st, _cwd, output)
st.output = output
ya.render()
end)
-- Helper function for accessing the `config_file` state variable
---@return string
local get_config_file = ya.sync(function(st)
return st.config_file
end)
return {
---User arguments for setup method
---@class SetupArgs
---@field config_file string Absolute path to a starship config file
---@field hide_flags boolean Whether to hide all flags (such as filter and search). Recommended for themes which are intended to take the full width of the terminal.
---@field flags_after_prompt boolean Whether to place flags (such as filter and search) after the starship prompt. By default this is true.
--- Setup plugin
--- @param st table State
--- @param args SetupArgs|nil
setup = function(st, args)
local hide_flags = false
local flags_after_prompt = true
-- Check setup args
if args ~= nil then
if args.config_file ~= nil then
local url = Url(args.config_file)
if url.is_regular then
local config_file = args.config_file
-- Manually replace '~' and '$HOME' at the start of the path with the OS environment variable
local home = os.getenv("HOME")
if home then
home = tostring(home)
config_file = config_file:gsub("^~", home):gsub("^$HOME", home)
end
st.config_file = config_file
end
end
if args.hide_flags ~= nil then
hide_flags = args.hide_flags
end
if args.flags_after_prompt ~= nil then
flags_after_prompt = args.flags_after_prompt
end
end
-- Replace default header widget
Header:children_remove(1, Header.LEFT)
Header:children_add(function(self)
local max = self._area.w - self._right_width
if max <= 0 then
return ""
end
if hide_flags or not st.output then
return ui.Line.parse(st.output or "")
end
-- Split `st.output` at the first line break (or keep as is if none was found)
local output = st.output:match("([^\n]*)\n?") or st.output
local flags = self:flags()
if flags_after_prompt then
output = output .. " " .. flags
else
output = flags .. " " .. output
end
return ui.Line.parse(output)
end, 1000, Header.LEFT)
-- Pass current working directory and custom config path (if specified) to the plugin's entry point
---Callback for subscribers to update the prompt
local callback = function()
local cwd = cx.active.current.cwd
if st.cwd ~= cwd then
st.cwd = cwd
if ya.confirm then
-- >= yazi 25.2.7
ya.manager_emit("plugin", {
st._id,
ya.quote(tostring(cwd), true),
})
else
-- < yazi 25.2.7
ya.manager_emit("plugin", {
st._id,
args = ya.quote(tostring(cwd), true),
})
end
end
end
-- Subscribe to events
ps.sub("cd", callback)
ps.sub("tab", callback)
end,
entry = function(_, job_or_args)
-- yazi 2024-11-29 changed the way arguments are passed to the plugin
-- entry point. They were moved inside {args = {...}}. If the user is using
-- a version before this change, they can use the old implementation.
-- https://github.com/sxyazi/yazi/pull/1966
local args = job_or_args.args or job_or_args
local command = Command("starship")
:arg("prompt")
:stdin(Command.INHERIT)
:cwd(args[1])
:env("STARSHIP_SHELL", "")
-- Point to custom starship config
local config_file = get_config_file()
if config_file then
command = command:env("STARSHIP_CONFIG", config_file)
end
local output = command:output()
if output then
save(args[1], output.stdout:gsub("^%s+", ""))
end
end,
}

View file

@ -1,10 +0,0 @@
column_width = 100
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"
collapse_simple_statement = "Never"
[sort_requires]
enabled = false

View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 dawsers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,32 +0,0 @@
# toggle-view.yazi
Toggle the different views: parent, current and preview.
## Requirements
- [Yazi](https://github.com/sxyazi/yazi/) v0.4 or later.
## Installation
```sh
ya pack -a dawsers/toggle-view
```
## Usage
Add this to your `~/.config/yazi/keymap.toml`:
``` toml
[manager]
prepend_keymap = [
{ on = "<C-1>", run = "plugin toggle-view --args=parent", desc = "Toggle parent" },
{ on = "<C-2>", run = "plugin toggle-view --args=current", desc = "Toggle current" },
{ on = "<C-3>", run = "plugin toggle-view --args=preview", desc = "Toggle preview" },
]
```
Now each key will toggle on/off one of the three panels: `Ctrl+1` for
*parent*, `Ctrl+2` for *current* and `Ctrl+3` for *preview*.
You can set your own key bindings.

View file

@ -1,63 +0,0 @@
--- @sync entry
-- Toggle different views on/off: parent, current, preview
local function entry(st, job)
local args = job.args or job
local action = args[1]
if not action then
return
end
if st.view == nil then
st.old_parent = MANAGER.ratio.parent
st.old_current = MANAGER.ratio.current
st.old_preview = MANAGER.ratio.preview
-- Get current tab ratios
local all_old = st.old_parent + st.old_current + st.old_preview
local area = ui.Rect { x= 0, y = 0, w = all_old, h = 10 }
local tab = Tab:new(area, cx.active)
st.parent = tab._chunks[1].w
st.current = tab._chunks[2].w
st.preview = tab._chunks[3].w
st.layout = Tab.layout
st.view = true -- initialized
end
if action == "parent" then
if st.parent > 0 then
st.parent = 0
else
st.parent = st.old_parent
end
elseif action == "current" then
if st.current > 0 then
st.current = 0
else
st.current = st.old_current
end
elseif action == "preview" then
if st.preview > 0 then
st.preview = 0
else
st.preview = st.old_preview
end
else
return
end
Tab.layout = function(self)
local all = st.parent + st.current + st.preview
self._chunks = ui.Layout()
:direction(ui.Layout.HORIZONTAL)
:constraints({
ui.Constraint.Ratio(st.parent, all),
ui.Constraint.Ratio(st.current, all),
ui.Constraint.Ratio(st.preview, all),
})
:split(self._area)
end
ya.app_emit("resize", {})
end
local function enabled(st) return st.view ~= nil end
return { entry = entry, enabled = enabled }

View file

@ -1,72 +0,0 @@
-- function to get paths of selected elements or current directory
-- of no elements are selected
local get_paths = ya.sync(function()
local paths = {}
-- get selected files
for _, u in pairs(cx.active.selected) do
paths[#paths + 1] = tostring(u)
end
-- if no files are selected, get current directory
if #paths == 0 then
if cx.active.current.cwd then
paths[1] = tostring(cx.active.current.cwd)
else
ya.err("what-size would return nil paths")
end
end
return paths
end)
-- Function to get total size from du output
local get_total_size = function(s)
local lines = {}
for line in s:gmatch("[^\n]+") do lines[#lines + 1] = line end
local last_line = lines[#lines]
local last_line_parts = {}
for part in last_line:gmatch("%S+") do last_line_parts[#last_line_parts + 1] = part end
local total_size = last_line_parts[1]
return total_size
end
-- Function to format file size
local function format_size(size)
local units = { "B", "KB", "MB", "GB", "TB" }
local unit_index = 1
while size > 1024 and unit_index < #units do
size = size / 1024
unit_index = unit_index + 1
end
return string.format("%.2f %s", size, units[unit_index])
end
return {
entry = function(self, job)
-- defaults not to use clipboard, use it only if required by the user
local clipboard = job.args.clipboard or job.args[1] == '-c'
local items = get_paths()
local cmd = "du"
local output, err = Command(cmd):arg("-scb"):args(items):output()
if not output then
ya.err("Failed to run diff, error: " .. err)
else
local total_size = get_total_size(output.stdout)
local formatted_size = format_size(tonumber(total_size))
local notification_content = "Total size: " .. formatted_size
if clipboard then
ya.clipboard(formatted_size)
notification_content = notification_content .. "\nCopied to clipboard."
end
ya.notify {
title = "What size",
content = notification_content,
timeout = 5,
}
end
end,
}

View file

@ -1,22 +0,0 @@
MIT License
Copyright (c) 2024 imsi32
Copyright (c) 2024 llanosrocas
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,39 +0,0 @@
# yatline-symlink.yazi
An addon to show symlink target in your [yatline.yazi](https://github.com/imsi32/yatline.yazi)'s status or header line.
![yatline-symlink example screenshot](2024-10-06-@13-18-32-scrot.png)
## Requirements
- yazi version >= 0.3.0
- [yatline.yazi](https://github.com/imsi32/yatline.yazi)
## Installation
```sh
ya pack -a lpanebr/yazi-plugins:yatline-symlink
```
## Usage
> [!IMPORTANT]
> Add this to your `~/.config/yazi/init.lua` after yatline.yazi's initialization.
```lua
require("yatline-symlink"):setup()
```
Then, add it in one of your sections in the yatline configuration using:
```lua
{ type = "coloreds", custom = false, name = "symlink" }
```
**Optional configuration:**
```lua
require("githead"):setup({
symlink_color = "white"
}
```

View file

@ -1,33 +0,0 @@
function hovered()
local hovered = cx.active.current.hovered
if hovered then
return hovered
else
return ""
end
end
local function setup(_, options)
options = options or {}
local config = {
symlink_color = options.symlink_color or "silver",
}
if Yatline ~= nil then
function Yatline.coloreds.get:symlink()
local symlink = {}
local linked = ""
local h = hovered()
if h.link_to ~= nil then
linked = " -> " .. tostring(h.link_to)
end
table.insert(symlink, { linked, config.symlink_color })
return symlink
end
end
end
return { setup = setup }

View file

@ -1,23 +0,0 @@
MIT License
Copyright (c) 2024 imsi32
Copyright (c) 2023 - sxyazi
Copyright (c) 2023 yazi-rs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,19 +0,0 @@
# yatline.yazi
The first Yazi plugin for customizing both header-line and status-line.
![yatline](https://github.com/user-attachments/assets/61013ec8-7fd9-42df-a9f4-f254663871fe)
> [!NOTE]
> Check out [wiki](https://github.com/imsi32/yatline.yazi/wiki) for installation steps, configuration and further information.
## Features
- Lualine-like Design
- Flexible
- Simple
- Automatic Configuration
- Themes (See: [yatline-themes](https://github.com/imsi32/yatline-themes))
- Add-ons (See: [yatline-addons](https://github.com/imsi32/yatline-addons))
## Credits
- [Lualine](https://github.com/nvim-lualine/lualine.nvim)
- [Yazi](https://github.com/sxyazi/yazi)

File diff suppressed because it is too large Load diff

@ -1 +0,0 @@
Subproject commit 9a095057d698aaaedc4dd23d638285bd3fd647e9