Update 2025-07-16

This commit is contained in:
Kristofers Solo 2025-07-16 15:33:59 +03:00
parent 1a19d1112b
commit eb47813a34
Signed by: kristoferssolo
GPG Key ID: 8687F2D3EEE6F0ED
20 changed files with 553 additions and 248 deletions

View File

@ -92,6 +92,7 @@ depends = [ "torrent", "zathura", "email" ]
[torrent.files] [torrent.files]
"config/rustmission.toml" = "~/.config/rustmission/config.toml" "config/rustmission.toml" = "~/.config/rustmission/config.toml"
"config/traxor/" = "~/.config/traxor/"
# "config/transmission-daemon.json" = "~/.config/transmission-daemon/settings.json" # "config/transmission-daemon.json" = "~/.config/transmission-daemon/settings.json"
[awesome.files] [awesome.files]

View File

@ -1,4 +1,4 @@
#? Config file for btop v. 1.4.3 #? Config file for btop v. 1.4.4
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes. #* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes" #* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
@ -57,7 +57,7 @@ update_ms = 500
#* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct", #* Processes sorting, "pid" "program" "arguments" "threads" "user" "memory" "cpu lazy" "cpu direct",
#* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly. #* "cpu lazy" sorts top process over time (easier to follow), "cpu direct" updates top process directly.
proc_sorting = "cpu direct" proc_sorting = "memory"
#* Reverse sorting order, True or False. #* Reverse sorting order, True or False.
proc_reversed = False proc_reversed = False
@ -150,7 +150,7 @@ background_update = True
custom_cpu_name = "" custom_cpu_name = ""
#* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ". #* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace " ".
#* Begin line with "exclude=" to change to exclude filter, otherwise defaults to "most include" filter. Example: disks_filter="exclude=/boot /home/user". #* Only disks matching the filter will be shown. Prepend exclude= to only show disks not matching the filter. Examples: disk_filter="/boot /home/user", disks_filter="exclude=/boot /home/user"
disks_filter = "exclude=/boot" disks_filter = "exclude=/boot"
#* Show graphs instead of meters for memory values. #* Show graphs instead of meters for memory values.

27
config/traxor/config.toml Normal file
View File

@ -0,0 +1,27 @@
[keybinds]
quit = "q"
next_tab = "l"
prev_tab = "h"
next_torrent = "j"
prev_torrent = "k"
switch_tab_1 = "1"
switch_tab_2 = "2"
switch_tab_3 = "3"
toggle_torrent = "enter"
toggle_all = "a"
delete = "d"
delete_force = "D"
select = " "
toggle_help = "?"
[colors]
highlight_background = "magenta"
highlight_foreground = "black"
warning_foreground = "yellow"
info_foreground = "blue"
error_foreground = "red"
[log]
traxor = "debug"
ratatui = "warn"
transmission_rpc = "warn"

View File

@ -5,57 +5,57 @@ hash = "50da29476e744dba37d77fb209328fd1"
[[plugin.deps]] [[plugin.deps]]
use = "dedukun/relative-motions" use = "dedukun/relative-motions"
rev = "2e3b617" rev = "a603d9e"
hash = "b67ee12053113983273e9118a7d1272b" hash = "e02a788e5b8ae0fb47fd0193dda589cc"
[[plugin.deps]] [[plugin.deps]]
use = "hankertrix/augment-command" use = "hankertrix/augment-command"
rev = "a03a237" rev = "edc1bcf"
hash = "56dfc522998328d0c417226e88da862c" hash = "d5874bfb59265c96e8d9d5ef53c9450"
[[plugin.deps]] [[plugin.deps]]
use = "kirasok/torrent-preview" use = "kirasok/torrent-preview"
rev = "4ca5996" rev = "f465282"
hash = "6af40ce6b2cd849b5fa32de04a598b06" hash = "b89b46a15035a51d010a254858ba9741"
[[plugin.deps]] [[plugin.deps]]
use = "ndtoan96/ouch" use = "ndtoan96/ouch"
rev = "1ee69a5" rev = "0742fff"
hash = "63679f3daf8551ff8755be38b5ced0f" hash = "2bd799b42b8e42b8ef100310be71f8d1"
[[plugin.deps]] [[plugin.deps]]
use = "pirafrank/what-size" use = "pirafrank/what-size"
rev = "0a4904c" rev = "d896656"
hash = "fca231a128488a554823374f8f6d5241" hash = "62251f94eb67648d42cdfcfb8be0fad2"
[[plugin.deps]] [[plugin.deps]]
use = "yazi-rs/plugins:git" use = "yazi-rs/plugins:git"
rev = "86d28e4" rev = "b886025"
hash = "e01006bfb38951ea89031bd918b20dbb" hash = "63b6c222bf2103b3023389dde5e2ecfe"
[[plugin.deps]] [[plugin.deps]]
use = "yazi-rs/plugins:chmod" use = "yazi-rs/plugins:chmod"
rev = "86d28e4" rev = "b886025"
hash = "a030fe48d91b04341ad2fba9be957df" hash = "1adc12c2b2b025411ab61eb8f0879574"
[[plugin.deps]] [[plugin.deps]]
use = "yazi-rs/plugins:full-border" use = "yazi-rs/plugins:full-border"
rev = "86d28e4" rev = "b886025"
hash = "3996fc74044bc44144b323686f887e1" hash = "3996fc74044bc44144b323686f887e1"
[[plugin.deps]] [[plugin.deps]]
use = "yazi-rs/plugins:mount" use = "yazi-rs/plugins:mount"
rev = "86d28e4" rev = "b886025"
hash = "b3f1d6ec3721d4061aad5f69cddb0cf9" hash = "f10a14e823382d90fab5b3ee54cb38fe"
[[plugin.deps]] [[plugin.deps]]
use = "yazi-rs/plugins:smart-filter" use = "yazi-rs/plugins:smart-filter"
rev = "86d28e4" rev = "b886025"
hash = "f660384d7ed12ecd456efed313453310" hash = "a9d553bd19a3cd7f4eab3abaac5d67ff"
[[plugin.deps]] [[plugin.deps]]
use = "yazi-rs/plugins:diff" use = "yazi-rs/plugins:diff"
rev = "86d28e4" rev = "b886025"
hash = "47865a70cade14a0b9b6bc6a54f16bdb" hash = "47865a70cade14a0b9b6bc6a54f16bdb"
[[plugin.deps]] [[plugin.deps]]
@ -70,8 +70,8 @@ hash = "9c68763dd4f2799f7cfee1e9c3e819a9"
[[plugin.deps]] [[plugin.deps]]
use = "boydaihungst/mediainfo" use = "boydaihungst/mediainfo"
rev = "a7d1aa6" rev = "cc12f3f"
hash = "844133c7247cda086819d63a9ca5e457" hash = "b92e44ad5004f1b45e5c3d717a60ed24"
[[plugin.deps]] [[plugin.deps]]
use = "iynaix/time-travel" use = "iynaix/time-travel"

View File

