diff --git a/modules/home/yazi.nix b/modules/home/yazi.nix index 3ebf14d..817c8c6 100644 --- a/modules/home/yazi.nix +++ b/modules/home/yazi.nix @@ -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 = ""; run ="tab_create"; } { on = ""; run ="tab_close"; } { on = ""; run ="tab_switch 1 --relative"; } { on = ""; run ="tab_switch -1 --relative"; } + { on = ""; 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 = ""; run = "arrow -1"; desc = "up"; } - # { on = ""; 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 = ""; 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; } diff --git a/modules/home/yazi/init.lua b/modules/home/yazi/init.lua index 118cc23..fd93a6c 100644 --- a/modules/home/yazi/init.lua +++ b/modules/home/yazi/init.lua @@ -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 = "" }, diff --git a/modules/home/yazi/plugins/dir-rules.yazi/main.lua b/modules/home/yazi/plugins/dir-rules.yazi/main.lua index e1b35dd..bba4685 100644 --- a/modules/home/yazi/plugins/dir-rules.yazi/main.lua +++ b/modules/home/yazi/plugins/dir-rules.yazi/main.lua @@ -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 diff --git a/modules/home/yazi/plugins/fg.yazi/main.lua b/modules/home/yazi/plugins/fg.yazi/main.lua deleted file mode 100644 index 4785c0c..0000000 --- a/modules/home/yazi/plugins/fg.yazi/main.lua +++ /dev/null @@ -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 = "", run = "quit" }, - { on = "", run = "select" }, - - - { on = "k", run = "up" }, - { on = "j", run = "down" }, - - - { on = "", run = "up" }, - { on = "", 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 diff --git a/modules/home/yazi/plugins/file-extra-metadata.yazi/LICENSE b/modules/home/yazi/plugins/file-extra-metadata.yazi/LICENSE deleted file mode 100644 index fb10e72..0000000 --- a/modules/home/yazi/plugins/file-extra-metadata.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/file-extra-metadata.yazi/README.md b/modules/home/yazi/plugins/file-extra-metadata.yazi/README.md deleted file mode 100644 index 29259b8..0000000 --- a/modules/home/yazi/plugins/file-extra-metadata.yazi/README.md +++ /dev/null @@ -1,102 +0,0 @@ -# file-extra-metadata - - - -- [file-extra-metadata](#file-extra-metadata) - - [Preview](#preview) - - [Before:](#before) - - [After:](#after) - - [Requirements](#requirements) - - [Installation](#installation) - - [For developer](#for-developer) - - -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 `` keybind in -`manager` section: - -```toml -[manager] -keymap = [ - # ... - # Spotting - { on = "", 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 }) -``` diff --git a/modules/home/yazi/plugins/file-extra-metadata.yazi/main.lua b/modules/home/yazi/plugins/file-extra-metadata.yazi/main.lua deleted file mode 100644 index e4b6f75..0000000 --- a/modules/home/yazi/plugins/file-extra-metadata.yazi/main.lua +++ /dev/null @@ -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 diff --git a/modules/home/yazi/plugins/lazygit.yazi/LICENSE b/modules/home/yazi/plugins/lazygit.yazi/LICENSE deleted file mode 100644 index ae1f60d..0000000 --- a/modules/home/yazi/plugins/lazygit.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/lazygit.yazi/README.md b/modules/home/yazi/plugins/lazygit.yazi/README.md deleted file mode 100644 index e96c9c6..0000000 --- a/modules/home/yazi/plugins/lazygit.yazi/README.md +++ /dev/null @@ -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 diff --git a/modules/home/yazi/plugins/lazygit.yazi/main.lua b/modules/home/yazi/plugins/lazygit.yazi/main.lua deleted file mode 100644 index a5925ea..0000000 --- a/modules/home/yazi/plugins/lazygit.yazi/main.lua +++ /dev/null @@ -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, -} \ No newline at end of file diff --git a/modules/home/yazi/plugins/mediainfo.yazi/LICENSE b/modules/home/yazi/plugins/mediainfo.yazi/LICENSE deleted file mode 100644 index 0399f1c..0000000 --- a/modules/home/yazi/plugins/mediainfo.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/mediainfo.yazi/README.md b/modules/home/yazi/plugins/mediainfo.yazi/README.md deleted file mode 100644 index 2568a01..0000000 --- a/modules/home/yazi/plugins/mediainfo.yazi/README.md +++ /dev/null @@ -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"}, -] -``` diff --git a/modules/home/yazi/plugins/mediainfo.yazi/main.lua b/modules/home/yazi/plugins/mediainfo.yazi/main.lua deleted file mode 100644 index aa74285..0000000 --- a/modules/home/yazi/plugins/mediainfo.yazi/main.lua +++ /dev/null @@ -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 diff --git a/modules/home/yazi/plugins/mime-ext.yazi/LICENSE b/modules/home/yazi/plugins/mime-ext.yazi/LICENSE deleted file mode 100644 index fb5b1d6..0000000 --- a/modules/home/yazi/plugins/mime-ext.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/mime-ext.yazi/README.md b/modules/home/yazi/plugins/mime-ext.yazi/README.md deleted file mode 100644 index e771576..0000000 --- a/modules/home/yazi/plugins/mime-ext.yazi/README.md +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/mime-ext.yazi/main.lua b/modules/home/yazi/plugins/mime-ext.yazi/main.lua deleted file mode 100644 index 94e5a3a..0000000 --- a/modules/home/yazi/plugins/mime-ext.yazi/main.lua +++ /dev/null @@ -1,1126 +0,0 @@ ---- @since 25.2.7 - -local FILES = { - [".envrc"] = "text/plain", - [".gitconfig"] = "text/plain", - [".gitignore"] = "text/plain", - [".luacheckrc"] = "text/lua", - [".npmrc"] = "text/plain", - [".styluaignore"] = "text/plain", - [".zshenv"] = "text/plain", - [".zshrc"] = "text/plain", - ["cargo.lock"] = "application/json", - ["flake.lock"] = "application/json", - license = "text/plain", -} - -local EXTS = { - ["123"] = "application/lotus-1-2-3", - ["3dml"] = "text/in3d.3dml", - ["3ds"] = "image/3ds", - ["3g2"] = "video/3gpp2", - ["3gp"] = "video/3gpp", - ["7z"] = "application/7z-compressed", - ["for"] = "text/fortran", - ["in"] = "text/plain", - ["n-gage"] = "application/nokia.n-gage.symbian.install", - ["sfd-hdstx"] = "application/hydrostatix.sof-data", - aab = "application/authorware-bin", - aac = "audio/aac", - aam = "application/authorware-map", - aas = "application/authorware-seg", - abw = "application/abiword", - ac = "application/pkix-attr-cert", - acc = "application/americandynamics.acc", - ace = "application/ace-compressed", - acu = "application/acucobol", - acutc = "application/acucorp", - adp = "audio/adpcm", - aep = "application/audiograph", - afm = "application/font-type1", - afp = "application/ibm.modcap", - ahead = "application/ahead.space", - ai = "application/postscript", - aif = "audio/aiff", - aifc = "audio/aiff", - aiff = "audio/aiff", - air = "application/adobe.air-application-installer-package+zip", - ait = "application/dvb.ait", - ami = "application/amiga.ami", - apk = "application/android.package-archive", - appcache = "text/cache-manifest", - application = "application/ms-application", - apr = "application/lotus-approach", - arc = "application/freearc", - asc = "application/pgp-signature", - asf = "video/ms-asf", - asm = "text/asm", - aso = "application/accpac.simply.aso", - ass = "text/ass", - asx = "video/ms-asf", - atc = "application/acucorp", - atom = "application/atom+xml", - atomcat = "application/atomcat+xml", - atomsvc = "application/atomsvc+xml", - atx = "application/antix.game-component", - au = "audio/basic", - avi = "video/msvideo", - avif = "image/avif", - aw = "application/applixware", - azf = "application/airzip.filesecure.azf", - azs = "application/airzip.filesecure.azs", - azw = "application/amazon.ebook", - bash = "text/shellscript", - bat = "application/msdownload", - bcpio = "application/bcpio", - bdf = "application/font-bdf", - bdm = "application/syncml.dm+wbxml", - bean = "text/plain", - beancount = "text/plain", - bed = "application/realvnc.bed", - bh2 = "application/fujitsu.oasysprs", - bin = "application/octet-stream", - blb = "application/blorb", - blorb = "application/blorb", - bmi = "application/bmi", - bmp = "image/bmp", - book = "application/framemaker", - box = "application/previewsystems.box", - boz = "application/bzip2", - bpk = "application/octet-stream", - btif = "image/prs.btif", - bz = "application/bzip", - bz2 = "application/bzip2", - c = "text/c", - c11amc = "application/cluetrust.cartomobile-config", - c11amz = "application/cluetrust.cartomobile-config-pkg", - c4d = "application/clonk.c4group", - c4f = "application/clonk.c4group", - c4g = "application/clonk.c4group", - c4p = "application/clonk.c4group", - c4u = "application/clonk.c4group", - cab = "application/ms-cab-compressed", - caf = "audio/caf", - cap = "application/tcpdump.pcap", - car = "application/curl.car", - cat = "application/ms-pki.seccat", - cb7 = "application/cbr", - cba = "application/cbr", - cbr = "application/cbr", - cbt = "application/cbr", - cbz = "application/cbr", - cc = "text/c", - cct = "application/director", - ccxml = "application/ccxml+xml", - cdbcmsg = "application/contact.cmsg", - cdf = "application/netcdf", - cdkey = "application/mediastation.cdkey", - cdmia = "application/cdmi-capability", - cdmic = "application/cdmi-container", - cdmid = "application/cdmi-domain", - cdmio = "application/cdmi-object", - cdmiq = "application/cdmi-queue", - cdx = "chemical/cdx", - cdxml = "application/chemdraw+xml", - cdy = "application/cinderella", - cer = "application/pkix-cert", - cfg = "text/plain", - cfs = "application/cfs-compressed", - cgm = "image/cgm", - chat = "application/chat", - chm = "application/ms-htmlhelp", - chrt = "application/kde.kchart", - cif = "chemical/cif", - cii = "application/anser-web-certificate-issue-initiation", - cil = "application/ms-artgalry", - cla = "application/claymore", - class = "application/java-vm", - clkk = "application/crick.clicker.keyboard", - clkp = "application/crick.clicker.palette", - clkt = "application/crick.clicker.template", - clkw = "application/crick.clicker.wordbank", - clkx = "application/crick.clicker", - clp = "application/msclip", - cmc = "application/cosmocaller", - cmdf = "chemical/cmdf", - cml = "chemical/cml", - cmp = "application/yellowriver-custom-menu", - cmx = "image/cmx", - cod = "application/rim.cod", - com = "application/msdownload", - conf = "text/plain", - cpio = "application/cpio", - cpp = "text/c", - cpt = "application/mac-compactpro", - crd = "application/mscardfile", - crl = "application/pkix-crl", - crt = "application/x509-ca-cert", - cryptonote = "application/rig.cryptonote", - csh = "application/csh", - csml = "chemical/csml", - csp = "application/commonspace", - css = "text/css", - cst = "application/director", - csv = "text/csv", - cu = "application/cu-seeme", - curl = "text/curl", - cww = "application/prs.cww", - cxt = "application/director", - cxx = "text/c", - dae = "model/collada+xml", - daf = "application/mobius.daf", - dart = "application/dart", - dataless = "application/fdsn.seed", - davmount = "application/davmount+xml", - dbk = "application/docbook+xml", - dcr = "application/director", - dcurl = "text/curl.dcurl", - dd2 = "application/oma.dd2+xml", - ddd = "application/fujixerox.ddd", - deb = "application/debian-package", - def = "text/plain", - deploy = "application/octet-stream", - der = "application/x509-ca-cert", - dfac = "application/dreamfactory", - dgc = "application/dgc-compressed", - dic = "text/c", - dir = "application/director", - dis = "application/mobius.dis", - dist = "application/octet-stream", - distz = "application/octet-stream", - djv = "image/djvu", - djvu = "image/djvu", - dll = "application/msdownload", - dmg = "application/apple-diskimage", - dmp = "application/tcpdump.pcap", - dms = "application/octet-stream", - dna = "application/dna", - doc = "application/msword", - docm = "application/ms-word.document.macroenabled.12", - docx = "application/openxmlformats-officedocument.wordprocessingml.document", - dot = "application/msword", - dotm = "application/ms-word.template.macroenabled.12", - dotx = "application/openxmlformats-officedocument.wordprocessingml.template", - dp = "application/osgi.dp", - dpg = "application/dpgraph", - dra = "audio/dra", - dsc = "text/prs.lines.tag", - dssc = "application/dssc+der", - dtb = "application/dtbook+xml", - dtd = "application/xml-dtd", - dts = "audio/dts", - dtshd = "audio/dts.hd", - dump = "application/octet-stream", - dvb = "video/dvb.file", - dvi = "application/dvi", - dwf = "model/dwf", - dwg = "image/dwg", - dxf = "image/dxf", - dxp = "application/spotfire.dxp", - dxr = "application/director", - ebuild = "application/gentoo.ebuild", - ecelp4800 = "audio/nuera.ecelp4800", - ecelp7470 = "audio/nuera.ecelp7470", - ecelp9600 = "audio/nuera.ecelp9600", - eclass = "application/gentoo.eclass", - ecma = "application/ecmascript", - edm = "application/novadigm.edm", - edx = "application/novadigm.edx", - efif = "application/picsel", - ei6 = "application/pg.osasli", - elc = "application/octet-stream", - emf = "application/msmetafile", - eml = "message/rfc822", - emma = "application/emma+xml", - emz = "application/msmetafile", - env = "text/plain", - eol = "audio/digital-winds", - eot = "application/ms-fontobject", - eps = "application/postscript", - epub = "application/epub+zip", - es3 = "application/eszigno3+xml", - esa = "application/osgi.subsystem", - esf = "application/epson.esf", - et3 = "application/eszigno3+xml", - etx = "text/setext", - eva = "application/eva", - evy = "application/envoy", - exe = "application/msdownload", - exi = "application/exi", - ext = "application/novadigm.ext", - ez = "application/andrew-inset", - ez2 = "application/ezpix-album", - ez3 = "application/ezpix-package", - f = "text/fortran", - f4v = "video/f4v", - f77 = "text/fortran", - f90 = "text/fortran", - fbs = "image/fastbidsheet", - fcdt = "application/adobe.formscentral.fcdt", - fcs = "application/isac.fcs", - fdf = "application/fdf", - fe_launch = "application/denovo.fcselayout-link", - fg5 = "application/fujitsu.oasysgp", - fgd = "application/director", - fh = "image/freehand", - fh4 = "image/freehand", - fh5 = "image/freehand", - fh7 = "image/freehand", - fhc = "image/freehand", - fig = "application/xfig", - fish = "text/shellscript", - flac = "audio/flac", - fli = "video/fli", - flo = "application/micrografx.flo", - flv = "video/flv", - flw = "application/kde.kivio", - flx = "text/fmi.flexstor", - fly = "text/fly", - fm = "application/framemaker", - fnc = "application/frogans.fnc", - fpx = "image/fpx", - frame = "application/framemaker", - fsc = "application/fsc.weblaunch", - fst = "image/fst", - ftc = "application/fluxtime.clip", - fti = "application/anser-web-funds-transfer-initiation", - fvt = "video/fvt", - fxp = "application/adobe.fxp", - fxpl = "application/adobe.fxp", - fzs = "application/fuzzysheet", - g2w = "application/geoplan", - g3 = "image/g3fax", - g3w = "application/geospace", - gac = "application/groove-account", - gam = "application/tads", - gbr = "application/rpki-ghostbusters", - gca = "application/gca-compressed", - gdl = "model/gdl", - geo = "application/dynageo", - gex = "application/geometry-explorer", - ggb = "application/geogebra.file", - ggs = "application/geogebra.slides", - ggt = "application/geogebra.tool", - ghf = "application/groove-help", - gif = "image/gif", - gim = "application/groove-identity-message", - gml = "application/gml+xml", - gmx = "application/gmx", - gnumeric = "application/gnumeric", - go = "text/go", - gph = "application/flographit", - gpx = "application/gpx+xml", - gqf = "application/grafeq", - gqs = "application/grafeq", - gram = "application/srgs", - gramps = "application/gramps-xml", - gre = "application/geometry-explorer", - grv = "application/groove-injector", - grxml = "application/srgs+xml", - gsf = "application/font-ghostscript", - gtar = "application/gtar", - gtm = "application/groove-tool-message", - gtw = "model/gtw", - gv = "text/graphviz", - gxf = "application/gxf", - gxt = "application/geonext", - h = "text/c", - h261 = "video/h261", - h263 = "video/h263", - h264 = "video/h264", - hal = "application/hal+xml", - hbci = "application/hbci", - hcl = "text/hcl", - hdf = "application/hdf", - hh = "text/c", - hlp = "application/winhlp", - hpgl = "application/hp-hpgl", - hpid = "application/hp-hpid", - hpp = "text/c", - hps = "application/hp-hps", - hqx = "application/mac-binhex40", - htke = "application/kenameaapp", - htm = "text/html", - html = "text/html", - hvd = "application/yamaha.hv-dic", - hvp = "application/yamaha.hv-voice", - hvs = "application/yamaha.hv-script", - i2g = "application/intergeo", - icc = "application/iccprofile", - ice = "conference/cooltalk", - icm = "application/iccprofile", - ico = "image/icon", - ics = "text/calendar", - ief = "image/ief", - ifb = "text/calendar", - ifm = "application/shana.informed.formdata", - iges = "model/iges", - igl = "application/igloader", - igm = "application/insors.igm", - igs = "model/iges", - igx = "application/micrografx.igx", - iif = "application/shana.informed.interchange", - imp = "application/accpac.simply.imp", - ims = "application/ms-ims", - ini = "text/plain", - ink = "application/inkml+xml", - inkml = "application/inkml+xml", - install = "application/install-instructions", - iota = "application/astraea-software.iota", - ipfix = "application/ipfix", - ipk = "application/shana.informed.package", - irm = "application/ibm.rights-management", - irp = "application/irepository.package+xml", - iso = "application/iso9660-image", - itp = "application/shana.informed.formtemplate", - ivp = "application/immervision-ivp", - ivu = "application/immervision-ivu", - jad = "text/sun.j2me.app-descriptor", - jam = "application/jam", - jar = "application/java-archive", - java = "text/java-source", - jisp = "application/jisp", - jlt = "application/hp-jlyt", - jnlp = "application/java-jnlp-file", - joda = "application/joost.joda-archive", - jpe = "image/jpeg", - jpeg = "image/jpeg", - jpg = "image/jpeg", - jpgm = "video/jpm", - jpgv = "video/jpeg", - jpm = "video/jpm", - js = "text/javascript", - json = "application/json", - jsonc = "application/json", - jsonml = "application/jsonml+json", - jsx = "text/jsx", - jxl = "image/jxl", - kar = "audio/midi", - karbon = "application/kde.karbon", - kfo = "application/kde.kformula", - kia = "application/kidspiration", - kml = "application/google-earth.kml+xml", - kmz = "application/google-earth.kmz", - kne = "application/kinar", - knp = "application/kinar", - kon = "application/kde.kontour", - kpr = "application/kde.kpresenter", - kpt = "application/kde.kpresenter", - kpxx = "application/ds-keypoint", - ksp = "application/kde.kspread", - ktr = "application/kahootz", - ktx = "image/ktx", - ktz = "application/kahootz", - kwd = "application/kde.kword", - kwt = "application/kde.kword", - lasxml = "application/las.las+xml", - latex = "application/latex", - lbd = "application/llamagraphics.life-balance.desktop", - lbe = "application/llamagraphics.life-balance.exchange+xml", - les = "application/hhe.lesson-player", - lha = "application/lzh-compressed", - link66 = "application/route66.link66+xml", - list = "text/plain", - list3820 = "application/ibm.modcap", - listafp = "application/ibm.modcap", - lnk = "application/ms-shortcut", - log = "text/plain", - lostxml = "application/lost+xml", - lrf = "application/octet-stream", - lrm = "application/ms-lrm", - ltf = "application/frogans.ltf", - lua = "text/lua", - lvp = "audio/lucent.voice", - lwp = "application/lotus-wordpro", - lzh = "application/lzh-compressed", - m13 = "application/msmediaview", - m14 = "application/msmediaview", - m1v = "video/mpeg", - m21 = "application/mp21", - m2a = "audio/mpeg", - m2t = "video/mp2t", - m2ts = "video/mp2t", - m2v = "video/mpeg", - m3a = "audio/mpeg", - m3u = "audio/mpegurl", - m3u8 = "application/apple.mpegurl", - m4a = "audio/mp4", - m4u = "video/mpegurl", - m4v = "video/m4v", - ma = "application/mathematica", - mads = "application/mads+xml", - mag = "application/ecowin.chart", - maker = "application/framemaker", - man = "text/troff", - mar = "application/octet-stream", - mathml = "application/mathml+xml", - mb = "application/mathematica", - mbk = "application/mobius.mbk", - mbox = "application/mbox", - mc1 = "application/medcalcdata", - mcd = "application/mcd", - mcurl = "text/curl.mcurl", - md = "text/markdown", - mdb = "application/msaccess", - mdi = "image/ms-modi", - me = "text/troff", - mesh = "model/mesh", - meta4 = "application/metalink4+xml", - metalink = "application/metalink+xml", - mets = "application/mets+xml", - mfm = "application/mfmp", - mft = "application/rpki-manifest", - mgp = "application/osgeo.mapguide.package", - mgz = "application/proteus.magazine", - mid = "audio/midi", - midi = "audio/midi", - mie = "application/mie", - mif = "application/mif", - mime = "message/rfc822", - mj2 = "video/mj2", - mjp2 = "video/mj2", - mjs = "text/javascript", - mk3d = "video/matroska", - mka = "audio/matroska", - mks = "video/matroska", - mkv = "video/matroska", - mlp = "application/dolby.mlp", - mmd = "application/chipnuts.karaoke-mmd", - mmf = "application/smaf", - mmr = "image/fujixerox.edmics-mmr", - mng = "video/mng", - mny = "application/msmoney", - mobi = "application/mobipocket-ebook", - mods = "application/mods+xml", - mov = "video/quicktime", - movie = "video/sgi-movie", - mp2 = "audio/mpeg", - mp21 = "application/mp21", - mp2a = "audio/mpeg", - mp3 = "audio/mpeg", - mp4 = "video/mp4", - mp4a = "audio/mp4", - mp4s = "application/mp4", - mp4v = "video/mp4", - mpc = "application/mophun.certificate", - mpe = "video/mpeg", - mpeg = "video/mpeg", - mpg = "video/mpeg", - mpg4 = "video/mp4", - mpga = "audio/mpeg", - mpkg = "application/apple.installer+xml", - mpm = "application/blueice.multipass", - mpn = "application/mophun.application", - mpp = "application/ms-project", - mpt = "application/ms-project", - mpy = "application/ibm.minipay", - mqy = "application/mobius.mqy", - mrc = "application/marc", - mrcx = "application/marcxml+xml", - ms = "text/troff", - mscml = "application/mediaservercontrol+xml", - mseed = "application/fdsn.mseed", - mseq = "application/mseq", - msf = "application/epson.msf", - msh = "model/mesh", - msi = "application/msdownload", - msl = "application/mobius.msl", - msty = "application/muvee.style", - mts = "video/mp2t", - mus = "application/musician", - musicxml = "application/recordare.musicxml+xml", - mvb = "application/msmediaview", - mwf = "application/mfer", - mxf = "application/mxf", - mxl = "application/recordare.musicxml", - mxml = "application/xv+xml", - mxs = "application/triscape.mxs", - mxu = "video/mpegurl", - n3 = "text/n3", - nb = "application/mathematica", - nbp = "application/wolfram.player", - nc = "application/netcdf", - ncx = "application/dtbncx+xml", - nfo = "text/nfo", - ngdat = "application/nokia.n-gage.data", - nitf = "application/nitf", - nix = "text/nix", - nlu = "application/neurolanguage.nlu", - nml = "application/enliven", - nnd = "application/noblenet-directory", - nns = "application/noblenet-sealer", - nnw = "application/noblenet-web", - npx = "image/net-fpx", - nsc = "application/conference", - nsf = "application/lotus-notes", - ntf = "application/nitf", - nzb = "application/nzb", - oa2 = "application/fujitsu.oasys2", - oa3 = "application/fujitsu.oasys3", - oas = "application/fujitsu.oasys", - obd = "application/msbinder", - obj = "application/tgif", - oda = "application/oda", - odb = "application/oasis.opendocument.database", - odc = "application/oasis.opendocument.chart", - odf = "application/oasis.opendocument.formula", - odft = "application/oasis.opendocument.formula-template", - odg = "application/oasis.opendocument.graphics", - odi = "application/oasis.opendocument.image", - odm = "application/oasis.opendocument.text-master", - odp = "application/oasis.opendocument.presentation", - ods = "application/oasis.opendocument.spreadsheet", - odt = "application/oasis.opendocument.text", - oga = "audio/ogg", - ogg = "audio/ogg", - ogv = "video/ogg", - ogx = "application/ogg", - omdoc = "application/omdoc+xml", - onepkg = "application/onenote", - onetmp = "application/onenote", - onetoc = "application/onenote", - onetoc2 = "application/onenote", - opf = "application/oebps-package+xml", - opml = "text/opml", - oprc = "application/palm", - opus = "audio/ogg", - org = "application/lotus-organizer", - osf = "application/yamaha.openscoreformat", - osfpvg = "application/yamaha.openscoreformat.osfpvg+xml", - otc = "application/oasis.opendocument.chart-template", - otf = "font/otf", - otg = "application/oasis.opendocument.graphics-template", - oth = "application/oasis.opendocument.text-web", - oti = "application/oasis.opendocument.image-template", - otp = "application/oasis.opendocument.presentation-template", - ots = "application/oasis.opendocument.spreadsheet-template", - ott = "application/oasis.opendocument.text-template", - oxps = "application/oxps", - oxt = "application/openofficeorg.extension", - p = "text/pascal", - p10 = "application/pkcs10", - p12 = "application/pkcs12", - p7b = "application/pkcs7-certificates", - p7c = "application/pkcs7-mime", - p7m = "application/pkcs7-mime", - p7r = "application/pkcs7-certreqresp", - p7s = "application/pkcs7-signature", - p8 = "application/pkcs8", - pas = "text/pascal", - patch = "text/diff", - paw = "application/pawaafile", - pbd = "application/powerbuilder6", - pbm = "image/portable-bitmap", - pcap = "application/tcpdump.pcap", - pcf = "application/font-pcf", - pcl = "application/hp-pcl", - pclxl = "application/hp-pclxl", - pct = "image/pict", - pcurl = "application/curl.pcurl", - pcx = "image/pcx", - pdb = "application/palm", - pdf = "application/pdf", - pfa = "application/font-type1", - pfb = "application/font-type1", - pfm = "application/font-type1", - pfr = "application/font-tdpfr", - pfx = "application/pkcs12", - pgm = "image/portable-graymap", - pgn = "application/chess-pgn", - pgp = "application/pgp-encrypted", - php = "text/php", - pic = "image/pict", - pkg = "application/octet-stream", - pki = "application/pkixcmp", - pkipath = "application/pkix-pkipath", - plb = "application/3gpp.pic-bw-large", - plc = "application/mobius.plc", - plf = "application/pocketlearn", - pls = "application/pls+xml", - pml = "application/ctc-posml", - png = "image/png", - pnm = "image/portable-anymap", - portpkg = "application/macports.portpkg", - pot = "application/ms-powerpoint", - potm = "application/ms-powerpoint.template.macroenabled.12", - potx = "application/openxmlformats-officedocument.presentationml.template", - ppam = "application/ms-powerpoint.addin.macroenabled.12", - ppd = "application/cups-ppd", - ppm = "image/portable-pixmap", - pps = "application/ms-powerpoint", - ppsm = "application/ms-powerpoint.slideshow.macroenabled.12", - ppsx = "application/openxmlformats-officedocument.presentationml.slideshow", - ppt = "application/ms-powerpoint", - pptm = "application/ms-powerpoint.presentation.macroenabled.12", - pptx = "application/openxmlformats-officedocument.presentationml.presentation", - pqa = "application/palm", - prc = "application/mobipocket-ebook", - pre = "application/lotus-freelance", - prf = "application/pics-rules", - ps = "application/postscript", - psb = "application/3gpp.pic-bw-small", - psd = "image/adobe.photoshop", - psf = "application/font-linux-psf", - pskcxml = "application/pskc+xml", - ptid = "application/pvi.ptid1", - pub = "application/mspublisher", - pvb = "application/3gpp.pic-bw-var", - pwn = "application/3m.post-it-notes", - py = "text/python", - pya = "audio/ms-playready.media.pya", - pyv = "video/ms-playready.media.pyv", - qam = "application/epson.quickanime", - qbo = "application/intu.qbo", - qfx = "application/intu.qfx", - qml = "text/qml", - qps = "application/publishare-delta-tree", - qt = "video/quicktime", - qwd = "application/quark.quarkxpress", - qwt = "application/quark.quarkxpress", - qxb = "application/quark.quarkxpress", - qxd = "application/quark.quarkxpress", - qxl = "application/quark.quarkxpress", - qxt = "application/quark.quarkxpress", - r = "text/r", - ra = "audio/pn-realaudio", - ram = "audio/pn-realaudio", - rar = "application/rar", - ras = "image/cmu-raster", - rb = "text/ruby", - rcprofile = "application/ipunplugged.rcprofile", - rdf = "application/rdf+xml", - rdz = "application/data-vision.rdz", - rep = "application/businessobjects", - res = "application/dtbresource+xml", - rgb = "image/rgb", - rif = "application/reginfo+xml", - rip = "audio/rip", - ris = "application/research-info-systems", - rl = "application/resource-lists+xml", - rlc = "image/fujixerox.edmics-rlc", - rld = "application/resource-lists-diff+xml", - rm = "application/rn-realmedia", - rmi = "audio/midi", - rmp = "audio/pn-realaudio-plugin", - rms = "application/jcp.javame.midlet-rms", - rmvb = "application/rn-realmedia-vbr", - rnc = "application/relax-ng-compact-syntax", - roa = "application/rpki-roa", - roff = "text/troff", - rp9 = "application/cloanto.rp9", - rpm = "application/rpm", - rpss = "application/nokia.radio-presets", - rpst = "application/nokia.radio-preset", - rq = "application/sparql-query", - rs = "text/rust", - rsd = "application/rsd+xml", - rss = "application/rss+xml", - rtf = "application/rtf", - rtx = "text/richtext", - s = "text/asm", - s3m = "audio/s3m", - saf = "application/yamaha.smaf-audio", - sbml = "application/sbml+xml", - sc = "application/ibm.secure-container", - scd = "application/msschedule", - scm = "application/lotus-screencam", - scq = "application/scvp-cv-request", - scs = "application/scvp-cv-response", - scss = "text/scss", - scurl = "text/curl.scurl", - sda = "application/stardivision.draw", - sdc = "application/stardivision.calc", - sdd = "application/stardivision.impress", - sdkd = "application/solent.sdkm+xml", - sdkm = "application/solent.sdkm+xml", - sdp = "application/sdp", - sdw = "application/stardivision.writer", - see = "application/seemail", - seed = "application/fdsn.seed", - sema = "application/sema", - semd = "application/semd", - semf = "application/semf", - ser = "application/java-serialized-object", - setpay = "application/set-payment-initiation", - setreg = "application/set-registration-initiation", - sfs = "application/spotfire.sfs", - sfv = "text/sfv", - sgi = "image/sgi", - sgl = "application/stardivision.writer-global", - sgm = "text/sgml", - sgml = "text/sgml", - sh = "text/shellscript", - shar = "application/shar", - shf = "application/shf+xml", - sid = "image/mrsid-image", - sig = "application/pgp-signature", - sil = "audio/silk", - silo = "model/mesh", - sis = "application/symbian.install", - sisx = "application/symbian.install", - sit = "application/stuffit", - sitx = "application/stuffitx", - skd = "application/koan", - skm = "application/koan", - skp = "application/koan", - skt = "application/koan", - sldm = "application/ms-powerpoint.slide.macroenabled.12", - sldx = "application/openxmlformats-officedocument.presentationml.slide", - slt = "application/epson.salt", - sm = "application/stepmania.stepchart", - smf = "application/stardivision.math", - smi = "application/smil+xml", - smil = "application/smil+xml", - smv = "video/smv", - smzip = "application/stepmania.package", - snd = "audio/basic", - snf = "application/font-snf", - so = "application/octet-stream", - spc = "application/pkcs7-certificates", - spf = "application/yamaha.smaf-phrase", - spl = "application/futuresplash", - spot = "text/in3d.spot", - spp = "application/scvp-vp-response", - spq = "application/scvp-vp-request", - spx = "audio/ogg", - sql = "application/sql", - src = "application/wais-source", - srt = "application/subrip", - sru = "application/sru+xml", - srx = "application/sparql-results+xml", - ssdl = "application/ssdl+xml", - sse = "application/kodak-descriptor", - ssf = "application/epson.ssf", - ssml = "application/ssml+xml", - st = "application/sailingtracker.track", - stc = "application/sun.xml.calc.template", - std = "application/sun.xml.draw.template", - stf = "application/wt.stf", - sti = "application/sun.xml.impress.template", - stk = "application/hyperstudio", - stl = "application/ms-pki.stl", - str = "application/pg.format", - stw = "application/sun.xml.writer.template", - sub = "text/dvb.subtitle", - sus = "application/sus-calendar", - susp = "application/sus-calendar", - sv4cpio = "application/sv4cpio", - sv4crc = "application/sv4crc", - svc = "application/dvb.service", - svd = "application/svd", - svg = "image/svg+xml", - svgz = "image/svg+xml", - swa = "application/director", - swf = "application/shockwave-flash", - swi = "application/aristanetworks.swi", - sxc = "application/sun.xml.calc", - sxd = "application/sun.xml.draw", - sxg = "application/sun.xml.writer.global", - sxi = "application/sun.xml.impress", - sxm = "application/sun.xml.math", - sxw = "application/sun.xml.writer", - t = "text/troff", - t3 = "application/t3vm-image", - taglet = "application/mynfc", - tao = "application/tao.intent-module-archive", - tar = "application/tar", - tcap = "application/3gpp2.tcap", - tcl = "application/tcl", - teacher = "application/smart.teacher", - tei = "application/tei+xml", - teicorpus = "application/tei+xml", - tex = "application/tex", - texi = "application/texinfo", - texinfo = "application/texinfo", - text = "text/plain", - tf = "text/hcl", - tfi = "application/thraud+xml", - tfm = "application/tex-tfm", - tfrc = "text/hcl", - tfstate = "application/json", - tfvars = "text/hcl", - tga = "image/tga", - thmx = "application/ms-officetheme", - tif = "image/tiff", - tiff = "image/tiff", - tmo = "application/tmobile-livetv", - toml = "text/toml", - torrent = "application/bittorrent", - tpl = "application/groove-tool-template", - tpt = "application/trid.tpt", - tr = "text/troff", - tra = "application/trueapp", - trm = "application/msterminal", - ts = "text/typescript", - tsd = "application/timestamped-data", - tsv = "text/tab-separated-values", - tsx = "text/tsx", - ttc = "font/collection", - ttf = "font/ttf", - ttl = "text/turtle", - twd = "application/simtech-mindmapper", - twds = "application/simtech-mindmapper", - txd = "application/genomatix.tuxedo", - txf = "application/mobius.txf", - txt = "text/plain", - u32 = "application/authorware-bin", - udeb = "application/debian-package", - ufd = "application/ufdl", - ufdl = "application/ufdl", - ulx = "application/glulx", - umj = "application/umajin", - unityweb = "application/unity", - uoml = "application/uoml+xml", - uri = "text/uri-list", - uris = "text/uri-list", - urls = "text/uri-list", - ustar = "application/ustar", - utz = "application/uiq.theme", - uu = "text/uuencode", - uva = "audio/dece.audio", - uvd = "application/dece.data", - uvf = "application/dece.data", - uvg = "image/dece.graphic", - uvh = "video/dece.hd", - uvi = "image/dece.graphic", - uvm = "video/dece.mobile", - uvp = "video/dece.pd", - uvs = "video/dece.sd", - uvt = "application/dece.ttml+xml", - uvu = "video/uvvu.mp4", - uvv = "video/dece.video", - uvva = "audio/dece.audio", - uvvd = "application/dece.data", - uvvf = "application/dece.data", - uvvg = "image/dece.graphic", - uvvh = "video/dece.hd", - uvvi = "image/dece.graphic", - uvvm = "video/dece.mobile", - uvvp = "video/dece.pd", - uvvs = "video/dece.sd", - uvvt = "application/dece.ttml+xml", - uvvu = "video/uvvu.mp4", - uvvv = "video/dece.video", - uvvx = "application/dece.unspecified", - uvvz = "application/dece.zip", - uvx = "application/dece.unspecified", - uvz = "application/dece.zip", - vcard = "text/vcard", - vcd = "application/cdlink", - vcf = "text/vcard", - vcg = "application/groove-vcard", - vcs = "text/vcalendar", - vcx = "application/vcx", - vis = "application/visionary", - viv = "video/vivo", - vob = "video/ms-vob", - vor = "application/stardivision.writer", - vox = "application/authorware-bin", - vrml = "model/vrml", - vsd = "application/visio", - vsf = "application/vsf", - vss = "application/visio", - vst = "application/visio", - vsw = "application/visio", - vtu = "model/vtu", - vxml = "application/voicexml+xml", - w3d = "application/director", - wad = "application/doom", - wasm = "application/wasm", - wav = "audio/wav", - wax = "audio/ms-wax", - wbmp = "image/wap.wbmp", - wbs = "application/criticaltools.wbs+xml", - wbxml = "application/wap.wbxml", - wcm = "application/ms-works", - wdb = "application/ms-works", - wdp = "image/ms-photo", - weba = "audio/webm", - webm = "video/webm", - webp = "image/webp", - wg = "application/pmi.widget", - wgt = "application/widget", - wks = "application/ms-works", - wm = "video/ms-wm", - wma = "audio/ms-wma", - wmd = "application/ms-wmd", - wmf = "application/msmetafile", - wml = "text/wap.wml", - wmlc = "application/wap.wmlc", - wmls = "text/wap.wmlscript", - wmlsc = "application/wap.wmlscriptc", - wmv = "video/ms-wmv", - wmx = "video/ms-wmx", - wmz = "application/ms-wmz", - woff = "font/woff", - woff2 = "font/woff2", - wpd = "application/wordperfect", - wpl = "application/ms-wpl", - wps = "application/ms-works", - wqd = "application/wqd", - wri = "application/mswrite", - wrl = "model/vrml", - wsdl = "application/wsdl+xml", - wspolicy = "application/wspolicy+xml", - wtb = "application/webturbo", - wvx = "video/ms-wvx", - x32 = "application/authorware-bin", - x3d = "model/x3d+xml", - x3db = "model/x3d+binary", - x3dbz = "model/x3d+binary", - x3dv = "model/x3d+vrml", - x3dvz = "model/x3d+vrml", - x3dz = "model/x3d+xml", - xaml = "application/xaml+xml", - xap = "application/silverlight-app", - xar = "application/xara", - xbap = "application/ms-xbap", - xbd = "application/fujixerox.docuworks.binder", - xbm = "image/xbitmap", - xdf = "application/xcap-diff+xml", - xdm = "application/syncml.dm+xml", - xdp = "application/adobe.xdp+xml", - xdssc = "application/dssc+xml", - xdw = "application/fujixerox.docuworks", - xenc = "application/xenc+xml", - xer = "application/patch-ops-error+xml", - xfdf = "application/adobe.xfdf", - xfdl = "application/xfdl", - xht = "application/xhtml+xml", - xhtml = "application/xhtml+xml", - xhvml = "application/xv+xml", - xif = "image/xiff", - xla = "application/ms-excel", - xlam = "application/ms-excel.addin.macroenabled.12", - xlc = "application/ms-excel", - xlf = "application/xliff+xml", - xlm = "application/ms-excel", - xls = "application/ms-excel", - xlsb = "application/ms-excel.sheet.binary.macroenabled.12", - xlsm = "application/ms-excel.sheet.macroenabled.12", - xlsx = "application/openxmlformats-officedocument.spreadsheetml.sheet", - xlt = "application/ms-excel", - xltm = "application/ms-excel.template.macroenabled.12", - xltx = "application/openxmlformats-officedocument.spreadsheetml.template", - xlw = "application/ms-excel", - xm = "audio/xm", - xml = "application/xml", - xo = "application/olpc-sugar", - xop = "application/xop+xml", - xpak = "application/gentoo.xpak", - xpi = "application/xpinstall", - xpl = "application/xproc+xml", - xpm = "image/xpixmap", - xpr = "application/is-xpr", - xps = "application/ms-xpsdocument", - xpw = "application/intercon.formnet", - xpx = "application/intercon.formnet", - xsl = "application/xml", - xslt = "application/xslt+xml", - xsm = "application/syncml+xml", - xspf = "application/xspf+xml", - xul = "application/mozilla.xul+xml", - xvm = "application/xv+xml", - xvml = "application/xv+xml", - xwd = "image/xwindowdump", - xyz = "chemical/xyz", - xz = "application/xz", - yaml = "text/yaml", - yang = "application/yang", - yin = "application/yin+xml", - yml = "text/yaml", - z1 = "application/zmachine", - z2 = "application/zmachine", - z3 = "application/zmachine", - z4 = "application/zmachine", - z5 = "application/zmachine", - z6 = "application/zmachine", - z7 = "application/zmachine", - z8 = "application/zmachine", - zaz = "application/zzazz.deck+xml", - zip = "application/zip", - zir = "application/zul", - zirz = "application/zul", - zmm = "application/handheld-entertainment+xml", - zsh = "text/shellscript", -} - -local options = ya.sync( - function(st) - return { - with_files = st.with_files, - with_exts = st.with_exts, - fallback_file1 = st.fallback_file1, - } - end -) - -local M = {} - -function M:setup(opts) - opts = opts or {} - - self.with_files = opts.with_files - self.with_exts = opts.with_exts - self.fallback_file1 = opts.fallback_file1 -end - -function M:fetch(job) - local opts = options() - local merged_files = ya.dict_merge(FILES, opts.with_files or {}) - local merged_exts = ya.dict_merge(EXTS, opts.with_exts or {}) - - local updates, unknown, state = {}, {}, {} - for i, file in ipairs(job.files) do - if file.cha.is_dummy then - state[i] = false - goto continue - end - - local mime - if file.cha.len == 0 then - mime = "inode/empty" - else - mime = merged_files[(file.url:name() or ""):lower()] - mime = mime or merged_exts[(file.url:ext() or ""):lower()] - end - - if mime then - updates[tostring(file.url)], state[i] = mime, true - elseif opts.fallback_file1 then - unknown[#unknown + 1] = file - else - updates[tostring(file.url)], state[i] = "application/octet-stream", true - end - ::continue:: - end - - if next(updates) then - ya.manager_emit("update_mimes", { updates = updates }) - end - - if #unknown > 0 then - return self.fallback_builtin(job, unknown, state) - end - - return state -end - -function M.fallback_builtin(job, unknown, state) - local indices = {} - for i, f in ipairs(job.files) do - indices[f:hash()] = i - end - - local result = require("mime"):fetch(ya.dict_merge(job, { files = unknown })) - for i, f in ipairs(unknown) do - if type(result) == "table" then - state[indices[f:hash()]] = result[i] - else - state[indices[f:hash()]] = result - end - end - return state -end - -return M diff --git a/modules/home/yazi/plugins/open-with-cmd.yazi/main.lua b/modules/home/yazi/plugins/open-with-cmd.yazi/main.lua deleted file mode 100644 index fee405f..0000000 --- a/modules/home/yazi/plugins/open-with-cmd.yazi/main.lua +++ /dev/null @@ -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, -} diff --git a/modules/home/yazi/plugins/ouch.yazi/LICENSE b/modules/home/yazi/plugins/ouch.yazi/LICENSE deleted file mode 100644 index 3f9d766..0000000 --- a/modules/home/yazi/plugins/ouch.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/ouch.yazi/README.md b/modules/home/yazi/plugins/ouch.yazi/README.md deleted file mode 100644 index fd2ee08..0000000 --- a/modules/home/yazi/plugins/ouch.yazi/README.md +++ /dev/null @@ -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" }, -] -``` diff --git a/modules/home/yazi/plugins/ouch.yazi/main.lua b/modules/home/yazi/plugins/ouch.yazi/main.lua deleted file mode 100644 index 6e5c9a6..0000000 --- a/modules/home/yazi/plugins/ouch.yazi/main.lua +++ /dev/null @@ -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 diff --git a/modules/home/yazi/plugins/restore.yazi/main.lua b/modules/home/yazi/plugins/restore.yazi/main.lua deleted file mode 100644 index 059205d..0000000 --- a/modules/home/yazi/plugins/restore.yazi/main.lua +++ /dev/null @@ -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 diff --git a/modules/home/yazi/plugins/rich-preview.yazi/main.lua b/modules/home/yazi/plugins/rich-preview.yazi/main.lua deleted file mode 100644 index e083fc3..0000000 --- a/modules/home/yazi/plugins/rich-preview.yazi/main.lua +++ /dev/null @@ -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 diff --git a/modules/home/yazi/plugins/smart-paste.yazi/main.lua b/modules/home/yazi/plugins/smart-paste.yazi/main.lua deleted file mode 100644 index 3ca0a22..0000000 --- a/modules/home/yazi/plugins/smart-paste.yazi/main.lua +++ /dev/null @@ -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, -} diff --git a/modules/home/yazi/plugins/smart-tab.yazi/main.lua b/modules/home/yazi/plugins/smart-tab.yazi/main.lua index ae3de58..107f706 100644 --- a/modules/home/yazi/plugins/smart-tab.yazi/main.lua +++ b/modules/home/yazi/plugins/smart-tab.yazi/main.lua @@ -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, } diff --git a/modules/home/yazi/plugins/starship.yazi/LICENSE b/modules/home/yazi/plugins/starship.yazi/LICENSE deleted file mode 100644 index c03ce66..0000000 --- a/modules/home/yazi/plugins/starship.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/starship.yazi/README.md b/modules/home/yazi/plugins/starship.yazi/README.md deleted file mode 100644 index e5d0097..0000000 --- a/modules/home/yazi/plugins/starship.yazi/README.md +++ /dev/null @@ -1,109 +0,0 @@ -# starship.yazi - -Starship prompt plugin for [Yazi](https://github.com/sxyazi/yazi) - - - -## 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`: - -
-Click to expand - -```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 -``` - -
- -> [!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) diff --git a/modules/home/yazi/plugins/starship.yazi/main.lua b/modules/home/yazi/plugins/starship.yazi/main.lua deleted file mode 100644 index 4048508..0000000 --- a/modules/home/yazi/plugins/starship.yazi/main.lua +++ /dev/null @@ -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, -} diff --git a/modules/home/yazi/plugins/starship.yazi/stylua.toml b/modules/home/yazi/plugins/starship.yazi/stylua.toml deleted file mode 100644 index 4bcc241..0000000 --- a/modules/home/yazi/plugins/starship.yazi/stylua.toml +++ /dev/null @@ -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 diff --git a/modules/home/yazi/plugins/toggle-view.yazi/LICENSE b/modules/home/yazi/plugins/toggle-view.yazi/LICENSE deleted file mode 100644 index c85eb72..0000000 --- a/modules/home/yazi/plugins/toggle-view.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/toggle-view.yazi/README.md b/modules/home/yazi/plugins/toggle-view.yazi/README.md deleted file mode 100644 index 73d4d53..0000000 --- a/modules/home/yazi/plugins/toggle-view.yazi/README.md +++ /dev/null @@ -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 = "", run = "plugin toggle-view --args=parent", desc = "Toggle parent" }, - { on = "", run = "plugin toggle-view --args=current", desc = "Toggle current" }, - { on = "", 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. - diff --git a/modules/home/yazi/plugins/toggle-view.yazi/main.lua b/modules/home/yazi/plugins/toggle-view.yazi/main.lua deleted file mode 100644 index 7078681..0000000 --- a/modules/home/yazi/plugins/toggle-view.yazi/main.lua +++ /dev/null @@ -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 } diff --git a/modules/home/yazi/plugins/what-size.yazi/main.lua b/modules/home/yazi/plugins/what-size.yazi/main.lua deleted file mode 100644 index e84e1c1..0000000 --- a/modules/home/yazi/plugins/what-size.yazi/main.lua +++ /dev/null @@ -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, -} diff --git a/modules/home/yazi/plugins/yatline-symlink.yazi/LICENSE b/modules/home/yazi/plugins/yatline-symlink.yazi/LICENSE deleted file mode 100644 index 0c37e85..0000000 --- a/modules/home/yazi/plugins/yatline-symlink.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/yatline-symlink.yazi/README.md b/modules/home/yazi/plugins/yatline-symlink.yazi/README.md deleted file mode 100644 index c138a10..0000000 --- a/modules/home/yazi/plugins/yatline-symlink.yazi/README.md +++ /dev/null @@ -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" -} -``` diff --git a/modules/home/yazi/plugins/yatline-symlink.yazi/main.lua b/modules/home/yazi/plugins/yatline-symlink.yazi/main.lua deleted file mode 100644 index a049e5a..0000000 --- a/modules/home/yazi/plugins/yatline-symlink.yazi/main.lua +++ /dev/null @@ -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 } diff --git a/modules/home/yazi/plugins/yatline.yazi/LICENSE b/modules/home/yazi/plugins/yatline.yazi/LICENSE deleted file mode 100644 index 6374a66..0000000 --- a/modules/home/yazi/plugins/yatline.yazi/LICENSE +++ /dev/null @@ -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. diff --git a/modules/home/yazi/plugins/yatline.yazi/README.md b/modules/home/yazi/plugins/yatline.yazi/README.md deleted file mode 100644 index 6e38134..0000000 --- a/modules/home/yazi/plugins/yatline.yazi/README.md +++ /dev/null @@ -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) diff --git a/modules/home/yazi/plugins/yatline.yazi/main.lua b/modules/home/yazi/plugins/yatline.yazi/main.lua deleted file mode 100644 index 712ae14..0000000 --- a/modules/home/yazi/plugins/yatline.yazi/main.lua +++ /dev/null @@ -1,1312 +0,0 @@ ---- @diagnostic disable: undefined-global, undefined-field ---- @alias Mode Mode Comes from Yazi. ---- @alias Rect Rect Comes from Yazi. ---- @alias Paragraph Paragraph Comes from Yazi. ---- @alias Line Line Comes from Yazi. ---- @alias Span Span Comes from Yazi. ---- @alias Color Color Comes from Yazi. ---- @alias Config Config The config used for setup. ---- @alias Coloreds Coloreds The array returned by colorizer in {{string, Color}, {string, Color} ... } format ---- @alias Side # [ LEFT ... RIGHT ] ---- | `enums.LEFT` # The left side of either the header-line or status-line. [ LEFT ... ] ---- | `enums.RIGHT` # The right side of either the header-line or status-line. [ ... RIGHT] ---- @alias SeparatorType ---- | `enums.OUTER` # Separators on the outer side of sections. [ c o | c o | c o ... ] or [ ... o c | o c | o c ] ---- | `enums.INNER` # Separators on the inner side of sections. [ c i c | c i c | c i c ... ] or [ ... c i c | c i c | c i c ] ---- @alias ComponentType ---- | `enums.A` # Components on the first section. [ A | | ... ] or [ ... | | A ] ---- | `enums.B` # Components on the second section. [ | B | ... ] or [ ... | B | ] ---- | `enums.C` # Components on the third section. [ | | C ... ] or [ ... C | | ] - ---==================-- --- Type Declaration -- ---==================-- - -Yatline = {} - -local Side = { LEFT = 0, RIGHT = 1 } -local SeparatorType = { OUTER = 0, INNER = 1 } -local ComponentType = { A = 0, B = 1, C = 2 } - ---=========================-- --- Variable Initialization -- ---=========================-- - -local section_separator_open -local section_separator_close - -local inverse_separator_open -local inverse_separator_close - -local part_separator_open -local part_separator_close - -local separator_style = { bg = nil, fg = nil } - -local style_a -local style_b -local style_c - -local style_a_normal_bg -local style_a_select_bg -local style_a_un_set_bg - -local permissions_t_fg -local permissions_r_fg -local permissions_w_fg -local permissions_x_fg -local permissions_s_fg - -local tab_width - -local selected_icon -local copied_icon -local cut_icon - -local selected_fg -local copied_fg -local cut_fg - -local task_total_icon -local task_succ_icon -local task_fail_icon -local task_found_icon -local task_processed_icon - -local task_total_fg -local task_succ_fg -local task_fail_fg -local task_found_fg -local task_processed_fg - -local show_background - -local section_order = { "section_a", "section_b", "section_c" } - ---=================-- --- Component Setup -- ---=================-- - ---- Sets the background of style_a according to the tab's mode. ---- @param mode Mode The mode of the active tab. ---- @see cx.active.mode To get the active tab's mode. -local function set_mode_style(mode) - if mode.is_select then - style_a.bg = style_a_select_bg - elseif mode.is_unset then - style_a.bg = style_a_un_set_bg - else - style_a.bg = style_a_normal_bg - end -end - ---- Sets the style of the component according to the its type. ---- @param component Span Component that will be styled. ---- @param component_type ComponentType Which section component will be in [ a | b | c ]. ---- @see Style To see how to style, in Yazi's documentation. -local function set_component_style(component, component_type) - if component_type == ComponentType.A then - component:style(style_a):bold() - elseif component_type == ComponentType.B then - component:style(style_b) - else - component:style(style_c) - end -end - ---- Connects component to a separator. ---- @param component Span Component that will be connected to separator. ---- @param side Side Left or right side of the either header-line or status-line. ---- @param separator_type SeparatorType Where will there be a separator in the section. ---- @return Line line A Line which has component and separator. -local function connect_separator(component, side, separator_type) - local open, close - if - separator_type == SeparatorType.OUTER and not (separator_style.bg == "reset" and separator_style.fg == "reset") - then - open = ui.Span(section_separator_open) - close = ui.Span(section_separator_close) - - if separator_style.fg == "reset" then - if separator_style.bg ~= "reset" and separator_style.bg ~= nil then - open = ui.Span(inverse_separator_open) - close = ui.Span(inverse_separator_close) - - separator_style.fg, separator_style.bg = separator_style.bg, separator_style.fg - else - return ui.Line({ component }) - end - end - else - open = ui.Span(part_separator_open) - close = ui.Span(part_separator_close) - end - - open:style(separator_style) - close:style(separator_style) - - if side == Side.LEFT then - return ui.Line({ component, close }) - else - return ui.Line({ open, component }) - end -end - ---==================-- --- Helper Functions -- ---==================-- - ---- Gets the file name from given file extension. ---- @param file_name string The name of a file whose extension will be taken. ---- @return string file_extension Extension of a file. -local function get_file_extension(file_name) - local extension = file_name:match("^.+%.(.+)$") - - if extension == nil or extension == "" then - return "null" - else - return extension - end -end - ---- Reverse the order of given array ---- @param array Line Array which wants to be reversed. ---- @return table reversed Reversed ordered given array. -local function reverse_order(array) - local reversed = {} - for i = #array, 1, -1 do - table.insert(reversed, array[i]) - end - - return reversed -end - ---- the number of characters in a UTF-8 string ---- @param s string The string to process. ---- @return integer The number of characters in the string. -local function utf8len(s) - -- count the number of non-continuing bytes - return select(2, s:gsub("[^\128-\193]", "")) -end - ---- like string.sub() but i, j are utf8 strings ---- a utf8-safe string.sub() ---- @param s string The string to process. ---- @param i integer The start position. ---- @param j integer The end position. ---- @return string The substring. -local function utf8sub(s, i, j) - -- pattern for matching UTF-8 characters - local pattern = "[%z\1-\127\194-\244][\128-\191]*" - - -- helper function for position calculation - --- @param pos integer The position of the character. - --- @param len integer The length of the string. - --- @return integer The relative position of the character. - local function posrelat(pos, len) - if pos < 0 then - pos = len + pos + 1 - end - return pos - end - - -- helper function to iterate over UTF-8 chars - local function chars(_s, no_subs) - local function map(f) - local _i = 0 - if no_subs then - for b, e in _s:gmatch("()" .. pattern .. "()") do - _i = _i + 1 - local c = e - b - f(_i, c, b) - end - else - for b, c in _s:gmatch("()(" .. pattern .. ")") do - _i = _i + 1 - f(_i, c, b) - end - end - end - return coroutine.wrap(function() - return map(coroutine.yield) - end) - end - - local l = utf8len(s) - - i = posrelat(i, l) - j = j and posrelat(j, l) or l - - if i < 1 then - i = 1 - end - if j > l then - j = l - end - - if i > j then - return "" - end - - local diff = j - i - local iter = chars(s, true) - - -- advance up to i - for _ = 1, i - 1 do - iter() - end - - local c, b = select(2, iter()) - - -- becareful with the edge case of empty string - if not b then - return "" - end - - -- i and j are the same, single-character sub - if diff == 0 then - return string.sub(s, b, b + c - 1) - end - - i = b - - -- advance up to j - for _ = 1, diff - 1 do - iter() - end - - c, b = select(2, iter()) - - return string.sub(s, i, b + c - 1) -end - ---- Trims the filename if it is longer than the max_length. ---- @param filename string The name of a file which will be trimmed. ---- @param max_length integer Maximum length of the filename. ---- @param trim_length integer Length of the trimmed filename. ---- @return string trimmed_filename Trimmed filename. -local function trim_filename(filename, max_length, trim_length) - if not max_length or not trim_length then - return filename - end - - -- Count UTF-8 characters - local len = utf8len(filename) - - if len <= max_length then - return filename - end - - if len <= trim_length * 2 then - return filename - end - - return utf8sub(filename, 1, trim_length) .. "..." .. utf8sub(filename, len - trim_length + 1, len) -end - ---========================-- --- Component String Group -- ---========================-- - -Yatline.string = {} -Yatline.string.get = {} -Yatline.string.has_separator = true - ---- Creates a component from given string according to other parameters. ---- @param string string The text which will be shown inside of the component. ---- @param component_type ComponentType Which section component will be in [ a | b | c ]. ---- @return Line line Customized Line which follows desired style of the parameters. ---- @see set_mode_style To know how mode style selected. ---- @see set_component_style To know how component style applied. -function Yatline.string.create(string, component_type) - local span = ui.Span(" " .. string .. " ") - set_mode_style(cx.active.mode) - set_component_style(span, component_type) - - return ui.Line({ span }) -end - ---- Configuration for getting hovered file's name ---- @class HoveredNameConfig ---- @field trimed? boolean Whether to trim the filename if it's too long (default: false) ---- @field max_length? integer Maximum length of the filename (default: 24) ---- @field trim_length? integer Length of each end when trimming (default: 10) ---- @field show_symlink? boolean Whether to show symlink target (default: false) ---- Gets the hovered file's name of the current active tab. ---- @param config? HoveredNameConfig Configuration for getting hovered file's name ---- @return string name Current active tab's hovered file's name -function Yatline.string.get:hovered_name(config) - local hovered = cx.active.current.hovered - if not hovered then - return "" - end - - if not config then - return hovered.name - end - - local trimed = config.trimed or false - local max_length = config.max_length or 24 - local trim_length = config.trim_length or 10 - local show_symlink = config.show_symlink or false - - local link_delimiter = " -> " - local linked = (show_symlink and hovered.link_to ~= nil) and (link_delimiter .. tostring(hovered.link_to)) or "" - - if trimed then - local trimmed_name = trim_filename(hovered.name, max_length, trim_length) - local trimmed_linked = #linked ~= 0 - and link_delimiter .. trim_filename( - string.sub(linked, #link_delimiter + 1, -1), - max_length, - trim_length - ) - or "" - return trimmed_name .. trimmed_linked - else - return hovered.name .. linked - end -end - ---- Configuration for getting hovered file's path ---- @class HoveredPathConfig ---- @field trimed? boolean Whether to trim the file path if it's too long (default: false) ---- @field max_length? integer Maximum length of the file path (default: 24) ---- @field trim_length? integer Length of each end when trimming (default: 10) ---- Gets the hovered file's path of the current active tab. ---- @param config? HoveredPathConfig Configuration for getting hovered file's path ---- @return string path Current active tab's hovered file's path. -function Yatline.string.get:hovered_path(config) - local hovered = cx.active.current.hovered - if not hovered then - return "" - end - - if not config then - return ya.readable_path(tostring(hovered.url)) - end - - local trimed = config.trimed or false - local max_length = config.max_length or 24 - local trim_length = config.trim_length or 10 - - if trimed then - return trim_filename(ya.readable_path(tostring(hovered.url)), max_length, trim_length) - else - return ya.readable_path(tostring(hovered.url)) - end -end - ---- Gets the hovered file's size of the current active tab. ---- @return string size Current active tab's hovered file's size. -function Yatline.string.get:hovered_size() - local hovered = cx.active.current.hovered - if hovered then - return ya.readable_size(hovered:size() or hovered.cha.len) - else - return "" - end -end - ---- Gets the hovered file's path of the current active tab. ---- @return string mime Current active tab's hovered file's mime. -function Yatline.string.get:hovered_mime() - local hovered = cx.active.current.hovered - if hovered then - return hovered:mime() - else - return "" - end -end - ---- Gets the hovered file's user and group ownership of the current active tab. ---- @return string ownership Current active tab's hovered file's user and group ownership. -function Yatline.string.get:hovered_ownership() - local hovered = cx.active.current.hovered - - if hovered then - return ya.user_name(hovered.cha.uid) .. ":" .. ya.group_name(hovered.cha.gid) - else - return "" - end -end - ---- Gets the hovered file's extension of the current active tab. ---- @param show_icon boolean Whether or not an icon will be shown. ---- @return string file_extension Current active tab's hovered file's extension. -function Yatline.string.get:hovered_file_extension(show_icon) - local hovered = cx.active.current.hovered - - if hovered then - local cha = hovered.cha - - local name - if cha.is_dir then - name = "dir" - else - name = get_file_extension(hovered.url:name()) - end - - if show_icon then - local icon = hovered:icon().text - return icon .. " " .. name - else - return name - end - else - return "" - end -end - ---- Configuration for getting curent active tab's path ---- @class TabPathConfig ---- @field trimed? boolean Whether to trim the current active tab's path if it's too long (default: false) ---- @field max_length? integer Maximum length of the current active tab's path (default: 24) ---- @field trim_length? integer Length of each end when trimming (default: 10) ---- Gets the path of the current active tab. ---- @param config? TabPathConfig Configuration for getting current active tab's path ---- @return string path Current active tab's path. -function Yatline.string.get:tab_path(config) - local cwd = cx.active.current.cwd - local filter = cx.active.current.files.filter - - local search = cwd.is_search and string.format(" (search: %s", cwd:frag()) or "" - - local suffix - if not filter then - suffix = search == "" and search or search .. ")" - elseif search == "" then - suffix = string.format(" (filter: %s)", tostring(filter)) - else - suffix = string.format("%s, filter: %s)", search, tostring(filter)) - end - - if not config then - return ya.readable_path(tostring(cwd)) .. suffix - end - - local trimed = config.trimed or false - local max_length = config.max_length or 24 - local trim_length = config.trim_length or 10 - - if trimed then - return trim_filename(ya.readable_path(tostring(cwd)), max_length, trim_length) .. suffix - else - return ya.readable_path(tostring(cwd)) .. suffix - end -end - ---- Gets the mode of active tab. ---- @return string mode Active tab's mode. -function Yatline.string.get:tab_mode() - local mode = tostring(cx.active.mode):upper() - if mode == "UNSET" then - mode = "UN-SET" - end - - return mode -end - ---- Gets the number of files in the current active tab. ---- @return string num_files Number of files in the current active tab. -function Yatline.string.get:tab_num_files() - return tostring(#cx.active.current.files) -end - ---- Gets the cursor position in the current active tab. ---- @return string cursor_position Current active tab's cursor position. -function Yatline.string.get:cursor_position() - local cursor = cx.active.current.cursor - local length = #cx.active.current.files - - if length ~= 0 then - return string.format(" %2d/%-2d", cursor + 1, length) - else - return "0" - end -end - ---- Gets the cursor position as percentage which is according to the number of files inside of current active tab. ---- @return string percentage Percentage of current active tab's cursor position and number of percentages. -function Yatline.string.get:cursor_percentage() - local percentage = 0 - local cursor = cx.active.current.cursor - local length = #cx.active.current.files - if cursor ~= 0 and length ~= 0 then - percentage = math.floor((cursor + 1) * 100 / length) - end - - if percentage == 0 then - return " Top " - elseif percentage == 100 then - return " Bot " - else - return string.format("%3d%% ", percentage) - end -end - ---- Gets the local date or time values. ---- @param format string Format for giving desired date or time values. ---- @return string date Date or time values. ---- @see os.date To see how format works. -function Yatline.string.get:date(format) - return tostring(os.date(format)) -end - ---======================-- --- Component Line Group -- ---======================-- - -Yatline.line = {} -Yatline.line.get = {} -Yatline.line.has_separator = false - ---- To follow component group naming and functions, returns the given line without any changes. ---- @param line Line The line already pre-defined. ---- @param component_type ComponentType Which section component will be in [ a | b | c ]. Will not be used. ---- @return Line line The given line as an input. -function Yatline.line.create(line, component_type) - return line -end - ---- Creates and returns line component for tabs. ---- @param side Side Left or right side of the either header-line or status-line. ---- @return Line line Customized Line which contains tabs. ---- @see set_mode_style To know how mode style selected. ---- @see set_component_style To know how component style applied. ---- @see connect_separator To know how component and separator connected. -function Yatline.line.get:tabs(side) - local tabs = #cx.tabs - local lines = {} - - local in_side - if side == "left" then - in_side = Side.LEFT - else - in_side = Side.RIGHT - end - - for i = 1, tabs do - local text = i - if tab_width > 2 then - text = ya.truncate(text .. " " .. cx.tabs[i]:name(), { max = tab_width }) - end - - separator_style = { bg = nil, fg = nil } - if i == cx.tabs.idx then - local span = ui.Span(" " .. text .. " ") - set_mode_style(cx.tabs[i].mode) - set_component_style(span, ComponentType.A) - - if style_a.bg ~= "reset" or show_background then - separator_style.fg = style_a.bg - if show_background then - separator_style.bg = style_c.bg - end - - lines[#lines + 1] = connect_separator(span, in_side, SeparatorType.OUTER) - else - separator_style.fg = style_a.fg - - lines[#lines + 1] = connect_separator(span, in_side, SeparatorType.INNER) - end - else - local span = ui.Span(" " .. text .. " ") - if show_background then - set_component_style(span, ComponentType.C) - else - span:style({ fg = style_c.fg }) - end - - if i == cx.tabs.idx - 1 then - set_mode_style(cx.tabs[i + 1].mode) - - local open, close - if style_a.bg ~= "reset" or (show_background and style_c.bg ~= "reset") then - if not show_background or (show_background and style_c.bg == "reset") then - separator_style.fg = style_a.bg - if show_background then - separator_style.bg = style_c.bg - end - - open = ui.Span(inverse_separator_open) - close = ui.Span(inverse_separator_close) - else - separator_style.bg = style_a.bg - if show_background then - separator_style.fg = style_c.bg - end - - open = ui.Span(section_separator_open) - close = ui.Span(section_separator_close) - end - else - separator_style.fg = style_c.fg - - open = ui.Span(part_separator_open) - close = ui.Span(part_separator_close) - end - - open:style(separator_style) - close:style(separator_style) - - if in_side == Side.LEFT then - lines[#lines + 1] = ui.Line({ span, close }) - else - lines[#lines + 1] = ui.Line({ open, span }) - end - else - separator_style.fg = style_c.fg - if show_background then - separator_style.bg = style_c.bg - end - - lines[#lines + 1] = connect_separator(span, in_side, SeparatorType.INNER) - end - end - end - - if in_side == Side.RIGHT then - local lines_in_right = {} - for i = #lines, 1, -1 do - lines_in_right[#lines_in_right + 1] = lines[i] - end - - return ui.Line(lines_in_right) - else - return ui.Line(lines) - end -end - ---==========================-- --- Component Coloreds Group -- ---==========================-- - -Yatline.coloreds = {} -Yatline.coloreds.get = {} -Yatline.coloreds.has_separator = true - ---- Creates a component from given Coloreds according to other parameters. ---- The component it created, can contain multiple strings with different foreground color. ---- @param coloreds Coloreds The array which contains an array which contains text which will be shown inside of the component and its foreground color. ---- @param component_type ComponentType Which section component will be in [ a | b | c ]. ---- @return Line line Customized Line which follows desired style of the parameters. ---- @see set_mode_style To know how mode style selected. ---- @see set_component_style To know how component style applied. -function Yatline.coloreds.create(coloreds, component_type) - set_mode_style(cx.active.mode) - - local spans = {} - for i, colored in ipairs(coloreds) do - local span = ui.Span(colored[1]) - set_component_style(span, component_type) - span:fg(colored[2]) - - spans[i] = span - end - - return ui.Line(spans) -end - ---- Gets the hovered file's permissions of the current active tab. ---- @return Coloreds coloreds Current active tab's hovered file's permissions -function Yatline.coloreds.get:permissions() - local hovered = cx.active.current.hovered - - if hovered then - local perm = hovered.cha:perm() - - if perm then - local coloreds = {} - coloreds[1] = { " ", "black" } - - for i = 1, #perm do - local c = perm:sub(i, i) - - local fg = permissions_t_fg - if c == "-" then - fg = permissions_s_fg - elseif c == "r" then - fg = permissions_r_fg - elseif c == "w" then - fg = permissions_w_fg - elseif c == "x" or c == "s" or c == "S" or c == "t" or c == "T" then - fg = permissions_x_fg - end - - coloreds[i + 1] = { c, fg } - end - - coloreds[#perm + 2] = { " ", "black" } - - return coloreds - else - return "" - end - else - return "" - end -end - ---- Gets the number of selected and yanked files of the active tab. ---- @return Coloreds coloreds Active tab's number of selected and yanked files. -function Yatline.coloreds.get:count() - local num_yanked = #cx.yanked - local num_selected = #cx.active.selected - - local yanked_fg, yanked_icon - if cx.yanked.is_cut then - yanked_fg = cut_fg - yanked_icon = cut_icon - else - yanked_fg = copied_fg - yanked_icon = copied_icon - end - - local coloreds = { - { string.format(" %s %d ", selected_icon, num_selected), selected_fg }, - { string.format(" %s %d ", yanked_icon, num_yanked), yanked_fg }, - } - - return coloreds -end - ---- Gets the number of task states. ---- @return Coloreds coloreds Number of task states. -function Yatline.coloreds.get:task_states() - local tasks = cx.tasks.progress - - local coloreds = { - { string.format(" %s %d ", task_total_icon, tasks.total), task_total_fg }, - { string.format(" %s %d ", task_succ_icon, tasks.succ), task_succ_fg }, - { string.format(" %s %d ", task_fail_icon, tasks.fail), task_fail_fg }, - } - - return coloreds -end - ---- Gets the number of task workloads. ---- @return Coloreds coloreds Number of task workloads. -function Yatline.coloreds.get:task_workload() - local tasks = cx.tasks.progress - - local coloreds = { - { string.format(" %s %d ", task_found_icon, tasks.found), task_found_fg }, - { string.format(" %s %d ", task_processed_icon, tasks.processed), task_processed_fg }, - } - - return coloreds -end - ---- Gets colored which contains string based component's string and desired foreground color. ---- @param component_name string String based component's name. ---- @param fg Color Desired foreground color. ---- @param params? table Array of parameters of string based component. It is optional. ---- @return Coloreds coloreds Array of solely array of string based component's string and desired foreground color. -function Yatline.coloreds.get:string_based_component(component_name, fg, params) - local getter = Yatline.string.get[component_name] - - if getter then - local output - if params then - output = getter(Yatline.string.get, table.unpack(params)) - else - output = getter() - end - - if output ~= nil and output ~= "" then - return { { " " .. output .. " ", fg } } - else - return "" - end - else - return "" - end -end - ---===============-- --- Configuration -- ---===============-- - ---- Configure separators if it is need to be added to the components. ---- Connects them with each component. ---- @param section_components table Array of components in one of the sections. ---- @param component_type ComponentType Which section component will be in [ a | b | c ]. ---- @param in_side Side Left or right side of the either header-line or status-line. ---- @param num_section_b_components integer Number of components in section-b. ---- @param num_section_c_components integer Number of components in section-c. ---- @return table section_line_components Array of line components whether or not connected with separators. ---- @see connect_separator To know how component and separator connected. -local function config_components_separators( - section_components, - component_type, - in_side, - num_section_b_components, - num_section_c_components -) - local num_section_components = #section_components - local section_line_components = {} - for i, component in ipairs(section_components) do - if component[2] == true then - separator_style = { bg = nil, fg = nil } - - local separator_type - if i ~= num_section_components then - if component_type == ComponentType.A then - separator_style = style_a - elseif component_type == ComponentType.B then - separator_style = style_b - else - separator_style = style_c - end - - separator_type = SeparatorType.INNER - else - if component_type == ComponentType.A then - separator_style.fg = style_a.bg - elseif component_type == ComponentType.B then - separator_style.fg = style_b.bg - else - separator_style.fg = style_c.bg - end - - if component_type == ComponentType.A and num_section_b_components ~= 0 then - separator_style.bg = style_b.bg - else - if num_section_c_components == 0 or component_type == ComponentType.C then - if show_background then - separator_style.bg = style_c.bg - end - else - separator_style.bg = style_c.bg - end - end - - separator_type = SeparatorType.OUTER - end - - section_line_components[i] = connect_separator(component[1], in_side, separator_type) - else - if in_side == Side.LEFT then - section_line_components[i] = component[1] - else - section_line_components[i] = component[1] - end - end - end - - return section_line_components -end - ---- Leads the given parameters to the other functions. ---- @param section_a_components table Components array whose components are in section-a of either side. ---- @param section_b_components table Components array whose components are in section-b of either side. ---- @param section_c_components table Components array whose components are in section-c of either side. ---- @param in_side Side Left or right side of the either header-line or status-line. ---- @return table section_a_line_components Array of components whose components are connected to separator and are in section-a of either side. ---- @return table section_b_line_components Array of components whose components are connected to separator and are in section-b of either side. ---- @return table section_c_line_components Array of components whose components are connected to separator and are in section-c of either side. ---- @see config_components_separators To know how separators are configured. -local function config_components(section_a_components, section_b_components, section_c_components, in_side) - local num_section_b_components = #section_b_components - local num_section_c_components = #section_c_components - - local section_a_line_components = config_components_separators( - section_a_components, - ComponentType.A, - in_side, - num_section_b_components, - num_section_c_components - ) - local section_b_line_components = config_components_separators( - section_b_components, - ComponentType.B, - in_side, - num_section_b_components, - num_section_c_components - ) - local section_c_line_components = config_components_separators( - section_c_components, - ComponentType.C, - in_side, - num_section_b_components, - num_section_c_components - ) - - return section_a_line_components, section_b_line_components, section_c_line_components -end - ---- Automatically creates and configures either left or right side according to their config. ---- @param side Config Configuration of either left or right side. ---- @return table section_a_components Components array whose components are in section-a of either side. ---- @return table section_b_components Components array whose components are in section-b of either side. ---- @return table section_c_components Components array whose components are in section-c of either side. -local function config_side(side) - local section_a_components = {} - local section_b_components = {} - local section_c_components = {} - - for _, section in ipairs(section_order) do - local components = side[section] - - local in_section, section_components - if section == "section_a" then - in_section = ComponentType.A - section_components = section_a_components - elseif section == "section_b" then - in_section = ComponentType.B - section_components = section_b_components - else - in_section = ComponentType.C - section_components = section_c_components - end - - for _, component in ipairs(components) do - local component_group = Yatline[component.type] - - if component_group then - if component.custom then - section_components[#section_components + 1] = - { component_group.create(component.name, in_section), component_group.has_separator } - else - local getter = component_group.get[component.name] - - if getter then - local output - if component.params then - output = getter(component_group.get, table.unpack(component.params)) - else - output = getter() - end - - if output ~= nil and output ~= "" then - section_components[#section_components + 1] = - { component_group.create(output, in_section), component_group.has_separator } - end - end - end - end - end - end - - return section_a_components, section_b_components, section_c_components -end - ---- Automatically creates and configures either header-line or status-line. ---- @param side Config Configuration of either left or right side. ---- @return table left_components Components array whose components are in left side of the line. ---- @return table right_components Components array whose components are in right side of the line. ---- @see config_side To know how components are gotten from side's config. ---- @see config_components To know how components are configured. -local function config_line(side, in_side) - local section_a_components, section_b_components, section_c_components = config_side(side) - - local section_a_line_components, section_b_line_components, section_c_line_components = - config_components(section_a_components, section_b_components, section_c_components, in_side) - - if in_side == Side.RIGHT then - section_a_line_components = reverse_order(section_a_line_components) - section_b_line_components = reverse_order(section_b_line_components) - section_c_line_components = reverse_order(section_c_line_components) - end - - local section_a_line = ui.Line(section_a_line_components) - local section_b_line = ui.Line(section_b_line_components) - local section_c_line = ui.Line(section_c_line_components) - - if in_side == Side.LEFT then - return ui.Line({ section_a_line, section_b_line, section_c_line }) - else - return ui.Line({ section_c_line, section_b_line, section_a_line }) - end -end - ---- Checks if either header-line or status-line contains components. ---- @param line Config Configuration of either header-line or status-line. ---- @return boolean show_line Returns yes if it contains components, otherwise returns no. -local function show_line(line) - local total_components = 0 - - for _, side in pairs(line) do - for _, section in pairs(side) do - total_components = total_components + #section - end - end - - return total_components ~= 0 -end - ---- Creates and configures paragraph which is used as left or right of either ---- header-line or status-line. ---- @param area Rect The area where paragraph will be placed in. ---- @param line? Line The line which used in paragraph. It is optional. ---- @return Paragraph paragraph Configured parapgraph. -local function config_paragraph(area, line) - local line_array = { line } or {} - if show_background then - return ui.Text(line_array):area(area):style(style_c) - else - return ui.Text(line_array):area(area) - end -end - -return { - setup = function(_, config) - config = config or {} - - tab_width = config.tab_width or 20 - - local component_positions = config.component_positions or { "header", "tab", "status" } - - show_background = config.show_background or false - - local display_header_line = config.display_header_line - if display_header_line == nil then - display_header_line = true - end - - local display_status_line = config.display_status_line - if display_status_line == nil then - display_status_line = true - end - - local header_line = config.header_line - or { - left = { section_a = {}, section_b = {}, section_c = {} }, - right = { section_a = {}, section_b = {}, section_c = {} }, - } - local status_line = config.status_line - or { - left = { section_a = {}, section_b = {}, section_c = {} }, - right = { section_a = {}, section_b = {}, section_c = {} }, - } - - if config.theme then - config = config.theme - end - - if config.section_separator then - section_separator_open = config.section_separator.open - section_separator_close = config.section_separator.close - else - section_separator_open = "" - section_separator_close = "" - end - - if config.inverse_separator then - inverse_separator_open = config.inverse_separator.open - inverse_separator_close = config.inverse_separator.close - else - inverse_separator_open = "" - inverse_separator_close = "" - end - - if config.part_separator then - part_separator_open = config.part_separator.open - part_separator_close = config.part_separator.close - else - part_separator_open = "" - part_separator_close = "" - end - - if config.style_a then - style_a = { bg = config.style_a.bg_mode.normal, fg = config.style_a.fg } - - style_a_normal_bg = config.style_a.bg_mode.normal - style_a_select_bg = config.style_a.bg_mode.select - style_a_un_set_bg = config.style_a.bg_mode.un_set - else - style_a = { bg = "white", fg = "black" } - - style_a_normal_bg = "white" - style_a_select_bg = "brightyellow" - style_a_un_set_bg = "brightred" - end - - style_b = config.style_b or { bg = "brightblack", fg = "brightwhite" } - style_c = config.style_c or { bg = "black", fg = "brightwhite" } - - permissions_t_fg = config.permissions_t_fg or "green" - permissions_r_fg = config.permissions_r_fg or "yellow" - permissions_w_fg = config.permissions_w_fg or "red" - permissions_x_fg = config.permissions_x_fg or "cyan" - permissions_s_fg = config.permissions_s_fg or "white" - - if config.selected then - selected_fg = config.selected.fg - selected_icon = config.selected.icon - else - selected_fg = "yellow" - selected_icon = "󰻭" - end - - if config.copied then - copied_fg = config.copied.fg - copied_icon = config.copied.icon - else - copied_fg = "green" - copied_icon = "" - end - - if config.cut then - cut_icon = config.cut.icon - cut_fg = config.cut.fg - else - cut_icon = "" - cut_fg = "red" - end - - if config.total then - task_total_icon = config.total.icon - task_total_fg = config.total.fg - else - task_total_icon = "󰮍" - task_total_fg = "yellow" - end - - if config.succ then - task_succ_icon = config.succ.icon - task_succ_fg = config.succ.fg - else - task_succ_icon = "" - task_succ_fg = "green" - end - - if config.fail then - task_fail_icon = config.fail.icon - task_fail_fg = config.fail.fg - else - task_fail_icon = "" - task_fail_fg = "red" - end - - if config.found then - task_found_icon = config.found.icon - task_found_fg = config.found.fg - else - task_found_icon = "󰮕" - task_found_fg = "blue" - end - - if config.processed then - task_processed_icon = config.processed.icon - task_processed_fg = config.processed.fg - else - task_processed_icon = "󰐍" - task_processed_fg = "green" - end - - Progress.partial_render = function(self) - local progress = cx.tasks.progress - if progress.total == 0 then - return { config_paragraph(self._area) } - end - - local gauge = ui.Gauge():area(self._area) - if progress.fail == 0 then - gauge = gauge:gauge_style(THEME.status.progress_normal) - else - gauge = gauge:gauge_style(THEME.status.progress_error) - end - - local percent = 99 - if progress.found ~= 0 then - percent = math.min(99, ya.round(progress.processed * 100 / progress.found)) - end - - local left = progress.total - progress.succ - return { - gauge - :percent(percent) - :label(ui.Span(string.format("%3d%%, %d left", percent, left)):style(THEME.status.progress_label)), - } - end - - if display_header_line then - if show_line(header_line) then - Header.redraw = function(self) - local left_line = config_line(header_line.left, Side.LEFT) - local right_line = config_line(header_line.right, Side.RIGHT) - - return { - config_paragraph(self._area, left_line), - ui.Text(right_line):area(self._area):align(ui.Text.RIGHT), - } - end - - Header.children_add = function() - return {} - end - Header.children_remove = function() - return {} - end - end - else - Header.redraw = function() - return {} - end - end - - if display_status_line then - if show_line(status_line) then - Status.redraw = function(self) - local left_line = config_line(status_line.left, Side.LEFT) - local right_line = config_line(status_line.right, Side.RIGHT) - local right_width = right_line:width() - - return { - config_paragraph(self._area, left_line), - ui.Text(right_line):area(self._area):align(ui.Text.RIGHT), - table.unpack(Progress:new(self._area, right_width):redraw()), - } - end - - Status.children_add = function() - return {} - end - Status.children_remove = function() - return {} - end - end - else - Status.redraw = function() - return {} - end - end - - Root.layout = function(self) - local constraints = {} - for _, component in ipairs(component_positions) do - if - (component == "header" and display_header_line) or (component == "status" and display_status_line) - then - table.insert(constraints, ui.Constraint.Length(1)) - elseif component == "tab" then - table.insert(constraints, ui.Constraint.Fill(1)) - end - end - - self._chunks = ui.Layout():direction(ui.Layout.VERTICAL):constraints(constraints):split(self._area) - end - - Root.build = function(self) - local childrens = {} - - local i = 1 - for _, component in ipairs(component_positions) do - if component == "header" and display_header_line then - table.insert(childrens, Header:new(self._chunks[i], cx.active)) - i = i + 1 - elseif component == "tab" then - table.insert(childrens, Tab:new(self._chunks[i], cx.active)) - i = i + 1 - elseif component == "status" and display_status_line then - table.insert(childrens, Status:new(self._chunks[i], cx.active)) - i = i + 1 - end - end - - self._children = childrens - end - end, -} diff --git a/modules/home/yazi/plugins/yazi-plugins b/modules/home/yazi/plugins/yazi-plugins deleted file mode 160000 index 9a09505..0000000 --- a/modules/home/yazi/plugins/yazi-plugins +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9a095057d698aaaedc4dd23d638285bd3fd647e9