From 09065ab75652e362d0b2b8a250ceef2ea3c66df6 Mon Sep 17 00:00:00 2001 From: Hydroxycarbamide Date: Thu, 10 Apr 2025 15:28:26 +0200 Subject: [PATCH 1/2] Update yazi and its plugins --- dot_config/yazi/keymap.toml | 13 +- dot_config/yazi/package.toml | 27 +- .../full-border.yazi/readonly_main.lua | 6 +- .../yazi/plugins/git.yazi/readonly_README.md | 38 +- .../yazi/plugins/git.yazi/readonly_main.lua | 179 +-- .../plugins/lazygit.yazi/readonly_main.lua | 4 +- .../plugins/mime-ext.yazi/readonly_LICENSE | 21 + .../plugins/mime-ext.yazi/readonly_README.md | 56 + .../plugins/mime-ext.yazi/readonly_main.lua | 1126 +++++++++++++++++ .../yazi/plugins/mount.yazi/readonly_LICENSE | 21 + .../plugins/mount.yazi/readonly_README.md | 51 + .../yazi/plugins/mount.yazi/readonly_main.lua | 285 +++++ .../plugins/vcs-files.yazi/readonly_LICENSE | 21 + .../plugins/vcs-files.yazi/readonly_README.md | 29 + .../plugins/vcs-files.yazi/readonly_main.lua | 33 + dot_config/yazi/yazi.toml | 8 +- 16 files changed, 1805 insertions(+), 113 deletions(-) create mode 100644 dot_config/yazi/plugins/mime-ext.yazi/readonly_LICENSE create mode 100644 dot_config/yazi/plugins/mime-ext.yazi/readonly_README.md create mode 100644 dot_config/yazi/plugins/mime-ext.yazi/readonly_main.lua create mode 100644 dot_config/yazi/plugins/mount.yazi/readonly_LICENSE create mode 100644 dot_config/yazi/plugins/mount.yazi/readonly_README.md create mode 100644 dot_config/yazi/plugins/mount.yazi/readonly_main.lua create mode 100644 dot_config/yazi/plugins/vcs-files.yazi/readonly_LICENSE create mode 100644 dot_config/yazi/plugins/vcs-files.yazi/readonly_README.md create mode 100644 dot_config/yazi/plugins/vcs-files.yazi/readonly_main.lua diff --git a/dot_config/yazi/keymap.toml b/dot_config/yazi/keymap.toml index ad4538c..47fda45 100644 --- a/dot_config/yazi/keymap.toml +++ b/dot_config/yazi/keymap.toml @@ -152,7 +152,7 @@ keymap = [ { on = "}", run = "tab_swap 1", desc = "Swap current tab with next tab" }, # Tasks - { on = "w", run = "tasks_show", desc = "Show task manager" }, + { on = "w", run = "tasks:show", desc = "Show task manager" }, # Help { on = "~", run = "help", desc = "Open help" }, @@ -164,6 +164,15 @@ on = [ "g", "i" ] run = "plugin lazygit" desc = "run lazygit" +[[manager.prepend_keymap]] +on = "M" +run = "plugin mount" + +[[manager.prepend_keymap]] +on = [ "g", "c" ] +run = "plugin vcs-files" +desc = "Show Git file changes" + [tasks] keymap = [ @@ -328,7 +337,7 @@ keymap = [ keymap = [ { on = "", run = "close", desc = "Cancel completion" }, { on = "", run = "close --submit", desc = "Submit the completion" }, - { on = "", run = [ "close --submit", "close_input --submit" ], desc = "Submit the completion and input" }, + { on = "", run = [ "close --submit", "input:close --submit" ], desc = "Submit the completion and input" }, { on = "", run = "arrow -1", desc = "Move cursor up" }, { on = "", run = "arrow 1", desc = "Move cursor down" }, diff --git a/dot_config/yazi/package.toml b/dot_config/yazi/package.toml index c984ae9..6ed011f 100644 --- a/dot_config/yazi/package.toml +++ b/dot_config/yazi/package.toml @@ -1,17 +1,32 @@ [[plugin.deps]] use = "yazi-rs/plugins:git" -rev = "5186af7" -hash = "771f18427fb75fb19990ce602bb322f4" +rev = "a1738e8" +hash = "e0ada736ea676c2bbb3ec705a49526ef" [[plugin.deps]] use = "yazi-rs/plugins:full-border" -rev = "5186af7" -hash = "ae9e1d0c6bfd68cdebc98cc684c22b45" +rev = "a1738e8" +hash = "1f3dad061209081a6b04dd6ff2cb06c7" [[plugin.deps]] use = "Lil-Dank/lazygit" -rev = "9f924e3" -hash = "2b0c33928986f126d5c5a4cac31a6b46" +rev = "7a08a09" +hash = "a1fa2b3e1826c3a34804ea8c548e9f80" + +[[plugin.deps]] +use = "yazi-rs/plugins:mime-ext" +rev = "a1738e8" +hash = "5e24c167e9ae9a203a48f2a438b8c705" + +[[plugin.deps]] +use = "yazi-rs/plugins:mount" +rev = "a1738e8" +hash = "dd97eede8e20e59cd2604e8006e470e2" + +[[plugin.deps]] +use = "yazi-rs/plugins:vcs-files" +rev = "a1738e8" +hash = "36405f8781fcaf33ceab24dffd5cea19" [flavor] deps = [] diff --git a/dot_config/yazi/plugins/full-border.yazi/readonly_main.lua b/dot_config/yazi/plugins/full-border.yazi/readonly_main.lua index 058371a..abb1c3e 100644 --- a/dot_config/yazi/plugins/full-border.yazi/readonly_main.lua +++ b/dot_config/yazi/plugins/full-border.yazi/readonly_main.lua @@ -1,4 +1,4 @@ ---- @since 25.2.7 +--- @since 25.2.26 local function setup(_, opts) local type = opts and opts.type or ui.Border.ROUNDED @@ -6,7 +6,7 @@ local function setup(_, opts) Tab.build = function(self, ...) local bar = function(c, x, y) - if x <= 0 or x == self._area.w - 1 then + if x <= 0 or x == self._area.w - 1 or th.mgr.border_symbol ~= "│" then return ui.Bar(ui.Bar.TOP) end @@ -24,7 +24,7 @@ local function setup(_, opts) c[3]:pad(ui.Pad.y(1)), } - local style = THEME.manager.border_style + local style = th.mgr.border_style self._base = ya.list_merge(self._base or {}, { ui.Border(ui.Border.ALL):area(self._area):type(type):style(style), ui.Bar(ui.Bar.RIGHT):area(self._chunks[1]):style(style), diff --git a/dot_config/yazi/plugins/git.yazi/readonly_README.md b/dot_config/yazi/plugins/git.yazi/readonly_README.md index 1054230..4c5b07c 100644 --- a/dot_config/yazi/plugins/git.yazi/readonly_README.md +++ b/dot_config/yazi/plugins/git.yazi/readonly_README.md @@ -1,7 +1,7 @@ # git.yazi > [!NOTE] -> Yazi v25.2.7 or later is required for this plugin to work. +> Yazi v25.2.26 or later is required for this plugin to work. Show the status of Git file changes as linemode in the file list. @@ -39,38 +39,38 @@ run = "git" You can customize the [Style](https://yazi-rs.github.io/docs/plugins/layout#style) of the status sign with: -- `THEME.git.modified` -- `THEME.git.added` -- `THEME.git.untracked` -- `THEME.git.ignored` -- `THEME.git.deleted` -- `THEME.git.updated` +- `th.git.modified` +- `th.git.added` +- `th.git.untracked` +- `th.git.ignored` +- `th.git.deleted` +- `th.git.updated` For example: ```lua -- ~/.config/yazi/init.lua -THEME.git = THEME.git or {} -THEME.git.modified = ui.Style():fg("blue") -THEME.git.deleted = ui.Style():fg("red"):bold() +th.git = th.git or {} +th.git.modified = ui.Style():fg("blue") +th.git.deleted = ui.Style():fg("red"):bold() ``` You can also customize the text of the status sign with: -- `THEME.git.modified_sign` -- `THEME.git.added_sign` -- `THEME.git.untracked_sign` -- `THEME.git.ignored_sign` -- `THEME.git.deleted_sign` -- `THEME.git.updated_sign` +- `th.git.modified_sign` +- `th.git.added_sign` +- `th.git.untracked_sign` +- `th.git.ignored_sign` +- `th.git.deleted_sign` +- `th.git.updated_sign` For example: ```lua -- ~/.config/yazi/init.lua -THEME.git = THEME.git or {} -THEME.git.modified_sign = "M" -THEME.git.deleted_sign = "D" +th.git = th.git or {} +th.git.modified_sign = "M" +th.git.deleted_sign = "D" ``` ## License diff --git a/dot_config/yazi/plugins/git.yazi/readonly_main.lua b/dot_config/yazi/plugins/git.yazi/readonly_main.lua index edd54fc..d8f365a 100644 --- a/dot_config/yazi/plugins/git.yazi/readonly_main.lua +++ b/dot_config/yazi/plugins/git.yazi/readonly_main.lua @@ -1,29 +1,45 @@ ---- @since 25.2.7 +--- @since 25.4.4 -local WIN = ya.target_family() == "windows" -local PATS = { - { "[MT]", 6 }, -- Modified - { "[AC]", 5 }, -- Added - { "?$", 4 }, -- Untracked - { "!$", 3 }, -- Ignored - { "D", 2 }, -- Deleted - { "U", 1 }, -- Updated - { "[AD][AD]", 1 }, -- Updated +local WINDOWS = ya.target_family() == "windows" + +-- The code of supported git status, +-- also used to determine which status to show for directories when they contain different statuses +-- see `bubble_up` +local CODES = { + excluded = 100, -- ignored directory + ignored = 6, -- ignored file + untracked = 5, + modified = 4, + added = 3, + deleted = 2, + updated = 1, + unknown = 0, +} + +local PATTERNS = { + { "!$", CODES.ignored }, + { "?$", CODES.untracked }, + { "[MT]", CODES.modified }, + { "[AC]", CODES.added }, + { "D", CODES.deleted }, + { "U", CODES.updated }, + { "[AD][AD]", CODES.updated }, } local function match(line) local signs = line:sub(1, 2) - for _, p in ipairs(PATS) do - local path - if signs:find(p[1]) then + for _, p in ipairs(PATTERNS) do + local path, pattern, code = nil, p[1], p[2] + if signs:find(pattern) then path = line:sub(4, 4) == '"' and line:sub(5, -2) or line:sub(4) - path = WIN and path:gsub("/", "\\") or path + path = WINDOWS and path:gsub("/", "\\") or path end if not path then elseif path:find("[/\\]$") then - return p[2] == 3 and 30 or p[2], path:sub(1, -2) + -- Mark the ignored directory as `excluded`, so we can process it further within `propagate_down` + return code == CODES.ignored and CODES.excluded or code, path:sub(1, -2) else - return p[2], path + return code, path end end end @@ -44,34 +60,36 @@ local function root(cwd) if cha and (cha.is_dir or is_worktree(next)) then return tostring(cwd) end - cwd = cwd:parent() + cwd = cwd.parent until not cwd end local function bubble_up(changed) local new, empty = {}, Url("") - for k, v in pairs(changed) do - if v ~= 3 and v ~= 30 then - local url = Url(k):parent() + for path, code in pairs(changed) do + if code ~= CODES.ignored then + local url = Url(path).parent while url and url ~= empty do local s = tostring(url) - new[s] = (new[s] or 0) > v and new[s] or v - url = url:parent() + new[s] = (new[s] or CODES.unknown) > code and new[s] or code + url = url.parent end end end return new end -local function propagate_down(ignored, cwd, repo) +local function propagate_down(excluded, cwd, repo) local new, rel = {}, cwd:strip_prefix(repo) - for k, v in pairs(ignored) do - if v == 30 then - if rel:starts_with(k) then - new[tostring(repo:join(rel))] = 30 - elseif cwd == repo:join(k):parent() then - new[k] = 3 - end + for _, path in ipairs(excluded) do + if rel:starts_with(path) then + -- If `cwd` is a subdirectory of an excluded directory, also mark it as `excluded` + new[tostring(cwd)] = CODES.excluded + elseif cwd == repo:join(path).parent then + -- If `path` is a direct subdirectory of `cwd`, mark it as `ignored` + new[path] = CODES.ignored + else + -- Skipping, we only care about `cwd` itself and its direct subdirectories for maximum performance end end return new @@ -80,84 +98,84 @@ end local add = ya.sync(function(st, cwd, repo, changed) st.dirs[cwd] = repo st.repos[repo] = st.repos[repo] or {} - for k, v in pairs(changed) do - if v == 0 then - st.repos[repo][k] = nil - elseif v == 30 then - st.dirs[k] = "" + for path, code in pairs(changed) do + if code == CODES.unknown then + st.repos[repo][path] = nil + elseif code == CODES.excluded then + -- Mark the directory with a special value `excluded` so that it can be distinguished during UI rendering + st.dirs[path] = CODES.excluded else - st.repos[repo][k] = v + st.repos[repo][path] = code end end ya.render() end) local remove = ya.sync(function(st, cwd) - local dir = st.dirs[cwd] - if not dir then + local repo = st.dirs[cwd] + if not repo then return end ya.render() st.dirs[cwd] = nil - if not st.repos[dir] then + if not st.repos[repo] then return end for _, r in pairs(st.dirs) do - if r == dir then + if r == repo then return end end - st.repos[dir] = nil + st.repos[repo] = nil end) local function setup(st, opts) - st.dirs = {} - st.repos = {} + st.dirs = {} -- Mapping between a directory and its corresponding repository + st.repos = {} -- Mapping between a repository and the status of each of its files opts = opts or {} opts.order = opts.order or 1500 - -- Chosen by ChatGPT fairly, PRs are welcome to adjust them - local t = THEME.git or {} + local t = th.git or {} local styles = { - [6] = t.modified and ui.Style(t.modified) or ui.Style():fg("#ffa500"), - [5] = t.added and ui.Style(t.added) or ui.Style():fg("#32cd32"), - [4] = t.untracked and ui.Style(t.untracked) or ui.Style():fg("#a9a9a9"), - [3] = t.ignored and ui.Style(t.ignored) or ui.Style():fg("#696969"), - [2] = t.deleted and ui.Style(t.deleted) or ui.Style():fg("#ff4500"), - [1] = t.updated and ui.Style(t.updated) or ui.Style():fg("#1e90ff"), + [CODES.ignored] = t.ignored and ui.Style(t.ignored) or ui.Style():fg("darkgray"), + [CODES.untracked] = t.untracked and ui.Style(t.untracked) or ui.Style():fg("magenta"), + [CODES.modified] = t.modified and ui.Style(t.modified) or ui.Style():fg("yellow"), + [CODES.added] = t.added and ui.Style(t.added) or ui.Style():fg("green"), + [CODES.deleted] = t.deleted and ui.Style(t.deleted) or ui.Style():fg("red"), + [CODES.updated] = t.updated and ui.Style(t.updated) or ui.Style():fg("yellow"), } local signs = { - [6] = t.modified_sign and t.modified_sign or "", - [5] = t.added_sign and t.added_sign or "", - [4] = t.untracked_sign and t.untracked_sign or "", - [3] = t.ignored_sign and t.ignored_sign or "", - [2] = t.deleted_sign and t.deleted_sign or "", - [1] = t.updated_sign and t.updated_sign or "U", + [CODES.ignored] = t.ignored_sign or "", + [CODES.untracked] = t.untracked_sign or "?", + [CODES.modified] = t.modified_sign or "", + [CODES.added] = t.added_sign or "", + [CODES.deleted] = t.deleted_sign or "", + [CODES.updated] = t.updated_sign or "", } Linemode:children_add(function(self) local url = self._file.url - local dir = st.dirs[tostring(url:parent())] - local change - if dir then - change = dir == "" and 3 or st.repos[dir][tostring(url):sub(#dir + 2)] + local repo = st.dirs[tostring(url.base)] + local code + if repo then + code = repo == CODES.excluded and CODES.ignored or st.repos[repo][tostring(url):sub(#repo + 2)] end - if not change or signs[change] == "" then + if not code or signs[code] == "" then return "" - elseif self._file:is_hovered() then - return ui.Line { " ", signs[change] } + elseif self._file.is_hovered then + return ui.Line { " ", signs[code] } else - return ui.Line { " ", ui.Span(signs[change]):style(styles[change]) } + return ui.Line { " ", ui.Span(signs[code]):style(styles[code]) } end end, opts.order) end local function fetch(_, job) - local cwd = job.files[1].url:parent() + local cwd = job.files[1].url.base local repo = root(cwd) if not repo then remove(tostring(cwd)) @@ -165,8 +183,8 @@ local function fetch(_, job) end local paths = {} - for _, f in ipairs(job.files) do - paths[#paths + 1] = tostring(f.url) + for _, file in ipairs(job.files) do + paths[#paths + 1] = tostring(file.url) end -- stylua: ignore @@ -180,27 +198,28 @@ local function fetch(_, job) return true, Err("Cannot spawn `git` command, error: %s", err) end - local changed, ignored = {}, {} + local changed, excluded = {}, {} for line in output.stdout:gmatch("[^\r\n]+") do - local sign, path = match(line) - if sign == 30 then - ignored[path] = sign + local code, path = match(line) + if code == CODES.excluded then + excluded[#excluded + 1] = path else - changed[path] = sign + changed[path] = code end end if job.files[1].cha.is_dir then ya.dict_merge(changed, bubble_up(changed)) - ya.dict_merge(changed, propagate_down(ignored, cwd, Url(repo))) - else - ya.dict_merge(changed, propagate_down(ignored, cwd, Url(repo))) + end + ya.dict_merge(changed, propagate_down(excluded, cwd, Url(repo))) + + -- Reset the status of any files that don't appear in the output of `git status` to `unknown`, + -- so that cleaning up outdated statuses from `st.repos` + for _, path in ipairs(paths) do + local s = path:sub(#repo + 2) + changed[s] = changed[s] or CODES.unknown end - for _, p in ipairs(paths) do - local s = p:sub(#repo + 2) - changed[s] = changed[s] or 0 - end add(tostring(cwd), repo, changed) return false diff --git a/dot_config/yazi/plugins/lazygit.yazi/readonly_main.lua b/dot_config/yazi/plugins/lazygit.yazi/readonly_main.lua index a5925ea..32d7f18 100644 --- a/dot_config/yazi/plugins/lazygit.yazi/readonly_main.lua +++ b/dot_config/yazi/plugins/lazygit.yazi/readonly_main.lua @@ -4,7 +4,7 @@ return { if output.stderr ~= "" then ya.notify({ title = "lazygit", - content = "Not in a git directory", + content = "Not in a git directory\nError: " .. output.stderr, level = "warn", timeout = 5, }) @@ -28,4 +28,4 @@ return { end end end, -} \ No newline at end of file +} diff --git a/dot_config/yazi/plugins/mime-ext.yazi/readonly_LICENSE b/dot_config/yazi/plugins/mime-ext.yazi/readonly_LICENSE new file mode 100644 index 0000000..fb5b1d6 --- /dev/null +++ b/dot_config/yazi/plugins/mime-ext.yazi/readonly_LICENSE @@ -0,0 +1,21 @@ +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/dot_config/yazi/plugins/mime-ext.yazi/readonly_README.md b/dot_config/yazi/plugins/mime-ext.yazi/readonly_README.md new file mode 100644 index 0000000..e771576 --- /dev/null +++ b/dot_config/yazi/plugins/mime-ext.yazi/readonly_README.md @@ -0,0 +1,56 @@ +# 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/dot_config/yazi/plugins/mime-ext.yazi/readonly_main.lua b/dot_config/yazi/plugins/mime-ext.yazi/readonly_main.lua new file mode 100644 index 0000000..c3e0638 --- /dev/null +++ b/dot_config/yazi/plugins/mime-ext.yazi/readonly_main.lua @@ -0,0 +1,1126 @@ +--- @since 25.4.4 + +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.mgr_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/dot_config/yazi/plugins/mount.yazi/readonly_LICENSE b/dot_config/yazi/plugins/mount.yazi/readonly_LICENSE new file mode 100644 index 0000000..fb5b1d6 --- /dev/null +++ b/dot_config/yazi/plugins/mount.yazi/readonly_LICENSE @@ -0,0 +1,21 @@ +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/dot_config/yazi/plugins/mount.yazi/readonly_README.md b/dot_config/yazi/plugins/mount.yazi/readonly_README.md new file mode 100644 index 0000000..6853be7 --- /dev/null +++ b/dot_config/yazi/plugins/mount.yazi/readonly_README.md @@ -0,0 +1,51 @@ +# mount.yazi + +> [!NOTE] +> Yazi v25.2.7 or later is required for this plugin to work. + +A mount manager for Yazi, providing disk mount, unmount, and eject functionality. + +Supported platforms: + +- Linux with [`udisksctl`](https://github.com/storaged-project/udisks) and [`lsblk`](https://github.com/util-linux/util-linux) +- macOS with `diskutil` + +https://github.com/user-attachments/assets/c6f780ab-458b-420f-85cf-2fc45fcfe3a2 + +## Installation + +```sh +ya pack -a yazi-rs/plugins:mount +``` + +## Usage + +Add this to your `~/.config/yazi/keymap.toml`: + +```toml +[[manager.prepend_keymap]] +on = "M" +run = "plugin mount" +``` + +Available keybindings: + +| Key binding | Alternate key | Action | +| ------------ | ------------- | --------------------- | +| q | - | Quit the plugin | +| k | | Move up | +| j | | Move down | +| l | | Enter the mount point | +| m | - | Mount the partition | +| u | - | Unmount the partition | +| e | - | Eject the disk | + +## TODO + +- Custom keybindings +- Windows support (I don't have an Windows machine for testing, PRs welcome!) +- Support mount, unmount, and eject the entire disk + +## License + +This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file. diff --git a/dot_config/yazi/plugins/mount.yazi/readonly_main.lua b/dot_config/yazi/plugins/mount.yazi/readonly_main.lua new file mode 100644 index 0000000..962eeef --- /dev/null +++ b/dot_config/yazi/plugins/mount.yazi/readonly_main.lua @@ -0,0 +1,285 @@ +--- @since 25.2.26 + +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 subscribe = ya.sync(function(self) + ps.unsub("mount") + ps.sub("mount", function() ya.mgr_emit("plugin", { self._id, "refresh" }) end) +end) + +local update_partitions = ya.sync(function(self, partitions) + self.partitions = partitions + self.cursor = math.max(0, math.min(self.cursor or 0, #self.partitions - 1)) + ya.render() +end) + +local active_partition = ya.sync(function(self) return self.partitions[self.cursor + 1] end) + +local update_cursor = ya.sync(function(self, cursor) + if #self.partitions == 0 then + self.cursor = 0 + else + self.cursor = ya.clamp(0, self.cursor + cursor, #self.partitions - 1) + end + ya.render() +end) + +local M = { + keys = { + { on = "q", run = "quit" }, + + { on = "k", run = "up" }, + { on = "j", run = "down" }, + { on = "l", run = { "enter", "quit" } }, + + { on = "", run = "up" }, + { on = "", run = "down" }, + { on = "", run = { "enter", "quit" } }, + + { on = "m", run = "mount" }, + { on = "u", run = "unmount" }, + { on = "e", run = "eject" }, + }, +} + +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 + +function M:entry(job) + if job.args[1] == "refresh" then + return update_partitions(self.obtain()) + end + + toggle_ui() + update_partitions(self.obtain()) + subscribe() + + local tx1, rx1 = ya.chan("mpsc") + local tx2, rx2 = ya.chan("mpsc") + function producer() + while true do + local cand = self.keys[ya.which { cands = self.keys, silent = true }] or { run = {} } + for _, r in ipairs(type(cand.run) == "table" and cand.run or { cand.run }) do + tx1:send(r) + if r == "quit" then + toggle_ui() + return + end + end + end + end + + function consumer1() + repeat + local run = rx1:recv() + if run == "quit" then + tx2:send(run) + break + elseif run == "up" then + update_cursor(-1) + elseif run == "down" then + update_cursor(1) + elseif run == "enter" then + local active = active_partition() + if active and active.dist then + ya.mgr_emit("cd", { active.dist }) + end + else + tx2:send(run) + end + until not run + end + + function consumer2() + repeat + local run = rx2:recv() + if run == "quit" then + break + elseif run == "mount" then + self.operate("mount") + elseif run == "unmount" then + self.operate("unmount") + elseif run == "eject" then + self.operate("eject") + end + until not run + end + + ya.join(producer, consumer1, consumer2) +end + +function M:reflow() return { self } end + +function M:redraw() + local rows = {} + for _, p in ipairs(self.partitions or {}) do + if not p.sub then + rows[#rows + 1] = ui.Row { p.main } + elseif p.sub == "" then + rows[#rows + 1] = ui.Row { p.main, p.label or "", p.dist or "", p.fstype or "" } + else + rows[#rows + 1] = ui.Row { " " .. p.sub, p.label or "", p.dist or "", p.fstype or "" } + end + end + + return { + ui.Clear(self._area), + ui.Border(ui.Border.ALL) + :area(self._area) + :type(ui.Border.ROUNDED) + :style(ui.Style():fg("blue")) + :title(ui.Line("Mount"):align(ui.Line.CENTER)), + ui.Table(rows) + :area(self._area:pad(ui.Pad(1, 2, 1, 2))) + :header(ui.Row({ "Src", "Label", "Dist", "FSType" }):style(ui.Style():bold())) + :row(self.cursor) + :row_style(ui.Style():fg("blue"):underline()) + :widths { + ui.Constraint.Length(20), + ui.Constraint.Length(20), + ui.Constraint.Percentage(70), + ui.Constraint.Length(10), + }, + } +end + +function M.obtain() + local tbl = {} + local last + for _, p in ipairs(fs.partitions()) do + local main, sub = M.split(p.src) + if main and last ~= main then + if p.src == main then + last, p.main, p.sub, tbl[#tbl + 1] = p.src, p.src, "", p + else + last, tbl[#tbl + 1] = main, { src = main, main = main, sub = "" } + end + end + if sub then + if tbl[#tbl].sub == "" and tbl[#tbl].main == main then + tbl[#tbl].sub = nil + end + p.main, p.sub, tbl[#tbl + 1] = main, sub, p + end + end + table.sort(M.fillin(tbl), function(a, b) + if a.main == b.main then + return (a.sub or "") < (b.sub or "") + else + return a.main > b.main + end + end) + return tbl +end + +function M.split(src) + local pats = { + { "^/dev/sd[a-z]", "%d+$" }, -- /dev/sda1 + { "^/dev/nvme%d+n%d+", "p%d+$" }, -- /dev/nvme0n1p1 + { "^/dev/mmcblk%d+", "p%d+$" }, -- /dev/mmcblk0p1 + { "^/dev/disk%d+", ".+$" }, -- /dev/disk1s1 + } + for _, p in ipairs(pats) do + local main = src:match(p[1]) + if main then + return main, src:sub(#main + 1):match(p[2]) + end + end +end + +function M.fillin(tbl) + if ya.target_os() ~= "linux" then + return tbl + end + + local sources, indices = {}, {} + for i, p in ipairs(tbl) do + if p.sub and not p.fstype then + sources[#sources + 1], indices[p.src] = p.src, i + end + end + if #sources == 0 then + return tbl + end + + local output, err = Command("lsblk"):args({ "-p", "-o", "name,fstype", "-J" }):args(sources):output() + if err then + ya.dbg("Failed to fetch filesystem types for unmounted partitions: " .. err) + return tbl + end + + local t = ya.json_decode(output and output.stdout or "") + for _, p in ipairs(t and t.blockdevices or {}) do + tbl[indices[p.name]].fstype = p.fstype + end + return tbl +end + +function M.operate(type) + local active = active_partition() + if not active then + return + elseif not active.sub then + return -- TODO: mount/unmount main disk + end + + local output, err + if ya.target_os() == "macos" then + output, err = Command("diskutil"):args({ type, active.src }):output() + end + if ya.target_os() == "linux" then + if type == "eject" then + Command("udisksctl"):args({ "unmount", "-b", active.src }):status() + output, err = Command("udisksctl"):args({ "power-off", "-b", active.src }):output() + else + output, err = Command("udisksctl"):args({ type, "-b", active.src }):output() + end + end + + if not output then + M.fail("Failed to %s `%s`: %s", type, active.src, err) + elseif not output.status.success then + M.fail("Failed to %s `%s`: %s", type, active.src, output.stderr) + end +end + +function M.fail(s, ...) ya.notify { title = "Mount", content = string.format(s, ...), timeout = 10, level = "error" } end + +function M:click() end + +function M:scroll() end + +function M:touch() end + +return M diff --git a/dot_config/yazi/plugins/vcs-files.yazi/readonly_LICENSE b/dot_config/yazi/plugins/vcs-files.yazi/readonly_LICENSE new file mode 100644 index 0000000..fb5b1d6 --- /dev/null +++ b/dot_config/yazi/plugins/vcs-files.yazi/readonly_LICENSE @@ -0,0 +1,21 @@ +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/dot_config/yazi/plugins/vcs-files.yazi/readonly_README.md b/dot_config/yazi/plugins/vcs-files.yazi/readonly_README.md new file mode 100644 index 0000000..a86dccf --- /dev/null +++ b/dot_config/yazi/plugins/vcs-files.yazi/readonly_README.md @@ -0,0 +1,29 @@ +# vcs-files.yazi + +Show Git file changes in Yazi. + +https://github.com/user-attachments/assets/465b801b-3516-4f57-be09-8405da21e34d + +## Installation + +```sh +ya pack -a yazi-rs/plugins:vcs-files +``` + +## Usage + +```toml +# keymap.toml +[[manager.prepend_keymap]] +on = [ "g", "c" ] +run = "plugin vcs-files" +desc = "Show Git file changes" +``` + +## TODO + +- [ ] Add support for other VCS (e.g. Mercurial, Subversion) + +## License + +This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file. diff --git a/dot_config/yazi/plugins/vcs-files.yazi/readonly_main.lua b/dot_config/yazi/plugins/vcs-files.yazi/readonly_main.lua new file mode 100644 index 0000000..516a037 --- /dev/null +++ b/dot_config/yazi/plugins/vcs-files.yazi/readonly_main.lua @@ -0,0 +1,33 @@ +--- @since 25.4.8 + +local root = ya.sync(function() return cx.active.current.cwd end) + +local function fail(content) return ya.notify { title = "VCS Files", content = content, timeout = 5, level = "error" } end + +local function entry() + local root = root() + local output, err = Command("git"):cwd(tostring(root)):args({ "diff", "--name-only", "HEAD" }):output() + if err then + return fail("Failed to run `git diff`, error: " .. err) + elseif not output.status.success then + return fail("Failed to run `git diff`, stderr: " .. output.stderr) + end + + local id = ya.id("ft") + local cwd = root:into_search("Git changes") + ya.mgr_emit("cd", { Url(cwd) }) + ya.mgr_emit("update_files", { op = fs.op("part", { id = id, url = Url(cwd), files = {} }) }) + + local files = {} + for line in output.stdout:gmatch("[^\r\n]+") do + local url = cwd:join(line) + local cha = fs.cha(url, true) + if cha then + files[#files + 1] = File { url = url, cha = cha } + end + end + ya.mgr_emit("update_files", { op = fs.op("part", { id = id, url = Url(cwd), files = files }) }) + ya.mgr_emit("update_files", { op = fs.op("done", { id = id, url = cwd, cha = Cha { kind = 16 } }) }) +end + +return { entry = entry } diff --git a/dot_config/yazi/yazi.toml b/dot_config/yazi/yazi.toml index b9d1cc6..b57c028 100644 --- a/dot_config/yazi/yazi.toml +++ b/dot_config/yazi/yazi.toml @@ -82,7 +82,7 @@ macro_workers = 25 bizarre_retry = 5 image_alloc = 536870912 # 512MB image_bound = [ 0, 0 ] -suppress_preload = false +suppress_preload = true [plugin] @@ -156,6 +156,12 @@ id = "git" name = "*/" run = "git" +[[plugin.prepend_fetchers]] +id = "mime" +name = "*" +run = "mime-ext" +prio = "high" + [input] cursor_blink = false From 189e89212d21aa0f5421bc89cbfddc88b89d096b Mon Sep 17 00:00:00 2001 From: Hydroxycarbamide Date: Thu, 10 Apr 2025 15:29:47 +0200 Subject: [PATCH 2/2] Update nvim submodule --- dot_config/nvim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dot_config/nvim b/dot_config/nvim index caad93b..d476987 160000 --- a/dot_config/nvim +++ b/dot_config/nvim @@ -1 +1 @@ -Subproject commit caad93bd07c2ba025a1a03d9e58429046306925f +Subproject commit d4769876253834a269cd2dd324fbb7436a9a4daf