Add ouch.yazi plugin
This commit is contained in:
Submodule config/yazi/plugins/ouch.yazi deleted from 2496cd9ac2
21
config/yazi/plugins/ouch.yazi/LICENSE
Normal file
21
config/yazi/plugins/ouch.yazi/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
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.
|
||||||
79
config/yazi/plugins/ouch.yazi/README.md
Normal file
79
config/yazi/plugins/ouch.yazi/README.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# ouch.yazi
|
||||||
|
|
||||||
|
[ouch](https://github.com/ouch-org/ouch) plugin for [Yazi](https://github.com/sxyazi/yazi).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Archive preview
|
||||||
|
- Compression
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Yazi package manager
|
||||||
|
```bash
|
||||||
|
ya pack -a ndtoan96/ouch
|
||||||
|
```
|
||||||
|
|
||||||
|
### Git
|
||||||
|
```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"
|
||||||
|
```
|
||||||
|
|
||||||
|
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" },
|
||||||
|
{ mime = "application/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"
|
||||||
|
desc = "Compress with ouch"
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin uses `zip` format by default. You can change the format when you name the output file, `ouch` will detect format based on file extension.
|
||||||
|
|
||||||
|
And, for example, if you would like to set `7z` as default format, you can use `plugin ouch 7z`.
|
||||||
|
|
||||||
|
### 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" },
|
||||||
|
]
|
||||||
|
```
|
||||||
148
config/yazi/plugins/ouch.yazi/main.lua
Normal file
148
config/yazi/plugins/ouch.yazi/main.lua
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
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]
|
||||||
|
if default_fmt == nil then
|
||||||
|
default_fmt = "zip"
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user