@ -94,6 +94,7 @@ ya pkg upgrade
| `skip_single_subdirectory_on_leave` | `true` or `false` | `true` | Skip directories when there is only one subdirectory and no other files when leaving directories. This behaviour can be turned off by passing the `--no-skip` flag to the `leave` command. | | `skip_single_subdirectory_on_leave` | `true` or `false` | `true` | Skip directories when there is only one subdirectory and no other files when leaving directories. This behaviour can be turned off by passing the `--no-skip` flag to the `leave` command. |
| `smooth_scrolling` | `true` or `false` | `false` | Self-explanatory, this option enables smooth scrolling. | | `smooth_scrolling` | `true` or `false` | `false` | Self-explanatory, this option enables smooth scrolling. |
| `scroll_delay` | A floating point number, like `0.02`, `0.05`, `0.1`, etc. | `0.02` | The delay, in seconds, between each call of the `arrow` command to scroll through the file list. The smaller the `scroll_delay`, the faster the file list is scrolled. Avoid setting a `scroll_delay` that is more than `1` second. This is due to the plugin being asynchronous, which will result in the plugin continuing to call the `arrow` command even when the directory has changed, or when you are in a different application that doesn't block Yazi, resulting in unexpected behaviour. | | `scroll_delay` | A floating point number, like `0.02`, `0.05`, `0.1`, etc. | `0.02` | The delay, in seconds, between each call of the `arrow` command to scroll through the file list. The smaller the `scroll_delay`, the faster the file list is scrolled. Avoid setting a `scroll_delay` that is more than `1` second. This is due to the plugin being asynchronous, which will result in the plugin continuing to call the `arrow` command even when the directory has changed, or when you are in a different application that doesn't block Yazi, resulting in unexpected behaviour. |
| `create_item_delay` | A floating point number, like `0.25`, `0.1`, `1e-2`, etc. | `0.25` | The delay, in seconds, before calling the `reveal` command to reveal the created item. This delay is mainly to ensure a smooth experience using the plugin's `archive` and `create` commands, as the `reveal` command will create a dummy file that doesn't exist and reveal that before jumping to the created item. This delay is dependent on how fast your file system is. For the `Ext4` file system, it seems that a delay of `0.1` seconds is ideal, while a delay of `0.25` seconds for the `Btrfs` file system seems to be appropriate. |
| `wraparound_file_navigation` | `true` or `false` | `true` | Wrap around from the bottom to the top or from the top to the bottom when using the `arrow` or `parent_arrow` command to navigate. | | `wraparound_file_navigation` | `true` or `false` | `true` | Wrap around from the bottom to the top or from the top to the bottom when using the `arrow` or `parent_arrow` command to navigate. |
If you would like to use the default configuration, which is shown below, If you would like to use the default configuration, which is shown below,
@ -130,6 +131,7 @@ require("augment-command"):setup({
skip_single_subdirectory_on_leave = true, skip_single_subdirectory_on_leave = true,
smooth_scrolling = false, smooth_scrolling = false,
scroll_delay = 0.02, scroll_delay = 0.02,
create_item_delay = 0.25,
wraparound_file_navigation = true, wraparound_file_navigation = true,
}) })
``` ```
@ -155,6 +157,7 @@ require("augment-command"):setup({
extract_retries = 5, extract_retries = 5,
encrypt_archives = true, encrypt_archives = true,
smooth_scrolling = true, smooth_scrolling = true,
create_item_delay = 0.1,
wraparound_file_navigation = false, wraparound_file_navigation = false,
}) })
``` ```
@ -1438,123 +1441,123 @@ You can view the full licence in the [`LICENSE`][Licence] file.
<!-- Open command --> <!-- Open command -->
[open-prompt-video]: https://github.com/user-attachments/assets/a792f9d9-97f3-4fab-95cc-03b33c58dd47 [open-prompt-video]: https://github.com/user-attachments/assets/1d483b04-a74d-42d2-a94d-2e7b4923d62d
[open-behaviour-video]: https://github.com/user-attachments/assets/b2e56c10-91cd-4556-9f64-355aa8948832 [open-behaviour-video]: https://github.com/user-attachments/assets/78a02383-52ee-4268-9d8a-24790d15fb9e
[open-auto-extract-archives-video]: https://github.com/user-attachments/assets/a406391a-b31d-4b45-afa1-b982ddd89eaf [open-auto-extract-archives-video]: https://github.com/user-attachments/assets/e720fef7-da81-455b-8c82-b338577a0aa2
[open-recursively-extract-archives-video]: https://github.com/user-attachments/assets/a960f152-4391-4d55-bd0e-0a08efb42729 [open-recursively-extract-archives-video]: https://github.com/user-attachments/assets/614b4358-0c56-41de-a97c-c514693e0da1
<!-- Extract command --> <!-- Extract command -->
[extract-must-have-hovered-item-video]: https://github.com/user-attachments/assets/ed310a81-c482-4eed-9d54-5f50a7cc7637 [extract-must-have-hovered-item-video]: https://github.com/user-attachments/assets/86014955-9997-47e2-82fb-8de938044d31
[extract-hovered-item-optional-video]: https://github.com/user-attachments/assets/85d5a6bf-ed35-4f9a-b782-faea119da7c5 [extract-hovered-item-optional-video]: https://github.com/user-attachments/assets/509597c2-9df6-4199-900d-ad7f092a12b4
[extract-prompt-video]: https://github.com/user-attachments/assets/40f41727-7e55-44d8-816c-e706d09e27b8 [extract-prompt-video]: https://github.com/user-attachments/assets/85a85efe-cc25-45d2-9414-aa4935196cb4
[extract-behaviour-video]: https://github.com/user-attachments/assets/6f4f68d4-d43c-4de6-8d85-7e22c0cc0cc6 [extract-behaviour-video]: https://github.com/user-attachments/assets/db06f14e-7e9e-47a0-a6b3-a22f468be24d
[extract-recursively-extract-archives-video]: https://github.com/user-attachments/assets/d9e7030c-9491-4dfa-a1f4-baf3a45eed64 [extract-recursively-extract-archives-video]: https://github.com/user-attachments/assets/cd57721c-4461-42d2-8756-0928ac6bba34
[extract-encrypted-archive-video]: https://github.com/user-attachments/assets/48acd16d-f285-4d58-94c3-b402d7784d94 [extract-encrypted-archive-video]: https://github.com/user-attachments/assets/98341d53-9218-4817-960c-e0811f5505cd
[extract-reveal-extracted-item-video]: https://github.com/user-attachments/assets/96d7fe43-024a-4b1e-b961-9ab9c708db83 [extract-reveal-extracted-item-video]: https://github.com/user-attachments/assets/4ae1f884-5f12-4133-8757-18a1081be0e4
[extract-remove-extracted-archive-video]: https://github.com/user-attachments/assets/7b700ffc-3ce6-4185-a8b0-8ecfd09c2519 [extract-remove-extracted-archive-video]: https://github.com/user-attachments/assets/2dd8467f-68a4-4560-b45e-4d2e2c635016
<!-- Enter command --> <!-- Enter command -->
[smart-enter-video]: https://github.com/user-attachments/assets/9fc60a42-8692-4ac8-8250-652958582b98 [smart-enter-video]: https://github.com/user-attachments/assets/63f11df6-46a7-416a-bb11-fe72ce094a95
[enter-skip-single-subdirectory-video]: https://github.com/user-attachments/assets/8069e828-d2dd-4c69-a0b8-fe13074de715 [enter-skip-single-subdirectory-video]: https://github.com/user-attachments/assets/33b3a3de-bb42-4bbd-ac61-b292fb2d6f6a
<!-- Leave command --> <!-- Leave command -->
[leave-skip-single-subdirectory-video]: https://github.com/user-attachments/assets/01330321-b9f9-4dad-b339-8923509e759c [leave-skip-single-subdirectory-video]: https://github.com/user-attachments/assets/b842328f-9d5d-4ddb-b21d-88903f59858e
<!-- Rename command --> <!-- Rename command -->
[rename-must-have-hovered-item-video]: https://github.com/user-attachments/assets/b6ec96f9-c8a2-490c-9003-8c361e83e336 [rename-must-have-hovered-item-video]: https://github.com/user-attachments/assets/afe0c9c6-9b0b-4077-8f0a-76feb33c5824
[rename-hovered-item-optional-video]: https://github.com/user-attachments/assets/8bf0001d-6d39-4c4f-a364-b399e65208e8 [rename-hovered-item-optional-video]: https://github.com/user-attachments/assets/62cb647b-0519-4d1d-8d99-55b2c8eb6258
[rename-prompt-video]: https://github.com/user-attachments/assets/a3926488-f127-4d35-b9ab-7943f01abcb3 [rename-prompt-video]: https://github.com/user-attachments/assets/48bf39cc-72db-4648-91d8-9c612fb144f7
[rename-behaviour-video]: https://github.com/user-attachments/assets/e3d65d76-34d5-45a4-918d-0b28e662840a [rename-behaviour-video]: https://github.com/user-attachments/assets/4276eebb-87ae-4442-a0e8-01ef32f52137
<!-- Remove command --> <!-- Remove command -->
[remove-must-have-hovered-item-video]: https://github.com/user-attachments/assets/3366c9fa-1a4c-4c3c-a37d-70814d23828d [remove-must-have-hovered-item-video]: https://github.com/user-attachments/assets/62422c9e-d81b-4789-8cf4-08178a7c2a0a
[remove-hovered-item-optional-video]: https://github.com/user-attachments/assets/01a3fc57-cc90-47f5-b744-d3eed00ac237 [remove-hovered-item-optional-video]: https://github.com/user-attachments/assets/079a0ad4-f496-4d41-9374-d1cd13bd5aa7
[remove-prompt-video]: https://github.com/user-attachments/assets/18940b9f-4f04-4ab3-a6a9-b35ee8084bd8 [remove-prompt-video]: https://github.com/user-attachments/assets/1dfffc05-99b8-4b1d-8a3e-b895e315b947
[remove-behaviour-video]: https://github.com/user-attachments/assets/e524ecdb-f94b-4e6e-b5b2-967470ac3f87 [remove-behaviour-video]: https://github.com/user-attachments/assets/0aa35c6d-9897-45ed-8d60-fff4a9d1cb80
<!-- Copy command --> <!-- Copy command -->
[copy-must-have-hovered-item-video]: https://github.com/user-attachments/assets/d4ffa133-16d3-44f7-923d-bdd743fa4a77 [copy-must-have-hovered-item-video]: https://github.com/user-attachments/assets/ebbfa383-1771-4515-a30b-5f97142be249
[copy-hovered-item-optional-video]: https://github.com/user-attachments/assets/d2a7f5cd-ab09-45fd-8865-068bb1c269f8 [copy-hovered-item-optional-video]: https://github.com/user-attachments/assets/44f62540-3778-42f2-bd1e-5b90e356198c
[copy-prompt-video]: https://github.com/user-attachments/assets/41d372c5-2992-410c-97ae-aca2c6fea4ee [copy-prompt-video]: https://github.com/user-attachments/assets/2cd1421f-991f-4c66-85e5-283b541f7ff6
[copy-behaviour-video]: https://github.com/user-attachments/assets/57658664-1a89-46c4-bb4b-3551b0061436 [copy-behaviour-video]: https://github.com/user-attachments/assets/abf9e1a9-969f-4ac2-8e72-088b770ae902
<!-- Create command --> <!-- Create command -->
[create-and-enter-directories-video]: https://github.com/user-attachments/assets/b27756db-f6ed-4598-b54f-214b7ccbe208 [create-and-enter-directories-video]: https://github.com/user-attachments/assets/8355ebe5-9870-4dd8-b40b-3048c7636dc2
[create-and-open-files-video]: https://github.com/user-attachments/assets/b7ff1e6c-4c70-4598-a5f6-a88e1559f5d9 [create-and-open-files-video]: https://github.com/user-attachments/assets/5ca0833b-f112-4469-a382-4e64c432731b
[create-and-open-files-and-directories-video]: https://github.com/user-attachments/assets/90dc6dd2-c39d-4ed5-a8b1-e17a18f0219f [create-and-open-files-and-directories-video]: https://github.com/user-attachments/assets/4739a197-4b7e-461b-b257-1d6aa070bcd5
[create-behaviour-video]: https://github.com/user-attachments/assets/44bdc556-cde7-4ab9-b3c0-05c4f1fa3120 [create-behaviour-video]: https://github.com/user-attachments/assets/158a429b-b217-4f3d-8f27-f0a3ea2e1cdc
[create-default-behaviour-video]: https://github.com/user-attachments/assets/4948fd32-27a9-4546-83f9-ad6fa9c6afa8 [create-default-behaviour-video]: https://github.com/user-attachments/assets/0a5e88af-eade-46dd-b76b-f80d6a87b8d4
<!-- Shell command --> <!-- Shell command -->
[shell-must-have-hovered-item-video]: https://github.com/user-attachments/assets/b68c51db-ccb7-447b-897e-fd99048c47c0 [shell-must-have-hovered-item-video]: https://github.com/user-attachments/assets/52f9ecf1-877f-4377-921a-f954771a0496
[shell-hovered-item-optional-video]: https://github.com/user-attachments/assets/4643b23e-a2df-465f-8f62-3501747038b8 [shell-hovered-item-optional-video]: https://github.com/user-attachments/assets/c15adf88-dc08-4555-99d8-1968a804bf03
[shell-prompt-video]: https://github.com/user-attachments/assets/929e6a68-7e3f-4614-8344-c0a482d471ad [shell-prompt-video]: https://github.com/user-attachments/assets/90f3f1b7-1de5-494a-aca2-0810ef1218eb
[shell-behaviour-video]: https://github.com/user-attachments/assets/3afd995a-225a-4cc1-8189-0241555a6345 [shell-behaviour-video]: https://github.com/user-attachments/assets/9837752d-ec91-4af8-a22e-28b821508e22
[shell-exit-if-directory-video]: https://github.com/user-attachments/assets/f7cef7a0-027b-462f-8fe0-b107e5844736 [shell-exit-if-directory-video]: https://github.com/user-attachments/assets/96b874dc-d97b-4ca8-a306-f8f243579142
<!-- Paste command --> <!-- Paste command -->
[smart-paste-video]: https://github.com/user-attachments/assets/946a8211-41a8-43a0-b56e-9c13f5a00f4d [smart-paste-video]: https://github.com/user-attachments/assets/d78e370b-1447-4dd7-8c1f-af56cd9eab6d
<!-- Tab create command --> <!-- Tab create command -->
[smart-tab-create-video]: https://github.com/user-attachments/assets/4ea25adc-53d0-4086-b8b3-73dcea6d5932 [smart-tab-create-video]: https://github.com/user-attachments/assets/16c50c24-70bc-47b7-9a1b-889c36ef6c70
<!-- Tab switch command --> <!-- Tab switch command -->
[smart-tab-switch-video]: https://github.com/user-attachments/assets/9e2190ad-1b4d-425e-90de-1eb41a445584 [smart-tab-switch-video]: https://github.com/user-attachments/assets/1bec33d2-6d2a-421e-95e0-80d8e427cfa6
<!-- Quit command --> <!-- Quit command -->
[quit-with-confirmation-video]: https://github.com/user-attachments/assets/d3c71ae0-7024-4f06-9398-457cad0f5c1d [quit-with-confirmation-video]: https://github.com/user-attachments/assets/6ef5c012-77c1-4147-8032-4a9be7da6145
<!-- Arrow command --> <!-- Arrow command -->
[smooth-arrow-video]: https://github.com/user-attachments/assets/04683520-6028-4246-b529-eac6d3a936cf [smooth-arrow-video]: https://github.com/user-attachments/assets/c670a888-d168-4166-990c-d3a19b886dc3
[wraparound-arrow-video]: https://github.com/user-attachments/assets/f2555189-4628-4745-89f4-9ecb4ef070ab [wraparound-arrow-video]: https://github.com/user-attachments/assets/91b4f5c1-6ab7-4b58-96b1-194078e3e52e
[smooth-wraparound-arrow-video]: https://github.com/user-attachments/assets/5d603738-a527-4e19-80fd-db41ae76e42b [smooth-wraparound-arrow-video]: https://github.com/user-attachments/assets/07bdd6d8-686e-49db-9073-874cefff6f8d
<!-- Parent arrow command --> <!-- Parent arrow command -->
[parent-arrow-video]: https://github.com/user-attachments/assets/166a83d6-c7ef-4269-b725-62dde60f078f [parent-arrow-video]: https://github.com/user-attachments/assets/67b4c0b5-5b94-4574-a7c1-0dda8e18b7b4
[smooth-parent-arrow-video]: https://github.com/user-attachments/assets/02a7090b-3373-43db-95ed-2b3a6fe683d3 [smooth-parent-arrow-video]: https://github.com/user-attachments/assets/1b7ac44c-f7bc-4847-aa8a-897380aed54e
[wraparound-parent-arrow-video]: https://github.com/user-attachments/assets/229e11f8-a5e4-4237-93f3-d6c8875c9e78 [wraparound-parent-arrow-video]: https://github.com/user-attachments/assets/ce35b55f-98dc-485d-a5e4-005ebe3ea169
[smooth-wraparound-parent-arrow-video]: https://github.com/user-attachments/assets/7739afe5-e34d-466e-adf2-3e8a8732f04d [smooth-wraparound-parent-arrow-video]: https://github.com/user-attachments/assets/5256f0c5-b96b-4f4c-ac1d-f4a3f087cc57
<!-- Archive command --> <!-- Archive command -->
[archive-must-have-hovered-item-video]: https://github.com/user-attachments/assets/6dac06c1-a69c-4b21-86f6-63f6cc693f22 [archive-must-have-hovered-item-video]: https://github.com/user-attachments/assets/a49929b3-3b0d-4a50-b5d6-9dae7c119e7e
[archive-hovered-item-optional-video]: https://github.com/user-attachments/assets/b33fbcdf-1e00-49db-aede-99c2c3a26171 [archive-hovered-item-optional-video]: https://github.com/user-attachments/assets/b1dfd41a-1125-4fc4-9fe7-dc5a0378b70b
[archive-prompt-video]: https://github.com/user-attachments/assets/ddc0a2e7-9b90-416f-97e3-57af5ad5f355 [archive-prompt-video]: https://github.com/user-attachments/assets/f247f71c-e846-4bff-a2cc-13fc645a2472
[archive-behaviour-video]: https://github.com/user-attachments/assets/437254d2-4746-41e7-9500-13cef60764b7 [archive-behaviour-video]: https://github.com/user-attachments/assets/531b04e9-4fe6-4a39-9a7e-4b16deae87c6
[archive-encrypt-files-video]: https://github.com/user-attachments/assets/d4269378-58ce-4b58-a420-13455576c58f [archive-encrypt-files-video]: https://github.com/user-attachments/assets/8330a9db-ff74-4f37-8b21-113c7010e353
[archive-reveal-created-archive-video]: https://github.com/user-attachments/assets/86f01452-42a4-4a97-9d31-ce6f9bc10407 [archive-reveal-created-archive-video]: https://github.com/user-attachments/assets/8ae784bc-e64e-4fd1-9ebc-93f759f5a3d7
[archive-remove-archived-files-video]: https://github.com/user-attachments/assets/012ed8b5-57ae-4cb3-8bf7-4e0af6bdb0d2 [archive-remove-archived-files-video]: https://github.com/user-attachments/assets/be37cb9d-8f1e-4548-98c0-33bcbd288b59
<!-- Emit command --> <!-- Emit command -->
[emit-yazi-command-video]: https://github.com/user-attachments/assets/d2fadf6b-1877-479f-9ac3-734cf227693f [emit-yazi-command-video]: https://github.com/user-attachments/assets/2f2a6231-b888-4041-be40-6d0adf6b1c8f
[emit-plugin-command-video]: https://github.com/user-attachments/assets/af28c33a-b915-413a-91b2-fc812c1d4d90 [emit-plugin-command-video]: https://github.com/user-attachments/assets/a6f93fb1-3a86-4580-8f17-b75fd7ce6650
[emit-augmented-command-video]: https://github.com/user-attachments/assets/08c2d3d6-8ae6-48e2-a045-9c9dc5d81bfd [emit-augmented-command-video]: https://github.com/user-attachments/assets/68e64f0e-e9f4-4e1d-ae3e-0c339b89763c
<!-- Editor command --> <!-- Editor command -->
[editor-must-have-hovered-item-video]: https://github.com/user-attachments/assets/ca6d4bac-57be-487e-98e7-805b396fb3d3 [editor-must-have-hovered-item-video]: https://github.com/user-attachments/assets/cefa765e-8ba1-407e-a144-b098641dde25
[editor-hovered-item-optional-video]: https://github.com/user-attachments/assets/3481a3be-d91c-4903-b7a1-80d3048fcf6b [editor-hovered-item-optional-video]: https://github.com/user-attachments/assets/76cce397-b159-4967-8429-fc6d8d0944e0
[editor-prompt-video]: https://github.com/user-attachments/assets/7cdb942f-0ad3-453c-93a5-ab89df5cd644 [editor-prompt-video]: https://github.com/user-attachments/assets/e6a9aef0-d31c-40e6-ac40-d091f8b67b25
[editor-behaviour-video]: https://github.com/user-attachments/assets/e7537e2e-56a0-4681-9820-5b48cd583bc8 [editor-behaviour-video]: https://github.com/user-attachments/assets/21e8a73c-4a82-4f57-96c1-e3208ea073ab
<!-- Pager command --> <!-- Pager command -->
[pager-must-have-hovered-item-video]: https://github.com/user-attachments/assets/292f503e-c7b0-45ad-97b3-75325f8bb0e7 [pager-must-have-hovered-item-video]: https://github.com/user-attachments/assets/09e5200f-3d68-4718-a34a-27dbd66f8fca
[pager-hovered-item-optional-video]: https://github.com/user-attachments/assets/ca5f1126-4761-4289-a441-4b44c7234e57 [pager-hovered-item-optional-video]: https://github.com/user-attachments/assets/95b30bce-ef3f-4051-af7a-6f217dc1a828
[pager-prompt-video]: https://github.com/user-attachments/assets/45d758e0-f95c-4e2e-92b2-094c2f475c00 [pager-prompt-video]: https://github.com/user-attachments/assets/ab44b3ab-2938-405a-8a86-294bb23f652f
[pager-behaviour-video]: https://github.com/user-attachments/assets/547ebf9c-ab85-4e72-85c0-e130739b9e68 [pager-behaviour-video]: https://github.com/user-attachments/assets/05085f86-a256-4ee8-a086-dc9cb9cddc9a

