Browse Source

Added yazi/fsel configs

master
chodak166 2 weeks ago
parent
commit
ade62929ac
  1. 22
      .config/fsel/config.toml
  2. 7
      .config/i3/config
  3. 12
      .config/nvim/lazy-lock.json
  4. 21
      .config/yazi/flavors/everforest-medium.yazi/LICENSE
  5. 21
      .config/yazi/flavors/everforest-medium.yazi/LICENSE-tmtheme
  6. 45
      .config/yazi/flavors/everforest-medium.yazi/README.md
  7. 179
      .config/yazi/flavors/everforest-medium.yazi/flavor.toml
  8. BIN
      .config/yazi/flavors/everforest-medium.yazi/preview.png
  9. 3186
      .config/yazi/flavors/everforest-medium.yazi/tmtheme.xml
  10. 21
      .config/yazi/flavors/gruvbox-material.yazi/LICENSE
  11. 201
      .config/yazi/flavors/gruvbox-material.yazi/LICENSE-tmtheme
  12. 42
      .config/yazi/flavors/gruvbox-material.yazi/README.md
  13. 214
      .config/yazi/flavors/gruvbox-material.yazi/flavor.toml
  14. BIN
      .config/yazi/flavors/gruvbox-material.yazi/preview.png
  15. 1376
      .config/yazi/flavors/gruvbox-material.yazi/tmtheme.xml
  16. 11
      .config/yazi/init.lua
  17. 56
      .config/yazi/keymap.toml
  18. 69
      .config/yazi/package.toml
  19. 21
      .config/yazi/plugins/chmod.yazi/LICENSE
  20. 28
      .config/yazi/plugins/chmod.yazi/README.md
  21. 47
      .config/yazi/plugins/chmod.yazi/main.lua
  22. 21
      .config/yazi/plugins/diff.yazi/LICENSE
  23. 28
      .config/yazi/plugins/diff.yazi/README.md
  24. 41
      .config/yazi/plugins/diff.yazi/main.lua
  25. 21
      .config/yazi/plugins/full-border.yazi/LICENSE
  26. 32
      .config/yazi/plugins/full-border.yazi/README.md
  27. 44
      .config/yazi/plugins/full-border.yazi/main.lua
  28. 21
      .config/yazi/plugins/git.yazi/LICENSE
  29. 86
      .config/yazi/plugins/git.yazi/README.md
  30. 259
      .config/yazi/plugins/git.yazi/main.lua
  31. 12
      .config/yazi/plugins/git.yazi/types.lua
  32. 21
      .config/yazi/plugins/gvfs.yazi/LICENSE
  33. 324
      .config/yazi/plugins/gvfs.yazi/README.md
  34. 23
      .config/yazi/plugins/gvfs.yazi/assets/automount.sh
  35. 9
      .config/yazi/plugins/gvfs.yazi/assets/gnome-keyring-daemon.service
  36. 2530
      .config/yazi/plugins/gvfs.yazi/main.lua
  37. 21
      .config/yazi/plugins/jump-to-char.yazi/LICENSE
  38. 28
      .config/yazi/plugins/jump-to-char.yazi/README.md
  39. 32
      .config/yazi/plugins/jump-to-char.yazi/main.lua
  40. 21
      .config/yazi/plugins/mount.yazi/LICENSE
  41. 50
      .config/yazi/plugins/mount.yazi/README.md
  42. 71
      .config/yazi/plugins/mount.yazi/cross.lua
  43. 272
      .config/yazi/plugins/mount.yazi/main.lua
  44. 54
      .config/yazi/plugins/mount.yazi/sudo.lua
  45. 19
      .config/yazi/plugins/open-with-cmd.yazi/LICENSE
  46. 25
      .config/yazi/plugins/open-with-cmd.yazi/README.md
  47. 19
      .config/yazi/plugins/open-with-cmd.yazi/main.lua
  48. 21
      .config/yazi/plugins/piper.yazi/LICENSE
  49. 102
      .config/yazi/plugins/piper.yazi/README.md
  50. 71
      .config/yazi/plugins/piper.yazi/main.lua
  51. 19
      .config/yazi/plugins/relative-motions.yazi/LICENSE
  52. 145
      .config/yazi/plugins/relative-motions.yazi/README.md
  53. 406
      .config/yazi/plugins/relative-motions.yazi/main.lua
  54. 21
      .config/yazi/plugins/smart-enter.yazi/LICENSE
  55. 40
      .config/yazi/plugins/smart-enter.yazi/README.md
  56. 11
      .config/yazi/plugins/smart-enter.yazi/main.lua
  57. 21
      .config/yazi/plugins/zoom.yazi/LICENSE
  58. 55
      .config/yazi/plugins/zoom.yazi/README.md
  59. 119
      .config/yazi/plugins/zoom.yazi/main.lua
  60. 3
      .config/yazi/theme.toml
  61. 37
      .config/yazi/yazi.toml
  62. 25
      .dotfiles.d/init/ubuntu/init-cargo-tools.sh
  63. 0
      .dotfiles.d/init/ubuntu/init-nvim.sh
  64. 3
      .dotfiles.d/init/ubuntu/init-shell.sh

22
.config/fsel/config.toml

@ -0,0 +1,22 @@
# Root level - UI/Color options go here
highlight_color = "LightBlue"
main_border_color = "White"
pin_color = "Orange"
terminal_launcher = "kitty -e" # or "tty" for TTY mode (-t/--tty)
# App launcher specific options
[app_launcher]
filter_desktop = true
filter_actions = false
list_executables_in_path = true
ranking_mode = "frecency"
pinned_order = "ranking"
# Dmenu mode overrides
[dmenu]
delimiter = " "
show_line_numbers = true
# Clipboard mode overrides
[cclip]
image_preview = true

7
.config/i3/config

@ -146,9 +146,14 @@ bindsym $mod+Return exec kitty
#bindsym Mod1+F2 exec dmenu_run
#let's replace dmenu by custom launcher:
bindsym $mod+d exec ulauncher
# bindsym $mod+d exec ulauncher
bindsym Mod1+F2 exec dmenu_run
# set $menu alacritty --title launcher -e fsel
bindsym $mod+d exec kitty --title launcher -o cursor_trail=0 -e fsel -r --detach
for_window [title="^launcher$"] floating enable, resize set width 500 height 430, border none
# run app assigned to current workspace
bindsym $mod+Shift+a exec $scriptsDir/autoapp
#################################################################

12
.config/nvim/lazy-lock.json

@ -1,10 +1,11 @@
{
"LazyVim": { "branch": "main", "commit": "83d90f339defdb109a6ede333865a66ffc7ef6aa" },
"avante.nvim": { "branch": "main", "commit": "f57f541959797bbca76e6e77efeb8b572e0bea2f" },
"avante.nvim": { "branch": "main", "commit": "0e40cb0c0f13b87be8a2276a844428d60c466d78" },
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
"catppuccin": { "branch": "main", "commit": "8edd468af4d63212b84d69b2ddb5ffc9023ef5eb" },
"conform.nvim": { "branch": "master", "commit": "18aeab3d63d350dcf44d64c462cc489a3412af40" },
"clangd_extensions.nvim": { "branch": "main", "commit": "78c2ecd659d54972be17aa6ba2deac3c53223b80" },
"conform.nvim": { "branch": "master", "commit": "619363c30309d29ffa631e67c8183f2a72caa373" },
"diffview.nvim": { "branch": "main", "commit": "4516612fe98ff56ae0415a259ff6361a89419b0a" },
"dotenv.nvim": { "branch": "main", "commit": "7d516e9293c6e3ac21830fb10a4e8674c02747c6" },
"dressing.nvim": { "branch": "master", "commit": "2d7c2db2507fa3c4956142ee607431ddb2828639" },
@ -26,16 +27,15 @@
"mini.pairs": { "branch": "main", "commit": "30cf2f01c4aaa2033db67376b9924fa2442c05d6" },
"noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" },
"nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
"nvim-dev-container": { "branch": "main", "commit": "365b4c815339d42133829006dce3e5f8b182b771" },
"nvim-lint": { "branch": "master", "commit": "d48f3a76189d03b2239f6df1b2f7e3fa8353743b" },
"nvim-lspconfig": { "branch": "master", "commit": "a4ed4e761c400849e8c9f8bda33e5083f890268c" },
"nvim-lspconfig": { "branch": "master", "commit": "9573948c38bfabeec353ae7dd7d3ffec4c506a6b" },
"nvim-treesitter": { "branch": "main", "commit": "4916d6592ede8c07973490d9322f187e07dfefac" },
"nvim-treesitter-textobjects": { "branch": "main", "commit": "851e865342e5a4cb1ae23d31caf6e991e1c99f1e" },
"nvim-ts-autotag": { "branch": "main", "commit": "88c1453db4ba7dd24131086fe51fdf74e587d275" },
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"render-markdown.nvim": { "branch": "main", "commit": "0fd43fb4b1f073931c4b481f5f3b7cea3749e190" },
"snacks.nvim": { "branch": "main", "commit": "0770753c88228f7f15449c6a5b242e3f7cd0d71c" },
"render-markdown.nvim": { "branch": "main", "commit": "5adf0895310c1904e5abfaad40a2baad7fe44a07" },
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" },
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
"tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" },
"trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" },

21
.config/yazi/flavors/everforest-medium.yazi/LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Chromium Oxide
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.

21
.config/yazi/flavors/everforest-medium.yazi/LICENSE-tmtheme

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Mitchell Hanberg
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.

45
.config/yazi/flavors/everforest-medium.yazi/README.md

@ -0,0 +1,45 @@
<div align="center">
<img src="https://github.com/sxyazi/yazi/blob/main/assets/logo.png?raw=true" alt="Yazi logo" width="20%">
</div>
<h3 align="center">
Example Flavor for <a href="https://github.com/sxyazi/yazi">Yazi</a>
</h3>
## 👀 Preview
<img src="preview.png" width="600" />
## 🎨 Installation
```bash
ya pkg add Chromium-3-Oxide/everforest-medium
```
Or:
```bash
ya pack -a Chromium-3-Oxide/everforest-medium
```
## ⚙ Usage
Add the these lines to your `theme.toml` configuration file to use it:
```toml
[flavor]
dark = "everforest-medium"
```
For Yazi versions before 0.4:
```toml
[flavor]
use = "everforest-medium"
```
## 📜 License
The flavor is MIT-licensed, and the included tmTheme is also MIT-licensed.
Check the [LICENSE](LICENSE) and [LICENSE-tmtheme](LICENSE-tmtheme) file for more details.

179
.config/yazi/flavors/everforest-medium.yazi/flavor.toml

