From c1d638374c76655896c06e9bc91cdb39857b7f15 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Wed, 11 Jun 2025 15:21:23 +0800 Subject: [PATCH] feat: new plugin `zoom.yazi` to zoom in or out of the preview image --- README.md | 1 + mount.yazi/main.lua | 2 +- zoom.yazi/LICENSE | 1 + zoom.yazi/README.md | 44 ++++++++++++++++++++++++++ zoom.yazi/main.lua | 77 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 124 insertions(+), 1 deletion(-) create mode 120000 zoom.yazi/LICENSE create mode 100644 zoom.yazi/README.md create mode 100644 zoom.yazi/main.lua diff --git a/README.md b/README.md index 17ea63c..c595b0d 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ For specific installation commands and configuration instructions, check the ind - [vcs-files.yazi](vcs-files.yazi) - Show Git file changes in Yazi. - [piper.yazi](piper.yazi) - Pipe any shell command as a previewer. - [types.yazi](types.yazi) - Type definitions for Yazi's Lua API, empowering an efficient plugin development experience. +- [zoom.yazi](zoom.yazi) - Zoom in or out of the preview image. - [smart-filter.yazi](smart-filter.yazi) - Makes filters smarter: continuous filtering, automatically enter unique directory, open file on submitting. - [chmod.yazi](chmod.yazi) - Execute `chmod` on the selected files to change their mode. - [mime-ext.yazi](mime-ext.yazi) - A mime-type provider based on a file extension database, replacing the builtin `file(1)` to speed up mime-type retrieval at the expense of accuracy. diff --git a/mount.yazi/main.lua b/mount.yazi/main.lua index 87c7313..2d9b645 100644 --- a/mount.yazi/main.lua +++ b/mount.yazi/main.lua @@ -274,7 +274,7 @@ function M.operate(type) end end -function M.fail(s, ...) ya.notify { title = "Mount", content = string.format(s, ...), timeout = 10, level = "error" } end +function M.fail(...) ya.notify { title = "Mount", content = string.format(...), timeout = 10, level = "error" } end function M:click() end diff --git a/zoom.yazi/LICENSE b/zoom.yazi/LICENSE new file mode 120000 index 0000000..ea5b606 --- /dev/null +++ b/zoom.yazi/LICENSE @@ -0,0 +1 @@ +../LICENSE \ No newline at end of file diff --git a/zoom.yazi/README.md b/zoom.yazi/README.md new file mode 100644 index 0000000..b14664f --- /dev/null +++ b/zoom.yazi/README.md @@ -0,0 +1,44 @@ +> [!NOTE] +> The latest Yazi nightly build is required to use this plugin at the moment. + +# zoom.yazi + +Enlarge or shrink the preview image of a file, which is useful for magnifying small files for viewing. + +Supported formats: + +- Images - [ImageMagick](https://imagemagick.org/) is required + +Note that, the maximum size of enlarged images is limited by the [`max_width`][max_width] and [`max_height`][max_height] configuration options, so you may need to increase them as needed. + +[max_width]: https://yazi-rs.github.io/docs/configuration/yazi#preview.max_width +[max_height]: https://yazi-rs.github.io/docs/configuration/yazi#preview.max_height + +## Installation + +```sh +ya pkg add yazi-rs/plugins:zoom +``` + +## Usage + +```toml +# keymap.toml +[[mgr.prepend_keymap]] +on = "+" +run = "plugin zoom 1" +desc = "Zoom in hovered file" + +[[mgr.prepend_keymap]] +on = "-" +run = "plugin zoom -1" +desc = "Zoom out hovered file" +``` + +## TODO + +- [ ] Support more file types (e.g., videos, PDFs), PRs welcome! + +## License + +This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file. diff --git a/zoom.yazi/main.lua b/zoom.yazi/main.lua new file mode 100644 index 0000000..45470fc --- /dev/null +++ b/zoom.yazi/main.lua @@ -0,0 +1,77 @@ +--- @since 25.6.11 + +local get = ya.sync(function(st) + local h = cx.active.current.hovered + if not h then + return + end + + if st.last ~= h:hash() then + st.level, st.last = 0, h:hash() + end + + return { + url = h.url, + mime = h:mime() or "", + level = st.level, + } +end) + +local save = ya.sync(function(st, level) st.level = level end) + +local function fail(...) return ya.notify { title = "Zoom", content = string.format(...), timeout = 5, level = "error" } end + +local function canvas() + local cw, ch = rt.term.cell_size() + if not cw then + return rt.preview.max_width, rt.preview.max_height + end + + local area = ui.area("preview") + return math.min(rt.preview.max_width, math.floor(area.w * cw)), + math.min(rt.preview.max_height, math.floor(area.h * ch)) +end + +local function entry(_, job) + local st = get(job.args[1]) + if not st then + return + end + + local info, err = ya.image_info(st.url) + if not info then + return fail("Failed to get image info: %s", err) + end + + local motion = tonumber(job.args[1]) or 0 + st.level = ya.clamp(-10, st.level + motion, 10) + + local max_w, max_h = canvas() + local min_w, min_h = math.min(max_w, info.w), math.min(max_h, info.h) + local new_w = min_w + math.floor(min_w * st.level * 0.1) + local new_h = min_h + math.floor(min_h * st.level * 0.1) + if new_w > max_w or new_h > max_h then + return -- Image larger than available preview area after zooming + end + + local tmp = os.tmpname() + -- stylua: ignore + local status, err = Command("magick"):arg { + tostring(st.url), + "-auto-orient", "-strip", + "-resize", string.format("%dx%d", new_w, new_h), + "-quality", rt.preview.image_quality, + string.format("JPG:%s", tmp), + }:status() + + if not status then + return fail("Failed to run `magick` command: %s", err) + elseif not status.success then + return fail("`magick` command exited with error code %d", status.code) + end + + save(st.level) + ya.image_show(Url(tmp), ui.area("preview")) +end + +return { entry = entry }