View File

@ -79,6 +79,7 @@
---@field skip_single_subdirectory_on_leave boolean Skip single subdir on leave ---@field skip_single_subdirectory_on_leave boolean Skip single subdir on leave
---@field smooth_scrolling boolean Whether to smoothly scroll or not ---@field smooth_scrolling boolean Whether to smoothly scroll or not
---@field scroll_delay number The scroll delay in seconds for smooth scrolling ---@field scroll_delay number The scroll delay in seconds for smooth scrolling
---@field create_item_delay number Delay in seconds before revealing
---@field wraparound_file_navigation boolean Have wraparound navigation or not ---@field wraparound_file_navigation boolean Have wraparound navigation or not
-- The full configuration for the plugin -- The full configuration for the plugin
@ -195,6 +196,7 @@ local DEFAULT_CONFIG = {
skip_single_subdirectory_on_leave = true, skip_single_subdirectory_on_leave = true,
smooth_scrolling = false, smooth_scrolling = false,
scroll_delay = 0.02, scroll_delay = 0.02,
create_item_delay = 0.25,
wraparound_file_navigation = true, wraparound_file_navigation = true,
} }
@ -1027,6 +1029,10 @@ end
local function get_sudo_edit_supported() local function get_sudo_edit_supported()
-- --
-- If the platform is Windows, return false immediately
-- as Windows does not have sudo
if ya.target_family() == "windows" then return false end
-- Call the "sudo --help" command and get the handle -- Call the "sudo --help" command and get the handle
-- --
-- The "2>&1" redirects the standard error -- The "2>&1" redirects the standard error
@ -3363,7 +3369,7 @@ local function execute_create(item_url, is_directory, args, config)
end end
-- Wait for a tiny bit for the file to be created -- Wait for a tiny bit for the file to be created
ya.sleep(10e-2) ya.sleep(config.create_item_delay)
-- Reveal the created item -- Reveal the created item
ya.emit("reveal", { tostring(item_url) }) ya.emit("reveal", { tostring(item_url) })
@ -4213,7 +4219,7 @@ local function handle_parent_arrow(args, config)
-- If smooth scrolling is not wanted, -- If smooth scrolling is not wanted,
-- call the function to execute the parent arrow command -- call the function to execute the parent arrow command
if not config.smooth_scrolling then execute_parent_arrow(args) end if not config.smooth_scrolling then return execute_parent_arrow(args) end
-- Otherwise, smooth scrolling is wanted, -- Otherwise, smooth scrolling is wanted,
-- so get the number of steps from the arguments given -- so get the number of steps from the arguments given
@ -4450,7 +4456,7 @@ local function handle_archive(args, config)
-- --
-- Wait for a tiny bit for the archive to be created -- Wait for a tiny bit for the archive to be created
ya.sleep(10e-2) ya.sleep(config.create_item_delay)
-- Reveal the archive -- Reveal the archive
ya.emit("reveal", { archive_path }) ya.emit("reveal", { archive_path })