@ -0,0 +1,179 @@
# vim:fileencoding=utf-8:foldmethod=marker
# : Manager {{{
[mgr]
cwd = { fg = "#7fbbb3" }
# Find
find_keyword = { fg = "#dbbc7f", bold = true, italic = true, underline = true }
find_position = { fg = "#d699b6", bg = "reset", bold = true, italic = true }
# Marker
marker_copied = { fg = "#a7c080", bg = "#a7c080" }
marker_cut = { fg = "#e67e80", bg = "#e67e80" }
marker_marked = { fg = "#7fbbb3", bg = "#7fbbb3" }
marker_selected = { fg = "#dbbc7f", bg = "#dbbc7f" }
# Count
count_copied = { fg = "#343f44", bg = "#a7c080" }
count_cut = { fg = "#343f44", bg = "#e67e80" }
count_selected = { fg = "#343f44", bg = "#dbbc7f" }
# Border
border_symbol = "│"
border_style = { fg = "#4f585e" }
# : }}}
# : Tabs {{{
[tabs]
active = { fg = "#343f44", bg = "#a7c080", bold = true }
inactive = { fg = "#a7c080", bg = "#3d484d" }
# : }}}
# : Mode {{{
[mode]
normal_main = { fg = "#3d484d", bg = "#a7c080", bold = true }
normal_alt = { fg = "#7fbbb3", bg = "#4f585e", bold = true }
# Select mode
select_main = { fg = "#3d484d", bg = "#e67e80", bold = true }
select_alt = { fg = "#7fbbb3", bg = "#4f585e", bold = true }
# Unset mode
unset_main = { fg = "#3d484d", bg = "#7fbbb3", bold = true }
unset_alt = { fg = "#7fbbb3", bg = "#4f585e", bold = true }
# : }}}
# : Status bar {{{
[status]
# Permissions
perm_sep = { fg = "#2d353b" }
perm_type = { fg = "#a7c080" }
perm_read = { fg = "#dbbc7f" }
perm_write = { fg = "#e67e80" }
perm_exec = { fg = "#7fbbb3" }
# Progress
progress_label = { bold = true }
progress_normal = { fg = "#7fbbb3", bg = "#232a2e" }
progress_error = { fg = "#e67e80", bg = "#232a2e" }
# : }}}
# : Pick {{{
[pick]
border = { fg = "#7fbbb3" }
active = { fg = "#d699b6", bold = true }
inactive = {}
# : }}}
# : Input {{{
[input]
border = { fg = "#7fbbb3" }
title = {}
value = {}
selected = { reversed = true }
# : }}}
# : Completion {{{
[cmp]
border = { fg = "#7fbbb3" }
# : }}}
# : Tasks {{{
[tasks]
border = { fg = "#7fbbb3" }
title = {}
hovered = { fg = "#d699b6", underline = true }
# : }}}
# : Which {{{
[which]
mask = { bg = "#2d353b" }
cand = { fg = "#7fbbb3" }
rest = { fg = "#2d353b" }
desc = { fg = "#d699b6" }
separator = " "
separator_style = { fg = "#2d353b" }
# : }}}
# : Help {{{
[help]
on = { fg = "#7fbbb3" }
run = { fg = "#d699b6" }
hovered = { reversed = true, bold = true }
footer = { fg = "#2d353b", bg = "#d3c6aa" }
# : }}}
# : Spotter {{{
[spot]
border = { fg = "#7fbbb3" }
title = { fg = "#7fbbb3" }
tbl_col = { fg = "#7fbbb3" }
tbl_cell = { fg = "#dbbc7f", reversed = true }
# : }}}
# : Notification {{{
[notify]
title_info = { fg = "#a7c080" }
title_warn = { fg = "#dbbc7f" }
title_error = { fg = "#e67e80" }
# : }}}
# : File-specific styles {{{
[filetype]
rules = [
# Images
{ mime = "image/*", fg = "#7fbbb3" },
# Media
{ mime = "{audio,video}/*", fg = "#d699b6" },
# Archives
{ mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#e67e80" },
# Documents
{ mime = "application/{pdf,doc,rtf}", fg = "#7fbbb3" },
# Virtual file system
{ mime = "vfs/{absent,stale}", fg = "#4f585e" },
# Fallback
{ url = "*", fg = "#83c092" },
{ url = "*/", fg = "#a7c080" },
]
# : }}}

BIN
.config/yazi/flavors/everforest-medium.yazi/preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

3186
.config/yazi/flavors/everforest-medium.yazi/tmtheme.xml

File diff suppressed because it is too large Load Diff

21
.config/yazi/flavors/gruvbox-material.yazi/LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 - Matthew Dong
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.

201
.config/yazi/flavors/gruvbox-material.yazi/LICENSE-tmtheme

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

42
.config/yazi/flavors/gruvbox-material.yazi/README.md

@ -0,0 +1,42 @@
<div align="center">
<img src="https://github.com/sxyazi/yazi/blob/main/assets/logo.png?raw=true" alt="Yazi logo" width="20%">
</div>
<h3 align="center">
Gruvbox Material Flavor for <a href="https://github.com/sxyazi/yazi">Yazi</a>
</h3>
## 👀 Preview
![gruvbox-material](./preview.png)
## 🎨 Installation
### Using package manager
```bash
ya pkg add matt-dong-123/gruvbox-material
```
### Manual install
```bash
# Linux/macOS
git clone https://github.com/matt-dong-123/gruvbox-material.yazi.git ~/.config/yazi/flavors/gruvbox-material.yazi
# Windows
git clone https://github.com/matt-dong-123/gruvbox-material.yazi.git %AppData%\yazi\config\flavors\gruvbox-material.yazi
```
## ⚙ Usage
Add the these lines to your `theme.toml` configuration file to use it:
```toml
[flavor]
dark = "gruvbox-material"
```
## 📜 License
Check the [LICENSE](LICENSE) file for more details.

214
.config/yazi/flavors/gruvbox-material.yazi/flavor.toml

@ -0,0 +1,214 @@
# vim:fileencoding=utf-8:foldmethod=marker
# : Manager {{{
[mgr]
cwd = { fg = "#89b482" }
# Find
find_keyword = { fg = "#d8a657", bold = true, italic = true, underline = true }
find_position = { fg = "#d3869b", bg = "reset", bold = true, italic = true }
# Marker
marker_copied = { fg = "#a9b665", bg = "#a9b665" }
marker_cut = { fg = "#ea6962", bg = "#ea6962" }
marker_marked = { fg = "#89b482", bg = "#89b482" }
marker_selected = { fg = "#d8a657", bg = "#d8a657" }
# Count
count_copied = { fg = "#282828", bg = "#a9b665" }
count_cut = { fg = "#282828", bg = "#ea6962" }
count_selected = { fg = "#282828", bg = "#d8a657" }
# Border
border_symbol = "│"
border_style = { fg = "#928374" }
# : }}}
# : Tabs {{{
[tabs]
active = { fg = "#282828", bg = "#7daea3", bold = true }
inactive = { fg = "#7daea3", bg = "#32302f" }
# : }}}
# : Mode {{{
[mode]
normal_main = { fg = "#282828", bg = "#7daea3", bold = true }
normal_alt = { fg = "#7daea3", bg = "#32302f" }
# Select mode
select_main = { fg = "#282828", bg = "#89b482", bold = true }
select_alt = { fg = "#89b482", bg = "#32302f" }
# Unset mode
unset_main = { fg = "#282828", bg = "#ea6962", bold = true }
unset_alt = { fg = "#ea6962", bg = "#32302f" }
# : }}}
# : Status bar {{{
[status]
# Permissions
perm_sep = { fg = "#928374" }
perm_type = { fg = "#7daea3" }
perm_read = { fg = "#d8a657" }
perm_write = { fg = "#ea6962" }
perm_exec = { fg = "#a9b665" }
# Progress
progress_label = { fg = "#ddc7a1", bold = true }
progress_normal = { fg = "#a9b665", bg = "#45403d" }
progress_error = { fg = "#d8a657", bg = "#ea6962" }
# : }}}
# : Pick {{{
[pick]
border = { fg = "#7daea3" }
active = { fg = "#d3869b", bold = true }
inactive = {}
# : }}}
# : Input {{{
[input]
border = { fg = "#7daea3" }
title = {}
value = {}
selected = { reversed = true }
# : }}}
# : Completion {{{
[cmp]
border = { fg = "#7daea3" }
# : }}}
# : Tasks {{{
[tasks]
border = { fg = "#7daea3" }
title = {}
hovered = { fg = "#d3869b", bold = true }
# : }}}
# : Which {{{
[which]
mask = { bg = "#32302f" }
cand = { fg = "#89b482" }
rest = { fg = "#a89984" }
desc = { fg = "#d3869b" }
separator = " "
separator_style = { fg = "#7c6f64" }
# : }}}
# : Help {{{
[help]
on = { fg = "#89b482" }
run = { fg = "#d3869b" }
hovered = { reversed = true, bold = true }
footer = { fg = "#32302f", bg = "#d4be98" }
# : }}}
# : Spotter {{{
[spot]
border = { fg = "#7daea3" }
title = { fg = "#7daea3" }
tbl_col = { fg = "#89b482" }
tbl_cell = { fg = "#d3869b", bg = "#45403d" }
# : }}}
# : Notification {{{
[notify]
title_info = { fg = "#a9b665" }
title_warn = { fg = "#d8a657" }
title_error = { fg = "#ea6962" }
# : }}}
# : File-specific styles {{{
[filetype]
rules = [
# Image
{ mime = "image/*", fg = "#89b482" },
# Media
{ mime = "{audio,video}/*", fg = "#d8a657" },
# Archive
{ mime = "application/{zip,rar,7z*,tar,gzip,xz,zstd,bzip*,lzma,compress,archive,cpio,arj,xar,ms-cab*}", fg = "#d3869b" },
# Document
{ mime = "application/{pdf,doc,rtf}", fg = "#a9b665" },
# Virtual file system
{ mime = "vfs/{absent,stale}", fg = "#a89984" },
# Fallback
{ url = "*", fg = "#d4be98" },
{ url = "*/", fg = "#7daea3" },
]
# : }}}
[icon]
dirs = [
{ name = ".config", text = "", fg = "#d3869b" },
{ name = ".git", text = "", fg = "#89b482" },
{ name = ".github", text = "", fg = "#7daea3" },
{ name = ".npm", text = "", fg = "#7daea3" },
{ name = "Desktop", text = "", fg = "#89b482" },
{ name = "Development", text = "", fg = "#89b482" },
{ name = "Documents", text = "", fg = "#89b482" },
{ name = "Downloads", text = "", fg = "#89b482" },
{ name = "Library", text = "", fg = "#89b482" },
{ name = "Movies", text = "", fg = "#89b482" },
{ name = "Music", text = "", fg = "#89b482" },
{ name = "Pictures", text = "", fg = "#89b482" },
{ name = "Public", text = "", fg = "#89b482" },
{ name = "Videos", text = "", fg = "#89b482" },
]
conds = [
# Special files
{ if = "orphan", text = "", fg = "#d4be98" },
{ if = "link", text = "", fg = "#928374" },
{ if = "block", text = "", fg = "#ea6962" },
{ if = "char", text = "", fg = "#ea6962" },
{ if = "fifo", text = "", fg = "#ea6962" },
{ if = "sock", text = "", fg = "#ea6962" },
{ if = "sticky", text = "", fg = "#ea6962" },
{ if = "dummy", text = "", fg = "#ea6962" },
# Fallback
{ if = "dir", text = "", fg = "#7daea3" },
{ if = "exec", text = "", fg = "#a9b665" },
{ if = "!dir", text = "", fg = "#d4be98" },
]

BIN
.config/yazi/flavors/gruvbox-material.yazi/preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

1376
.config/yazi/flavors/gruvbox-material.yazi/tmtheme.xml

File diff suppressed because it is too large Load Diff

11
.config/yazi/init.lua

@ -0,0 +1,11 @@
require("full-border"):setup({
-- Available values: ui.Border.PLAIN, ui.Border.ROUNDED
type = ui.Border.ROUNDED,
})
require("git"):setup({
-- Order of status signs showing in the linemode
order = 1500,
})
-- require("relative-motions"):setup({ show_numbers = "relative", show_motion = true, enter_mode = "first" })

56
.config/yazi/keymap.toml

@ -0,0 +1,56 @@
[[mgr.prepend_keymap]]
on = "M"
run = "plugin mount"
# [[mgr.prepend_keymap]]
# on = [ "m" ]
# run = "plugin relative-motions"
# desc = "Trigger a new relative motion"
[[mgr.prepend_keymap]]
on = "f"
run = "plugin jump-to-char"
desc = "Jump to char"
[[mgr.prepend_keymap]]
on = "F"
run = "filter --smart"
desc = "Filter files"
[[mgr.prepend_keymap]]
on = "l"
run = "plugin smart-enter"
desc = "Enter the child directory, or open the file"
[[mgr.prepend_keymap]]
on = [ "C" ]
run = "plugin chmod"
desc = "Chmod on selected files"
[[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"
# [[mgr.prepend_keymap]]
# on = "o"
# run = "plugin open-with-cmd -- block"
# desc = "Open with command in the terminal"
[[mgr.prepend_keymap]]
on = "L"
run = "plugin open-with-cmd"
desc = "Open with command"
[[mgr.prepend_keymap]]
on = "<C-d>"
run = "plugin diff"
desc = "Diff the selected with the hovered file"

69
.config/yazi/package.toml

@ -0,0 +1,69 @@
[[plugin.deps]]
use = "yazi-rs/plugins:mount"
rev = "598cdb6"
hash = "e3260d0b1feded8c8e3ae3afa1169e30"
[[plugin.deps]]
use = "yazi-rs/plugins:smart-enter"
rev = "598cdb6"
hash = "187cc58ba7ac3befd49c342129e6f1b6"
[[plugin.deps]]
use = "yazi-rs/plugins:full-border"
rev = "598cdb6"
hash = "7b625412411be411153886894d9acaf"
[[plugin.deps]]
use = "yazi-rs/plugins:git"
rev = "598cdb6"
hash = "88e56a64b7ce7c4314427452343fef17"
[[plugin.deps]]
use = "yazi-rs/plugins:chmod"
rev = "598cdb6"
hash = "f0c8c378184d5f8abd1b095a443d336d"
[[plugin.deps]]
use = "yazi-rs/plugins:zoom"
rev = "598cdb6"
hash = "fa268cb59989a87780605fdcfb8d99a9"
[[plugin.deps]]
use = "yazi-rs/plugins:piper"
rev = "598cdb6"
hash = "d99cfbc3812e7738505f9e4bedb759cd"
[[plugin.deps]]
use = "boydaihungst/gvfs"
rev = "3abc0a2"
hash = "eed89e75671723c8f9390a2862af0e4e"
[[plugin.deps]]
use = "Ape/open-with-cmd"
rev = "eba191d"
hash = "722a60eca1b338c9c24bb508d2d48578"
[[plugin.deps]]
use = "yazi-rs/plugins:diff"
rev = "598cdb6"
hash = "8b1af6b5a69797ee951f2a80ce570818"
[[plugin.deps]]
use = "dedukun/relative-motions"
rev = "a603d9e"
hash = "e02a788e5b8ae0fb47fd0193dda589cc"
[[plugin.deps]]
use = "yazi-rs/plugins:jump-to-char"
rev = "598cdb6"
hash = "7a4b4237223aaa94e589d1c01a23542a"
[[flavor.deps]]
use = "Chromium-3-Oxide/everforest-medium"
rev = "e1ead7b"
hash = "f7dc46200e53da5e94858630184a9220"
[[flavor.deps]]
use = "matt-dong-123/gruvbox-material"
rev = "e0fd2d8"
hash = "8f46ca96c0bbe1bdfb4fa201dd5eed4b"

21
.config/yazi/plugins/chmod.yazi/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.

28
.config/yazi/plugins/chmod.yazi/README.md

@ -0,0 +1,28 @@
# chmod.yazi
Execute `chmod` on the selected files to change their mode. This plugin is only available on Unix platforms since it relies on [`chmod(2)`](https://man7.org/linux/man-pages/man2/chmod.2.html).
https://github.com/yazi-rs/plugins/assets/17523360/7aa3abc2-d057-498c-8473-a6282c59c464
## Installation
```sh
ya pkg add yazi-rs/plugins:chmod
```
## Usage
Add this to your `~/.config/yazi/keymap.toml`:
```toml
[[mgr.prepend_keymap]]
on = [ "c", "m" ]
run = "plugin chmod"
desc = "Chmod on selected files"
```
Note that, the keybindings above are just examples, please tune them up as needed to ensure they don't conflict with your other actions/plugins.
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

47
.config/yazi/plugins/chmod.yazi/main.lua

@ -0,0 +1,47 @@
--- @since 26.1.22
local selected_or_hovered = ya.sync(function()
local tab, paths = cx.active, {}
for _, u in pairs(tab.selected) do
paths[#paths + 1] = tostring(u)
end
if #paths == 0 and tab.current.hovered then
paths[1] = tostring(tab.current.hovered.url)
end
return paths
end)
local function fail(s, ...)
ya.notify {
title = "Chmod",
content = string.format(s, ...),
level = "error",
timeout = 5,
}
end
return {
entry = function()
ya.emit("escape", { visual = true })
local urls = selected_or_hovered()
if #urls == 0 then
return ya.notify { title = "Chmod", content = "No file selected", level = "warn", timeout = 5 }
end
local value, event = ya.input {
title = "Chmod:",
pos = { "top-center", y = 3, w = 40 },
}
if event ~= 1 then
return
end
local output, err = Command("chmod"):arg(value):arg(urls):output()
if not output then
fail("Failed to run chmod: %s", err)
elseif not output.status.success then
fail("Chmod failed with stderr:\n%s", output.stderr:gsub("^chmod:%s*", ""))
end
end,
}

21
.config/yazi/plugins/diff.yazi/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.

28
.config/yazi/plugins/diff.yazi/README.md

@ -0,0 +1,28 @@
# diff.yazi
Diff the selected file with the hovered file, create a living patch, and copy it to the clipboard.
https://github.com/yazi-rs/plugins/assets/17523360/eff5e949-386a-44ea-82f9-4cb4a2c37aad
## Installation
```sh
ya pkg add yazi-rs/plugins:diff
```
## Usage
Add this to your `~/.config/yazi/keymap.toml`:
```toml
[[mgr.prepend_keymap]]
on = "<C-d>"
run = "plugin diff"
desc = "Diff the selected with the hovered file"
```
Note that, the keybindings above are just examples, please tune them up as needed to ensure they don't conflict with your other actions/plugins.
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

41
.config/yazi/plugins/diff.yazi/main.lua

@ -0,0 +1,41 @@
--- @since 26.1.22
local function info(content)
return ya.notify {
title = "Diff",
content = content,
timeout = 5,
}
end
local selected_path = ya.sync(function()
for _, u in pairs(cx.active.selected) do
return u.cache or u
end
end)
local hovered_path = ya.sync(function()
local h = cx.active.current.hovered
return h and h.path
end)
return {
entry = function()
local a, b = selected_path(), hovered_path()
if not a then
return info("No file selected")
elseif not b then
return info("No file hovered")
end
local output, err = Command("diff"):arg("-Naur"):arg(tostring(a)):arg(tostring(b)):output()
if not output then
return info("Failed to run diff, error: " .. err)
elseif output.stdout == "" then
return info("No differences found")
end
ya.clipboard(output.stdout)
info("Diff copied to clipboard")
end,
}

21
.config/yazi/plugins/full-border.yazi/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.

32
.config/yazi/plugins/full-border.yazi/README.md

@ -0,0 +1,32 @@
# full-border.yazi
Add a full border to Yazi to make it look fancier.
![full-border](https://github.com/yazi-rs/plugins/assets/17523360/ef81b560-2465-4d36-abf2-5d21dcb7b987)
## Installation
```sh
ya pkg add yazi-rs/plugins:full-border
```
## Usage
Add this to your `init.lua` to enable the plugin:
```lua
require("full-border"):setup()
```
Or you can customize the border type:
```lua
require("full-border"):setup {
-- Available values: ui.Border.PLAIN, ui.Border.ROUNDED
type = ui.Border.ROUNDED,
}
```
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

44
.config/yazi/plugins/full-border.yazi/main.lua

@ -0,0 +1,44 @@
--- @since 26.5.6
local function setup(_, opts)
local type = opts and opts.type or ui.Border.ROUNDED
local old_build = Tab.build
Tab.build = function(self, ...)
local bar = function(c, x, y)
if x <= 0 or x == self._area.w - 1 or th.mgr.border_symbol ~= "" then
return ui.Bar(ui.Edge.TOP)
end
return ui.Bar(ui.Edge.TOP)
:area(ui.Rect {
x = x,
y = math.max(0, y),
w = ya.clamp(0, self._area.w - x, 1),
h = math.min(1, self._area.h),
})
:symbol(c)
end
local c = self._chunks
self._chunks = {
c[1]:pad(ui.Pad.y(1)),
c[2]:pad(ui.Pad.y(1)),
c[3]:pad(ui.Pad.y(1)),
}
local style = th.mgr.border_style
self._base = ya.list_merge(self._base or {}, {
ui.Border(ui.Edge.ALL):area(self._area):type(type):style(style),
bar("", c[2].x, c[1].y),
bar("", c[2].x, c[1].bottom - 1),
bar("", c[2].right - 1, c[2].y),
bar("", c[2].right - 1, c[2].bottom - 1),
})
old_build(self, ...)
end
end
return { setup = setup }

21
.config/yazi/plugins/git.yazi/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.

86
.config/yazi/plugins/git.yazi/README.md

@ -0,0 +1,86 @@
# git.yazi
Show the status of Git file changes as linemode in the file list.
https://github.com/user-attachments/assets/34976be9-a871-4ffe-9d5a-c4cdd0bf4576
## Installation
```sh
ya pkg add yazi-rs/plugins:git
```
## Setup
Add the following to your `~/.config/yazi/init.lua`:
```lua
require("git"):setup {
-- Order of status signs showing in the linemode
order = 1500,
}
```
And register it as fetchers in your `~/.config/yazi/yazi.toml`:
```toml
[[plugin.prepend_fetchers]]
id = "git" # Remove if Yazi > v26.1.22
url = "*"
run = "git"
group = "git"
[[plugin.prepend_fetchers]]
id = "git" # Remove if Yazi > v26.1.22
url = "*/"
run = "git"
group = "git"
```
## Advanced
You can customize the [Style](https://yazi-rs.github.io/docs/configuration/theme#types.style) of the status sign with:
- `[git].unknown` - status cannot/not yet determined
- `[git].modified` - modified file
- `[git].added` - added file
- `[git].untracked` - untracked file
- `[git].ignored` - ignored file
- `[git].deleted` - deleted file
- `[git].updated` - updated file
- `[git].clean` - clean file
For example:
```toml
# theme.toml / flavor.toml
[git]
modified = { fg = "blue" }
deleted = { fg = "red", bold = true }
```
You can also customize the text of the status sign with:
- `[git].unknown_sign` - status cannot/not yet determined
- `[git].modified_sign` - modified file
- `[git].added_sign` - added file
- `[git].untracked_sign` - untracked file
- `[git].ignored_sign` - ignored file
- `[git].deleted_sign` - deleted file
- `[git].updated_sign` - updated file
- `[git].clean_sign` - clean file
For example:
```toml
# theme.toml / flavor.toml
[git]
unknown_sign = " "
modified_sign = "M"
deleted_sign = "D"
clean_sign = "✔"
```
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

259
.config/yazi/plugins/git.yazi/main.lua

@ -0,0 +1,259 @@
--- @since 26.5.6
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`
---@enum CODES
local CODES = {
unknown = 100, -- status cannot/not yet determined
excluded = 99, -- ignored directory
ignored = 6, -- ignored file
untracked = 5,
modified = 4,
added = 3,
deleted = 2,
updated = 1,
clean = 0,
}
local PATTERNS = {
{ "!$", CODES.ignored },
{ "?$", CODES.untracked },
{ "[MT]", CODES.modified },
{ "[AC]", CODES.added },
{ "D", CODES.deleted },
{ "U", CODES.updated },
{ "[AD][AD]", CODES.updated },
}
---@param line string
---@return CODES, string
local function match(line)
local signs = line:sub(1, 2)
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 = WINDOWS and path:gsub("/", "\\") or path
end
if not path then
elseif path:find("[/\\]$") then
-- 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 code, path
end
---@diagnostic disable-next-line: missing-return
end
end
---@param cwd Url
---@return string?
local function root(cwd)
local is_worktree = function(url)
local file, head = io.open(tostring(url)), nil
if file then
head = file:read(8)
file:close()
end
return head == "gitdir: "
end
repeat
local next = cwd:join(".git")
local cha = fs.cha(next)
if cha and (cha.is_dir or is_worktree(next)) then
return tostring(cwd)
end
cwd = cwd.parent
until not cwd
end
---@param changed Changes
---@return Changes
local function bubble_up(changed)
local new, empty = {}, Url("")
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 CODES.clean) > code and new[s] or code
url = url.parent
end
end
end
return new
end
---@param excluded string[]
---@param cwd Url
---@param repo Url
---@return Changes
local function propagate_down(excluded, cwd, repo)
local new, rel = {}, cwd:strip_prefix(repo)
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
end
---@param cwd string
---@param repo string
---@param changed Changes
local add = ya.sync(function(st, cwd, repo, changed)
---@cast st State
st.dirs[cwd] = repo
st.repos[repo] = st.repos[repo] or {}
for path, code in pairs(changed) do
if code == CODES.clean 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][path] = code
end
end
ui.render()
end)
---@param cwd string
local remove = ya.sync(function(st, cwd)
---@cast st State
local repo = st.dirs[cwd]
if not repo then
return
end
ui.render()
st.dirs[cwd] = nil
if not st.repos[repo] then
return
end
for _, r in pairs(st.dirs) do
if r == repo then
return
end
end
st.repos[repo] = nil
end)
---@param st State
---@param opts Options
local function setup(st, opts)
st.dirs = {}
st.repos = {}
opts = opts or {}
opts.order = opts.order or 1500
local t = th.git or {}
local styles = {
[CODES.unknown] = t.unknown or ui.Style(),
[CODES.ignored] = t.ignored or ui.Style():fg("darkgray"),
[CODES.untracked] = t.untracked or ui.Style():fg("magenta"),
[CODES.modified] = t.modified or ui.Style():fg("yellow"),
[CODES.added] = t.added or ui.Style():fg("green"),
[CODES.deleted] = t.deleted or ui.Style():fg("red"),
[CODES.updated] = t.updated or ui.Style():fg("yellow"),
[CODES.clean] = t.clean or ui.Style(),
}
local signs = {
[CODES.unknown] = t.unknown_sign or "",
[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 " ",
[CODES.clean] = t.clean_sign or "",
}
Linemode:children_add(function(self)
if not self._file.in_current then
return ""
end
local url = self._file.url
local repo = st.dirs[tostring(url.base or url.parent)]
local code = CODES.unknown
if repo then
code = repo == CODES.excluded and CODES.ignored or st.repos[repo][tostring(url):sub(#repo + 2)] or CODES.clean
end
if signs[code] == "" then
return ""
elseif self._file.is_hovered then
return ui.Line { " ", signs[code] }
else
return ui.Line { " ", ui.Span(signs[code]):style(styles[code]) }
end
end, opts.order)
end
---@type UnstableFetcher
local function fetch(_, job)
local cwd = job.files[1].url.base or job.files[1].url.parent
local repo = root(cwd)
if not repo then
remove(tostring(cwd))
return true
end
local paths = {}
for _, file in ipairs(job.files) do
paths[#paths + 1] = tostring(file.url)
end
-- stylua: ignore
local output, err = Command("git")
:cwd(tostring(cwd))
:arg({ "--no-optional-locks", "-c", "core.quotePath=", "status", "--porcelain", "-unormal", "--no-renames", "--ignored=matching" })
:arg(paths)
:output()
if not output then
return true, Err("Cannot spawn `git` command, error: %s", err)
end
local changed, excluded = {}, {}
for line in output.stdout:gmatch("[^\r\n]+") do
local code, path = match(line)
if code == CODES.excluded then
excluded[#excluded + 1] = path
else
changed[path] = code
end
end
if job.files[1].cha.is_dir then
ya.dict_merge(changed, bubble_up(changed))
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 `clean`,
-- 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.clean
end
add(tostring(cwd), repo, changed)
return false
end
return { setup = setup, fetch = fetch }

12
.config/yazi/plugins/git.yazi/types.lua

@ -0,0 +1,12 @@
---@class State
---@field dirs table<string, string|CODES> Mapping between a directory and its corresponding repository
---@field repos table<string, Changes> Mapping between a repository and the status of each of its files
---@class Options
---@field order number The order in which the status is displayed
---@field renamed boolean Whether to include renamed files in the status (or treat them as modified)
-- TODO: move this to `types.yazi` once it's get stable
---@alias UnstableFetcher fun(self: unknown, job: { files: File[] }): boolean, Error?
---@alias Changes table<string, CODES>

21
.config/yazi/plugins/gvfs.yazi/LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 boydaihungst
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

324
.config/yazi/plugins/gvfs.yazi/README.md

@ -0,0 +1,324 @@
# gvfs.yazi
<!-- toc -->
- [Preview](#preview)
- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Note for mounting using fstab](#note-for-mounting-using-fstab)
- [Troubleshooting](#troubleshooting)
<!-- tocstop -->
[gvfs.yazi](https://github.com/boydaihungst/gvfs.yazi) uses [gvfs](https://wiki.gnome.org/Projects/gvfs) and [gio from glib](https://github.com/GNOME/glib) to transparently mount and unmount devices or remote storage in read and write mode,
allowing you to navigate inside, view, and edit individual or groups of files and folders.
Supported protocols: MTP, Hard disk/drive, SMB, SFTP, NFS, GPhoto2 (PTP), FTP, Google Drive (via [GOA](./GNOME_ONLINE_ACCOUNTS_GOA.md)), One drive (via [GOA](./GNOME_ONLINE_ACCOUNTS_GOA.md)), DNS-SD, DAV (WebDAV), AFP, AFC. You need to install corresponding packages to use them.
Tested: MTP, Hard disk/drive (Encrypted and Unencrypted), GPhoto2 (PTP), DAV, SFTP, FTP, SMB, NFSv4, Google Drive, One Drive. You may need to unlock and turn screen on to mount some devices (Android MTP, etc.)
> [!NOTE]
>
> - This plugin only supports Linux
## Preview
https://github.com/user-attachments/assets/6aad98f7-081a-4e06-b398-5f7e8ca4ab39
Google-drive:
https://github.com/user-attachments/assets/fb74a710-5f05-4bf4-b95f-10f40583c5a0
## Features
- Supports all gvfs schemes/protocols (mtp, smb, ftp, sftp, nfs, gphoto2, afp, afc, sshfs, dav, davs, dav+sd, davs+sd, dns-sd)
- Mount hardware device or saved scheme/mount URI (use `--select-then-mount`)
- Auto-jump to mounted location after mount (use `select-then-mount --jump`)
- Unmount and eject hardware devices (use `select-then-unmount --eject`)
- Auto select the first device or saved scheme/mount URI if there is only one listed.
- Jump to mounted location (use `jump-to-device`)
- After jumped to mounted location, jump back to the previous location
with a single keybind. Make it easier to copy/paste files. (use `jump-back-prev-cwd`)
- Add/Edit/Remove scheme/mount URI (use `add-mount`, `edit-mount`, `remove-mount`). Check this for schemes/mount URI format: [schemes.html](<https://wiki.gnome.org/Projects(2f)gvfs(2f)schemes.html>)
- (Optional) Remember passwords using Keyring or Password Store (need `secret-tool` + `keyring` or `pass` + `gpg` installed)
## Requirements
1. [yazi >= 25.5.31](https://github.com/sxyazi/yazi)
2. This plugin only supports Linux, and requires having [GLib](https://github.com/GNOME/glib), [gvfs](https://gitlab.gnome.org/GNOME/gvfs) (need D-Bus Session)
```sh
# Ubuntu
sudo apt install gvfs libglib2.0-dev
# Fedora
sudo dnf install gvfs gvfs-fuse
# Arch
sudo pacman -S gvfs glib2
# Gentoo (Use elogind (openrc) or systemd)
# Add fuse USE flag to /etc/portage/package.use/gvfs.conf:
gnome-base/gvfs fuse
# Then run this to install gvfs:
sudo emerge -av gnome-base/gvfs
```
3. And other `gvfs` protocol packages, choose what you need, all of them are optional:
```sh
# Ubuntu
# This included all protocols
sudo apt install gvfs-backends gvfs-libs
# Fedora
sudo dnf install gvfs-afc gvfs-afp gvfs-archive gvfs-goa gvfs-gphoto2 gvfs-mtp gvfs-nfs gvfs-smb
# Arch
sudo pacman -S gvfs-mtp gvfs-afc gvfs-google gvfs-gphoto2 gvfs-nfs gvfs-smb gvfs-afc gvfs-dnssd gvfs-goa gvfs-onedrive gvfs-wsdd
# Gentoo
# Edit /etc/portage/package.use/gvfs.conf again, add more USE flags:
# https://wiki.gentoo.org/wiki/GVfs
gnome-base/gvfs afp gnome-online-accounts google ios mtp nfs onedrive samba zeroconf fuse gphoto2
# Then run this to update gvfs:
sudo emerge -av gnome-base/gvfs
```
4. For headless session (non-active console, like connect to a computer via SSH, etc.)
If you see `GVFS.yazi can only run on DBUS session` error message, please refer to [HEADLESS_WORKAROUND.md](./HEADLESS_WORKAROUND.md) for a workaround.
5. (Optional) Store passwords with Keyring or Password Store (secret-tool + keyring or pass + gpg)
There are two methods to securely store passwords. Please refer to [SECURE_SAVED_PASSWORD.md](./SECURE_SAVED_PASSWORD.md) for more information.
6. Restart to make sure gvfs deamon is started.
## Installation
```sh
ya pkg add boydaihungst/gvfs
```
Modify your `~/.config/yazi/init.lua` to include (`setup` function is required):
```lua
require("gvfs"):setup({
-- (Optional) Allowed keys to select device.
which_keys = "1234567890qwertyuiopasdfghjklzxcvbnm-=[]\\;',./!@#$%^&*()_+{}|:\"<>?",
-- (Optional) Table of blacklisted devices. These devices will be ignored in any actions
-- List of device properties to match, or a string to match the device name:
-- https://github.com/boydaihungst/gvfs.yazi/blob/master/main.lua#L144
blacklist_devices = { { name = "Wireless Device", scheme = "mtp" }, { scheme = "file" }, "Device Name"},
-- (Optional) Save file.
-- Default: ~/.config/yazi/gvfs.private
save_path = os.getenv("HOME") .. "/.config/yazi/gvfs.private",
-- (Optional) Save file for automount devices. Use with `automount-when-cd` action.
-- Default: ~/.config/yazi/gvfs_automounts.private
save_path_automounts = os.getenv("HOME") .. "/.config/yazi/gvfs_automounts.private",
-- (Optional) Input box position.
-- Default: { "top-center", y = 3, w = 60 },
-- Position, which is a table:
-- `1`: Origin position, available values: "top-left", "top-center", "top-right",
-- "bottom-left", "bottom-center", "bottom-right", "center", and "hovered".
-- "hovered" is the position of hovered file/folder
-- `x`: X offset from the origin position.
-- `y`: Y offset from the origin position.
-- `w`: Width of the input.
-- `h`: Height of the input.
input_position = { "center", y = 0, w = 60 },
-- (Optional) Select where to save passwords.
-- Default: nil
-- Available options: "keyring", "pass", or nil
password_vault = "keyring",
-- (Optional) Only need if you set password_vault = "pass"
-- Read the guide at SECURE_SAVED_PASSWORD.md to get your key_grip
key_grip = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
-- (Optional) Auto-save password after mount.
-- Default: false
save_password_autoconfirm = true,
-- (Optional) mountpoint of gvfs. Default: /run/user/USER_ID/gvfs
-- On some system it could be ~/.gvfs
-- You can't decide this path, it will be created automatically. Only changed if you know where gvfs mountpoint is.
-- Use command `ps aux | grep gvfs` to search for gvfs process and get the mountpoint path.
-- root_mountpoint = (os.getenv("XDG_RUNTIME_DIR") or ("/run/user/" .. ya.uid())) .. "/gvfs"
})
```
## Usage
> [!NOTE]
>
> - Moving files to the Trash bin does not work with some protocols (e.g., Android MTP). Please use permanent delete instead.
> - Scheme/Mount URIs shouldn't contain password, because they are saved as plain text in `yazi/config/gvfs.private`.
> - Google Drive, One drive are created via GNOME Online Accounts (GOA).
> Guide to setup [GNOME_ONLINE_ACCOUNTS_GOA.md](./GNOME_ONLINE_ACCOUNTS_GOA.md)
> - MTP, GPhoto2, AFC, Hard disk/drive, fstab with x-gvfs-show mount option, Google Drive + One drive protocols are listed automatically. So you don't need to add them via `add-mount` command.
> For other protocols (smb, ftp, sftp, etc), use `add-mount` command to add [Schemes/Mount URI](<https://wiki.gnome.org/Projects(2f)gvfs(2f)schemes.html>).
> - There is a bug in Yazi that prevents mounted folders from refreshing after they are mounted/unmounted.
> If you encounter this issue, try opening a new tab or moving the cursor up and down to trigger a refresh.
> - Mount Windows bitlocker drives requires bitlocker password to unlock: https://aka.ms/myrecoverykey or https://support.microsoft.com/en-us/windows/find-your-bitlocker-recovery-key-6b71ad27-0b89-ea08-f143-056f5ab347d6
> - Mount hard drives may require polkit rule to fix permission denied error. Refer to [HEADLESS_WORKAROUND.md](./HEADLESS_WORKAROUND.md) for a workaround.
Add this to your `~/.config/yazi/keymap.toml`:
```toml
[mgr]
prepend_keymap = [
# Mount
{ on = [ "M", "m" ], run = "plugin gvfs -- select-then-mount", desc = "Select device then mount" },
# or this if you want to jump to mountpoint after mounted
{ on = [ "M", "m" ], run = "plugin gvfs -- select-then-mount --jump", desc = "Select device to mount and jump to its mount point" },
# This will remount device under current working directory (cwd)
# -> cwd = /run/user/1000/gvfs/DEVICE_1/FOLDER_A
# -> device mountpoint = /run/user/1000/gvfs/DEVICE_1
# -> remount this DEVIEC_1 if needed
{ on = [ "M", "R" ], run = "plugin gvfs -- remount-current-cwd-device", desc = "Remount device under cwd" },
{ on = [ "M", "u" ], run = "plugin gvfs -- select-then-unmount", desc = "Select device then unmount" },
# Or this if you want to unmount and eject device.
# -> Ejected device can safely be removed.
# -> Ejecting a device will unmount all paritions/volumes under it.
# -> Fallback to normal unmount if not supported by device.
{ on = [ "M", "u" ], run = "plugin gvfs -- select-then-unmount --eject", desc = "Select device then eject" },
# Also support force unmount/eject.
# -> Ignore outstanding file operations when unmounting or ejecting
{ on = [ "M", "U" ], run = "plugin gvfs -- select-then-unmount --eject --force", desc = "Select device then force to eject/unmount" },
# Add Scheme/Mount URI:
# -> Available schemes: mtp, gphoto2, smb, sftp, ftp, nfs, dns-sd, dav, davs, dav+sd, davs+sd, afp, afc, sshfs
# -> Read more about the schemes here: https://wiki.gnome.org/Projects(2f)gvfs(2f)schemes.html
# -> Explain about the scheme:
# -> If it shows like this: {ftp,ftps,ftpis}://[user@]host[:port]
# -> All of the value within [] is optional. For values within {}, you must choose exactly one. All others are required.
# -> empty [user] or "anonymous" user is anonymous user in (ftp)
# -> ftp://anonymous@192.168.1.2:9999 -> skip user input step.
# -> ftp://192.168.1.2:9999 -> input empty value in user input box.
# -> Example: {ftp,ftps,ftpis}://[user@]host[:port] => ip and port: "ftp://myusername@192.168.1.2:9999" or domain: "ftps://myusername@github.com"
# -> More examples: smb://user@192.168.1.2/share, smb://WORKGROUP;user@192.168.1.2/share, sftp://user@192.168.1.2/, ftp://192.168.1.2/
# !WARNING: - Scheme/Mount URI shouldn't contain password.
# - Google Drive, One drive are listed automatically via GNOME Online Accounts (GOA). Avoid adding them.
# - MTP, GPhoto2, AFC, Hard disk/drive, fstab with x-gvfs-show are also listed automatically. Avoid adding them.
# - SSH, SFTP, FTP(s), AFC, DNS_SD now support [/share]. For example: sftp://user@192.168.1.2/home/user_name -> /share = /home/user_name
# - ssh:// is alias for sftp://.
# -> {sftp,ssh}://[user@]host[:port]. Host can be Host alias in .ssh/config file, ip or domain.
# -> For example (home is Host alias in .ssh/config file: Host home):
# -> ssh://user_name@home/home/user_name -> this will mount root path, but jump to subfolder /home/user_name
# -> sftp://user_name@192.168.1.2/home/user_name -> same as above but with ip
# -> sftp://user_name@192.168.1.2:9999/home/user_name -> same as above but with ip and port
{ on = [ "M", "a" ], run = "plugin gvfs -- add-mount", desc = "Add a GVFS mount URI" },
# Edit a Scheme/Mount URI
# -> Will clear saved passwords for that mount URI.
{ on = [ "M", "e" ], run = "plugin gvfs -- edit-mount", desc = "Edit a GVFS mount URI" },
# Remove a Scheme/Mount URI
# -> Will clear saved passwords for that mount URI.
{ on = [ "M", "r" ], run = "plugin gvfs -- remove-mount", desc = "Remove a GVFS mount URI" },
# Jump
{ on = [ "g", "m" ], run = "plugin gvfs -- jump-to-device", desc = "Select device then jump to its mount point" },
# If you use `x-systemd.automount` in /etc/fstab or manually added automount unit,
# then you can use `--automount` argument to auto mount device before jump.
# Otherwise it won't show up in the jump list.
{ on = [ "g", "m" ], run = "plugin gvfs -- jump-to-device --automount", desc = "Automount then select device to jump to its mount point" },
{ on = [ "`", "`" ], run = "plugin gvfs -- jump-back-prev-cwd", desc = "Jump back to the position before jumped to device" },
# Automount (This is different from `x-systemd.automount` in /etc/fstab)
# -> Hover over any file/folder under a mounted device then run `automount-when-cd` action to enable automount when cd/jump for that device.
# -> When you cd/jump to unmounted device mountpoint or its sub folder, this will auto-mount the device before jump.
# -> Works with any command or any bookmark plugin that change cwd. For example, use `yamb` to add bookmarks and jump to them, use yazi's built-in `cd` `back` `forward` commands:
# -> { on = [ "m", "a" ], run = [ "plugin yamb -- save", "plugin gvfs -- automount-when-cd" ], desc = "Add bookmark and enable automount when cd"}
{ on = [ "M", "t" ], run = "plugin gvfs -- automount-when-cd", desc = "Enable automount when cd to device under cwd" },
{ on = [ "M", "T" ], run = "plugin gvfs -- automount-when-cd --disabled", desc = "Disable automount when cd to device under cwd" },
]
```
It's highly recommended to add these lines to your `~/.config/yazi/yazi.toml`,
because GVFS is slow that can make yazi freeze when it preloads or previews a large number of files.
Especially when you use `Google-drive` or `One-drive`.
- Replace `1000` with your real user id (run `id -u` to get user id).
- Replace `USER_NAME` with your real user name (run `whoami` to get username).
> [!IMPORTANT]
>
> For yazi (>=v25.12.29) replace `name` with `url`
```toml
[plugin]
prepend_preloaders = [
# Do not preload files in mounted locations:
# Environment variable won't work here.
# Using absolute path instead.
{ name = "/run/user/1000/gvfs/**/*", run = "noop" },
# For mounted hard disk/drive
{ name = "/run/media/USER_NAME/**/*", run = "noop" },
]
prepend_previewers = [
# Allow to preview folder.
{ name = "*/", run = "folder" },
# Do not previewing files in mounted locations.
# Uncomment the line below to allow previewing text files.
# { mime = "{text/*,application/x-subrip}", run = "code" },
# Using absolute path.
{ name = "/run/user/1000/gvfs/**/*", run = "noop" },
# For mounted hard disk/drive.
{ name = "/run/media/USER_NAME/**/*", run = "noop" },
]
```
## Note for mounting using fstab
If you are using fstab to mount, you need to add `x-gvfs-show` to the mount options.
And with it you can only use `jump-to-device` and `jump-back-prev-cwd` actions.
- Example `/etc/fstab`:
- Mount on demand (manually mount):
```
192.168.1.10/hdd /mnt/myshare cifs noauto,credentials=/etc/samba/credentials,x-gvfs-show,iocharset=utf8,uid=1000,gid=1000,file_mode=0660,dir_mode=0770,nofail 0 0
UUID=XXXX-XXXX /mnt/myshare2 exfat noauto,defaults,x-gvfs-show 0 0
```
- Mount on access, add `x-systemd-automount` to the mount options:
Use `jump-to-device --automount`.
This will auto mount all mount entries that have `x-systemd-automount`, before jump to.
- Mount at boot, remove `noauto` from the mount options
Reload fstab:
```sh
sudo systemctl daemon-reload && sudo systemctl restart local-fs.target && sudo mount -a
```
If you changed mount options (like uid=, gid=, umask=, exfat, ntfs, etc.), already-mounted filesystems won't update unless you unmount and remount them.
You can manually remount a specific entry with these commands:
```sh
sudo umount /mnt/myshare
sudo mount -a
```
## Troubleshooting
If you have any problems with one of the protocols, please manually mount it using `gio mount Scheme/Mount URI`. See the [list of supported schemes](<https://wiki.gnome.org/Projects(2f)gvfs(2f)schemes.html>).
Then create an issue ticket and include the output of `gio mount -li` along with the list of mount points under `/run/user/1000/gvfs/` and `/run/media/USERNAME`

23
.config/yazi/plugins/gvfs.yazi/assets/automount.sh

@ -0,0 +1,23 @@
#!/bin/sh
# Iterate over all automount units
for unit in $(systemctl list-units --type=automount --no-legend | awk '{print $1}'); do
# Extract the mount path from the unit name
path=$(systemctl show -p Where --value "$unit")
# Skip certain system directories
case "$path" in
/proc* | /sys* | /dev*) continue ;;
esac
# Derive the corresponding .mount unit name from the path
mount_unit=$(systemd-escape -p --suffix=mount "$path")
# Check if the .mount unit is active (i.e., the filesystem is mounted)
if systemctl is-active --quiet "$mount_unit"; then
continue
fi
# If not mounted, log and then access the directory to trigger the automount
ls "$path" >/dev/null 2>&1 &
done

9
.config/yazi/plugins/gvfs.yazi/assets/gnome-keyring-daemon.service

@ -0,0 +1,9 @@
[Unit]
Description=GNOME Keyring Daemon
[Service]
ExecStart=/usr/bin/gnome-keyring-daemon --foreground --components=secrets,pkcs11,ssh
Restart=on-failure
[Install]
WantedBy=default.target

2530
.config/yazi/plugins/gvfs.yazi/main.lua

File diff suppressed because it is too large Load Diff

21
.config/yazi/plugins/jump-to-char.yazi/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.

28
.config/yazi/plugins/jump-to-char.yazi/README.md

@ -0,0 +1,28 @@
# jump-to-char.yazi
Vim-like `f<char>`, jump to the next file whose name starts with `<char>`.
https://github.com/yazi-rs/plugins/assets/17523360/aac9341c-b416-4e0c-aaba-889d48389869
## Installation
```sh
ya pkg add yazi-rs/plugins:jump-to-char
```
## Usage
Add this to your `~/.config/yazi/keymap.toml`:
```toml
[[mgr.prepend_keymap]]
on = "f"
run = "plugin jump-to-char"
desc = "Jump to char"
```
Note that, the keybindings above are just examples, please tune them up as needed to ensure they don't conflict with your other actions/plugins.
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

32
.config/yazi/plugins/jump-to-char.yazi/main.lua

@ -0,0 +1,32 @@
--- @since 25.5.31
local AVAILABLE_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789."
local changed = ya.sync(function(st, new)
local b = st.last ~= new
st.last = new
return b or not cx.active.finder
end)
local escape = function(s) return s == "." and "\\." or s end
return {
entry = function()
local cands = {}
for i = 1, #AVAILABLE_CHARS do
cands[#cands + 1] = { on = AVAILABLE_CHARS:sub(i, i) }
end
local idx = ya.which { cands = cands, silent = true }
if not idx then
return
end
local kw = escape(cands[idx].on)
if changed(kw) then
ya.emit("find_do", { "^" .. kw })
else
ya.emit("find_arrow", {})
end
end,
}

21
.config/yazi/plugins/mount.yazi/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.

50
.config/yazi/plugins/mount.yazi/README.md

@ -0,0 +1,50 @@
# mount.yazi
A mount manager for Yazi, providing disk mount, unmount, and eject functionality.
Supported platforms:
- Linux with [`udisksctl`](https://github.com/storaged-project/udisks), `lsblk` and `eject` both provided by [`util-linux`](https://github.com/util-linux/util-linux)
- macOS with `diskutil`, which is pre-installed
https://github.com/user-attachments/assets/c6f780ab-458b-420f-85cf-2fc45fcfe3a2
## Installation
```sh
ya pkg add yazi-rs/plugins:mount
```
## Usage
Add this to your `~/.config/yazi/keymap.toml`:
```toml
[[mgr.prepend_keymap]]
on = "M"
run = "plugin mount"
```
Note that, the keybindings above are just examples, please tune them up as needed to ensure they don't conflict with your other actions/plugins.
## Actions
| Key binding | Alternate key | Action |
| ------------ | ------------- | --------------------- |
| <kbd>q</kbd> | - | Quit the plugin |
| <kbd>k</kbd> | <kbd></kbd> | Move up |
| <kbd>j</kbd> | <kbd></kbd> | Move down |
| <kbd>l</kbd> | <kbd></kbd> | Enter the mount point |
| <kbd>m</kbd> | - | Mount the partition |
| <kbd>u</kbd> | - | Unmount the partition |
| <kbd>e</kbd> | - | Eject the disk |
## TODO
- Custom keybindings
- Windows support (I don't use Windows myself, PRs welcome!)
- Support mount, unmount, and eject the entire disk
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

71
.config/yazi/plugins/mount.yazi/cross.lua

@ -0,0 +1,71 @@
local M = {}
--- @param type "mount"|"unmount"|"eject"
--- @param partition table
function M.operate(type, partition)
if not partition then
return
elseif not partition.sub then
return -- TODO: mount/unmount main disk
end
local cmd, output, err
if ya.target_os() == "macos" then
cmd, output, err = "diskutil", M.diskutil(type, partition.src)
elseif ya.target_os() == "linux" then
if type == "eject" and partition.src:match("^/dev/sr%d+") then
M.udisksctl("unmount", partition.src)
cmd, output, err = "eject", M.eject(partition.src)
elseif type == "eject" then
M.udisksctl("unmount", partition.src)
cmd, output, err = "udisksctl", M.udisksctl("power-off", partition.src)
else
cmd, output, err = "udisksctl", M.udisksctl(type, partition.src)
end
end
if not cmd then
M.fail("mount.yazi is not currently supported on your platform")
elseif not output then
M.fail("Failed to spawn `%s`: %s", cmd, err)
elseif not output.status.success then
M.fail("Failed to %s `%s`: %s", type, partition.src, output.stderr)
end
end
--- @param type "mount"|"unmount"|"eject"
--- @param src string
--- @return Output? output
--- @return Error? err
function M.diskutil(type, src) return Command("diskutil"):arg({ type, src }):output() end
--- @param type "mount"|"unmount"|"power-off"
--- @param src string
--- @return Output? output
--- @return Error? err
function M.udisksctl(type, src)
local args = { type, "-b", src, "--no-user-interaction" }
local output, err = Command("udisksctl"):arg(args):output()
if not output or err then
return nil, err
elseif output.stderr:find("org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain", 1, true) then
local tx, rx = table.unpack(require(".main").permit)
tx:send(true)
ya.emit("which:dismiss", {})
local output, err = require(".sudo").run_with_sudo("udisksctl", args)
rx:recv()
return output, err
else
return output
end
end
--- @param src string
--- @return Output? output
--- @return Error? err
function M.eject(src) return Command("eject"):arg({ "--traytoggle", src }):output() end
function M.fail(...) ya.notify { title = "Mount", content = string.format(...), timeout = 10, level = "error" } end
return M

272
.config/yazi/plugins/mount.yazi/main.lua

@ -0,0 +1,272 @@
--- @since 26.5.6
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
ui.render()
end)
local subscribe = ya.sync(function()
ps.unsub("mount")
ps.sub("mount", function()
-- TODO: use `ya.async()`
ya.emit("plugin", { "mount", "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))
ui.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
ui.render()
end)
local M = {
keys = {
{ on = "q", run = "quit" },
{ on = "<Esc>", run = "quit" },
{ on = "<Enter>", run = { "enter", "quit" } },
{ on = "k", run = "up" },
{ on = "j", run = "down" },
{ on = "l", run = { "enter", "quit" } },
{ on = "<Up>", run = "up" },
{ on = "<Down>", run = "down" },
{ on = "<Right>", run = { "enter", "quit" } },
{ on = "m", run = "mount" },
{ on = "u", run = "unmount" },
{ on = "e", run = "eject" },
},
permit = table.pack(ya.chan("mpsc", 1)),
}
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()
self.permit[1]:send(true)
while true do
self.permit[2]:recv()
local idx = ya.which { cands = self.keys, silent = true }
self.permit[1]:send(true)
local cand = self.keys[idx] 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.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
require(".cross").operate("mount", active_partition())
elseif run == "unmount" then
require(".cross").operate("unmount", active_partition())
elseif run == "eject" then
require(".cross").operate("eject", active_partition())
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.Edge.ALL)
:area(self._area)
:type(ui.Border.ROUNDED)
:style(ui.Style():fg("blue"))
:title(ui.Line("Mount"):align(ui.Align.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(20),
},
}
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
{ "^/dev/sr%d+", ".+$" }, -- /dev/sr0
{ "^/dev/fd%d+", ".+$" }, -- /dev/fd0
{ "^/dev/md%d+", "p%d+$" }, -- /dev/md0p1
{ "^/dev/nbd%d+", "p%d+$" }, -- /dev/nbd0p1
{ "^/dev/bcache%d+", "p%d+$" }, -- /dev/bcache0p1
{ "^/dev/mapper/", ".+$" }, -- /dev/mapper/<name>
}
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"):arg({ "-p", "-o", "name,fstype", "-J" }):arg(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:click() end
function M:scroll() end
function M:touch() end
return M

54
.config/yazi/plugins/mount.yazi/sudo.lua

@ -0,0 +1,54 @@
local M = {}
--- Verify if `sudo` is already authenticated
--- @return boolean
--- @return Error?
function M.sudo_already()
local status, err = Command("sudo"):arg({ "--validate", "--non-interactive" }):status()
return status and status.success or false, err
end
--- Run a program with `sudo` privilege
--- @param program string
--- @param args table
--- @return Output? output
--- @return Error? err
function M.run_with_sudo(program, args)
local cmd = Command("sudo")
:arg({ "--stdin", "--user", "#" .. ya.uid(), "--", program })
:arg(args)
:stdin(Command.PIPED)
:stdout(Command.PIPED)
:stderr(Command.PIPED)
if M.sudo_already() then
return cmd:output()
end
local value, event = ya.input {
pos = { "top-center", y = 3, w = 40 },
title = string.format("Password for `sudo %s`:", program),
obscure = true,
}
if not value or event ~= 1 then
return nil, Err("Sudo password input cancelled")
end
local child, err = cmd:spawn()
if not child or err then
return nil, err
end
child:write_all(value .. "\n")
child:flush()
local output, err = child:wait_with_output()
if not output or err then
return nil, err
elseif output.status.success or M.sudo_already() then
return output
else
return nil, Err("Incorrect sudo password")
end
end
return M

19
.config/yazi/plugins/open-with-cmd.yazi/LICENSE

@ -0,0 +1,19 @@
Copyright (c) 2024 Lauri Niskanen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

25
.config/yazi/plugins/open-with-cmd.yazi/README.md

@ -0,0 +1,25 @@
# open-with-cmd.yazi
This is a Yazi plugin for opening files with a prompted command.
## Installation
Install the plugin:
```
ya pkg add Ape/open-with-cmd
```
Create `~/.config/yazi/keymap.toml` and add:
```
[[manager.prepend_keymap]]
on = "o"
run = "plugin open-with-cmd -- block"
desc = "Open with command in the terminal"
[[manager.prepend_keymap]]
on = "O"
run = "plugin open-with-cmd"
desc = "Open with command"
```

19
.config/yazi/plugins/open-with-cmd.yazi/main.lua

@ -0,0 +1,19 @@
return {
entry = function(_, job)
local block = job.args[1] and job.args[1] == "block"
local value, event = ya.input({
title = block and "Open with (block):" or "Open with:",
pos = { "hovered", y = 1, w = 50 },
})
if event == 1 then
local s = ya.target_family() == "windows" and " %*" or ' "$@"'
ya.emit("shell", {
value .. s,
block = block,
orphan = not block,
})
end
end,
}

21
.config/yazi/plugins/piper.yazi/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.

102
.config/yazi/plugins/piper.yazi/README.md

@ -0,0 +1,102 @@
# piper.yazi
Pipe any shell command as a previewer.
## Installation
```sh
ya pkg add yazi-rs/plugins:piper
```
## Usage
Piper is a general-purpose previewer - you can pass any shell command to `piper` and it will use the command's output as the preview content.
It accepts a string parameter, which is the shell command to be executed, for example:
```toml
# ~/.config/yazi/yazi.toml
[[plugin.prepend_previewers]]
url = "*"
run = 'piper -- echo "$1"'
```
This will set `piper` as the previewer for all file types and use `$1` (file path) as the preview content.
## Variables
Available variables:
- `$w`: the width of the preview area.
- `$h`: the height of the preview area.
- `$1`: the path to the file being previewed.
## Examples
Here are some configuration examples:
### Preview tarballs with [`tar`](https://man7.org/linux/man-pages/man1/tar.1.html)
```toml
[[plugin.prepend_previewers]]
url = "*.tar*"
run = 'piper --format=url -- tar tf "$1"'
```
In this example, `--format=url` tells `piper` to parse the `tar` output as file URLs, so you'll be able to get a list of files with icons.
### Preview CSV with [`bat`](https://github.com/sharkdp/bat)
```toml
[[plugin.prepend_previewers]]
url = "*.csv"
run = 'piper -- bat -p --color=always "$1"'
```
Note that certain distributions might use a different name than `bat`, like Debian and Ubuntu use `batcat`, so please adjust accordingly.
### Preview Markdown with [`glow`](https://github.com/charmbracelet/glow)
```toml
[[plugin.prepend_previewers]]
url = "*.md"
run = 'piper -- CLICOLOR_FORCE=1 glow -w=$w -s=dark "$1"'
```
Note that there's [a bug in Glow v2.0](https://github.com/charmbracelet/glow/issues/440#issuecomment-2307992634) that causes slight color differences between tty and non-tty environments.
### Preview directory tree with [`eza`](https://github.com/eza-community/eza)
```toml
[[plugin.prepend_previewers]]
url = "*/"
run = 'piper -- eza -TL=3 --color=always --icons=always --group-directories-first --no-quotes "$1"'
```
### Preview the schema of a SQLite database
```toml
[[plugin.prepend_previewers]]
mime = "application/sqlite3"
run = 'piper -- sqlite3 "$1" ".schema --indent"'
```
### Use [`hexyl`](https://github.com/sharkdp/hexyl) as fallback previewer
Yazi defaults to using [`file -bL "$1"`](https://github.com/sxyazi/yazi/blob/main/yazi-plugin/preset/plugins/file.lua) if there's no matched previewer.
This example uses `hexyl` as a fallback previewer instead of `file`.
```toml
[[plugin.append_previewers]]
url = "*"
run = 'piper -- hexyl --border=none --terminal-width=$w "$1"'
```
## Related projects
[`faster-piper.yazi`](https://github.com/alberti42/faster-piper.yazi): a cache-based, scrolling-optimized rewrite compatible with `piper.yazi`.
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.

71
.config/yazi/plugins/piper.yazi/main.lua

@ -0,0 +1,71 @@
--- @since 26.1.22
local M = {}
local function fail(job, s) ya.preview_widget(job, ui.Text.parse(s):area(job.area):wrap(ui.Wrap.YES)) end
function M:peek(job)
local child, err = Command("sh")
:arg({ "-c", job.args[1], "sh", tostring(job.file.path) })
:env("w", job.area.w)
:env("h", job.area.h)
:env("CYGWIN", "noupcaseenv")
:stdout(Command.PIPED)
:stderr(Command.PIPED)
:spawn()
if not child then
return fail(job, "sh: " .. err)
end
local limit = job.area.h
local i, outs, errs = 0, {}, {}
repeat
local next, event = child:read_line()
if event == 1 then
errs[#errs + 1] = next
elseif event ~= 0 then
break
end
i = i + 1
if i > job.skip then
outs[#outs + 1] = next
end
until i >= job.skip + limit
child:start_kill()
if #errs > 0 then
fail(job, table.concat(errs, ""))
elseif job.skip > 0 and i < job.skip + limit then
ya.emit("peek", { math.max(0, i - limit), only_if = job.file.url, upper_bound = true })
else
ya.preview_widget(job, M.format(job, outs))
end
end
function M:seek(job) require("code"):seek(job) end
function M.format(job, lines)
local format = job.args.format
if format ~= "url" then
local s = table.concat(lines, ""):gsub("\t", string.rep(" ", rt.preview.tab_size))
return ui.Text.parse(s):area(job.area)
end
for i = 1, #lines do
lines[i] = lines[i]:gsub("[\r\n]+$", "")
local icon = File({
url = Url(lines[i]),
cha = Cha { mode = tonumber(lines[i]:sub(-1) == "/" and "40700" or "100644", 8) },
}):icon()
if icon then
lines[i] = ui.Line { ui.Span(" " .. icon.text .. " "):style(icon.style), lines[i] }
end
end
return ui.Text(lines):area(job.area)
end
return M

19
.config/yazi/plugins/relative-motions.yazi/LICENSE

@ -0,0 +1,19 @@
Copyright (c) 2024 dedukun
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.

145
.config/yazi/plugins/relative-motions.yazi/README.md

@ -0,0 +1,145 @@
# relative-motions.yazi
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>
## Requirements
- [Yazi](https://github.com/sxyazi/yazi) v25.5.28+
## Installation
```sh
ya pkg add dedukun/relative-motions
```
## Configuration
If you want to use the numbers directly to start a motion add this to your `keymap.toml`:
<details>
```toml
[[mgr.prepend_keymap]]
on = [ "1" ]
run = "plugin relative-motions 1"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "2" ]
run = "plugin relative-motions 2"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "3" ]
run = "plugin relative-motions 3"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "4" ]
run = "plugin relative-motions 4"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "5" ]
run = "plugin relative-motions 5"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "6" ]
run = "plugin relative-motions 6"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "7" ]
run = "plugin relative-motions 7"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "8" ]
run = "plugin relative-motions 8"
desc = "Move in relative steps"
[[mgr.prepend_keymap]]
on = [ "9" ]
run = "plugin relative-motions 9"
desc = "Move in relative steps"
```
</details>
Alternatively you can use a key to trigger a new motion without any initial value, for that add the following in `keymap.toml`:
```toml
[[mgr.prepend_keymap]]
on = [ "m" ]
run = "plugin relative-motions"
desc = "Trigger a new relative motion"
```
---
Additionally there are a couple of initial configurations that can be given to the plugin's `setup` function:
| Configuration | Values | Default | Description |
| -------------- | ----------------------------------------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `show_numbers` | `relative`, `absolute`, `relative_absolute` or `none` | `none` | Shows relative or absolute numbers before the file icon |
| `show_motion` | `true` or `false` | `false` | Shows current motion in Status bar |
| `only_motions` | `true` or `false` | `false` | If true, only the motion movements will be enabled, i.e., the commands for delete, cut, yank and visual selection will be disabled |
| `enter_mode` | `cache`, `first` or `cache_or_first` | `cache_or_first` | The method to enter folders |
If you want, for example, to enable relative numbers as well as to show the motion in the status bar,
add the following to Yazi's `init.lua`, i.e. `~/.config/yazi/init.lua`:
```lua
-- ~/.config/yazi/init.lua
require("relative-motions"):setup({ show_numbers="relative", show_motion = true, enter_mode ="first" })
```
> [!NOTE]
> The `show_numbers` and `show_motion` functionalities overwrite [`Current:redraw`](https://github.com/sxyazi/yazi/blob/e3c91115a2c096724303a0b364e7625691e4beba/yazi-plugin/preset/components/current.lua#L28)
> and [`Status:children_redraw`](https://github.com/sxyazi/yazi/blob/e3c91115a2c096724303a0b364e7625691e4beba/yazi-plugin/preset/components/status.lua#L177) respectively.
> If you have custom implementations for any of this functions
> you can add the provided `Entity:number` and `Status:motion` to your implementations, just check [here](https://github.com/dedukun/relative-motions.yazi/blob/main/init.lua#L126) how we are doing things.
## Usage
This plugin adds the some basic vim motions like `3k`, `12j`, `10gg`, etc.
The following table show all the available motions:
| Command | Description |
| -------------- | --------------------- |
| `j`/`<Down>` | Move `n` lines down |
| `k`/`<Up>` | Move `n` lines up |
| `h`/`<Left>` | Move `n` folders back |
| `l`/`<Right>` | Enter `n` folders |
| `gj`/`g<Down>` | Go `n` lines down |
| `gk`/`g<Up>` | Go `n` lines up |
| `gg` | Go to line |
Furthermore, the following operations were also added:
| Command | Description |
| ------- | ------------- |
| `v` | visual select |
| `y` | Yank |
| `x` | Cut |
| `d` | Delete motion |
This however must be followed by a direction, which can be `j`/`<Down>`, `k`/`<Up>` or repeating the command key,
which will operate from the cursor down, e.g. `2yy` will copy two files.
Finally, we also support some tab operations:
| Command | Description |
| ------- | ------------------------------------ |
| `t` | create `n` tabs |
| `H` | Move `n` tabs left |
| `L` | Move `n` tabs right |
| `gt` | Go to the `n` tab |
| `w` | Close tab `n` |
| `W` | Close `n` tabs right |
| `<` | Swap current tab with `n` tabs left |
| `>` | Swap current tab with `n` tabs right |
| `~` | Swap current tab with tab `n` |

406
.config/yazi/plugins/relative-motions.yazi/main.lua

@ -0,0 +1,406 @@
--- @since 25.5.28
-- stylua: ignore
local MOTIONS_AND_OP_KEYS = {
{ on = "0" }, { on = "1" }, { on = "2" }, { on = "3" }, { on = "4" },
{ on = "5" }, { on = "6" }, { on = "7" }, { on = "8" }, { on = "9" },
-- commands
{ on = "d" }, { on = "v" }, { on = "y" }, { on = "x" },
-- tab commands
{ on = "t" }, { on = "L" }, { on = "H" }, { on = "w" },
{ on = "W" }, { on = "<" }, { on = ">" }, { on = "~" },
-- movement
{ on = "g" }, { on = "j" }, { on = "k" }, { on = "h" }, { on = "l" }, { on = "<Down>" }, { on = "<Up>" }, { on = "<Left>" }, { on = "<Right>" }
}
-- stylua: ignore
local MOTION_KEYS = {
{ on = "0" }, { on = "1" }, { on = "2" }, { on = "3" }, { on = "4" },
{ on = "5" }, { on = "6" }, { on = "7" }, { on = "8" }, { on = "9" },
-- movement
{ on = "g" }, { on = "j" }, { on = "k" }, { on = "h" }, { on = "l" }, { on = "<Down>" }, { on = "<Up>" }, { on = "<Left>" }, { on = "<Right>" }
}
-- stylua: ignore
local DIRECTION_KEYS = {
{ on = "j" }, { on = "k" }, { on = "<Down>" }, { on = "<Up>" },
-- tab movement
{ on = "t" }
}
local SHOW_NUMBERS_ABSOLUTE = 0
local SHOW_NUMBERS_RELATIVE = 1
local SHOW_NUMBERS_RELATIVE_ABSOLUTE = 2
local ENTER_MODE_FIRST = 0
local ENTER_MODE_CACHE = 1
local ENTER_MODE_CACHE_OR_FIRST = 2
-----------------------------------------------
----------------- R E N D E R -----------------
-----------------------------------------------
local render_motion_setup = ya.sync(function(_)
if ui.render then
ui.render()
else
ya.render()
end
Status.motion = function() return ui.Span("") end
Status.children_redraw = function(self, side)
local lines = {}
if side == self.RIGHT then
lines[1] = self:motion(self)
end
for _, c in ipairs(side == self.RIGHT and self._right or self._left) do
lines[#lines + 1] = (type(c[1]) == "string" and self[c[1]] or c[1])(self)
end
return ui.Line(lines)
end
-- TODO: check why it doesn't work line this
-- Status:children_add(function() return ui.Span("") end, 1000, Status.RIGHT)
end)
local render_motion = ya.sync(function(_, motion_num, motion_cmd)
if ui.render then
ui.render()
else
ya.render()
end
Status.motion = function(self)
if not motion_num then
return ui.Span("")
end
local style = self:style()
local motion_span
if not motion_cmd then
motion_span = ui.Span(string.format(" %3d ", motion_num))
else
motion_span = ui.Span(string.format(" %3d%s ", motion_num, motion_cmd))
end
local status_config = th.status
local separator_open = status_config.sep_right.open
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 {
ui.Span(separator_open):fg(bg_style),
motion_span:style(style.main),
ui.Span(separator_close):fg(bg_style),
ui.Span(" "),
}
end
end)
local render_numbers = ya.sync(function(_, mode)
if ui.render then
ui.render()
else
ya.render()
end
Entity.number = function(_, index, total, file, hovered)
local idx
if mode == SHOW_NUMBERS_RELATIVE then
idx = math.abs(hovered - index)
elseif mode == SHOW_NUMBERS_ABSOLUTE then
idx = file.idx
else -- SHOW_NUMBERS_RELATIVE_ABSOLUTE
if hovered == index then
idx = file.idx
else
idx = math.abs(hovered - index)
end
end
local num_format = "%" .. #tostring(total) .. "d"
-- emulate vim's hovered offset
if hovered == index then
return ui.Span(string.format(num_format .. " ", idx))
else
return ui.Span(string.format(" " .. num_format, idx))
end
end
Current.redraw = function(self)
local files = self._folder.window
if #files == 0 then
return self:empty()
end
local hovered_index
for i, f in ipairs(files) do
if f.is_hovered then
hovered_index = i
break
end
end
local entities, linemodes = {}, {}
for i, f in ipairs(files) do
linemodes[#linemodes + 1] = Linemode:new(f):redraw()
local entity = Entity:new(f)
entities[#entities + 1] = ui.Line({ Entity:number(i, #self._folder.files, f, hovered_index), entity:redraw() })
:style(entity:style())
end
return {
ui.List(entities):area(self._area),
ui.Text(linemodes):area(self._area):align(ui.Align.RIGHT),
}
end
end)
local function render_clear() render_motion() end
-----------------------------------------------
--------- C O M M A N D P A R S E R ---------
-----------------------------------------------
local get_keys = ya.sync(function(state) return state._only_motions and MOTION_KEYS or MOTIONS_AND_OP_KEYS end)
local function normal_direction(dir)
if dir == "<Down>" then
return "j"
elseif dir == "<Up>" then
return "k"
elseif dir == "<Left>" then
return "h"
elseif dir == "<Right>" then
return "l"
end
return dir
end
local function get_cmd(first_char, keys)
local last_key
local lines = first_char or ""
while true do
render_motion(tonumber(lines))
local key = ya.which { cands = keys, silent = true }
if not key then
return nil, nil, nil
end
last_key = keys[key].on
if not tonumber(last_key) then
last_key = normal_direction(last_key)
break
end
lines = lines .. last_key
end
render_motion(tonumber(lines), last_key)
-- command direction
local direction
if last_key == "g" or last_key == "v" or last_key == "d" or last_key == "y" or last_key == "x" then
DIRECTION_KEYS[#DIRECTION_KEYS + 1] = {
on = last_key,
}
local direction_key = ya.which { cands = DIRECTION_KEYS, silent = true }
if not direction_key then
return nil, nil, nil
end
direction = DIRECTION_KEYS[direction_key].on
direction = normal_direction(direction)
end
return tonumber(lines), last_key, direction
end
local function is_tab_command(command)
local tab_commands = { "t", "L", "H", "w", "W", "<", ">", "~" }
for _, cmd in ipairs(tab_commands) do
if command == cmd then
return true
end
end
return false
end
local get_active_tab = ya.sync(function(_) return cx.tabs.idx end)
local get_cache_or_first_dir = ya.sync(function(state)
if state._enter_mode == ENTER_MODE_CACHE then
return nil
elseif state._enter_mode == ENTER_MODE_CACHE_OR_FIRST then
local hovered_file = cx.active.current.hovered
if hovered_file ~= nil and hovered_file.cha.is_dir then
return cx.active.current.cursor
end
end
local files = cx.active.current.files
local index = 1
for i = 1, #files do
if files[i].cha.is_dir then
index = i
break
end
end
return index - 1
end)
-----------------------------------------------
---------- E N T R Y / S E T U P ----------
-----------------------------------------------
return {
entry = function(_, job)
local initial_value
local args = job.args
-- this is checking if the argument is a valid number
if #args > 0 then
initial_value = tostring(tonumber(args[1]))
if initial_value == "nil" then
return
end
end
local lines, cmd, direction = get_cmd(initial_value, get_keys())
if not lines or not cmd then
-- command was cancelled
render_clear()
return
end
if cmd == "g" then
if direction == "g" then
ya.mgr_emit("arrow", { "top" })
ya.mgr_emit("arrow", { lines - 1 })
render_clear()
return
elseif direction == "j" then
cmd = "j"
elseif direction == "k" then
cmd = "k"
elseif direction == "t" then
ya.mgr_emit("tab_switch", { lines - 1 })
render_clear()
return
else
-- no valid direction
render_clear()
return
end
end
if cmd == "j" then
ya.mgr_emit("arrow", { lines })
elseif cmd == "k" then
ya.mgr_emit("arrow", { -lines })
elseif cmd == "h" then
for _ = 1, lines do
ya.mgr_emit("leave", {})
end
elseif cmd == "l" then
for _ = 1, lines do
ya.mgr_emit("enter", {})
local file_idx = get_cache_or_first_dir()
if file_idx then
ya.mgr_emit("arrow", { "top" })
ya.mgr_emit("arrow", { file_idx })
end
end
elseif is_tab_command(cmd) then
if cmd == "t" then
for _ = 1, lines do
ya.mgr_emit("tab_create", {})
end
elseif cmd == "H" then
ya.mgr_emit("tab_switch", { -lines, relative = true })
elseif cmd == "L" then
ya.mgr_emit("tab_switch", { lines, relative = true })
elseif cmd == "w" then
ya.mgr_emit("tab_close", { lines - 1 })
elseif cmd == "W" then
local curr_tab = get_active_tab()
local del_tab = curr_tab + lines - 1
for _ = curr_tab, del_tab do
ya.mgr_emit("tab_close", { curr_tab - 1 })
end
ya.mgr_emit("tab_switch", { curr_tab - 1 })
elseif cmd == "<" then
ya.mgr_emit("tab_swap", { -lines })
elseif cmd == ">" then
ya.mgr_emit("tab_swap", { lines })
elseif cmd == "~" then
local jump = lines - get_active_tab()
ya.mgr_emit("tab_swap", { jump })
end
else
ya.mgr_emit("visual_mode", {})
-- invert direction when user specifies it
if direction == "k" then
ya.mgr_emit("arrow", { -lines })
elseif direction == "j" then
ya.mgr_emit("arrow", { lines })
else
ya.mgr_emit("arrow", { lines - 1 })
end
ya.mgr_emit("escape", {})
if cmd == "d" then
ya.mgr_emit("remove", {})
elseif cmd == "y" then
ya.mgr_emit("yank", {})
elseif cmd == "x" then
ya.mgr_emit("yank", { cut = true })
end
end
render_clear()
end,
setup = function(state, args)
if not args then
return
end
-- initialize state variables
state._only_motions = args["only_motions"] or false
if args["show_motion"] then
render_motion_setup()
end
if args["enter_mode"] == "cache" then
state._enter_mode = ENTER_MODE_CACHE
elseif args["enter_mode"] == "first" then
state._enter_mode = ENTER_MODE_FIRST
elseif args["enter_mode"] == "cache_or_first" then
state._enter_mode = ENTER_MODE_CACHE_OR_FIRST
else
state._enter_mode = ENTER_MODE_CACHE_OR_FIRST
end
if args["show_numbers"] == "absolute" then
render_numbers(SHOW_NUMBERS_ABSOLUTE)
elseif args["show_numbers"] == "relative" then
render_numbers(SHOW_NUMBERS_RELATIVE)
elseif args["show_numbers"] == "relative_absolute" then
render_numbers(SHOW_NUMBERS_RELATIVE_ABSOLUTE)
end
end,
}

21
.config/yazi/plugins/smart-enter.yazi/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.

40
.config/yazi/plugins/smart-enter.yazi/README.md

@ -0,0 +1,40 @@
# smart-enter.yazi
[`Open`][open] files or [`enter`][enter] directories all in one key!
## Installation
```sh
ya pkg add yazi-rs/plugins:smart-enter
```
## Usage
Bind your <kbd>l</kbd> key to the plugin, in your `~/.config/yazi/keymap.toml`:
```toml
[[mgr.prepend_keymap]]
on = "l"
run = "plugin smart-enter"
desc = "Enter the child directory, or open the file"
```
## Advanced
By default, `--hovered` is passed to the [`open`][open] action, make the behavior consistent with [`enter`][enter] avoiding accidental triggers,
which means both will only target the currently hovered file.
If you still want `open` to target multiple selected files, add this to your `~/.config/yazi/init.lua`:
```lua
require("smart-enter"):setup {
open_multi = true,
}
```
## License
This plugin is MIT-licensed. For more information check the [LICENSE](LICENSE) file.
[open]: https://yazi-rs.github.io/docs/configuration/keymap/#mgr.open
[enter]: https://yazi-rs.github.io/docs/configuration/keymap/#mgr.enter

11
.config/yazi/plugins/smart-enter.yazi/main.lua

@ -0,0 +1,11 @@
--- @since 25.5.31
--- @sync entry
local function setup(self, opts) self.open_multi = opts.open_multi end
local function entry(self)
local h = cx.active.current.hovered
ya.emit(h and h.cha.is_dir and "enter" or "open", { hovered = not self.open_multi })
end
return { entry = entry, setup = setup }

21
.config/yazi/plugins/zoom.yazi/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.

55
.config/yazi/plugins/zoom.yazi/README.md

@ -0,0 +1,55 @@
# zoom.yazi
Enlarge or shrink the preview image of a file, which is useful for magnifying small files for viewing.
Supported formats:
- Images - requires [ImageMagick](https://imagemagick.org/) (>= 7.1.1)
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.
https://github.com/user-attachments/assets/b28912b1-da63-43d3-a21f-b9e6767ed4a9
[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"
```
Note that, the keybindings above are just examples, please tune them up as needed to ensure they don't conflict with your other actions/plugins.
## Advanced
If you want to apply a default zoom parameter to image previews, you can specify it while setting this plugin up as a custom previewer, for example:
```toml
[[plugin.prepend_previewers]]
mime = "image/{jpeg,png,webp}"
run = "zoom 5"
```
## 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.