View File

@ -22,7 +22,8 @@ return {
local value, event = ya.input { local value, event = ya.input {
title = "Chmod:", title = "Chmod:",
position = { "top-center", y = 3, w = 40 }, pos = { "top-center", y = 3, w = 40 },
position = { "top-center", y = 3, w = 40 }, -- TODO: remove
} }
if event ~= 1 then if event ~= 1 then
return return

View File

@ -34,6 +34,9 @@ run = "git"
## Advanced ## Advanced
> [!NOTE]
> The following configuration must be put before `require("git"):setup()`
You can customize the [Style](https://yazi-rs.github.io/docs/plugins/layout#style) of the status sign with: You can customize the [Style](https://yazi-rs.github.io/docs/plugins/layout#style) of the status sign with:
- `th.git.modified` - `th.git.modified`

View File

@ -5,6 +5,7 @@ local WINDOWS = ya.target_family() == "windows"
-- The code of supported git status, -- The code of supported git status,
-- also used to determine which status to show for directories when they contain different statuses -- also used to determine which status to show for directories when they contain different statuses
-- see `bubble_up` -- see `bubble_up`
---@enum CODES
local CODES = { local CODES = {
excluded = 100, -- ignored directory excluded = 100, -- ignored directory
ignored = 6, -- ignored file ignored = 6, -- ignored file
@ -26,6 +27,8 @@ local PATTERNS = {
{ "[AD][AD]", CODES.updated }, { "[AD][AD]", CODES.updated },
} }
---@param line string
---@return CODES, string
local function match(line) local function match(line)
local signs = line:sub(1, 2) local signs = line:sub(1, 2)
for _, p in ipairs(PATTERNS) do for _, p in ipairs(PATTERNS) do
@ -41,9 +44,12 @@ local function match(line)
else else
return code, path return code, path
end end
---@diagnostic disable-next-line: missing-return
end end
end end
---@param cwd Url
---@return string?
local function root(cwd) local function root(cwd)
local is_worktree = function(url) local is_worktree = function(url)
local file, head = io.open(tostring(url)), nil local file, head = io.open(tostring(url)), nil
@ -64,6 +70,8 @@ local function root(cwd)
until not cwd until not cwd
end end
---@param changed Changes
---@return Changes
local function bubble_up(changed) local function bubble_up(changed)
local new, empty = {}, Url("") local new, empty = {}, Url("")
for path, code in pairs(changed) do for path, code in pairs(changed) do
@ -79,6 +87,10 @@ local function bubble_up(changed)
return new return new
end end
---@param excluded string[]
---@param cwd Url
---@param repo Url
---@return Changes
local function propagate_down(excluded, cwd, repo) local function propagate_down(excluded, cwd, repo)
local new, rel = {}, cwd:strip_prefix(repo) local new, rel = {}, cwd:strip_prefix(repo)
for _, path in ipairs(excluded) do for _, path in ipairs(excluded) do
@ -95,7 +107,12 @@ local function propagate_down(excluded, cwd, repo)
return new return new
end end
---@param cwd string
---@param repo string
---@param changed Changes
local add = ya.sync(function(st, cwd, repo, changed) local add = ya.sync(function(st, cwd, repo, changed)
---@cast st State
st.dirs[cwd] = repo st.dirs[cwd] = repo
st.repos[repo] = st.repos[repo] or {} st.repos[repo] = st.repos[repo] or {}
for path, code in pairs(changed) do for path, code in pairs(changed) do
@ -108,16 +125,29 @@ local add = ya.sync(function(st, cwd, repo, changed)
st.repos[repo][path] = code st.repos[repo][path] = code
end end
end end
ya.render() -- TODO: remove this
if ui.render then
ui.render()
else
ya.render()
end
end) end)
---@param cwd string
local remove = ya.sync(function(st, cwd) local remove = ya.sync(function(st, cwd)
---@cast st State
local repo = st.dirs[cwd] local repo = st.dirs[cwd]
if not repo then if not repo then
return return
end end
ya.render() -- TODO: remove this
if ui.render then
ui.render()
else
ya.render()
end
st.dirs[cwd] = nil st.dirs[cwd] = nil
if not st.repos[repo] then if not st.repos[repo] then
return return
@ -131,9 +161,11 @@ local remove = ya.sync(function(st, cwd)
st.repos[repo] = nil st.repos[repo] = nil
end) end)
---@param st State
---@param opts Options
local function setup(st, opts) local function setup(st, opts)
st.dirs = {} -- Mapping between a directory and its corresponding repository st.dirs = {}
st.repos = {} -- Mapping between a repository and the status of each of its files st.repos = {}
opts = opts or {} opts = opts or {}
opts.order = opts.order or 1500 opts.order = opts.order or 1500
@ -174,6 +206,7 @@ local function setup(st, opts)
end, opts.order) end, opts.order)
end end
---@type UnstableFetcher
local function fetch(_, job) local function fetch(_, job)
local cwd = job.files[1].url.base local cwd = job.files[1].url.base
local repo = root(cwd) local repo = root(cwd)

View File

@ -1,9 +1,12 @@
# mediainfo.yazi # mediainfo.yazi (fork)
<!--toc:start--> <!--toc:start-->
- [mediainfo.yazi](#mediainfo-yazi) - [mediainfo.yazi (fork)](#mediainfoyazi-fork)
- [Preview](#preview)
- [Installation](#installation) - [Installation](#installation)
- [Configuration:](#configuration)
- [Custom theme](#custom-theme)
<!--toc:end--> <!--toc:end-->
This is a Yazi plugin for previewing media files. The preview shows thumbnail This is a Yazi plugin for previewing media files. The preview shows thumbnail
@ -16,50 +19,52 @@ using `ffmpeg` if available and media metadata using `mediainfo`.
- Video - Video
![video](assets/2025-02-15-09-15-39.png) ![video](assets/2025-02-15-09-15-39.png)
- Audio file with cover - Audio file with cover
![audio_with_cover_picture](assets/2025-02-15-09-14-23.png) ![audio_with_cover_picture](assets/2025-02-15-09-14-23.png)
- Images - Images
![image](assets/2025-02-15-16-52-39.png) ![image](assets/2025-02-15-16-52-39.png)
- Subtitle - Subtitle
![subrip](assets/2025-02-15-16-51-11.png) ![subrip](assets/2025-02-15-16-51-11.png)
- SVG+XML file doesn't have useful information, so it only show the image preview. - SVG+XML file doesn't have useful information, so it only show the image preview.
- There are more extensions which are supported by mediainfo. Just add file's MIME type to `previewers`, `preloaders`. - There are more file extensions which are supported by mediainfo. Just add file's MIME type to `previewers`, `preloaders`.
Use `spotter` to determine File's MIME type. [Default is `<Tab>` key](https://github.com/sxyazi/yazi/blob/1a6abae974370702c8865459344bf256de58359e/yazi-config/preset/keymap-default.toml#L59)
## Installation ## Installation
Install mediainfo CLI: - Install mediainfo CLI:
- [https://mediaarea.net/en/MediaInfo/Download](https://mediaarea.net/en/MediaInfo/Download) - [https://mediaarea.net/en/MediaInfo/Download](https://mediaarea.net/en/MediaInfo/Download)
- Run this command in terminal to check if it's installed correctly: - Run this command in terminal to check if it's installed correctly:
```bash
mediainfo --version
```
If it output `Not found` then add it to your PATH environment variable. It's better to ask ChatGPT to help you (Prompt: `Add MediaInfo CLI to PATH environment variable in Windows`).
- Install this plugin:
```bash ```bash
mediainfo --version ya pkg add boydaihungst/mediainfo
``` ```
- If it output `Not found` then add it to your PATH environment variable. It's better to ask ChatGPT to help you (Prompt: `Add MediaInfo CLI to PATH environment variable in Windows`). ## Configuration:
Install + config this plugin:
> [!IMPORTANT] > `mediainfo` use video, image, svg, magick built-in plugins behind the scene to render preview image, song cover. > [!IMPORTANT] > `mediainfo` use video, image, svg, magick built-in plugins behind the scene to render preview image, song cover.
> So you can remove those 3 plugins from `preloaders` and `previewers` sections in `yazi.toml`. > So you can remove those 3 plugins from `preloaders` and `previewers` sections in `yazi.toml`.
If you have cache problem, run this cmd, and follow the tips: `yazi --clear-cache` If you have cache problem, run this cmd, and follow the tips: `yazi --clear-cache`
```bash Config folder for each OS: https://yazi-rs.github.io/docs/configuration/overview.
ya pkg add boydaihungst/mediainfo
# or
ya pack -a boydaihungst/mediainfo
```
Config folder for each OS: https://yazi-rs.github.io/docs/configuration/overview
Create `.../yazi/yazi.toml` and add: Create `.../yazi/yazi.toml` and add:
```toml ```toml
@ -68,22 +73,24 @@ Create `.../yazi/yazi.toml` and add:
# Replace magick, image, video with mediainfo # Replace magick, image, video with mediainfo
{ mime = "{audio,video,image}/*", run = "mediainfo" }, { mime = "{audio,video,image}/*", run = "mediainfo" },
{ mime = "application/subrip", run = "mediainfo" }, { mime = "application/subrip", run = "mediainfo" },
# Adobe Illustrator
{ mime = "application/postscript", run = "mediainfo" },
] ]
prepend_previewers = [ prepend_previewers = [
# Replace magick, image, video with mediainfo # Replace magick, image, video with mediainfo
{ mime = "{audio,video,image}/*", run = "mediainfo"}, { mime = "{audio,video,image}/*", run = "mediainfo"},
{ mime = "application/subrip", run = "mediainfo" }, { mime = "application/subrip", run = "mediainfo" },
# Adobe Illustrator
{ mime = "application/postscript", run = "mediainfo" },
] ]
# There are more extensions which are supported by mediainfo. # There are more extensions which are supported by mediainfo.
# Just add file's MIME type to `previewers`, `preloaders` above. # Just add file's MIME type to `previewers`, `preloaders` above.
# https://mediaarea.net/en/MediaInfo/Support/Formats # https://mediaarea.net/en/MediaInfo/Support/Formats
``` ```
## Custom theme ## Custom theme
Using the same style with spotter Using the same style with spotter. [Read more](https://github.com/sxyazi/yazi/pull/2391)
Read more: https://github.com/sxyazi/yazi/pull/2391
Edit or add `yazi/theme.toml`: Edit or add `yazi/theme.toml`:

View File

@ -22,8 +22,26 @@ local magick_image_mimes = {
["svg+xml"] = true, ["svg+xml"] = true,
} }
local seekable_mimes = {
["application/postscript"] = true,
["image/adobe.photoshop"] = true,
}
local M = {} local M = {}
local suffix = "_mediainfo" local suffix = "_mediainfo"
local SHELL = os.getenv("SHELL") or ""
local function is_valid_utf8(str)
return utf8.len(str) ~= nil
end
local function path_quote(path)
if not path or tostring(path) == "" then
return path
end
local result = "'" .. string.gsub(tostring(path), "'", "'\\''") .. "'"
return result
end
local function read_mediainfo_cached_file(file_path) local function read_mediainfo_cached_file(file_path)
-- Open the file in read mode -- Open the file in read mode
@ -37,6 +55,41 @@ local function read_mediainfo_cached_file(file_path)
end end
end end
local set_state = ya.sync(function(state, key, value)
state[key] = value
end)
local get_state = ya.sync(function(state, key)
return state[key]
end)
local force_render = ya.sync(function(_, _)
(ui.render or ya.render)()
end)
local function image_layer_count(job)
local cache = ya.file_cache({ file = job.file, skip = 0 })
if not cache then
return 0
end
local layer_count = get_state("f" .. tostring(cache))
if layer_count then
return layer_count
end
local output, err = Command("identify"):arg({ tostring(job.file.url) }):output()
if err then
return 0
end
layer_count = 0
for line in output.stdout:gmatch("[^\r\n]+") do
if line:match("%S") then
layer_count = layer_count + 1
end
end
set_state("f" .. tostring(cache), layer_count)
return layer_count
end
function M:peek(job) function M:peek(job)
local start = os.clock() local start = os.clock()
local cache_img_url_no_skip = ya.file_cache({ file = job.file, skip = 0 }) local cache_img_url_no_skip = ya.file_cache({ file = job.file, skip = 0 })
@ -46,21 +99,22 @@ function M:peek(job)
local is_video = string.find(job.mime, "^video/") local is_video = string.find(job.mime, "^video/")
local is_audio = string.find(job.mime, "^audio/") local is_audio = string.find(job.mime, "^audio/")
local is_image = string.find(job.mime, "^image/") local is_image = string.find(job.mime, "^image/")
local is_seekable = seekable_mimes[job.mime] or is_video
local cache_img_url = (is_audio or is_image) and cache_img_url_no_skip local cache_img_url = (is_audio or is_image) and cache_img_url_no_skip
if is_video then if is_seekable then
cache_img_url = ya.file_cache({ file = job.file, skip = math.min(90, job.skip) }) cache_img_url = ya.file_cache(job)
end end
local ok, err = self:preload(job) local preload_status, preload_err = self:preload(job)
if not ok or err then if not preload_status then
return return
end end
local cache_mediainfo_path = tostring(cache_img_url_no_skip) .. suffix
ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock())) ya.sleep(math.max(0, rt.preview.image_delay / 1000 + start - os.clock()))
local cache_mediainfo_path = tostring(cache_img_url_no_skip) .. suffix
local output = read_mediainfo_cached_file(cache_mediainfo_path) local output = read_mediainfo_cached_file(cache_mediainfo_path)
local lines = {} local lines = {}
local max_lines = math.floor(job.area.h / 2) local limit = job.area.h
local last_line = 0 local last_line = 0
local is_wrap = rt.preview.wrap == "yes" local is_wrap = rt.preview.wrap == "yes"
@ -68,8 +122,8 @@ function M:peek(job)
local max_width = math.max(1, job.area.w) local max_width = math.max(1, job.area.w)
if output:match("^Error:") then if output:match("^Error:") then
job.args.force_reload_mediainfo = true job.args.force_reload_mediainfo = true
local _ok, _err = self:preload(job) preload_status, preload_err = self:preload(job)
if not _ok or _err then if not preload_status or preload_err then
return return
end end
output = read_mediainfo_cached_file(cache_mediainfo_path) output = read_mediainfo_cached_file(cache_mediainfo_path)
@ -90,37 +144,71 @@ function M:peek(job)
end end
if line then if line then
local line_height = math.max(1, is_wrap and math.ceil(line:width() / max_width) or 1) local line_height = math.max(1, is_wrap and math.ceil(ui.width(line) / max_width) or 1)
if (last_line + line_height) > job.skip then if (last_line + line_height) > job.skip then
table.insert(lines, line) table.insert(lines, line)
end end
if (last_line + line_height) >= job.skip + max_lines then if (last_line + line_height) >= job.skip + limit then
last_line = job.skip + max_lines last_line = job.skip + limit
break break
end end
last_line = last_line + line_height last_line = last_line + line_height
end end
end end
end end
local mediainfo_height = math.min(max_lines, last_line) local mediainfo_height = math.min(limit, last_line)
if (job.skip > 0 and #lines == 0) and (not is_video or (is_video and job.skip >= 90)) then if
ya.emit("peek", { math.max(0, job.skip - max_lines), only_if = job.file.url, upper_bound = false }) (job.skip > 0 and #lines == 0)
and (
not is_seekable
or (is_video and job.skip >= 90)
or (
(job.mime == "image/adobe.photoshop" or job.mime == "application/postscript")
and image_layer_count(job) < (1 + math.floor(math.max(0, job.skip / (get_state("units") or 0))))
)
)
then
ya.emit(
"peek",
{ math.max(0, job.skip - (get_state("units") or limit)), only_if = job.file.url, upper_bound = true }
)
return return
end end
force_render()
local rendered_img_rect = cache_img_url local rendered_img_rect = cache_img_url
and fs.cha(cache_img_url)
and ya.image_show( and ya.image_show(
cache_img_url, cache_img_url,
ui.Rect({ ui.Rect({
x = job.area.x, x = job.area.x,
y = job.area.y, y = job.area.y,
w = job.area.w, w = job.area.w,
h = job.area.h - mediainfo_height, h = mediainfo_height > 0 and math.max(job.area.h - mediainfo_height, job.area.h / 2) or job.area.h,
}) })
) )
or nil or nil
local image_height = rendered_img_rect and rendered_img_rect.h or 0 local image_height = rendered_img_rect and rendered_img_rect.h or 0
-- NOTE: Workaround case audio has no cover image. Prevent regenerate preview image
if is_audio and image_height == 1 then
local info = ya.image_info(cache_img_url)
if not info or (info.w == 1 and info.h == 1) then
image_height = 0
end
end
-- NOTE: Workaround case video.lua doesn't doesn't generate preview image because of `skip` overflow video duration
if is_video and not rendered_img_rect then
image_height = math.max(job.area.h - mediainfo_height, 0)
end
-- Handle image preload error
if preload_err then
table.insert(lines, ui.Line(tostring(preload_err)):style(th.spot.title or ui.Style():fg("red")))
end
ya.preview_widget(job, { ya.preview_widget(job, {
ui.Text(lines) ui.Text(lines)
:area(ui.Rect({ :area(ui.Rect({
@ -136,6 +224,7 @@ end
function M:seek(job) function M:seek(job)
local h = cx.active.current.hovered local h = cx.active.current.hovered
if h and h.url == job.file.url then if h and h.url == job.file.url then
set_state("units", job.units)
ya.emit("peek", { ya.emit("peek", {
math.max(0, cx.active.preview.skip + job.units), math.max(0, cx.active.preview.skip + job.units),
only_if = job.file.url, only_if = job.file.url,
@ -144,89 +233,172 @@ function M:seek(job)
end end
function M:preload(job) function M:preload(job)
local cache_img_url_no_skip = ya.file_cache({ file = job.file, skip = 0 }) local cache_img_url = ya.file_cache({ file = job.file, skip = 0 })
local cache_img_url_no_skip_cha = cache_img_url_no_skip and fs.cha(cache_img_url_no_skip) if not cache_img_url then
if not cache_img_url_no_skip then
return true return true
end end
local cache_mediainfo_url = Url(tostring(cache_img_url_no_skip) .. suffix) local cache_mediainfo_url = Url(tostring(cache_img_url) .. suffix)
cache_img_url = seekable_mimes[job.mime] and ya.file_cache(job) or cache_img_url
local cache_img_url_cha = cache_img_url and fs.cha(cache_img_url)
local err_msg = "" local err_msg = ""
-- seekable mimetype local is_valid_utf8_path = is_valid_utf8(tostring(job.file.url))
if job.mime and string.find(job.mime, "^video/") then -- video mimetype
local video = require("video") if job.mime then
local cache_img_status, video_preload_err = video:preload({ file = job.file, skip = math.min(90, job.skip) }) if string.find(job.mime, "^video/") then
if not cache_img_status and video_preload_err then local cache_img_status, video_preload_err = require("video"):preload(job)
err_msg = err_msg if not cache_img_status and video_preload_err then
.. string.format("Failed to start `%s`, Do you have `%s` installed?\n", "ffmpeg", "ffmpeg") err_msg = err_msg
end .. string.format("Failed to start `%s`, Do you have `%s` installed?\n", "ffmpeg", "ffmpeg")
end end
-- none-seekable mimetype -- audo and image mimetype
if cache_img_url_no_skip and (not cache_img_url_no_skip_cha or cache_img_url_no_skip_cha.len <= 0) then elseif cache_img_url and (not cache_img_url_cha or cache_img_url_cha.len <= 0) then
-- audio -- audio
if job.mime and string.find(job.mime, "^audio/") then if string.find(job.mime, "^audio/") then
local qv = 31 - math.floor(rt.preview.image_quality * 0.3) local qv = 31 - math.floor(rt.preview.image_quality * 0.3)
local status, _ = Command("ffmpeg"):arg({ local audio_preload_output, audio_preload_err = Command("ffmpeg"):arg({
"-v", "-v",
"quiet", "error",
"-threads", "-threads",
1, 1,
"-hwaccel", "-hwaccel",
"auto", "auto",
"-skip_frame", "-skip_frame",
"nokey", "nokey",
"-an", "-an",
"-sn", "-sn",
"-dn", "-dn",
"-i", "-i",
tostring(job.file.url), tostring(job.file.url),
"-vframes", "-vframes",
1, 1,
"-q:v", "-q:v",
qv, qv,
"-vf", "-vf",
string.format("scale=-1:'min(%d,ih)':flags=fast_bilinear", rt.preview.max_height / 2), string.format("scale=-1:'min(%d,ih)':flags=fast_bilinear", rt.preview.max_height / 2),
"-f", "-f",
"image2", "image2",
"-y", "-y",
tostring(cache_img_url_no_skip), tostring(cache_img_url),
}):status() }):output()
-- NOTE: Some audio types doesn't have cover image -> error ""
-- NOTE: Ignore this err msg because some audio types doesn't have cover image if (audio_preload_output.stderr ~= nil and audio_preload_output.stderr ~= "") or audio_preload_err then
-- err_msg = err_msg
-- if not status or not status.success then .. string.format("Failed to start `%s`, Do you have `%s` installed?\n", "ffmpeg", "ffmpeg")
-- err_msg = err_msg else
-- .. string.format("Failed to start `%s`, Do you have `%s` installed?\n", "ffmpeg", "ffmpeg") cache_img_url_cha = fs.cha(cache_img_url)
-- end if not cache_img_url_cha then
-- NOTE: Workaround case audio has no cover image. Prevent regenerate preview image
audio_preload_output, audio_preload_err = require("magick")
.with_limit()
:arg({
"-size",
"1x1",
"canvas:none",
string.format("PNG32:%s", cache_img_url),
})
:output()
if
(audio_preload_output.stderr ~= nil and audio_preload_output.stderr ~= "")
or audio_preload_err
then
err_msg = err_msg
.. string.format(
"Failed to start `%s`, Do you have `%s` installed?\n",
"magick",
"magick"
)
end
end
end
-- image -- image
elseif job.mime and string.find(job.mime, "^image/") then elseif string.find(job.mime, "^image/") or job.mime == "application/postscript" then
local svg_plugin_ok, svg_plugin = pcall(require, "svg") local svg_plugin_ok, svg_plugin = pcall(require, "svg")
local mime = job.mime:match(".*/(.*)$") local _, magick_plugin = pcall(require, "magick")
local mime = job.mime:match(".*/(.*)$")
local image = magick_image_mimes[mime] local image_plugin = magick_image_mimes[mime]
and ((mime == "svg+xml" and svg_plugin_ok) and svg_plugin or require("magick")) and ((mime == "svg+xml" and svg_plugin_ok) and svg_plugin or magick_plugin)
or require("image") or require("image")
local no_skip_job = { skip = 0, file = job.file }
-- image = ya.dict_merge(image, no_skip_job) local cache_img_status, image_preload_err
local cache_img_status, image_preload_err = image:preload(no_skip_job) -- psd, ai, eps
if not cache_img_status and image_preload_err then if mime == "adobe.photoshop" or job.mime == "application/postscript" then
err_msg = err_msg .. "Failed to cache image , check cache folder permissions\n" local layer_index = 0
local units = get_state("units")
if units ~= nil then
local max_layer = image_layer_count(job)
layer_index = math.floor(math.max(0, job.skip / units))
if layer_index + 1 > max_layer then
layer_index = max_layer - 1
end
end
cache_img_status, image_preload_err = magick_plugin
.with_limit()
:arg({
"-background",
"none",
tostring(job.file.url) .. "[" .. tostring(layer_index) .. "]",
"-auto-orient",
"-strip",
"-resize",
string.format("%dx%d>", rt.preview.max_width, rt.preview.max_height),
"-quality",
rt.preview.image_quality,
string.format("PNG32:%s", cache_img_url),
})
:status()
elseif mime == "svg+xml" and not is_valid_utf8_path then
-- svg under invalid utf8 path
cache_img_status, image_preload_err = magick_plugin
.with_limit()
:arg({
"-background",
"none",
tostring(job.file.url),
"-auto-orient",
"-strip",
"-flatten",
"-resize",
string.format("%dx%d>", rt.preview.max_width, rt.preview.max_height),
"-quality",
rt.preview.image_quality,
string.format("PNG32:%s", cache_img_url),
})
:status()
else
-- other image
local no_skip_job = { skip = 0, file = job.file, args = {} }
cache_img_status, image_preload_err = image_plugin:preload(no_skip_job)
end
if not cache_img_status then
err_msg = err_msg .. (image_preload_err and (tostring(image_preload_err)) or "")
end
end end
end end
end end
local cache_mediainfo_cha = fs.cha(cache_mediainfo_url) local cache_mediainfo_cha = fs.cha(cache_mediainfo_url)
if cache_mediainfo_cha and not job.args.force_reload_mediainfo then if cache_mediainfo_cha and not job.args.force_reload_mediainfo then
return true return true, err_msg ~= "" and ("Error: " .. err_msg) or nil
end end
local cmd = "mediainfo" local cmd = "mediainfo"
local output, err = Command(cmd):arg({ tostring(job.file.url) }):stdout(Command.PIPED):output() local output, err
if is_valid_utf8_path then
output, err = Command(cmd):arg({ tostring(job.file.url) }):output()
else
cmd = "cd "
.. path_quote(job.file.url.parent)
.. " && "
.. cmd
.. " "
.. path_quote(tostring(job.file.url.name))
output, err = Command(SHELL):arg({ "-c", cmd }):arg({ tostring(job.file.url) }):output()
end
if err then if err then
err_msg = err_msg .. string.format("Failed to start `%s`, Do you have `%s` installed?\n", cmd, cmd) err_msg = err_msg .. string.format("Failed to start `%s`, Do you have `%s` installed?\n", cmd, cmd)
end end
return fs.write( return fs.write(
cache_mediainfo_url, cache_mediainfo_url,
(err_msg ~= "" and "Error: " .. err_msg or "") .. (output and output.stdout or "") (err_msg ~= "" and ("Error: " .. err_msg) or "") .. (output and output.stdout or "")
) )
end end

View File

@ -7,7 +7,12 @@ local toggle_ui = ya.sync(function(self)
else else
self.children = Modal:children_add(self, 10) self.children = Modal:children_add(self, 10)
end end
ya.render() -- TODO: remove this
if ui.render then
ui.render()
else
ya.render()
end
end) end)
local subscribe = ya.sync(function(self) local subscribe = ya.sync(function(self)
@ -18,7 +23,12 @@ end)
local update_partitions = ya.sync(function(self, partitions) local update_partitions = ya.sync(function(self, partitions)
self.partitions = partitions self.partitions = partitions
self.cursor = math.max(0, math.min(self.cursor or 0, #self.partitions - 1)) self.cursor = math.max(0, math.min(self.cursor or 0, #self.partitions - 1))
ya.render() -- TODO: remove this
if ui.render then
ui.render()
else
ya.render()
end
end) end)
local active_partition = ya.sync(function(self) return self.partitions[self.cursor + 1] end) local active_partition = ya.sync(function(self) return self.partitions[self.cursor + 1] end)
@ -29,7 +39,12 @@ local update_cursor = ya.sync(function(self, cursor)
else else
self.cursor = ya.clamp(0, self.cursor + cursor, #self.partitions - 1) self.cursor = ya.clamp(0, self.cursor + cursor, #self.partitions - 1)
end end
ya.render() -- TODO: remove this
if ui.render then
ui.render()
else
ya.render()
end
end) end)
local M = { local M = {

View File

@ -12,7 +12,7 @@
### Yazi package manager ### Yazi package manager
```bash ```bash
ya pack -a ndtoan96/ouch ya pkg add ndtoan96/ouch
``` ```
### Git ### Git
@ -43,8 +43,12 @@ prepend_previewers = [
{ mime = "application/x-bzip2", run = "ouch" }, { mime = "application/x-bzip2", run = "ouch" },
{ mime = "application/x-7z-compressed", run = "ouch" }, { mime = "application/x-7z-compressed", run = "ouch" },
{ mime = "application/x-rar", run = "ouch" }, { mime = "application/x-rar", run = "ouch" },
{ mime = "application/vnd.rar", run = "ouch" },
{ mime = "application/x-xz", run = "ouch" }, { mime = "application/x-xz", run = "ouch" },
{ mime = "application/xz", run = "ouch" }, { mime = "application/xz", run = "ouch" },
{ mime = "application/x-zstd", run = "ouch" },
{ mime = "application/zstd", run = "ouch" },
{ mime = "application/java-archive", run = "ouch" },
] ]
``` ```

View File

@ -126,6 +126,7 @@ function M:entry(job)
title = "Create archive:", title = "Create archive:",
value = default_name .. "." .. default_fmt, value = default_name .. "." .. default_fmt,
position = { "top-center", y = 3, w = 40 }, position = { "top-center", y = 3, w = 40 },
pos = { "top-center", y = 3, w = 40 },
}) })
if name_event ~= 1 then if name_event ~= 1 then
return return
@ -136,6 +137,7 @@ function M:entry(job)
local confirm, confirm_event = ya.input({ local confirm, confirm_event = ya.input({
title = "Overwrite " .. output_name .. "? (y/N)", title = "Overwrite " .. output_name .. "? (y/N)",
position = { "top-center", y = 3, w = 40 }, position = { "top-center", y = 3, w = 40 },
pos = { "top-center", y = 3, w = 40 },
}) })
if not (confirm_event == 1 and confirm:lower() == "y") then if not (confirm_event == 1 and confirm:lower() == "y") then
return return

View File

@ -2,7 +2,7 @@
A [Yazi](https://github.com/sxyazi/yazi) plugin based about vim motions. A [Yazi](https://github.com/sxyazi/yazi) plugin based about vim motions.
https://github.com/dedukun/relative-motions.yazi/assets/25795432/04fb186a-5efe-442d-8d7b-2dccb6eee408 <https://github.com/dedukun/relative-motions.yazi/assets/25795432/04fb186a-5efe-442d-8d7b-2dccb6eee408>
## Requirements ## Requirements
@ -11,7 +11,7 @@ https://github.com/dedukun/relative-motions.yazi/assets/25795432/04fb186a-5efe-4
## Installation ## Installation
```sh ```sh
ya pack -a dedukun/relative-motions ya pkg add dedukun/relative-motions
``` ```
## Configuration ## Configuration
@ -21,47 +21,47 @@ If you want to use the numbers directly to start a motion add this to your `keym
<details> <details>
```toml ```toml
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "1" ] on = [ "1" ]
run = "plugin relative-motions 1" run = "plugin relative-motions 1"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "2" ] on = [ "2" ]
run = "plugin relative-motions 2" run = "plugin relative-motions 2"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "3" ] on = [ "3" ]
run = "plugin relative-motions 3" run = "plugin relative-motions 3"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "4" ] on = [ "4" ]
run = "plugin relative-motions 4" run = "plugin relative-motions 4"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "5" ] on = [ "5" ]
run = "plugin relative-motions 5" run = "plugin relative-motions 5"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "6" ] on = [ "6" ]
run = "plugin relative-motions 6" run = "plugin relative-motions 6"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "7" ] on = [ "7" ]
run = "plugin relative-motions 7" run = "plugin relative-motions 7"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "8" ] on = [ "8" ]
run = "plugin relative-motions 8" run = "plugin relative-motions 8"
desc = "Move in relative steps" desc = "Move in relative steps"
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "9" ] on = [ "9" ]
run = "plugin relative-motions 9" run = "plugin relative-motions 9"
desc = "Move in relative steps" desc = "Move in relative steps"
@ -72,7 +72,7 @@ desc = "Move in relative steps"
Alternatively you can use a key to trigger a new motion without any initial value, for that add the following in `keymap.toml`: Alternatively you can use a key to trigger a new motion without any initial value, for that add the following in `keymap.toml`:
```toml ```toml
[[manager.prepend_keymap]] [[mgr.prepend_keymap]]
on = [ "m" ] on = [ "m" ]
run = "plugin relative-motions" run = "plugin relative-motions"
desc = "Trigger a new relative motion" desc = "Trigger a new relative motion"

View File

@ -40,7 +40,11 @@ local ENTER_MODE_CACHE_OR_FIRST = 2
----------------------------------------------- -----------------------------------------------
local render_motion_setup = ya.sync(function(_) local render_motion_setup = ya.sync(function(_)
ya.render() if ui.render then
ui.render()
else
ya.render()
end
Status.motion = function() return ui.Span("") end Status.motion = function() return ui.Span("") end
@ -60,7 +64,11 @@ local render_motion_setup = ya.sync(function(_)
end) end)
local render_motion = ya.sync(function(_, motion_num, motion_cmd) local render_motion = ya.sync(function(_, motion_num, motion_cmd)
ya.render() if ui.render then
ui.render()
else
ya.render()
end
Status.motion = function(self) Status.motion = function(self)
if not motion_num then if not motion_num then
@ -80,17 +88,29 @@ local render_motion = ya.sync(function(_, motion_num, motion_cmd)
local separator_open = status_config.sep_right.open local separator_open = status_config.sep_right.open
local separator_close = status_config.sep_right.close local separator_close = status_config.sep_right.close
-- TODO: REMOVE THIS IN NEXT RELEASE
local bg_style
if type(style.main.bg) == "function" then
bg_style = style.main:bg()
else
bg_style = style.main.bg
end
return ui.Line { return ui.Line {
ui.Span(separator_open):fg(style.main.bg), ui.Span(separator_open):fg(bg_style),
motion_span:style(style.main), motion_span:style(style.main),
ui.Span(separator_close):fg(style.main.bg), ui.Span(separator_close):fg(bg_style),
ui.Span(" "), ui.Span(" "),
} }
end end
end) end)
local render_numbers = ya.sync(function(_, mode) local render_numbers = ya.sync(function(_, mode)
ya.render() if ui.render then
ui.render()
else
ya.render()
end
Entity.number = function(_, index, total, file, hovered) Entity.number = function(_, index, total, file, hovered)
local idx local idx

View File

@ -16,7 +16,8 @@ end)
local function prompt() local function prompt()
return ya.input { return ya.input {
title = "Smart filter:", title = "Smart filter:",
position = { "center", w = 50 }, pos = { "center", w = 50 },
position = { "center", w = 50 }, -- TODO: remove
realtime = true, realtime = true,
debounce = 0.1, debounce = 0.1,
} }

View File

@ -2,12 +2,10 @@ local M = {}
function M:peek(job) function M:peek(job)
local child = Command("transmission-show") local child = Command("transmission-show")
:args({ :arg(tostring(job.file.url))
tostring(job.file.url), :stdout(Command.PIPED)
}) :stderr(Command.PIPED)
:stdout(Command.PIPED) :spawn()
:stderr(Command.PIPED)
:spawn()
if not child then if not child then
return require("code"):peek(job) return require("code"):peek(job)
@ -33,8 +31,8 @@ function M:peek(job)
if job.skip > 0 and i < job.skip + limit then 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 }) ya.manager_emit("peek", { math.max(0, i - limit), only_if = job.file.url, upper_bound = true })
else else
lines = lines:gsub("\t", string.rep(" ", PREVIEW.tab_size)) lines = lines:gsub("\t", string.rep(" ", rt.preview.tab_size))
ya.preview_widgets(job, { ui.Text.parse(lines):area(job.area) }) ya.preview_widget(job, { ui.Text.parse(lines):area(job.area) })
end end
end end
@ -43,4 +41,3 @@ function M:seek(job)
end end
return M return M

View File

@ -26,6 +26,13 @@ what-size supports Yazi on Linux, macOS, and Windows.
## Installation ## Installation
```sh
ya pkg add pirafrank/what-size
```
or
**DEPRECATED**
```sh ```sh
ya pack -a 'pirafrank/what-size' ya pack -a 'pirafrank/what-size'
``` ```
@ -35,26 +42,26 @@ ya pack -a 'pirafrank/what-size'
Add this to your `~/.config/yazi/keymap.toml`: Add this to your `~/.config/yazi/keymap.toml`:
```toml ```toml
[manager] [[mgr.prepend_keymap]]
prepend_keymap = [ on = [ ".", "s" ]
{ on = [ ".", "s" ], run = "plugin what-size", desc = "Calc size of selection or cwd" }, run = "plugin what-size"
] desc = "Calc size of selection or cwd"
``` ```
If you want to copy the result to clipboard, you can add `--clipboard` or `-c` as 2nd positional argument: If you want to copy the result to clipboard, you can add `--clipboard` or `-c` as 2nd positional argument:
```toml ```toml
[manager] [[mgr.prepend_keymap]]
prepend_keymap = [ on = [ ".", "s" ]
{ on = [ ".", "s" ], run = "plugin what-size -- '--clipboard'", desc = "Calc size of selection or cwd" }, run = "plugin what-size -- '--clipboard'"
] desc = "Calc size of selection or cwd"
``` ```
```toml ```toml
[manager] [[mgr.prepend_keymap]]
prepend_keymap = [ on = [ ".", "s" ]
{ on = [ ".", "s" ], run = "plugin what-size -- '-c'", desc = "Calc size of selection or cwd" }, run = "plugin what-size -- '-c'"
] desc = "Calc size of selection or cwd"
``` ```
Change to whatever keybinding you like. Change to whatever keybinding you like.

View File

@ -46,7 +46,13 @@ local function get_total_size(items)
return total return total
else else
local arg = ya.target_os() == "macos" and "-scA" or "-scb" local arg = ya.target_os() == "macos" and "-scA" or "-scb"
local output, err = Command("du"):arg(arg):arg(items):output() -- pass args as string
local cmd = Command("du"):arg(arg)
for _, path in ipairs(items) do
cmd = cmd:arg(path)
end
local output, err = cmd:output()
if not output then if not output then
ya.err("Failed to run du: " .. err) ya.err("Failed to run du: " .. err)
end end
@ -93,4 +99,4 @@ return {
timeout = 4, timeout = 4,
} }
end, end,
} }