119
.config/yazi/plugins/zoom.yazi/main.lua

@ -0,0 +1,119 @@
--- @since 26.1.22
local get = ya.sync(function(st, url) return st.last == url and st.level end)
local save = ya.sync(function(st, url, new)
local h = cx.active.current.hovered
if h and h.url == url then
st.last, st.level = url, new
return true
end
end)
local lock = ya.sync(function(st, url, old, new)
if st.last == url and st.level == old then
st.level = new
return true
end
end)
local move = ya.sync(function(st)
local h = cx.active.current.hovered
if not h then
return
end
if st.last ~= h.url then
st.last, st.level = Url(h.url), 0
end
return { url = h.url, level = st.level }
end)
local function end_(job, err)
if not job.old_level then
ya.preview_widget(job, err and ui.Text(err):area(job.area):wrap(ui.Wrap.YES))
elseif err then
ya.notify { title = "Zoom", content = tostring(err), timeout = 5, level = "error" }
end
end
local function canvas(area)
local cw, ch = rt.term.cell_size()
if not cw then
return rt.preview.max_width, rt.preview.max_height
end
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 peek(_, job)
local url = job.file.url
local info, err = ya.image_info(url)
if not info then
return end_(job, Err("Failed to get image info: %s", err))
end
local level = ya.clamp(-10, job.new_level or get(Url(url)) or tonumber(job.args[1]) or 0, 10)
local sync = function()
if job.old_level then
return lock(url, job.old_level, level)
else
return save(url, level)
end
end
local max_w, max_h = canvas(job.area)
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 * level * 0.1)
local new_h = min_h + math.floor(min_h * level * 0.1)
if new_w > max_w or new_h > max_h then
if job.old_level then
return sync() -- Image larger than available preview area after zooming
else
new_w, new_h = max_w, max_h -- Run as a previewer, render the image anyway
end
end
local tmp = os.tmpname()
-- stylua: ignore
local output, err = Command("magick"):arg {
tostring(job.file.path),
"-auto-orient", "-strip",
"-sample", string.format("%dx%d", new_w, new_h),
"-quality", rt.preview.image_quality,
string.format("JPG:%s", tmp),
}:output()
if not output then
end_(job, Err("Failed to start `magick`, error: %s", err))
elseif not output.status.success then
end_(job, Err("`magick` exited with error code %s: %s", output.status.code, output.stderr))
elseif sync() then
ya.image_show(Url(tmp), job.area)
end
end_(job)
end
local function entry(self, job)
local st = move()
if not st then
return
end
local motion = tonumber(job.args[1]) or 0
local new = ya.clamp(-10, st.level + motion, 10)
if new ~= st.level then
peek(self, {
area = ui.area("preview"),
args = {},
file = File { url = st.url, cha = Cha { mode = tonumber("100644", 8) } },
skip = 0,
new_level = new,
old_level = st.level,
})
end
end
return { peek = peek, entry = entry }

3
.config/yazi/theme.toml

@ -0,0 +1,3 @@
[flavor]
# dark = "everforest-medium"
dark = "gruvbox-material"

37
.config/yazi/yazi.toml

@ -0,0 +1,37 @@
[[plugin.prepend_fetchers]]
# id = "git" # Remove if Yazi > v26.1.22
url = "*"
run = "git"
group = "git"
[[plugin.prepend_fetchers]]
# id = "git" # Remove if Yazi > v26.1.22
url = "*/"
run = "git"
group = "git"
# [opener]
# edit = [
# { run = 'nvim "$@"', desc = "Open in Neovim", block = true, for = "unix" },
# ]
# [[plugin.prepend_previewers]]
# url = "*"
# run = 'piper -- echo "$1"'
[[plugin.prepend_previewers]]
url = "*.md"
run = 'piper -- CLICOLOR_FORCE=1 glow -w=$w -s=dark "$1"'
[[plugin.prepend_previewers]]
url = "*/"
run = 'piper -- eza -TL=3 --color=always --icons=always --group-directories-first --no-quotes "$1"'
[[plugin.prepend_previewers]]
mime = "application/sqlite3"
run = 'piper -- sqlite3 "$1" ".schema --indent"'
[[plugin.append_previewers]]
url = "*"
run = 'piper -- hexyl --border=none --terminal-width=$w "$1"'

25
.dotfiles.d/init/ubuntu/init-cargo-tools.sh

@ -0,0 +1,25 @@
#!/bin/bash
set -euo pipefail
echo "[1/4] Updating apt and installing prerequisites (curl, build-essential)..."
sudo apt update -qq
sudo apt install -y curl build-essential imagemagick
sudo ln -s /usr/bin/convert /usr/bin/magick
echo "[2/4] Downloading and installing rustup (latest rustc/cargo)..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "[3/4] Sourcing cargo environment..."
source "$HOME/.cargo/env"
echo " -> Installed: $(rustc --version)"
echo " -> Installed: $(cargo --version)"
echo "[4/4] Installing tools..."
cargo install fsel
cargo install yazi
cargo install glow
cargo install resvg
echo "Done!"

0
.dotfiles.d/init/init-nvim.sh → .dotfiles.d/init/ubuntu/init-nvim.sh

3
.dotfiles.d/init/init-shell.sh → .dotfiles.d/init/ubuntu/init-shell.sh

@ -2,13 +2,12 @@
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
# ubuntu
sudo apt update -y
sudo apt install -y zsh eza unzip locales
sudo chsh -s $(which zsh) $USER
source "${SCRIPT_DIR}/ensure-locale.sh"
source "${SCRIPT_DIR}/../ensure-locale.sh"
cd ~
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
Loading…
Cancel
Save