mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-22 07:11:03 +00:00
Compare commits
No commits in common. "main" and "v0.2.2" have entirely different histories.
1555 changed files with 19110 additions and 82534 deletions
|
|
@ -1,16 +0,0 @@
|
|||
[env]
|
||||
MACOSX_DEPLOYMENT_TARGET = "10.12"
|
||||
JEMALLOC_SYS_WITH_LG_PAGE = "16"
|
||||
|
||||
# environment variable for tikv-jemalloc-sys
|
||||
#
|
||||
# https://jemalloc.net/jemalloc.3.html#opt.narenas
|
||||
# narenas is the maximum number of arenas to use for automatic multiplexing
|
||||
# of threads and arenas. The default is four times the number of CPUs,
|
||||
# or one if there is a single CPU.
|
||||
#
|
||||
# Improve memory efficiency by reducing fragmentation and ensuring all threads allocate from the same pool
|
||||
JEMALLOC_SYS_WITH_MALLOC_CONF = "narenas:1"
|
||||
|
||||
[target.aarch64-apple-darwin]
|
||||
rustflags = [ "-Ctarget-cpu=apple-m1" ]
|
||||
56
.github/DISCUSSION_TEMPLATE/1-q-a.yml
vendored
56
.github/DISCUSSION_TEMPLATE/1-q-a.yml
vendored
|
|
@ -1,56 +0,0 @@
|
|||
body:
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: What system are you running Yazi on?
|
||||
options:
|
||||
- Linux X11
|
||||
- Linux Wayland
|
||||
- macOS
|
||||
- Windows
|
||||
- Windows WSL
|
||||
- FreeBSD X11
|
||||
- FreeBSD Wayland
|
||||
- Android
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: terminal
|
||||
attributes:
|
||||
label: What terminal are you running Yazi in?
|
||||
placeholder: "ex: kitty v0.32.2"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: env
|
||||
attributes:
|
||||
label: "`ya env` output"
|
||||
description: Run `ya env` and paste the environment information here.
|
||||
render: Shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the question
|
||||
description: A clear and concise description of what the question is
|
||||
placeholder: Tell us what you want to know
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
label: Anything else?
|
||||
description: |
|
||||
Add any other context about the problem here. You can attach screenshots by clicking
|
||||
this area to highlight it and then drag the files in.
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Before submitting the post, please make sure you have completed the following
|
||||
options:
|
||||
- label: I have read all the documentation
|
||||
required: true
|
||||
- label: I have searched the existing discussions/issues
|
||||
required: true
|
||||
58
.github/ISSUE_TEMPLATE/bug.yml
vendored
58
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: 🐞 Bug Report
|
||||
name: Bug Report
|
||||
description: Create a report to help us improve
|
||||
labels: [bug]
|
||||
assignees: []
|
||||
|
|
@ -12,25 +12,30 @@ body:
|
|||
- Linux Wayland
|
||||
- macOS
|
||||
- Windows
|
||||
- Windows WSL
|
||||
- FreeBSD X11
|
||||
- FreeBSD Wayland
|
||||
- Android
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: terminal
|
||||
attributes:
|
||||
label: What terminal are you running Yazi in?
|
||||
placeholder: "ex: kitty v0.32.2"
|
||||
placeholder: "ex: Kitty v0.30.1"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: env
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: "`ya env` output"
|
||||
description: Run `ya env` and paste the environment information here.
|
||||
render: Shell
|
||||
label: Yazi version
|
||||
description: Please do a `yazi -V` and paste the output here.
|
||||
placeholder: "ex: yazi 0.1.5 (3867c29 2023-11-25)"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: tried_main
|
||||
attributes:
|
||||
label: Did you try the latest main branch to see if the problem has already been fixed?
|
||||
options:
|
||||
- Tried, but the problem is still present
|
||||
- Not tried, and I'll explain why below
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
|
@ -42,14 +47,28 @@ body:
|
|||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproducer
|
||||
id: expected
|
||||
attributes:
|
||||
label: Minimal reproducer
|
||||
description: A [minimal reproducer](https://stackoverflow.com/help/minimal-reproducible-example) is required, otherwise the issue might be closed without further notice.
|
||||
label: Expected Behavior
|
||||
description: A clear and concise description of what you expected to happen
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: to_repro
|
||||
attributes:
|
||||
label: To Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
Please include as much information as possible that can help to reproduce and understand the issue.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Configuration
|
||||
description: |
|
||||
Please include the relevant section(s) of your `yazi.toml`, `keymap.toml`, or `theme.toml` configuration file.
|
||||
You can enter "no config" if the issue happens without you having made a config file.
|
||||
- type: textarea
|
||||
id: other
|
||||
attributes:
|
||||
|
|
@ -57,14 +76,3 @@ body:
|
|||
description: |
|
||||
Add any other context about the problem here. You can attach screenshots by clicking
|
||||
this area to highlight it and then drag the files in.
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Before submitting the issue, please make sure you have completed the following
|
||||
options:
|
||||
- label: I tried the [latest nightly build](https://yazi-rs.github.io/docs/installation#binaries), and the issue is still reproducible
|
||||
required: true
|
||||
- label: I updated the environment information (`ya env`) field to the nightly that I tried
|
||||
required: true
|
||||
- label: I can reproduce it after disabling all custom configs/plugins (`mv ~/.config/yazi ~/.config/yazi-backup`)
|
||||
|
|
|
|||
14
.github/ISSUE_TEMPLATE/config.yml
vendored
14
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -1,14 +1,8 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 🚧 Build Issues
|
||||
url: https://github.com/sxyazi/yazi/discussions/new?category=3-build-issues
|
||||
about: If you have issues building Yazi from source code
|
||||
- name: 📝 Documentation Improvement
|
||||
url: https://github.com/yazi-rs/yazi-rs.github.io
|
||||
about: If you'd like to help improve the documentation
|
||||
- name: 💬 GitHub Discussions
|
||||
url: https://github.com/sxyazi/yazi/discussions/new?category=1-q-a
|
||||
about: When you have questions that are not bug reports or feature requests
|
||||
- name: 🌐 Discord Server / Telegram Group
|
||||
- name: Discord server / Telegram group
|
||||
url: https://github.com/sxyazi/yazi#discussion
|
||||
about: If you'd prefer more realtime conversation with the community
|
||||
- name: GitHub Discussions
|
||||
url: https://github.com/sxyazi/yazi/discussions
|
||||
about: When you have questions that are not bug reports or feature requests
|
||||
|
|
|
|||
31
.github/ISSUE_TEMPLATE/feature.yml
vendored
31
.github/ISSUE_TEMPLATE/feature.yml
vendored
|
|
@ -1,27 +1,17 @@
|
|||
name: 💡 Feature Request
|
||||
name: Feature Request
|
||||
description: Suggest an idea for this project
|
||||
labels: [feature]
|
||||
assignees: []
|
||||
body:
|
||||
- type: textarea
|
||||
id: env
|
||||
attributes:
|
||||
label: "`ya env` output"
|
||||
description: Run `ya env` and paste the environment information here.
|
||||
render: Shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: problem
|
||||
attributes:
|
||||
label: Please describe the problem you're trying to solve
|
||||
label: Is your feature request related to a problem? Please describe
|
||||
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: contribute
|
||||
attributes:
|
||||
label: Would you be willing to contribute this feature?
|
||||
label: Will you be willing to contribute this feature?
|
||||
description: The feature has a much higher chance of completion if you are willing to get involved!
|
||||
options:
|
||||
- label: Yes, I'll give it a shot
|
||||
|
|
@ -32,18 +22,13 @@ body:
|
|||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Describe alternatives you've considered
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Before submitting the issue, please make sure you have completed the following
|
||||
options:
|
||||
- label: I have searched the existing issues/discussions
|
||||
required: true
|
||||
- label: The [latest nightly build](https://yazi-rs.github.io/docs/installation/#binaries) doesn't already have this feature
|
||||
required: true
|
||||
|
|
|
|||
15
.github/dependabot.yml
vendored
15
.github/dependabot.yml
vendored
|
|
@ -1,15 +0,0 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "ci"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/scripts/validate-form"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
commit-message:
|
||||
prefix: "ci"
|
||||
24
.github/pull_request_template.md
vendored
24
.github/pull_request_template.md
vendored
|
|
@ -1,24 +0,0 @@
|
|||
## Which issue does this PR resolve?
|
||||
|
||||
<!--
|
||||
For any fixes and enhancements, we usually require an associated issue to be filed where clearly detailed your proposed changes and why they are necessary, which ensures we are aligned and reduces the risk of re-work.
|
||||
|
||||
You can use GitHub syntax to link an issue to this PR, such as `Resolves #1000`, which indicates this PR will resolve issue #1000.
|
||||
-->
|
||||
|
||||
Resolves #
|
||||
|
||||
## Rationale of this PR
|
||||
|
||||
<!--
|
||||
A clear and concise description of the rationale of the changes, to help our reviewers understand your intent and why it is necessary.
|
||||
|
||||
If it has already been detailed in the associated issue, please skip this section.
|
||||
-->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] I have read [CONTRIBUTING.md](https://github.com/sxyazi/yazi/blob/main/CONTRIBUTING.md)
|
||||
- [ ] I confirm this PR follows the [AI Policy](https://github.com/sxyazi/yazi/blob/main/CONTRIBUTING.md#ai-policy)
|
||||
|
||||
<!-- AI bots are not allowed to open PRs in this repository. All PRs must be made by humans and comply with the AI policy. -->
|
||||
30
.github/workflows/cachix.yml
vendored
30
.github/workflows/cachix.yml
vendored
|
|
@ -1,30 +0,0 @@
|
|||
name: Cachix
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish Flake
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@v31
|
||||
|
||||
- name: Authenticate with Cachix
|
||||
uses: cachix/cachix-action@v17
|
||||
with:
|
||||
name: yazi
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Build Flake
|
||||
run: nix build -L
|
||||
58
.github/workflows/check.yml
vendored
58
.github/workflows/check.yml
vendored
|
|
@ -1,58 +0,0 @@
|
|||
name: Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: true
|
||||
RUSTC_WRAPPER: sccache
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
run: |
|
||||
rustup toolchain install stable --profile minimal
|
||||
rustup component add clippy
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.10
|
||||
|
||||
- name: Clippy
|
||||
run: cargo clippy --all
|
||||
|
||||
rustfmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
run: |
|
||||
rustup toolchain install nightly --profile minimal
|
||||
rustup component add rustfmt --toolchain nightly
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.10
|
||||
|
||||
- name: Rustfmt
|
||||
run: find . -name '*.rs' -not -path './target/*' -exec rustfmt +nightly --check {} +
|
||||
|
||||
stylua:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: JohnnyMorganz/stylua-action@v5
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
version: latest
|
||||
args: --color always --check .
|
||||
260
.github/workflows/draft.yml
vendored
260
.github/workflows/draft.yml
vendored
|
|
@ -1,260 +0,0 @@
|
|||
name: Draft
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ["v[0-9]+.[0-9]+.[0-9]+"]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-unix:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: ubuntu-latest
|
||||
target: aarch64-unknown-linux-gnu
|
||||
gcc: gcc-aarch64-linux-gnu
|
||||
- os: ubuntu-latest
|
||||
target: i686-unknown-linux-gnu
|
||||
gcc: gcc-i686-linux-gnu
|
||||
- os: ubuntu-latest
|
||||
target: riscv64gc-unknown-linux-gnu
|
||||
gcc: gcc-riscv64-linux-gnu
|
||||
- os: ubuntu-latest
|
||||
target: sparc64-unknown-linux-gnu
|
||||
gcc: gcc-sparc64-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
CARGO_TARGET_I686_UNKNOWN_LINUX_GNU_LINKER: i686-linux-gnu-gcc
|
||||
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc
|
||||
CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER: sparc64-linux-gnu-gcc
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Install gcc
|
||||
if: matrix.gcc != ''
|
||||
run: sudo apt update && sudo apt install -yq ${{ matrix.gcc }}
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.10
|
||||
|
||||
- name: Build
|
||||
run: ./scripts/build.sh ${{ matrix.target }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
path: |
|
||||
yazi-${{ matrix.target }}.zip
|
||||
yazi-${{ matrix.target }}.deb
|
||||
|
||||
build-windows:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
- os: windows-latest
|
||||
target: aarch64-pc-windows-msvc
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
RUSTC_WRAPPER: sccache
|
||||
YAZI_GEN_COMPLETIONS: true
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER: lld-link.exe
|
||||
CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER: lld-link.exe
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.10
|
||||
|
||||
- name: Build
|
||||
run: cargo build --profile release-windows --locked --target ${{ matrix.target }}
|
||||
|
||||
- name: Pack artifact
|
||||
env:
|
||||
TARGET_NAME: yazi-${{ matrix.target }}
|
||||
run: |
|
||||
New-Item -ItemType Directory -Path "${env:TARGET_NAME}\completions"
|
||||
Copy-Item -Path "target\${{ matrix.target }}\release-windows\ya.exe" -Destination ${env:TARGET_NAME}
|
||||
Copy-Item -Path "target\${{ matrix.target }}\release-windows\yazi.exe" -Destination ${env:TARGET_NAME}
|
||||
Copy-Item -Path "yazi-cli\completions\*" -Destination "${env:TARGET_NAME}\completions"
|
||||
Copy-Item -Path "yazi-boot\completions\*" -Destination "${env:TARGET_NAME}\completions"
|
||||
Copy-Item -Path "README.md", "LICENSE" -Destination ${env:TARGET_NAME}
|
||||
Compress-Archive -Path ${env:TARGET_NAME} -DestinationPath "${env:TARGET_NAME}.zip"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
path: yazi-${{ matrix.target }}.zip
|
||||
|
||||
build-musl:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
- target: aarch64-unknown-linux-musl
|
||||
container:
|
||||
image: docker://ghcr.io/cross-rs/${{ matrix.target }}:edge
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.10
|
||||
|
||||
- name: Build
|
||||
run: ./scripts/build.sh ${{ matrix.target }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
path: |
|
||||
yazi-${{ matrix.target }}.zip
|
||||
yazi-${{ matrix.target }}.deb
|
||||
|
||||
build-snap:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
arch: amd64
|
||||
- os: ubuntu-24.04-arm
|
||||
arch: arm64
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup LXD
|
||||
uses: canonical/setup-lxd@v1
|
||||
|
||||
- name: Setup snapcraft
|
||||
run: sudo snap install --classic snapcraft
|
||||
|
||||
- name: Build snap
|
||||
run: snapcraft --verbose
|
||||
|
||||
- name: Rename snap
|
||||
run: mv yazi_*.snap yazi-${{ matrix.arch }}.snap
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: snap-${{ matrix.arch }}
|
||||
path: yazi-${{ matrix.arch }}.snap
|
||||
|
||||
snap:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-snap]
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: snap-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Setup snapcraft
|
||||
run: sudo snap install --classic snapcraft
|
||||
|
||||
- name: Push snap to candidate channel
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
|
||||
run: |
|
||||
parallel 'snapcraft upload -v --release latest/candidate {}' ::: yazi-*.snap || true
|
||||
|
||||
- name: Push snap to edge channel
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
|
||||
run: |
|
||||
parallel 'snapcraft upload -v --release latest/edge {}' ::: yazi-*.snap || true
|
||||
|
||||
draft:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-unix, build-windows, build-musl, build-snap]
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
merge-multiple: true
|
||||
|
||||
- name: Draft
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
draft: true
|
||||
files: |
|
||||
yazi-*.zip
|
||||
yazi-*.deb
|
||||
yazi-*.snap
|
||||
generate_release_notes: true
|
||||
|
||||
nightly:
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
permissions:
|
||||
contents: write
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-unix, build-windows, build-musl, build-snap]
|
||||
steps:
|
||||
- run: |
|
||||
echo 'NIGHTLY_BODY<<EOF' >> $GITHUB_ENV
|
||||
echo "From commit: ${GITHUB_SHA:0:8}" >> $GITHUB_ENV
|
||||
echo "Generated on: $(date -u +"%Y-%m-%d %H:%M") UTC" >> $GITHUB_ENV
|
||||
echo "Nightly changelog: https://github.com/sxyazi/yazi/blob/main/CHANGELOG.md#unreleased" >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
merge-multiple: true
|
||||
|
||||
- name: Update the tag
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git tag --force nightly && git push --force origin tag nightly
|
||||
|
||||
- name: Nightly
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
tag_name: nightly
|
||||
prerelease: true
|
||||
files: |
|
||||
yazi-*.zip
|
||||
yazi-*.deb
|
||||
yazi-*.snap
|
||||
name: Nightly Build
|
||||
body: ${{ env.NIGHTLY_BODY }}
|
||||
target_commitish: ${{ github.sha }}
|
||||
10
.github/workflows/lock.yml
vendored
10
.github/workflows/lock.yml
vendored
|
|
@ -14,18 +14,14 @@ jobs:
|
|||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
discussions: write
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v6
|
||||
- uses: dessant/lock-threads@v4
|
||||
with:
|
||||
issue-inactive-days: "30"
|
||||
issue-comment: >
|
||||
I'm going to lock this issue because it has been closed for _30 days_. ⏳
|
||||
|
||||
This helps our maintainers find and focus on the active issues.
|
||||
If you have found a problem that seems similar to this, please file a new
|
||||
If you have found a problem that seems similar to this, please open a new
|
||||
issue and complete the issue template so we can capture all the details
|
||||
necessary to investigate further.
|
||||
pr-inactive-days: "30"
|
||||
discussion-inactive-days: "30"
|
||||
process-only: "issues,prs,discussions"
|
||||
process-only: "issues"
|
||||
|
|
|
|||
2
.github/workflows/no-response.yml
vendored
2
.github/workflows/no-response.yml
vendored
|
|
@ -7,7 +7,7 @@ on:
|
|||
- cron: "10 * * * *"
|
||||
|
||||
jobs:
|
||||
no-response:
|
||||
noResponse:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
|
|
|
|||
37
.github/workflows/publish.yml
vendored
37
.github/workflows/publish.yml
vendored
|
|
@ -1,37 +0,0 @@
|
|||
name: Publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
winget:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
merge-multiple: true
|
||||
|
||||
- name: Publish to Winget
|
||||
uses: vedantmgoyal9/winget-releaser@main
|
||||
with:
|
||||
identifier: sxyazi.yazi
|
||||
installers-regex: 'yazi-(x86_64|aarch64)-pc-windows-msvc\.zip$'
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
|
||||
snapcraft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
merge-multiple: true
|
||||
|
||||
- name: Promote snap to stable
|
||||
env:
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
|
||||
run: |
|
||||
sudo snap install --classic snapcraft
|
||||
snapcraft promote yazi --from-channel latest/candidate --to-channel latest/stable --yes
|
||||
90
.github/workflows/release.yml
vendored
Normal file
90
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- os: ubuntu-latest
|
||||
target: aarch64-unknown-linux-gnu
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
- os: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
- os: windows-latest
|
||||
target: aarch64-pc-windows-msvc
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install stable toolchain
|
||||
run: rustup toolchain install stable --profile minimal
|
||||
|
||||
- name: Add aarch64 target
|
||||
if: contains(fromJson('["aarch64-unknown-linux-gnu", "aarch64-apple-darwin", "aarch64-pc-windows-msvc"]'), matrix.target)
|
||||
run: rustup target add ${{ matrix.target }}
|
||||
|
||||
- name: Install gcc-aarch64-linux-gnu
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -yq gcc-aarch64-linux-gnu
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
YAZI_GEN_COMPLETIONS: true
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: /usr/bin/aarch64-linux-gnu-gcc
|
||||
run: cargo build --release --locked --target ${{ matrix.target }}
|
||||
|
||||
- name: Build snap
|
||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
uses: snapcore/action-build@v1
|
||||
|
||||
- name: Pack artifacts [Linux & macOS]
|
||||
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
|
||||
env:
|
||||
TARGET_NAME: yazi-${{ matrix.target }}
|
||||
run: |
|
||||
mkdir $TARGET_NAME
|
||||
cp target/${{ matrix.target }}/release/yazi $TARGET_NAME
|
||||
cp -r yazi-config/completions $TARGET_NAME
|
||||
cp README.md LICENSE $TARGET_NAME
|
||||
zip -r $TARGET_NAME.zip $TARGET_NAME
|
||||
|
||||
- name: Pack artifacts [Windows]
|
||||
if: matrix.os == 'windows-latest'
|
||||
env:
|
||||
TARGET_NAME: yazi-${{ matrix.target }}
|
||||
run: |
|
||||
New-Item -ItemType Directory -Path ${env:TARGET_NAME}
|
||||
Copy-Item -Path "target\${{ matrix.target }}\release\yazi.exe" -Destination ${env:TARGET_NAME}
|
||||
Copy-Item -Path "yazi-config\completions" -Destination ${env:TARGET_NAME} -Recurse
|
||||
Copy-Item -Path "README.md", "LICENSE" -Destination ${env:TARGET_NAME}
|
||||
Compress-Archive -Path ${env:TARGET_NAME} -DestinationPath "${env:TARGET_NAME}.zip"
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
draft: true
|
||||
files: |
|
||||
yazi-${{ matrix.target }}.zip
|
||||
yazi*.snap
|
||||
generate_release_notes: true
|
||||
27
.github/workflows/test.yml
vendored
27
.github/workflows/test.yml
vendored
|
|
@ -2,35 +2,32 @@ name: Test
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
branches: ["main"]
|
||||
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: true
|
||||
RUSTC_WRAPPER: sccache
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install stable toolchain
|
||||
run: rustup toolchain install stable --profile minimal
|
||||
|
||||
- name: Setup sccache
|
||||
uses: mozilla-actions/sccache-action@v0.0.10
|
||||
- name: Cache dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
|
||||
- name: Test
|
||||
run: cargo test --workspace --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
|
|
|
|||
34
.github/workflows/validate-issue.yml
vendored
34
.github/workflows/validate-issue.yml
vendored
|
|
@ -1,34 +0,0 @@
|
|||
name: Validate Issue
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
schedule:
|
||||
- cron: "20 * * * *"
|
||||
|
||||
jobs:
|
||||
check-version:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
cd scripts/validate-form
|
||||
npm ci
|
||||
|
||||
- name: Validate Issue
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const script = require('./scripts/validate-form/main.js')
|
||||
await script({github, context, core})
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
36
.github/workflows/validate-pr.yml
vendored
36
.github/workflows/validate-pr.yml
vendored
|
|
@ -1,36 +0,0 @@
|
|||
name: Validate PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
check-list:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v7
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
cd scripts/validate-form
|
||||
npm ci
|
||||
|
||||
- name: Validate PR
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const script = require('./scripts/validate-form/main.js')
|
||||
await script({github, context, core})
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,6 +1,5 @@
|
|||
target/
|
||||
yazi-*/completions
|
||||
node_modules/
|
||||
yazi-config/completions
|
||||
|
||||
.DS_Store
|
||||
|
||||
|
|
@ -10,5 +9,3 @@ result-*
|
|||
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
*.snap
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||
"runtime.version": "Lua 5.5",
|
||||
"runtime.special": {
|
||||
"fail": "error"
|
||||
},
|
||||
"workspace.library": ["~/.config/yazi/plugins/types.yazi/"],
|
||||
"diagnostics.disable": ["redefined-local"]
|
||||
}
|
||||
1785
CHANGELOG.md
1785
CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
|
@ -1,76 +0,0 @@
|
|||
# Code of Conduct
|
||||
|
||||
## Goal
|
||||
|
||||
Our goal is to create a welcoming and safe space where anyone can contribute and seek help for this project in a respectful, collaborative
|
||||
and harassment-free way.
|
||||
|
||||
All contributions are welcome and encourage everyone to participate regardless of age, body size, disability, ethnicity, sex characteristics,
|
||||
gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion,
|
||||
or sexual identity and orientation.
|
||||
|
||||
## Standards
|
||||
|
||||
Our standards are as follows:
|
||||
|
||||
- Respect different viewpoints and opinions
|
||||
- Do not harass, attack, or discriminate against others for any reason. We have zero tolerance for harassment
|
||||
- Communicate professionally and constructively. Do not post spam or go off-topic
|
||||
- Assume goodwill in conversations. Misunderstandings happen, so give others the benefit of the doubt before jumping to conclusions
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
- Trolling, insulting or derogatory comments, and personal attacks
|
||||
- Harassing or bullying another person
|
||||
- Publishing others' private information without their explicit permission
|
||||
- Posting things unrelated to the topic being discussed
|
||||
- Other conduct that could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported here: https://discord.com/users/638378964804698112
|
||||
All reporters are guaranteed privacy, and your reports will always be kept private and secure.
|
||||
|
||||
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate.
|
||||
The following is a list of consequences that you may face if you are found to be breaking the terms of the CoC.
|
||||
|
||||
### 1. Correction
|
||||
|
||||
A private warning with an explanation as to why the behavior was not appropriate.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
A private or public warning with consequences for continued behavior.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
A temporary ban from any sort of interaction or public communication with the community for a specified period of time.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
A permanent ban from any sort of public interaction within the community.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the
|
||||
community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official
|
||||
social media account, or acting as an appointed representative at an online or offline event.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.1, available at
|
||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||
[https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||
[FAQ]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
||||
174
CONTRIBUTING.md
174
CONTRIBUTING.md
|
|
@ -1,174 +0,0 @@
|
|||
# Contributing to Yazi
|
||||
|
||||
Thank you for your interest in contributing to Yazi! We welcome contributions in the form of bug reports, feature requests, documentation improvements, and code changes.
|
||||
|
||||
This guide will help you understand how to contribute to the project.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Getting Started](#getting-started)
|
||||
2. [Project Structure](#project-structure)
|
||||
3. [Development Setup](#development-setup)
|
||||
4. [How to Contribute](#how-to-contribute)
|
||||
5. [Pull Requests](#pull-requests)
|
||||
6. [AI Policy](#ai-policy)
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before you begin, ensure you have met the following requirements:
|
||||
|
||||
- Rust installed on your machine. You can download it from [rustup.rs](https://rustup.rs).
|
||||
- Familiarity with Git and GitHub.
|
||||
|
||||
### Fork the Repository
|
||||
|
||||
1. Fork the [Yazi repository](https://github.com/sxyazi/yazi) to your GitHub account.
|
||||
2. Clone your fork to your local machine:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/<your-username>/yazi.git
|
||||
```
|
||||
|
||||
3. Set up the upstream remote:
|
||||
```sh
|
||||
git remote add upstream https://github.com/sxyazi/yazi.git
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
A brief overview of the project's structure:
|
||||
|
||||
```sh
|
||||
.
|
||||
├── assets/ # Assets like images and fonts
|
||||
├── nix/ # Nix-related configurations
|
||||
├── scripts/ # Helper scripts used by CI/CD
|
||||
├── snap/ # Snapcraft configuration
|
||||
├── yazi-adapter/ # Yazi image adapter
|
||||
├── yazi-binding/ # Yazi Lua bindings
|
||||
├── yazi-boot/ # Yazi bootstrapper
|
||||
├── yazi-cli/ # Yazi command-line interface
|
||||
├── yazi-codegen/ # Yazi code generator
|
||||
├── yazi-config/ # Yazi configuration file parser
|
||||
├── yazi-core/ # Yazi core logic
|
||||
├── yazi-dds/ # Yazi data distribution service
|
||||
├── yazi-ffi/ # Yazi foreign function interface
|
||||
├── yazi-fm/ # Yazi file manager
|
||||
├── yazi-fs/ # Yazi file system
|
||||
├── yazi-macro/ # Yazi macros
|
||||
├── yazi-plugin/ # Yazi plugin system
|
||||
├── yazi-proxy/ # Yazi event proxy
|
||||
├── yazi-scheduler/ # Yazi task scheduler
|
||||
├── yazi-shared/ # Yazi shared library
|
||||
├── yazi-term/ # Yazi terminal extensions
|
||||
├── yazi-widgets/ # Yazi user interface widgets
|
||||
├── .github/ # GitHub-specific files and workflows
|
||||
├── Cargo.toml # Rust workflow configuration
|
||||
└── README.md # Project overview
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
1. Ensure the latest stable Rust is installed:
|
||||
|
||||
```sh
|
||||
rustc --version
|
||||
cargo --version
|
||||
```
|
||||
|
||||
2. Build the project:
|
||||
|
||||
```sh
|
||||
cargo build
|
||||
```
|
||||
|
||||
3. Run the tests:
|
||||
|
||||
```sh
|
||||
cargo test --workspace --verbose
|
||||
```
|
||||
|
||||
4. Format the code (requires `rustfmt` nightly):
|
||||
|
||||
```sh
|
||||
rustup component add rustfmt --toolchain nightly
|
||||
rustfmt +nightly **/*.rs
|
||||
```
|
||||
|
||||
## How to Contribute
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
If you encounter a bug and have found a way to reliably reproduce it on the latest `main` branch, please file a [bug report](https://github.com/sxyazi/yazi/issues/new?template=bug.yml) with a [minimal reproducer](https://stackoverflow.com/help/minimal-reproducible-example).
|
||||
|
||||
### Suggesting Features
|
||||
|
||||
If you want to request a feature, please file a [feature request](https://github.com/sxyazi/yazi/issues/new?template=feature.yml). Please make sure to search for existing issues and discussions before submitting.
|
||||
|
||||
### Improving Documentation
|
||||
|
||||
Yazi's documentation placed at [yazi-rs/yazi-rs.github.io](https://github.com/yazi-rs/yazi-rs.github.io), contributions related to documentation need to be made there.
|
||||
|
||||
### Improving Icons
|
||||
|
||||
Yazi's icon originates from [`nvim-web-devicons`](https://github.com/nvim-tree/nvim-web-devicons), and it is periodically grabbed and updated with the latest changes from upstream via [`generate.lua`](https://github.com/sxyazi/yazi/blob/main/scripts/icons/generate.lua).
|
||||
|
||||
Contributions related to the icon should be made upstream to facilitate easier automation of this process.
|
||||
|
||||
### Submitting Code Changes
|
||||
|
||||
1. Create a new branch for your changes:
|
||||
|
||||
```sh
|
||||
git checkout -b your-branch-name
|
||||
```
|
||||
|
||||
2. Make your changes. Ensure that your code follows the project's [coding style](https://github.com/sxyazi/yazi/blob/main/rustfmt.toml) and passes all tests.
|
||||
3. Commit your changes with a descriptive commit message:
|
||||
|
||||
```sh
|
||||
git commit -m "feat: an awesome feature"
|
||||
```
|
||||
|
||||
4. Push your changes to your fork:
|
||||
|
||||
```sh
|
||||
git push origin your-branch-name
|
||||
```
|
||||
|
||||
## Pull Requests
|
||||
|
||||
If you have an idea, before raising a pull request, we encourage you to file an issue to propose it, ensuring that we are aligned and reducing the risk of re-work.
|
||||
|
||||
We want you to succeed, and it can be discouraging to find that a lot of re-work is needed.
|
||||
|
||||
### Process
|
||||
|
||||
1. Ensure your fork is up-to-date with the upstream repository:
|
||||
|
||||
```sh
|
||||
git fetch upstream
|
||||
git checkout main
|
||||
git merge upstream/main
|
||||
```
|
||||
|
||||
2. Rebase your feature branch onto the `main` branch:
|
||||
|
||||
```sh
|
||||
git checkout your-branch-name
|
||||
git rebase main
|
||||
```
|
||||
|
||||
3. Create a pull request to the `main` branch of the upstream repository. Follow the pull request template and ensure that:
|
||||
- Your code passes all tests and lints.
|
||||
- Your pull request description clearly explains the changes and why they are needed.
|
||||
4. Address any review comments. Make sure to push updates to the same branch on your fork.
|
||||
|
||||
## AI Policy
|
||||
|
||||
1. All issue, PR, and discussion descriptions must be written by humans, not AI.
|
||||
2. Any use of AI must be disclosed. You must declare which model you used and the extent of AI assistance.
|
||||
3. Any AI-generated code must be reviewed, tested, and simplified by a human before publishing. This requires you to fully understand how it interacts with the greater system without AI assistance.
|
||||
4. Any AI tools used must explicitly state they do not assert copyright over the work.
|
||||
4724
Cargo.lock
generated
4724
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
92
Cargo.toml
92
Cargo.toml
|
|
@ -1,97 +1,9 @@
|
|||
[workspace]
|
||||
resolver = "3"
|
||||
members = [ "yazi-*" ]
|
||||
default-members = [ "yazi-fm", "yazi-cli" ]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
version = "26.5.6"
|
||||
license = "MIT"
|
||||
authors = [ "sxyazi <sxyazi@gmail.com>" ]
|
||||
homepage = "https://yazi-rs.github.io"
|
||||
repository = "https://github.com/sxyazi/yazi"
|
||||
rust-version = "1.95.0"
|
||||
|
||||
[profile.dev]
|
||||
debug = "line-tables-only"
|
||||
resolver = "2"
|
||||
members = [ "yazi-*" ]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
panic = "abort"
|
||||
strip = true
|
||||
|
||||
[profile.release-windows]
|
||||
inherits = "release"
|
||||
panic = "unwind"
|
||||
|
||||
[profile.dev-opt]
|
||||
inherits = "release"
|
||||
codegen-units = 256
|
||||
incremental = true
|
||||
lto = false
|
||||
|
||||
[profile.dev.package."*"]
|
||||
debug = false
|
||||
|
||||
[workspace.dependencies]
|
||||
ansi-to-tui = "8.0.1"
|
||||
anyhow = "1.0.104"
|
||||
arc-swap = { version = "1.9.2", features = [ "serde" ] }
|
||||
base64 = "0.22.1"
|
||||
bitflags = { version = "2.13.1", features = [ "serde" ] }
|
||||
chrono = "0.4.45"
|
||||
clap = { version = "4.6.2", features = [ "derive" ] }
|
||||
compact_str = { version = "0.10.0", features = [ "serde" ] }
|
||||
core-foundation-sys = "0.8.7"
|
||||
data-encoding = "2.11.0"
|
||||
dirs = "6.0.0"
|
||||
dyn-clone = "1.0.20"
|
||||
either = { version = "1.16.0" }
|
||||
foldhash = "0.2.0"
|
||||
futures = "0.3.33"
|
||||
globset = "0.4.19"
|
||||
hashbrown = { version = "0.17.1", features = [ "serde" ] }
|
||||
image = { version = "0.25.10", default-features = false, features = [ "avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "tiff", "webp" ] }
|
||||
indexmap = { version = "2.14.0", features = [ "serde" ] }
|
||||
inventory = "0.3.24"
|
||||
libc = "0.2.186"
|
||||
lru = "0.18.1"
|
||||
mlua = { version = "0.12.0", features = [ "anyhow", "async", "error-send", "lua55", "macros", "serde" ] }
|
||||
objc2 = "0.6.4"
|
||||
ordered-float = { version = "5.3.0", features = [ "serde" ] }
|
||||
parking_lot = "0.12.5"
|
||||
paste = "1.0.15"
|
||||
percent-encoding = "2.3.2"
|
||||
rand = { version = "0.10.2", default-features = false, features = [ "std", "sys_rng" ] }
|
||||
ratatui-core = { version = "0.1.2", default-features = false, features = [ "std", "layout-cache", "serde", "underline-color" ] }
|
||||
ratatui-widgets = { version = "0.3.2", default-features = false, features = [ "std", "unstable-rendered-line-info" ] }
|
||||
regex = "1.13.1"
|
||||
russh = { version = "0.62.2", default-features = false, features = [ "ring", "rsa" ] }
|
||||
scopeguard = "1.2.0"
|
||||
serde = { version = "1.0.229", features = [ "derive" ] }
|
||||
serde_json = "1.0.151"
|
||||
serde_with = "3.21.0"
|
||||
strum = { version = "0.28.0", features = [ "derive" ] }
|
||||
syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||
thiserror = "2.0.19"
|
||||
tokio = { version = "1.53.0", features = [ "full" ] }
|
||||
tokio-stream = "0.1.18"
|
||||
tokio-util = "0.7.18"
|
||||
toml = { version = "1.1.3" }
|
||||
tracing = { version = "0.1.44", features = [ "max_level_debug", "release_max_level_debug" ] }
|
||||
twox-hash = { version = "2.1.3", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
|
||||
typed-path = "0.12.3"
|
||||
unicode-width = { version = "0.2.2", default-features = false }
|
||||
uzers = "0.12.2"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
format_push_string = "warn"
|
||||
if_same_then_else = "allow"
|
||||
implicit_clone = "warn"
|
||||
len_without_is_empty = "allow"
|
||||
missing_safety_doc = "allow"
|
||||
module_inception = "allow"
|
||||
option_map_unit_fn = "allow"
|
||||
unit_arg = "allow"
|
||||
use_self = "warn"
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 nvim-tree
|
||||
|
||||
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.
|
||||
90
README.md
90
README.md
|
|
@ -1,11 +1,3 @@
|
|||
<div align="center">
|
||||
<sup>Special thanks to:</sup><br>
|
||||
|
||||
| <a href="https://go.warp.dev/yazi" target="_blank"><img alt="Warp sponsorship" width=350 src="https://github.com/warpdotdev/brand-assets/blob/main/Github/Sponsor/Warp-Github-LG-02.png"><br><b>Warp, built for coding with multiple AI agents</b><br><sup>Available for macOS, Linux and Windows</sup></a> |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
</div>
|
||||
|
||||
## Yazi - ⚡️ Blazing Fast Terminal File Manager
|
||||
|
||||
Yazi (means "duck") is a terminal file manager written in Rust, based on non-blocking async I/O. It aims to provide an efficient, user-friendly, and customizable file management experience.
|
||||
|
|
@ -14,26 +6,19 @@ Yazi (means "duck") is a terminal file manager written in Rust, based on non-blo
|
|||
|
||||
- 🚀 **Full Asynchronous Support**: All I/O operations are asynchronous, CPU tasks are spread across multiple threads, making the most of available resources.
|
||||
- 💪 **Powerful Async Task Scheduling and Management**: Provides real-time progress updates, task cancellation, and internal task priority assignment.
|
||||
- 🖼️ **Built-in Support for Multiple Image Protocols**: Also integrated with Überzug++ and Chafa, covering almost all terminals.
|
||||
- 🖼️ **Built-in Support for Multiple Image Protocols**: Also integrated with Überzug++, covering almost all terminals.
|
||||
- 🌟 **Built-in Code Highlighting and Image Decoding**: Combined with the pre-loading mechanism, greatly accelerates image and normal file loading.
|
||||
- 🔌 **Concurrent Plugin System**: UI plugins (rewriting most of the UI), functional plugins, custom previewer/preloader/spotter/fetcher; Just some pieces of Lua.
|
||||
- ☁️ **Virtual Filesystem**: Remote file management, custom search engines.
|
||||
- 📡 **Data Distribution Service**: Built on a client-server architecture (no additional server process required), integrated with a Lua-based publish-subscribe model, achieving cross-instance communication and state persistence.
|
||||
- 📦 **Package Manager**: Install plugins and themes with one command, keeping them up-to-date, or pin them to a specific version.
|
||||
- 🧰 Integration with ripgrep, fd, fzf, zoxide
|
||||
- 💫 Vim-like input/pick/confirm/which/notify component, auto-completion for cd paths
|
||||
- 🏷️ Multi-Tab Support, Cross-directory selection, Scrollable Preview (for videos, PDFs, archives, code, directories, etc.)
|
||||
- 🔄 Bulk Rename/Create, Archive Extraction, Visual Mode, File Chooser, [Git Integration](https://github.com/yazi-rs/plugins/tree/main/git.yazi), [Mount Manager](https://github.com/yazi-rs/plugins/tree/main/mount.yazi)
|
||||
- 🎨 Theme System, Mouse Support, Drag and Drop, Trash Bin, Custom Layouts, CSI u, OSC 52
|
||||
- 🔌 **Concurrent Plugin System**: UI plugins (rewriting most of the UI), functional plugins (coming soon), custom previewer, and custom preloader; Just some pieces of Lua.
|
||||
- 🧰 Integration with fd, rg, fzf, zoxide
|
||||
- 💫 Vim-like input/select component, auto-completion for cd paths
|
||||
- 🏷️ Multi-Tab Support, Scrollable Preview (for videos, PDFs, archives, directories, code, etc.)
|
||||
- 🔄 Batch Renaming, Visual Mode, File Chooser
|
||||
- 🎨 Theme System, Custom Layouts, Trash Bin, CSI u
|
||||
- ... and more!
|
||||
|
||||
https://github.com/sxyazi/yazi/assets/17523360/92ff23fa-0cd5-4f04-b387-894c12265cc7
|
||||
|
||||
## Project status
|
||||
|
||||
Public beta, can be used as a daily driver.
|
||||
|
||||
Yazi is currently in heavy development, expect breaking changes.
|
||||
⚠️ Note: Yazi is currently in heavy development and may be unstable. The API is subject to change without prior notice.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
|
@ -47,48 +32,33 @@ Yazi is currently in heavy development, expect breaking changes.
|
|||
|
||||
## Image Preview
|
||||
|
||||
| Platform | Protocol | Support |
|
||||
| ---------------------------------------------------------------------------- | -------------------------------------- | -------------------------------------- |
|
||||
| [kitty](https://github.com/kovidgoyal/kitty) (>= 0.28.0) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
|
||||
| [iTerm2](https://iterm2.com) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [WezTerm](https://github.com/wez/wezterm) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [Konsole](https://invent.kde.org/utilities/konsole) | [Kitty old protocol][kgp-old] | ✅ Built-in |
|
||||
| [foot](https://codeberg.org/dnkl/foot) | [Sixel graphics format][sixel] | ✅ Built-in |
|
||||
| [Ghostty](https://github.com/ghostty-org/ghostty) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
|
||||
| [Windows Terminal](https://github.com/microsoft/terminal) (>= v1.22.10352.0) | [Sixel graphics format][sixel] | ✅ Built-in |
|
||||
| [st with Sixel patch](https://github.com/bakkeby/st-flexipatch) | [Sixel graphics format][sixel] | ✅ Built-in |
|
||||
| [Warp](https://www.warp.dev) (macOS/Linux only) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [Tabby](https://github.com/Eugeny/tabby) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [VSCode](https://github.com/microsoft/vscode) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| [Rio](https://github.com/raphamorim/rio) (>= 0.3.9) | [Kitty unicode placeholders][kgp] | ✅ Built-in |
|
||||
| [Black Box](https://gitlab.gnome.org/raggesilver/blackbox) | [Sixel graphics format][sixel] | ✅ Built-in |
|
||||
| [Bobcat](https://github.com/ismail-yilmaz/Bobcat) | [Inline images protocol][iip] | ✅ Built-in |
|
||||
| X11 / Wayland | Window system protocol | ☑️ [Überzug++][ueberzug] required |
|
||||
| Fallback | [ASCII art (Unicode block)][ascii-art] | ☑️ [Chafa][chafa] required (>= 1.16.0) |
|
||||
| Platform | Protocol | Support |
|
||||
| ----------------- | ----------------------------------------------------------------------------------------------------- | --------------------- |
|
||||
| kitty | [Kitty unicode placeholders](https://sw.kovidgoyal.net/kitty/graphics-protocol/#unicode-placeholders) | ✅ Built-in |
|
||||
| Konsole | [Kitty old protocol](https://github.com/sxyazi/yazi/blob/main/yazi-adaptor/src/kitty_old.rs) | ✅ Built-in |
|
||||
| iTerm2 | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
|
||||
| WezTerm | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
|
||||
| Mintty (Git Bash) | [Inline images protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
|
||||
| foot | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
||||
| Ghostty | [Kitty old protocol](https://github.com/sxyazi/yazi/blob/main/yazi-adaptor/src/kitty_old.rs) | ✅ Built-in |
|
||||
| Black Box | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
||||
| Tabby | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
||||
| Hyper | [Sixel graphics format](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) | ✅ Built-in |
|
||||
| X11 / Wayland | Window system protocol | ☑️ Überzug++ required |
|
||||
| Fallback | [Chafa](https://hpjansson.org/chafa/) | ☑️ Überzug++ required |
|
||||
|
||||
See https://yazi-rs.github.io/docs/image-preview for details.
|
||||
Yazi automatically selects the appropriate preview method for you, based on the priority from top to bottom.
|
||||
That's relying on the `$TERM`, `$TERM_PROGRAM`, and `$XDG_SESSION_TYPE` variables, make sure you don't overwrite them by mistake!
|
||||
|
||||
<!-- Protocols -->
|
||||
For instance, if your terminal is Alacritty, which doesn't support displaying images itself, but you are running on an X11/Wayland environment,
|
||||
it will automatically use the "Window system protocol" to display images -- this requires you to have [Überzug++](https://github.com/jstkdng/ueberzugpp) installed.
|
||||
|
||||
[kgp]: https://sw.kovidgoyal.net/kitty/graphics-protocol/#unicode-placeholders
|
||||
[kgp-old]: https://github.com/sxyazi/yazi/blob/main/yazi-adapter/src/drivers/kgp_old.rs
|
||||
[iip]: https://iterm2.com/documentation-images.html
|
||||
[sixel]: https://www.vt100.net/docs/vt3xx-gp/chapter14.html
|
||||
[ascii-art]: https://en.wikipedia.org/wiki/ASCII_art
|
||||
Here is a guide for tmux users: [Image preview within tmux](https://github.com/sxyazi/yazi/wiki/Image-preview-within-tmux)
|
||||
|
||||
<!-- Dependencies -->
|
||||
## TODO
|
||||
|
||||
[ueberzug]: https://github.com/jstkdng/ueberzugpp
|
||||
[chafa]: https://hpjansson.org/chafa/
|
||||
|
||||
## Special Thanks
|
||||
|
||||
<img alt="RustRover logo" align="right" width="200" src="https://resources.jetbrains.com/storage/products/company/brand/logos/RustRover.svg">
|
||||
|
||||
Thanks to RustRover team for providing open-source licenses to support the maintenance of Yazi.
|
||||
|
||||
Active code contributors can contact @sxyazi to get a license (if any are still available).
|
||||
See [Feature requests](https://github.com/sxyazi/yazi/issues/51) for more details.
|
||||
|
||||
## License
|
||||
|
||||
Yazi is MIT-licensed. For more information check the [LICENSE](LICENSE) file.
|
||||
Yazi is MIT licensed. For more information check the [LICENSE](LICENSE) file.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
[Desktop Entry]
|
||||
Name=Yazi File Manager
|
||||
Name=Yazi
|
||||
Icon=yazi
|
||||
Comment=Blazing fast terminal file manager written in Rust, based on async I/O
|
||||
Terminal=true
|
||||
TryExec=yazi
|
||||
Exec=yazi %f
|
||||
Exec=yazi %u
|
||||
Type=Application
|
||||
MimeType=inode/directory
|
||||
Categories=System;FileManager;FileTools;ConsoleOnly
|
||||
Categories=Utility;Core;System;FileTools;FileManager;ConsoleOnly
|
||||
Keywords=File;Manager;Explorer;Browser;Launcher
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"flagWords":[],"version":"0.2","language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg","foldhash","tilded","futs","chdir","hashbrown","JEMALLOC","RUSTFLAGS","RDONLY","GETPATH","fcntl","casefold","inodes","Splatable","casefied","thiserror","memchr","memmem","russh","deadpool","keepalive","nodelay","publickey","deadpool","initing","treelize","TOCTOU","fellback","watchee","Textlike","sstr","pointee","writef","wakeup","nonblocking","sigwinch","timespec","termios","tcgetattr","tcsetattr","tcgetwinsize","rustix","codepoint","codepoints","Raterm","mimetypes","Mimelist","renderables","redrawer","Padable"]}
|
||||
{"flagWords":[],"version":"0.2","language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty"]}
|
||||
21
flake.lock
generated
21
flake.lock
generated
|
|
@ -5,11 +5,11 @@
|
|||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -20,11 +20,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1783279667,
|
||||
"narHash": "sha256-/NAkDSsve+GNM0Bt6tleJdCGfsTlK89nPjkVOzZMo0s=",
|
||||
"lastModified": 1701174899,
|
||||
"narHash": "sha256-1W+FMe8mWsJKXoBc+QgKmEeRj33kTFnPq7XCjU+bfnA=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f205b5574fd0cb7da5b702a2da51507b7f4fdd1b",
|
||||
"rev": "010c7296f3b19a58b206fdf7d68d75a5b0a09e9e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -43,16 +43,19 @@
|
|||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": [
|
||||
"flake-utils"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1783320166,
|
||||
"narHash": "sha256-l7C/OsjcnWDOk2K3ssj+SBduwL67LashjBqis9+t468=",
|
||||
"lastModified": 1701224160,
|
||||
"narHash": "sha256-qnMmxNMKmd6Soel0cfauyMJ+LzuZbvmiDQPSIuTbQ+M=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "20ee15370c9256669d66968b89ee20a4b0a4e673",
|
||||
"rev": "4a080e26d55eaedb95ab1bf8eeaeb84149c10f12",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
93
flake.nix
93
flake.nix
|
|
@ -4,68 +4,51 @@
|
|||
flake-utils.url = "github:numtide/flake-utils";
|
||||
rust-overlay = {
|
||||
url = "github:oxalica/rust-overlay";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
flake-utils.follows = "flake-utils";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
rust-overlay,
|
||||
flake-utils,
|
||||
...
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ rust-overlay.overlays.default ];
|
||||
};
|
||||
toolchain = pkgs.rust-bin.stable.latest.default;
|
||||
rustPlatform = pkgs.makeRustPlatform {
|
||||
cargo = toolchain;
|
||||
rustc = toolchain;
|
||||
};
|
||||
|
||||
rev = self.shortRev or self.dirtyShortRev or "dirty";
|
||||
date = self.lastModifiedDate or self.lastModified or "19700101";
|
||||
version =
|
||||
(builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.version
|
||||
+ "pre${builtins.substring 0 8 date}_${rev}";
|
||||
in
|
||||
{
|
||||
packages = {
|
||||
yazi-unwrapped = pkgs.callPackage ./nix/yazi-unwrapped.nix {
|
||||
inherit
|
||||
version
|
||||
rev
|
||||
date
|
||||
rustPlatform
|
||||
;
|
||||
outputs = { self, nixpkgs, flake-utils, rust-overlay, ... }@inputs:
|
||||
let
|
||||
# Nixpkgs overlays
|
||||
overlays = [
|
||||
rust-overlay.overlays.default
|
||||
(final: prev: {
|
||||
rustToolchain = final.rust-bin.stable.latest.default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
};
|
||||
yazi = pkgs.callPackage ./nix/yazi.nix {
|
||||
inherit (self.packages.${system}) yazi-unwrapped;
|
||||
};
|
||||
default = self.packages.${system}.yazi;
|
||||
};
|
||||
})
|
||||
];
|
||||
in
|
||||
flake-utils.lib.eachDefaultSystem
|
||||
(system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system overlays; };
|
||||
versionSuffix = "pre${
|
||||
builtins.substring 0 8
|
||||
(self.lastModifiedDate or self.lastModified or "19700101")
|
||||
}_${self.shortRev or "dirty"}";
|
||||
version = (builtins.fromTOML
|
||||
(builtins.readFile ./yazi-fm/Cargo.toml)).package.version
|
||||
+ versionSuffix;
|
||||
yazi = pkgs.callPackage ./nix/yazi.nix { inherit version; };
|
||||
in
|
||||
{
|
||||
packages.default = yazi;
|
||||
packages.yazi = yazi;
|
||||
|
||||
devShells = {
|
||||
default = pkgs.callPackage ./nix/shell.nix {
|
||||
inherit toolchain;
|
||||
inherit (self.packages.${system}) yazi yazi-unwrapped;
|
||||
};
|
||||
};
|
||||
formatter = pkgs.nixpkgs-fmt;
|
||||
|
||||
formatter = pkgs.nixfmt-tree;
|
||||
}
|
||||
)
|
||||
devShells.default = import ./nix/shell.nix { inherit pkgs inputs; };
|
||||
})
|
||||
// {
|
||||
overlays = {
|
||||
default = self.overlays.yazi;
|
||||
yazi = _: prev: {
|
||||
inherit (self.packages.${prev.stdenv.system}) yazi yazi-unwrapped;
|
||||
overlays = rec {
|
||||
default = yazi;
|
||||
yazi = final: prev: {
|
||||
yazi = self.packages."${final.system}".yazi;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,25 +1,26 @@
|
|||
{
|
||||
mkShell,
|
||||
yazi,
|
||||
toolchain,
|
||||
cspell,
|
||||
yazi-unwrapped,
|
||||
}:
|
||||
{ pkgs, ... }:
|
||||
|
||||
mkShell {
|
||||
packages = yazi.passthru.runtimePaths ++ [
|
||||
(toolchain.override {
|
||||
extensions = [
|
||||
"rust-src"
|
||||
"rustfmt"
|
||||
"rust-analyzer"
|
||||
"clippy"
|
||||
];
|
||||
})
|
||||
cspell
|
||||
pkgs.mkShell {
|
||||
packages = with pkgs; [
|
||||
rustToolchain
|
||||
rust-analyzer
|
||||
|
||||
nodePackages.cspell
|
||||
|
||||
file
|
||||
jq
|
||||
poppler_utils
|
||||
unar
|
||||
ffmpegthumbnailer
|
||||
fd
|
||||
ripgrep
|
||||
fzf
|
||||
zoxide
|
||||
];
|
||||
|
||||
inputsFrom = [ yazi-unwrapped ];
|
||||
buildInputs = with pkgs;
|
||||
lib.optionals stdenv.isDarwin
|
||||
(with darwin.apple_sdk.frameworks; [ Foundation ]);
|
||||
|
||||
env.RUST_BACKTRACE = "1";
|
||||
env = { RUST_BACKTRACE = "1"; };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
{
|
||||
rustPlatform,
|
||||
version ? "git",
|
||||
rev ? "unknown",
|
||||
date ? "19700101",
|
||||
lib,
|
||||
|
||||
installShellFiles,
|
||||
fetchFromGitHub,
|
||||
rust-jemalloc-sys,
|
||||
|
||||
imagemagick,
|
||||
}:
|
||||
let
|
||||
src = lib.fileset.toSource {
|
||||
root = ../.;
|
||||
fileset = lib.fileset.unions [
|
||||
../assets
|
||||
../Cargo.toml
|
||||
../Cargo.lock
|
||||
(lib.fileset.fromSource (lib.sources.sourceByRegex ../. [ "^yazi-.*" ]))
|
||||
];
|
||||
};
|
||||
in
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "yazi";
|
||||
inherit version src;
|
||||
|
||||
cargoLock = {
|
||||
lockFile = "${src}/Cargo.lock";
|
||||
};
|
||||
|
||||
env = {
|
||||
YAZI_GEN_COMPLETIONS = true;
|
||||
VERGEN_GIT_SHA = rev;
|
||||
VERGEN_BUILD_DATE = builtins.concatStringsSep "-" (builtins.match "(.{4})(.{2})(.{2}).*" date);
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
installShellFiles
|
||||
imagemagick
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
rust-jemalloc-sys
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
installShellCompletion --cmd yazi \
|
||||
--bash ./yazi-boot/completions/yazi.bash \
|
||||
--fish ./yazi-boot/completions/yazi.fish \
|
||||
--zsh ./yazi-boot/completions/_yazi
|
||||
|
||||
installShellCompletion --cmd ya \
|
||||
--bash ./yazi-cli/completions/ya.bash \
|
||||
--fish ./yazi-cli/completions/ya.fish \
|
||||
--zsh ./yazi-cli/completions/_ya
|
||||
|
||||
# Resize logo
|
||||
for RES in 16 24 32 48 64 128 256; do
|
||||
mkdir -p $out/share/icons/hicolor/"$RES"x"$RES"/apps
|
||||
magick assets/logo.png -resize "$RES"x"$RES" $out/share/icons/hicolor/"$RES"x"$RES"/apps/yazi.png
|
||||
done
|
||||
|
||||
installManPage ${finalAttrs.passthru.srcs.man_src}/yazi{.1,-config.5}
|
||||
|
||||
mkdir -p $out/share/applications
|
||||
install -m644 assets/yazi.desktop $out/share/applications/
|
||||
'';
|
||||
|
||||
passthru.srcs = {
|
||||
man_src = fetchFromGitHub {
|
||||
name = "manpages"; # needed to ensure name is unique
|
||||
owner = "yazi-rs";
|
||||
repo = "manpages";
|
||||
rev = "8950e968f4a1ad0b83d5836ec54a070855068dbf";
|
||||
hash = "sha256-kEVXejDg4ChFoMNBvKlwdFEyUuTcY2VuK9j0PdafKus=";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
meta = {
|
||||
description = "Blazing fast terminal file manager written in Rust, based on async I/O";
|
||||
homepage = "https://github.com/sxyazi/yazi";
|
||||
license = lib.licenses.mit;
|
||||
mainProgram = "yazi";
|
||||
};
|
||||
})
|
||||
169
nix/yazi.nix
169
nix/yazi.nix
|
|
@ -1,109 +1,82 @@
|
|||
{
|
||||
lib,
|
||||
formats,
|
||||
runCommand,
|
||||
makeWrapper,
|
||||
{ makeRustPlatform
|
||||
, rustToolchain
|
||||
, version ? "git"
|
||||
, lib
|
||||
|
||||
runtimeDeps ? (ps: ps),
|
||||
, makeWrapper
|
||||
, installShellFiles
|
||||
, stdenv
|
||||
, darwin
|
||||
|
||||
# deps
|
||||
file,
|
||||
yazi-unwrapped,
|
||||
|
||||
# default optional deps
|
||||
jq,
|
||||
poppler-utils,
|
||||
_7zz,
|
||||
ffmpeg,
|
||||
fd,
|
||||
ripgrep,
|
||||
resvg,
|
||||
fzf,
|
||||
zoxide,
|
||||
imagemagick,
|
||||
chafa,
|
||||
|
||||
settings ? { },
|
||||
plugins ? { },
|
||||
flavors ? { },
|
||||
initLua ? null,
|
||||
, withFile ? true
|
||||
, file
|
||||
, withJq ? true
|
||||
, jq
|
||||
, withPoppler ? true
|
||||
, poppler_utils
|
||||
, withUnar ? true
|
||||
, unar
|
||||
, withFfmpegthumbnailer ? true
|
||||
, ffmpegthumbnailer
|
||||
, withFd ? true
|
||||
, fd
|
||||
, withRipgrep ? true
|
||||
, ripgrep
|
||||
, withFzf ? true
|
||||
, fzf
|
||||
, withZoxide ? true
|
||||
, zoxide
|
||||
, imagemagick
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
concatMapStringsSep
|
||||
optionalString
|
||||
makeBinPath
|
||||
mapAttrsToList
|
||||
;
|
||||
|
||||
defaultDeps = [
|
||||
jq
|
||||
poppler-utils
|
||||
_7zz
|
||||
ffmpeg
|
||||
fd
|
||||
ripgrep
|
||||
resvg
|
||||
fzf
|
||||
zoxide
|
||||
imagemagick
|
||||
chafa
|
||||
];
|
||||
runtimePaths = [ file ] ++ (runtimeDeps defaultDeps);
|
||||
(makeRustPlatform { cargo = rustToolchain; rustc = rustToolchain; }).buildRustPackage {
|
||||
pname = "yazi";
|
||||
inherit version;
|
||||
|
||||
settingsFormat = formats.toml { };
|
||||
src = ../.;
|
||||
YAZI_GEN_COMPLETIONS = true;
|
||||
|
||||
files = [
|
||||
"yazi"
|
||||
"theme"
|
||||
"keymap"
|
||||
];
|
||||
cargoLock.lockFile = ../Cargo.lock;
|
||||
|
||||
configHome =
|
||||
if (settings == { } && initLua == null && plugins == { } && flavors == { }) then
|
||||
null
|
||||
else
|
||||
runCommand "YAZI_CONFIG_HOME" { } ''
|
||||
mkdir -p $out
|
||||
${concatMapStringsSep "\n" (
|
||||
name:
|
||||
optionalString (settings ? ${name} && settings.${name} != { }) ''
|
||||
ln -s ${settingsFormat.generate "${name}.toml" settings.${name}} $out/${name}.toml
|
||||
''
|
||||
) files}
|
||||
nativeBuildInputs = [ makeWrapper installShellFiles imagemagick ];
|
||||
buildInputs = lib.optionals stdenv.isDarwin (
|
||||
with darwin.apple_sdk.frameworks; [ Foundation ]
|
||||
);
|
||||
|
||||
mkdir $out/plugins
|
||||
${optionalString (plugins != { }) ''
|
||||
${concatStringsSep "\n" (
|
||||
mapAttrsToList (name: value: "ln -s ${value} $out/plugins/${name}") plugins
|
||||
)}
|
||||
''}
|
||||
postInstall = with lib;
|
||||
let
|
||||
runtimePaths = [ ]
|
||||
++ optional withFile file
|
||||
++ optional withJq jq
|
||||
++ optional withPoppler poppler_utils
|
||||
++ optional withUnar unar
|
||||
++ optional withFfmpegthumbnailer ffmpegthumbnailer
|
||||
++ optional withFd fd
|
||||
++ optional withRipgrep ripgrep
|
||||
++ optional withFzf fzf
|
||||
++ optional withZoxide zoxide;
|
||||
in
|
||||
''
|
||||
wrapProgram $out/bin/yazi \
|
||||
--prefix PATH : "${makeBinPath runtimePaths}"
|
||||
installShellCompletion --cmd yazi \
|
||||
--bash ./yazi-config/completions/yazi.bash \
|
||||
--fish ./yazi-config/completions/yazi.fish \
|
||||
--zsh ./yazi-config/completions/_yazi
|
||||
|
||||
mkdir $out/flavors
|
||||
${optionalString (flavors != { }) ''
|
||||
${concatStringsSep "\n" (
|
||||
mapAttrsToList (name: value: "ln -s ${value} $out/flavors/${name}") flavors
|
||||
)}
|
||||
''}
|
||||
# Resize logo
|
||||
for RES in 16 24 32 48 64 128 256; do
|
||||
mkdir -p $out/share/icons/hicolor/"$RES"x"$RES"/apps
|
||||
convert assets/logo.png -resize "$RES"x"$RES" $out/share/icons/hicolor/"$RES"x"$RES"/apps/yazi.png
|
||||
done
|
||||
|
||||
mkdir -p $out/share/applications
|
||||
install -m644 assets/yazi.desktop $out/share/applications/
|
||||
'';
|
||||
|
||||
${optionalString (initLua != null) "ln -s ${initLua} $out/init.lua"}
|
||||
'';
|
||||
in
|
||||
runCommand yazi-unwrapped.name
|
||||
{
|
||||
inherit (yazi-unwrapped) pname version meta;
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
|
||||
passthru.runtimePaths = runtimePaths;
|
||||
}
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
ln -s ${yazi-unwrapped}/share $out/share
|
||||
ln -s ${yazi-unwrapped}/bin/ya $out/bin/ya
|
||||
makeWrapper ${yazi-unwrapped}/bin/yazi $out/bin/yazi \
|
||||
--prefix PATH : "${makeBinPath runtimePaths}" \
|
||||
${optionalString (configHome != null) "--set YAZI_CONFIG_HOME ${configHome}"}
|
||||
''
|
||||
meta = with lib; {
|
||||
description = "Blazing fast terminal file manager written in Rust, based on async I/O";
|
||||
homepage = "https://github.com/sxyazi/yazi";
|
||||
license = licenses.mit;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
color = "Never"
|
||||
condense_wildcard_suffixes = true
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
enum_discrim_align_threshold = 99
|
||||
fn_single_line = true
|
||||
format_code_in_doc_comments = false
|
||||
|
|
@ -10,7 +10,7 @@ format_macro_bodies = true
|
|||
format_strings = false
|
||||
hard_tabs = true
|
||||
hex_literal_case = "Lower"
|
||||
show_parse_errors = false
|
||||
hide_parse_errors = true
|
||||
imports_indent = "Visual"
|
||||
imports_layout = "Horizontal"
|
||||
imports_granularity = "Crate"
|
||||
|
|
@ -27,5 +27,5 @@ unstable_features = true
|
|||
use_field_init_shorthand = true
|
||||
use_small_heuristics = "Max"
|
||||
use_try_shorthand = true
|
||||
style_edition = "2024"
|
||||
version = "Two"
|
||||
wrap_comments = true
|
||||
|
|
|
|||
|
|
@ -1,34 +1,20 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
export ARTIFACT_NAME="yazi-$1"
|
||||
export YAZI_GEN_COMPLETIONS=1
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $SCRIPT_DIR/..
|
||||
|
||||
# Build the target
|
||||
git config --global --add safe.directory "*"
|
||||
cargo build --release --locked --target "$1"
|
||||
cargo +stable build --release --target aarch64-apple-darwin
|
||||
cargo +stable build --release --target x86_64-apple-darwin
|
||||
cargo +stable build --release --target x86_64-unknown-linux-gnu
|
||||
cargo +stable build --release --target x86_64-pc-windows-gnu
|
||||
|
||||
# Copy the binaries to a known location
|
||||
mkdir -p "target/release"
|
||||
cp "target/$1/release/ya" "target/release/ya"
|
||||
cp "target/$1/release/yazi" "target/release/yazi"
|
||||
mv target/aarch64-apple-darwin/release/yazi yazi-aarch64-apple-darwin
|
||||
mv target/x86_64-apple-darwin/release/yazi yazi-x86_64-apple-darwin
|
||||
mv target/x86_64-unknown-linux-gnu/release/yazi yazi-x86_64-unknown-linux-gnu
|
||||
mv target/x86_64-pc-windows-gnu/release/yazi.exe yazi-x86_64-pc-windows-gnu.exe
|
||||
|
||||
# Package deb
|
||||
if [[ "$ARTIFACT_NAME" == *-linux-* ]] && { [[ "$ARTIFACT_NAME" == *-aarch64-* ]] || [[ "$ARTIFACT_NAME" == *-x86_64-* ]]; }; then
|
||||
cargo install cargo-deb
|
||||
cargo deb -p yazi-packing --no-build --target "$1" -o "$ARTIFACT_NAME.deb"
|
||||
fi
|
||||
|
||||
# Create the artifact
|
||||
mkdir -p "$ARTIFACT_NAME/completions"
|
||||
cp "target/release/ya" "$ARTIFACT_NAME"
|
||||
cp "target/release/yazi" "$ARTIFACT_NAME"
|
||||
cp yazi-cli/completions/* "$ARTIFACT_NAME/completions"
|
||||
cp yazi-boot/completions/* "$ARTIFACT_NAME/completions"
|
||||
cp README.md LICENSE "$ARTIFACT_NAME"
|
||||
|
||||
# Zip the artifact
|
||||
if ! command -v zip &> /dev/null; then
|
||||
apt-get update && apt-get install -yq zip
|
||||
fi
|
||||
zip -r "$ARTIFACT_NAME.zip" "$ARTIFACT_NAME"
|
||||
zip -j yazi-aarch64-apple-darwin.zip yazi-aarch64-apple-darwin
|
||||
zip -j yazi-x86_64-apple-darwin.zip yazi-x86_64-apple-darwin
|
||||
zip -j yazi-x86_64-unknown-linux-gnu.zip yazi-x86_64-unknown-linux-gnu
|
||||
zip -j yazi-x86_64-pc-windows-gnu.zip yazi-x86_64-pc-windows-gnu.exe
|
||||
|
|
|
|||
|
|
@ -1,20 +1,13 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $SCRIPT_DIR/..
|
||||
|
||||
echo "Bumping version: $1"
|
||||
|
||||
TOML_FILES="$(git ls-files '*Cargo.toml')"
|
||||
perl -pi -e 's/^version .*= .*$/version = "'"$1"'"/' -- $TOML_FILES
|
||||
perl -pi -e 's/^(yazi-[a-z]+)\s*=\s*{.*$/\1 = { path = "..\/\1", version = "'"$1"'" }/' -- $TOML_FILES
|
||||
perl -pi -e "s/^version .*= .*\$/version = \"$1\"/" -- $TOML_FILES
|
||||
perl -pi -e "s/^(yazi-[a-z]+)\\s*=\\s*{.*\$/\\1 = { path = \"..\/\\1\", version = \"$1\" }/" -- $TOML_FILES
|
||||
|
||||
# Insert "## [v$1]" after "## [Unreleased]"
|
||||
perl -0777 -pe "s/^(## \[Unreleased\]\s*)/\\1## [v$1]\n\n/m" -i CHANGELOG.md
|
||||
# Determine previous version and append compare link
|
||||
prev_ver=$(grep -oE '^\[v[0-9][^]]+\]' CHANGELOG.md | tail -n1 | tr -d '[]')
|
||||
link="\[v$1\]: https://github.com/sxyazi/yazi/compare/$prev_ver...v$1"
|
||||
perl -pi -e 's{(\['"$prev_ver"'\]:[^\n]+\n)}{$1'"$link"'\n}s' CHANGELOG.md
|
||||
|
||||
eslint -c ~/.config/rules/eslint/eslint.config.js --fix -- $TOML_FILES
|
||||
ESLINT_USE_FLAT_CONFIG=true eslint -c ~/.config/rules/eslint/eslint.config.cjs --fix -- $TOML_FILES
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
local dark = {
|
||||
icons_by_filename = require("default.icons_by_filename"),
|
||||
icons_by_file_extension = require("default.icons_by_file_extension"),
|
||||
}
|
||||
local light = {
|
||||
icons_by_filename = require("light.icons_by_filename"),
|
||||
icons_by_file_extension = require("light.icons_by_file_extension"),
|
||||
}
|
||||
|
||||
function rearrange(by)
|
||||
local map = {}
|
||||
local source = by == "exts" and "icons_by_file_extension" or "icons_by_filename"
|
||||
for k, v in pairs(dark[source]) do
|
||||
map[k] = map[k] or {}
|
||||
map[k].icon = v.icon
|
||||
map[k].fg_dark = v.color:lower()
|
||||
end
|
||||
for k, v in pairs(light[source]) do
|
||||
map[k].fg_light = v.color:lower()
|
||||
end
|
||||
return map
|
||||
end
|
||||
|
||||
function dump(map)
|
||||
local list = {}
|
||||
for k, v in pairs(map) do
|
||||
list[#list + 1] = { name = k, text = v.icon, fg_dark = v.fg_dark, fg_light = v.fg_light }
|
||||
end
|
||||
table.sort(list, function(a, b) return a.name:lower() < b.name:lower() end)
|
||||
local dark, light = "", ""
|
||||
for _, v in ipairs(list) do
|
||||
-- stylua: ignore
|
||||
dark = dark .. string.format('\t{ name = "%s", text = "%s", fg = "%s" },\n', v.name, v.text, v.fg_dark)
|
||||
light = light .. string.format('\t{ name = "%s", text = "%s", fg = "%s" },\n', v.name, v.text, v.fg_light)
|
||||
end
|
||||
return dark, light
|
||||
end
|
||||
|
||||
function save(typ, files, exts)
|
||||
local p = string.format("../../yazi-config/preset/theme-%s.toml", typ)
|
||||
local s = io.open(p, "r"):read("*a")
|
||||
s = s:gsub("files = %[\n(.-)\n%]", string.format("files = [\n%s]", files))
|
||||
s = s:gsub("exts = %[\n(.-)\n%]", string.format("exts = [\n%s]", exts))
|
||||
io.open(p, "w"):write(s)
|
||||
end
|
||||
|
||||
local dark_files, light_files = dump(rearrange("files"))
|
||||
local dark_exts, light_exts = dump(rearrange("exts"))
|
||||
|
||||
save("dark", dark_files, dark_exts)
|
||||
save("light", light_files, light_exts)
|
||||
7
scripts/publish.sh
Executable file
7
scripts/publish.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
cargo publish -p yazi-shared
|
||||
cargo publish -p yazi-config
|
||||
cargo publish -p yazi-adaptor
|
||||
cargo publish -p yazi-scheduler
|
||||
cargo publish -p yazi-plugin
|
||||
cargo publish -p yazi-core
|
||||
cargo publish -p yazi-fm
|
||||
|
|
@ -1,269 +0,0 @@
|
|||
const LABEL_NAME = "needs info"
|
||||
const RE_VERSION = /Yazi\s+Version\s*:\s\d+\.\d+\.\d+\s\(/gm
|
||||
const RE_DEPENDENCIES = /Dependencies\s+[/a-z]+\s*:\s/gm
|
||||
const RE_CHECKLIST = /#{3}\s+Checklist\s+(?:^-\s+\[x]\s+.+?(?:\n|\r\n|$)){2}/gm
|
||||
const RE_PR_CHECKLIST = /#{2}\s+Checklist\s+(?:^-\s+\[x]\s+.+?(?:\n|\r\n|$)){2}/gm
|
||||
|
||||
function pullRequestBody(content) {
|
||||
if (RE_PR_CHECKLIST.test(content)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return "All required checklist items must be checked in the PR description."
|
||||
}
|
||||
|
||||
function bugReportBody(creator, content, hash) {
|
||||
if (RE_DEPENDENCIES.test(content) && RE_CHECKLIST.test(content) && new RegExp(` \\(${hash}[a-f0-9]? `).test(content)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return `Hey @${creator}, thank you for opening the issue to help improve Yazi, appreciate it!
|
||||
|
||||
I noticed that you did not correctly follow the issue template. Please ensure that:
|
||||
|
||||
- The bug can still be reproduced on the [newest nightly build](https://yazi-rs.github.io/docs/installation/#binaries).
|
||||
- The environment info (\`ya env\`) is updated for the newest nightly.
|
||||
- The non-optional items in the checklist are checked.
|
||||
|
||||
Issues with \`${LABEL_NAME}\` will be marked ready once edited with the proper content, or closed after 2 days of inactivity.
|
||||
|
||||
Our maintainers work on Yazi in their free time, this helps them work efficiently, understand your setup quickly, and find a more appropriate solution. Thanks for your understanding! 🙏
|
||||
`
|
||||
}
|
||||
|
||||
function featureRequestBody(creator, content) {
|
||||
if (RE_VERSION.test(content) && RE_DEPENDENCIES.test(content) && RE_CHECKLIST.test(content)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return `Hey @${creator}, thank you for opening the issue to help improve Yazi, appreciate it!
|
||||
|
||||
I noticed that you did not correctly follow the issue template. Please ensure that:
|
||||
|
||||
- The requested feature does not exist in the [newest nightly build](https://yazi-rs.github.io/docs/installation/#binaries).
|
||||
- The environment info (\`ya env\`) is updated for the newest nightly.
|
||||
- The non-optional items in the checklist are checked.
|
||||
|
||||
Issues with \`${LABEL_NAME}\` will be marked ready once edited with the proper content, or closed after 2 days of inactivity.
|
||||
|
||||
Our maintainers work on Yazi in their free time, this helps them work efficiently, understand your setup quickly, and find a more appropriate solution. Thanks for your understanding! 🙏
|
||||
`
|
||||
}
|
||||
|
||||
function skipValidation(context) {
|
||||
const login = context.payload.issue?.user?.login || context.payload.pull_request?.user?.login
|
||||
const owner = context.payload.repository?.owner?.login || context.repo.owner
|
||||
return !!login && login === owner
|
||||
}
|
||||
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
async function nightlyHash() {
|
||||
try {
|
||||
const { data: tagRef } = await github.rest.git.getRef({ owner: "sxyazi", repo: "yazi", ref: "tags/nightly" })
|
||||
return tagRef.object.sha.slice(0, 7)
|
||||
} catch (e) {
|
||||
if (e.status === 404) {
|
||||
core.error("Nightly tag not found")
|
||||
} else {
|
||||
core.error(`Error fetching nightly version: ${e.message}`)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function hasLabel(id, label) {
|
||||
try {
|
||||
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
})
|
||||
return labels.some(l => l.name === label)
|
||||
} catch (e) {
|
||||
core.error(`Error checking labels: ${e.message}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function lastLabeledAt(id) {
|
||||
try {
|
||||
const { data: events } = await github.rest.issues.listEvents({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
per_page: 100,
|
||||
})
|
||||
|
||||
const all = events.filter(v => v.event === "labeled" && v.label?.name === LABEL_NAME)
|
||||
return all.at(-1)?.created_at
|
||||
} catch (e) {
|
||||
core.error(`Error getting label timestamp: ${e.message}`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function removedLabelManually(id) {
|
||||
try {
|
||||
const { data: events } = await github.rest.issues.listEvents({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
per_page: 100,
|
||||
})
|
||||
|
||||
const all = events.filter(v => v.event === "unlabeled" && v.label?.name === LABEL_NAME)
|
||||
return all.length === 0 ? false : !all.at(-1).actor.login.endsWith("[bot]")
|
||||
} catch (e) {
|
||||
core.error(`Error checking label removal history: ${e.message}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function updateLabels(id, mark, body) {
|
||||
try {
|
||||
const marked = await hasLabel(id, LABEL_NAME)
|
||||
|
||||
if (!mark && marked) {
|
||||
await github.rest.issues.removeLabel({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
name: LABEL_NAME,
|
||||
})
|
||||
await hideOldComments(id)
|
||||
} else if (mark && !marked && !await removedLabelManually(id)) {
|
||||
await github.rest.issues.addLabels({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
labels: [LABEL_NAME],
|
||||
})
|
||||
await hideOldComments(id)
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
body,
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
core.error(`Error updating labels: ${e.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function hideOldComments(id) {
|
||||
try {
|
||||
const comments = await github.paginate(github.rest.issues.listComments, {
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
per_page: 100,
|
||||
})
|
||||
|
||||
for (const c of comments) {
|
||||
const byBot = c.user?.login?.endsWith("[bot]") || c.user?.type === "Bot"
|
||||
const contains = c?.body?.includes("or closed after 2 days of inactivity")
|
||||
if (!byBot || !contains || !c.node_id) continue
|
||||
|
||||
try {
|
||||
await github.graphql(
|
||||
`mutation($subjectId: ID!, $classifier: ReportedContentClassifiers!) {
|
||||
minimizeComment(input: {subjectId: $subjectId, classifier: $classifier}) {
|
||||
minimizedComment { isMinimized }
|
||||
}
|
||||
}`,
|
||||
{ subjectId: c.node_id, classifier: "OUTDATED" },
|
||||
)
|
||||
} catch (e) {
|
||||
core.error(`Error minimizing comment ${c.id}: ${e.message}`)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
core.error(`Error listing comments: ${e.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function closeOldIssues() {
|
||||
try {
|
||||
const { data: issues } = await github.rest.issues.listForRepo({
|
||||
...context.repo,
|
||||
state: "open",
|
||||
labels: LABEL_NAME,
|
||||
})
|
||||
|
||||
const now = new Date()
|
||||
const twoDaysAgo = new Date(now - 2 * 24 * 60 * 60 * 1000)
|
||||
|
||||
for (const issue of issues) {
|
||||
const markedAt = new Date(await lastLabeledAt(issue.number) || issue.created_at)
|
||||
if (markedAt < twoDaysAgo) {
|
||||
await github.rest.issues.update({
|
||||
...context.repo,
|
||||
issue_number: issue.number,
|
||||
state: "closed",
|
||||
state_reason: "not_planned",
|
||||
})
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: issue.number,
|
||||
body: `This issue has been automatically closed because it was marked as \`${LABEL_NAME}\` for more than 2 days without updates.
|
||||
If the problem persists, please file a new issue and complete the issue template so we can capture all the details necessary to investigate further.`,
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
core.error(`Error checking old issues: ${e.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function closeUnsupportedIssue(id) {
|
||||
try {
|
||||
await github.rest.issues.update({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
state: "closed",
|
||||
state_reason: "not_planned",
|
||||
})
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: id,
|
||||
body: `Unsupported issue template.
|
||||
Either the [Bug Report](https://github.com/sxyazi/yazi/issues/new?template=bug.yml) or [Feature Request](https://github.com/sxyazi/yazi/issues/new?template=feature.yml) template should be used.`,
|
||||
})
|
||||
} catch (e) {
|
||||
core.error(`Error closing unsupported issue: ${e.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (context.eventName === "schedule") {
|
||||
await closeOldIssues()
|
||||
return
|
||||
}
|
||||
|
||||
if (skipValidation(context)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (context.eventName === "issues") {
|
||||
const id = context.payload.issue.number
|
||||
const content = context.payload.issue.body || ""
|
||||
const creator = context.payload.issue.user.login
|
||||
|
||||
const hash = await nightlyHash()
|
||||
if (!hash) return
|
||||
|
||||
if (await hasLabel(id, "bug")) {
|
||||
const body = bugReportBody(creator, content, hash)
|
||||
await updateLabels(id, !!body, body)
|
||||
} else if (await hasLabel(id, "feature")) {
|
||||
const body = featureRequestBody(creator, content)
|
||||
await updateLabels(id, !!body, body)
|
||||
} else if (context.payload.action === "opened") {
|
||||
await closeUnsupportedIssue(id)
|
||||
}
|
||||
} else if (context.eventName === "pull_request" || context.eventName === "pull_request_target") {
|
||||
const content = context.payload.pull_request.body || ""
|
||||
|
||||
const body = pullRequestBody(content)
|
||||
if (body) {
|
||||
core.setFailed(body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await main()
|
||||
}
|
||||
256
scripts/validate-form/package-lock.json
generated
256
scripts/validate-form/package-lock.json
generated
|
|
@ -1,256 +0,0 @@
|
|||
{
|
||||
"name": "validate-form",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "validate-form",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@actions/core": "^3.0.1",
|
||||
"@actions/github": "^9.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.1.tgz",
|
||||
"integrity": "sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^3.0.0",
|
||||
"@actions/http-client": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-3.0.0.tgz",
|
||||
"integrity": "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github": {
|
||||
"version": "9.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-9.1.1.tgz",
|
||||
"integrity": "sha512-tL5JbYOBZHc0ngEnCsaDcryUizIUIlQyIMwy1Wkx93H5HzbBJ7TbiPx2PnFjBwZW0Vh05JmfFZhecE6gglYegA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@octokit/core": "^7.0.6",
|
||||
"@octokit/plugin-paginate-rest": "^14.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
||||
"@octokit/request": "^10.0.7",
|
||||
"@octokit/request-error": "^7.1.0",
|
||||
"undici": "^6.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github/node_modules/@actions/http-client": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^6.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-4.0.1.tgz",
|
||||
"integrity": "sha512-+Nvd1ImaOZBSoPbsUtEhv+1z99H12xzncCkz0a3RuehINE81FZSe2QTj3uvAPTcJX/SCzUQHQ0D1GrPMbrPitg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^6.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz",
|
||||
"integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz",
|
||||
"integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz",
|
||||
"integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^6.0.0",
|
||||
"@octokit/graphql": "^9.0.3",
|
||||
"@octokit/request": "^10.0.6",
|
||||
"@octokit/request-error": "^7.0.2",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"before-after-hook": "^4.0.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "11.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz",
|
||||
"integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^16.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz",
|
||||
"integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^10.0.6",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "27.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz",
|
||||
"integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz",
|
||||
"integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz",
|
||||
"integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "10.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.8.tgz",
|
||||
"integrity": "sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^11.0.3",
|
||||
"@octokit/request-error": "^7.0.2",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"fast-content-type-parse": "^3.0.0",
|
||||
"json-with-bigint": "^3.5.3",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz",
|
||||
"integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz",
|
||||
"integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^27.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz",
|
||||
"integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/fast-content-type-parse": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz",
|
||||
"integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-with-bigint": {
|
||||
"version": "3.5.8",
|
||||
"resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.8.tgz",
|
||||
"integrity": "sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.27.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz",
|
||||
"integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"name": "validate-form",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@actions/core": "^3.0.1",
|
||||
"@actions/github": "^9.1.1"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
name: yazi
|
||||
base: core24
|
||||
base: core22
|
||||
adopt-info: yazi
|
||||
summary: Blazing fast terminal file manager written in Rust, based on async I/O.
|
||||
description: |
|
||||
|
|
@ -9,157 +9,25 @@ license: MIT
|
|||
grade: stable
|
||||
confinement: classic
|
||||
|
||||
platforms:
|
||||
amd64:
|
||||
arm64:
|
||||
architectures:
|
||||
- amd64
|
||||
# - arm64
|
||||
|
||||
apps:
|
||||
yazi:
|
||||
command: yazi
|
||||
environment:
|
||||
PATH: $SNAP/bin:$SNAP/usr/bin:$PATH
|
||||
ya:
|
||||
command: ya
|
||||
environment:
|
||||
PATH: $SNAP/bin:$SNAP/usr/bin:$PATH
|
||||
PATH: $SNAP/bin:$PATH
|
||||
|
||||
parts:
|
||||
yazi:
|
||||
plugin: rust
|
||||
source: https://github.com/sxyazi/yazi.git
|
||||
stage-snaps:
|
||||
- jq
|
||||
stage-packages:
|
||||
- 7zip-standalone
|
||||
- chafa
|
||||
- fd-find
|
||||
- ffmpeg
|
||||
# - fzf
|
||||
- libglu1-mesa
|
||||
- libglut3.12
|
||||
- poppler-utils
|
||||
- ripgrep
|
||||
- wl-clipboard
|
||||
- xclip
|
||||
- zoxide
|
||||
override-build: |
|
||||
craftctl default
|
||||
craftctl set version=$(git describe --tags --abbrev=0)
|
||||
build-attributes:
|
||||
- enable-patchelf
|
||||
organize:
|
||||
# Ubuntu's `fd` package installs a binary named `fdfind`. Rename it in the snap.
|
||||
usr/bin/fdfind: usr/bin/fd
|
||||
prime:
|
||||
# Remove unused items bought in by dependency packages
|
||||
- -usr/bin/fc-*
|
||||
- -usr/bin/ffplay
|
||||
- -usr/bin/pdfattach
|
||||
- -usr/bin/pdfdetach
|
||||
- -usr/bin/pdffonts
|
||||
- -usr/bin/pdfimages
|
||||
- -usr/bin/pdfinfo
|
||||
- -usr/bin/pdfseparate
|
||||
- -usr/bin/pdfsig
|
||||
- -usr/bin/pdftocairo
|
||||
- -usr/bin/pdftohtml
|
||||
- -usr/bin/pdftops
|
||||
- -usr/bin/pdftotext
|
||||
- -usr/bin/pdfunite
|
||||
# Remove unused libraries identified by snapcraft's linter
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_bad_*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_civil_time.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_cord*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_examine_stack.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_exponential_biased.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_failure_signal_handler.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_flags*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_hash*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_log_severity.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_periodic_sampler.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_random*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_raw_hash_set.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_scoped_set_env.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_statusor.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_status.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_strerror.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libabsl_str_format_internal.so.*
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libcaca++.so.0.99.20
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libcjson_utils.so.1.7.17
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libfftw3_omp.so.3.6.10
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libfftw3_threads.so.3.6.10
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libflite_cmu_grapheme_lang.so.2.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libflite_cmu_grapheme_lex.so.2.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libflite_cmu_indic_lang.so.2.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libflite_cmu_indic_lex.so.2.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libflite_cmu_time_awb.so.2.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libfreebl3.so
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libfreeblpriv3.so
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libGLX_mesa.so.0.0.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libhwy_contrib.so.1.0.7
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libhwy_test.so.1.0.7
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libicui18n.so.74.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libicuio.so.74.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libicutest.so.74.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libicutu.so.74.2
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjacknet.so.0.1.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libjackserver.so.0.1.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libnssckbi.so
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libnssdbm3.so
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libpulse-simple.so.0.1.1
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libsoftokn3.so
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libsphinxad.so.3.0.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libssl3.so
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libtheora.so.0.3.10
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libxcb-dri2.so.0.0.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libxcb-glx.so.0.0.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libxcb-present.so.0.0.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libxcb-sync.so.1.0.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libxshmfence.so.1.0.0
|
||||
- -usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libzvbi-chains.so.0.0.0
|
||||
|
||||
# The Ubuntu `imagemagick` package does not ship a `magick` binary,
|
||||
# which `yazi` looks for. Building the package oursleves yields the
|
||||
# expected binary without much overhead, and works across platforms.
|
||||
magick:
|
||||
plugin: autotools
|
||||
source: https://github.com/ImageMagick/ImageMagick.git
|
||||
source-type: git
|
||||
source-tag: 7.1.2-0
|
||||
source-depth: 1
|
||||
stage-packages:
|
||||
- libgomp1
|
||||
autotools-configure-parameters:
|
||||
- --prefix=/usr
|
||||
build-attributes:
|
||||
- enable-patchelf
|
||||
organize:
|
||||
# `libgomp1` installs libgomp into the multiarch directory, but the
|
||||
# `magick` binary's RPATH only searches `$ORIGIN/../lib` (i.e. usr/lib).
|
||||
# Move it alongside the Magick libraries so the bundled binary can load
|
||||
# it at runtime; otherwise magick fails with:
|
||||
# "libgomp.so.1: cannot open shared object file: No such file or directory"
|
||||
usr/lib/$CRAFT_ARCH_TRIPLET_BUILD_FOR/libgomp.so*: usr/lib/
|
||||
prime:
|
||||
- usr/bin/magick
|
||||
- usr/lib/libgomp.so*
|
||||
- usr/lib/libMagickCore-7.Q16HDRI.so*
|
||||
- usr/lib/libMagickWand-7.Q16HDRI.so*
|
||||
|
||||
cleanup:
|
||||
after: [yazi, magick]
|
||||
plugin: nil
|
||||
build-packages:
|
||||
- patchelf
|
||||
build-snaps:
|
||||
- core24
|
||||
override-prime: |
|
||||
# Ubuntu's /usr/bin/7zz is a simple bash wrapper that just exec's
|
||||
# /usr/lib/7zip/7zz - this just shortcuts that and places the actual
|
||||
# executable at $SNAP/usr/bin/7zz.
|
||||
mv $CRAFT_PRIME/usr/lib/7zip/7zz $CRAFT_PRIME/usr/bin/7zz
|
||||
|
||||
# Ensure we don't ship duplicates of files that exist in the core24
|
||||
# snap.
|
||||
cd /snap/core24/current
|
||||
find . -type f,l -exec rm -rf "${CRAFT_PRIME}/{}" \;
|
||||
cargo install fd-find --root $CRAFT_PART_INSTALL
|
||||
cargo install ripgrep --root $CRAFT_PART_INSTALL
|
||||
cargo install zoxide --root $CRAFT_PART_INSTALL
|
||||
git clone --depth 1 https://github.com/junegunn/fzf.git fzf
|
||||
fzf/install --bin && mv fzf/bin/fzf $CRAFT_PART_INSTALL/bin/
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
syntax = "Lua54"
|
||||
indent_width = 2
|
||||
call_parentheses = "NoSingleTable"
|
||||
collapse_simple_statement = "FunctionOnly"
|
||||
|
||||
[sort_requires]
|
||||
enabled = true
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
[package]
|
||||
name = "yazi-actor"
|
||||
description = "Yazi actor model"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[features]
|
||||
default = [ "vendored-lua" ]
|
||||
vendored-lua = [ "mlua/vendored" ]
|
||||
|
||||
[dependencies]
|
||||
yazi-binding = { path = "../yazi-binding", version = "26.5.6" }
|
||||
yazi-boot = { path = "../yazi-boot", version = "26.5.6" }
|
||||
yazi-config = { path = "../yazi-config", version = "26.5.6" }
|
||||
yazi-core = { path = "../yazi-core", version = "26.5.6" }
|
||||
yazi-dds = { path = "../yazi-dds", version = "26.5.6" }
|
||||
yazi-emulator = { path = "../yazi-emulator", version = "26.5.6" }
|
||||
yazi-fs = { path = "../yazi-fs", version = "26.5.6" }
|
||||
yazi-macro = { path = "../yazi-macro", version = "26.5.6" }
|
||||
yazi-parser = { path = "../yazi-parser", version = "26.5.6" }
|
||||
yazi-plugin = { path = "../yazi-plugin", version = "26.5.6" }
|
||||
yazi-proxy = { path = "../yazi-proxy", version = "26.5.6" }
|
||||
yazi-runner = { path = "../yazi-runner", version = "26.5.6" }
|
||||
yazi-scheduler = { path = "../yazi-scheduler", version = "26.5.6" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "26.5.6" }
|
||||
yazi-shim = { path = "../yazi-shim", version = "26.5.6" }
|
||||
yazi-term = { path = "../yazi-term", version = "26.5.6" }
|
||||
yazi-tty = { path = "../yazi-tty", version = "26.5.9" }
|
||||
yazi-tui = { path = "../yazi-tui", version = "26.5.6" }
|
||||
yazi-vfs = { path = "../yazi-vfs", version = "26.5.6" }
|
||||
yazi-watcher = { path = "../yazi-watcher", version = "26.5.6" }
|
||||
yazi-widgets = { path = "../yazi-widgets", version = "26.5.6" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = { workspace = true }
|
||||
either = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
hashbrown = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
inventory = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
paste = { workspace = true }
|
||||
ratatui-core = { workspace = true }
|
||||
scopeguard = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
libc = { workspace = true }
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
# yazi-actor
|
||||
|
||||
This crate is part of [Yazi][source], and it is not supposed to be used outside, as there are no guarantees about the stability of its API.
|
||||
|
||||
[source]: https://github.com/sxyazi/yazi
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_parser::spark::SparkKind;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::Ctx;
|
||||
|
||||
pub trait Actor {
|
||||
type Form;
|
||||
|
||||
const NAME: &str;
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data>;
|
||||
|
||||
fn hook(_cx: &Ctx, _form: &Self::Form) -> Option<SparkKind> { None }
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use mlua::IntoLua;
|
||||
use tracing::error;
|
||||
use yazi_actor::lives::Lives;
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_dds::{LOCAL, Payload, REMOTE};
|
||||
use yazi_macro::succ;
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct AcceptPayload;
|
||||
|
||||
impl Actor for AcceptPayload {
|
||||
type Form = Payload<'static>;
|
||||
|
||||
const NAME: &str = "accept_payload";
|
||||
|
||||
fn act(cx: &mut Ctx, payload: Payload) -> Result<Data> {
|
||||
let kind = payload.body.kind();
|
||||
let lock = if payload.receiver == 0 || payload.receiver != payload.sender {
|
||||
REMOTE.read()
|
||||
} else {
|
||||
LOCAL.read()
|
||||
};
|
||||
|
||||
let Some(handlers) = lock.get(kind).filter(|&m| !m.is_empty()).cloned() else { succ!() };
|
||||
drop(lock);
|
||||
|
||||
let kind = kind.to_owned();
|
||||
succ!(Lives::scope(cx.core, |_| {
|
||||
let body = payload.body.into_lua(&LUA)?;
|
||||
for (id, cb) in handlers {
|
||||
if let Err(e) = runtime_scope!(LUA, &id, cb.call::<()>(body.clone())) {
|
||||
error!("Failed to run `{kind}` event handler in your `{id}` plugin: {e}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})?);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_core::mgr::CdSource;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::{data::Data, strand::StrandLike, url::UrlLike};
|
||||
|
||||
use crate::Actor;
|
||||
|
||||
pub struct Bootstrap;
|
||||
|
||||
impl Actor for Bootstrap {
|
||||
type Form = VoidForm;
|
||||
|
||||
const NAME: &str = "bootstrap";
|
||||
|
||||
fn act(cx: &mut Ctx, _: Self::Form) -> Result<Data> {
|
||||
cx.mgr.tabs.resize_with(BOOT.files.len(), Default::default);
|
||||
|
||||
for (i, file) in BOOT.files.iter().enumerate().rev() {
|
||||
cx.tab = i;
|
||||
if file.is_empty() {
|
||||
act!(mgr:cd, cx, (BOOT.cwds[i].clone(), CdSource::Tab))?;
|
||||
} else if let Ok(u) = BOOT.cwds[i].try_join(file) {
|
||||
act!(mgr:reveal, cx, (u, CdSource::Tab))?;
|
||||
}
|
||||
}
|
||||
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::notify::{MessageLevel, MessageOpt};
|
||||
use yazi_macro::act;
|
||||
use yazi_parser::app::DeprecateForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Deprecate;
|
||||
|
||||
impl Actor for Deprecate {
|
||||
type Form = DeprecateForm;
|
||||
|
||||
const NAME: &str = "deprecate";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
act!(notify:push, cx, MessageOpt {
|
||||
title: "Deprecated API".to_owned(),
|
||||
content: form.content.into_owned(),
|
||||
level: MessageLevel::Warn,
|
||||
timeout: std::time::Duration::from_secs(20),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use mlua::{ObjectLike, Table};
|
||||
use tracing::error;
|
||||
use yazi_actor::lives::Lives;
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::app::DndForm;
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Dnd;
|
||||
|
||||
impl Actor for Dnd {
|
||||
type Form = DndForm;
|
||||
|
||||
const NAME: &str = "dnd";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() };
|
||||
let area = yazi_binding::elements::Rect::from(size);
|
||||
|
||||
let result = Lives::scope(cx.core, move |_| {
|
||||
runtime_scope!(LUA, "root", {
|
||||
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;
|
||||
|
||||
if form.event.is_drag() {
|
||||
root.call_method::<()>("drag", form.event)?;
|
||||
} else {
|
||||
root.call_method::<()>("drop", form.event)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
|
||||
if let Err(ref e) = result {
|
||||
error!("{e}");
|
||||
}
|
||||
succ!(result?);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_macro::act;
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::Actor;
|
||||
|
||||
pub struct Focus;
|
||||
|
||||
impl Actor for Focus {
|
||||
type Form = VoidForm;
|
||||
|
||||
const NAME: &str = "focus";
|
||||
|
||||
fn act(cx: &mut Ctx, _: Self::Form) -> Result<Data> { act!(mgr:refresh, cx) }
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::app::LuaForm;
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_shared::data::{Data, Sendable};
|
||||
|
||||
use crate::{Actor, Ctx, lives::Lives};
|
||||
|
||||
pub struct Lua;
|
||||
|
||||
impl Actor for Lua {
|
||||
type Form = LuaForm;
|
||||
|
||||
const NAME: &str = "lua";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let chunk = LUA.load(&*form.code).set_name("anonymous");
|
||||
let result = Lives::scope(cx.core, |_| {
|
||||
runtime_scope!(LUA, "inline", Sendable::value_to_data(&LUA, chunk.eval()?))
|
||||
});
|
||||
succ!(result?);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
yazi_macro::mod_flat!(
|
||||
accept_payload
|
||||
bootstrap
|
||||
deprecate
|
||||
dnd
|
||||
focus
|
||||
lua
|
||||
mouse
|
||||
plugin
|
||||
plugin_do
|
||||
quit
|
||||
reflow
|
||||
resize
|
||||
resume
|
||||
stop
|
||||
theme
|
||||
title
|
||||
update_progress
|
||||
);
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use mlua::{ObjectLike, Table};
|
||||
use tracing::error;
|
||||
use yazi_actor::lives::Lives;
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::app::MouseForm;
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_term::event::MouseEventKind;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Mouse;
|
||||
|
||||
impl Actor for Mouse {
|
||||
type Form = MouseForm;
|
||||
|
||||
const NAME: &str = "mouse";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() };
|
||||
let area = yazi_binding::elements::Rect::from(size);
|
||||
|
||||
let result = Lives::scope(cx.core, move |_| {
|
||||
runtime_scope!(LUA, "root", {
|
||||
let root = LUA.globals().raw_get::<Table>("Root")?.call_method::<Table>("new", area)?;
|
||||
|
||||
match form.event.kind {
|
||||
MouseEventKind::Down(_) => root.call_method("click", (form.event, false))?,
|
||||
MouseEventKind::Up(_) => root.call_method("click", (form.event, true))?,
|
||||
|
||||
MouseEventKind::ScrollDown => root.call_method("scroll", (form.event, 1))?,
|
||||
MouseEventKind::ScrollUp => root.call_method("scroll", (form.event, -1))?,
|
||||
|
||||
MouseEventKind::ScrollRight => root.call_method("touch", (form.event, 1))?,
|
||||
MouseEventKind::ScrollLeft => root.call_method("touch", (form.event, -1))?,
|
||||
|
||||
MouseEventKind::Moved => root.call_method("move", form.event)?,
|
||||
MouseEventKind::Drag(_) => root.call_method("drag", form.event)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
|
||||
if let Err(ref e) = result {
|
||||
error!("{e}");
|
||||
}
|
||||
succ!(result?);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::app::PluginMode;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_parser::app::PluginForm;
|
||||
use yazi_proxy::AppProxy;
|
||||
use yazi_runner::loader::LOADER;
|
||||
use yazi_scheduler::NotifyProxy;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Plugin;
|
||||
|
||||
impl Actor for Plugin {
|
||||
type Form = PluginForm;
|
||||
|
||||
const NAME: &str = "plugin";
|
||||
|
||||
fn act(cx: &mut Ctx, Self::Form { mut opt }: Self::Form) -> Result<Data> {
|
||||
let mut hits = false;
|
||||
if let Some(chunk) = LOADER.read().get(&*opt.id) {
|
||||
hits = true;
|
||||
opt.mode = opt.mode.auto_then(chunk.sync_entry);
|
||||
}
|
||||
|
||||
if opt.mode == PluginMode::Async {
|
||||
succ!(cx.core.tasks.scheduler.plugin_entry(opt.into()));
|
||||
} else if opt.mode == PluginMode::Sync && hits {
|
||||
return act!(app:plugin_do, cx, opt);
|
||||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
match LOADER.ensure(&opt.id, |_| ()).await {
|
||||
Ok(()) => AppProxy::plugin_do(opt),
|
||||
Err(e) => NotifyProxy::push_error("Plugin load failed", e.to_string()),
|
||||
}
|
||||
});
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use mlua::ObjectLike;
|
||||
use scopeguard::defer;
|
||||
use tracing::{error, warn};
|
||||
use yazi_binding::runtime_mut;
|
||||
use yazi_core::app::PluginMode;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::app::PluginForm;
|
||||
use yazi_plugin::LUA;
|
||||
use yazi_runner::{entry::EntryJob, loader::{LOADER, Loader}};
|
||||
use yazi_scheduler::NotifyProxy;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx, lives::Lives};
|
||||
|
||||
pub struct PluginDo;
|
||||
|
||||
impl Actor for PluginDo {
|
||||
type Form = PluginForm;
|
||||
|
||||
const NAME: &str = "plugin_do";
|
||||
|
||||
fn act(cx: &mut Ctx, Self::Form { opt }: Self::Form) -> Result<Data> {
|
||||
let loader = LOADER.read();
|
||||
let Some(chunk) = loader.get(&*opt.id) else {
|
||||
succ!(warn!("plugin `{}` not found", opt.id));
|
||||
};
|
||||
|
||||
if let Err(e) = Loader::compatible_or_error(&opt.id, chunk) {
|
||||
succ!(NotifyProxy::push_error("Incompatible plugin", e.to_string()));
|
||||
}
|
||||
|
||||
if opt.mode.auto_then(chunk.sync_entry) != PluginMode::Sync {
|
||||
succ!(cx.core.tasks.scheduler.plugin_entry(opt.into()));
|
||||
}
|
||||
|
||||
let blocking = runtime_mut!(LUA)?.critical_push(&opt.id, true);
|
||||
defer! { _ = runtime_mut!(LUA).map(|mut r| r.critical_pop(blocking)) }
|
||||
|
||||
let plugin = match LOADER.load_chunk(&LUA, &opt.id, chunk) {
|
||||
Ok(t) => t,
|
||||
Err(e) => succ!(warn!("{e}")),
|
||||
};
|
||||
drop(loader);
|
||||
|
||||
let result = Lives::scope(cx.core, |_| {
|
||||
if let Some(cb) = opt.callback {
|
||||
cb(&LUA, plugin)
|
||||
} else {
|
||||
plugin.call_method("entry", EntryJob { args: opt.args, ..Default::default() })
|
||||
}
|
||||
});
|
||||
if let Err(ref e) = result {
|
||||
error!("Sync plugin `{}` failed: {e}", opt.id);
|
||||
}
|
||||
succ!(result?);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
use std::process;
|
||||
|
||||
use anyhow::Result;
|
||||
use yazi_boot::ARGS;
|
||||
use yazi_fs::engine::{Engine, local::Local};
|
||||
use yazi_parser::app::QuitForm;
|
||||
use yazi_shared::{data::Data, strand::{StrandBuf, StrandLike, ToStrand}};
|
||||
use yazi_tui::Raterm;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Quit;
|
||||
|
||||
impl Actor for Quit {
|
||||
type Form = QuitForm;
|
||||
|
||||
const NAME: &str = "quit";
|
||||
|
||||
fn act(cx: &mut Ctx, Self::Form { opt }: Self::Form) -> Result<Data> {
|
||||
cx.tasks.shutdown();
|
||||
cx.mgr.shutdown();
|
||||
|
||||
futures::executor::block_on(async {
|
||||
_ = futures::join!(
|
||||
yazi_dds::shutdown(),
|
||||
yazi_dds::STATE.drain(),
|
||||
Self::cwd_to_file(cx, opt.no_cwd_file),
|
||||
Self::selected_to_file(opt.selected)
|
||||
);
|
||||
});
|
||||
|
||||
Raterm::stop();
|
||||
process::exit(opt.code);
|
||||
}
|
||||
}
|
||||
|
||||
impl Quit {
|
||||
async fn cwd_to_file(cx: &Ctx<'_>, no: bool) {
|
||||
if let Some(p) = ARGS.cwd_file.as_ref().filter(|_| !no) {
|
||||
let cwd = cx.mgr.cwd().to_strand();
|
||||
Local::regular(p).write(cwd.encoded_bytes()).await.ok();
|
||||
}
|
||||
}
|
||||
|
||||
async fn selected_to_file(selected: Option<StrandBuf>) {
|
||||
if let (Some(s), Some(p)) = (selected, &ARGS.chooser_file) {
|
||||
Local::regular(p).write(s.encoded_bytes()).await.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use mlua::{LuaString, Value};
|
||||
use ratatui_core::layout::Position;
|
||||
use tracing::error;
|
||||
use yazi_actor::lives::Lives;
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::app::ReflowForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Reflow;
|
||||
|
||||
impl Actor for Reflow {
|
||||
type Form = ReflowForm;
|
||||
|
||||
const NAME: &str = "reflow";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let Some(size) = cx.term.as_ref().and_then(|t| t.size().ok()) else { succ!() };
|
||||
let mut layout = LAYOUT.get();
|
||||
|
||||
let result = Lives::scope(cx.core, |_| {
|
||||
let comps = (form.reflow)((Position::ORIGIN, size).into())?;
|
||||
|
||||
for v in comps.sequence_values::<Value>() {
|
||||
let Value::Table(t) = v? else {
|
||||
error!("`reflow()` must return a table of components");
|
||||
continue;
|
||||
};
|
||||
|
||||
let id: LuaString = t.get("_id")?;
|
||||
match &*id.as_bytes() {
|
||||
b"current" => layout.current = *t.raw_get::<yazi_binding::elements::Rect>("_area")?,
|
||||
b"preview" => layout.preview = *t.raw_get::<yazi_binding::elements::Rect>("_area")?,
|
||||
b"progress" => layout.progress = *t.raw_get::<yazi_binding::elements::Rect>("_area")?,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
if layout != LAYOUT.get() {
|
||||
LAYOUT.set(layout);
|
||||
render!();
|
||||
}
|
||||
|
||||
if let Err(ref e) = result {
|
||||
error!("Failed to `reflow()` the `Root` component:\n{e}");
|
||||
}
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_macro::act;
|
||||
use yazi_parser::app::ReflowForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::Actor;
|
||||
|
||||
pub struct Resize;
|
||||
|
||||
impl Actor for Resize {
|
||||
type Form = ReflowForm;
|
||||
|
||||
const NAME: &str = "resize";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
act!(app:reflow, cx, form)?;
|
||||
|
||||
cx.current_mut().arrow(0);
|
||||
cx.parent_mut().map(|f| f.arrow(0));
|
||||
cx.current_mut().sync_page(true);
|
||||
|
||||
act!(mgr:peek, cx)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::app::ReflowForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_tui::Raterm;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Resume;
|
||||
|
||||
impl Actor for Resume {
|
||||
type Form = ReflowForm;
|
||||
|
||||
const NAME: &str = "resume";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
cx.active_mut().preview.reset();
|
||||
|
||||
drop(cx.term.take());
|
||||
*cx.term = Some(Raterm::start()?);
|
||||
|
||||
// While the app resumes, it's possible that the terminal size has changed.
|
||||
// We need to trigger a resize, and render the UI based on the resized area.
|
||||
act!(app:resize, cx, form.reflow)?;
|
||||
|
||||
act!(app:title, cx).ok();
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Stop;
|
||||
|
||||
impl Actor for Stop {
|
||||
type Form = VoidForm;
|
||||
|
||||
const NAME: &str = "stop";
|
||||
|
||||
fn act(cx: &mut Ctx, _: Self::Form) -> Result<Data> {
|
||||
cx.active_mut().preview.reset_image();
|
||||
|
||||
*cx.term = None;
|
||||
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_config::{THEME, build_flavor};
|
||||
use yazi_emulator::EMULATOR;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_shim::serde::Overlay;
|
||||
|
||||
use crate::Actor;
|
||||
|
||||
pub struct Theme;
|
||||
|
||||
impl Actor for Theme {
|
||||
type Form = VoidForm;
|
||||
|
||||
const NAME: &str = "theme";
|
||||
|
||||
fn act(_cx: &mut Ctx, _: Self::Form) -> Result<Data> {
|
||||
THEME.overlay(build_flavor(EMULATOR.light, true)?);
|
||||
yazi_plugin::theme::reset()?;
|
||||
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_macro::{succ, writef};
|
||||
use yazi_parser::{app::TitleForm, spark::SparkKind};
|
||||
use yazi_shared::{Source, data::Data};
|
||||
use yazi_tty::{TTY, sequence::SetTitle};
|
||||
use yazi_tui::RatermState;
|
||||
|
||||
use crate::Actor;
|
||||
|
||||
pub struct Title;
|
||||
|
||||
impl Actor for Title {
|
||||
type Form = TitleForm;
|
||||
|
||||
const NAME: &str = "title";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let s = form.value.unwrap_or_else(|| format!("Yazi: {}", cx.tab().name()).into());
|
||||
writef!(TTY.writer(), "{}", SetTitle(&s))?;
|
||||
|
||||
yazi_tui::STATE.set(RatermState { title: !s.is_empty(), ..yazi_tui::STATE.get() });
|
||||
succ!()
|
||||
}
|
||||
|
||||
fn hook(cx: &Ctx, _form: &Self::Form) -> Option<SparkKind> {
|
||||
match cx.source() {
|
||||
Source::Ind => Some(SparkKind::IndAppTitle),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_actor::Ctx;
|
||||
use yazi_macro::{act, render, render_partial, succ};
|
||||
use yazi_parser::app::UpdateProgressForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::Actor;
|
||||
|
||||
pub struct UpdateProgress;
|
||||
|
||||
impl Actor for UpdateProgress {
|
||||
type Form = UpdateProgressForm;
|
||||
|
||||
const NAME: &str = "update_progress";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
// Update the progress of all tasks.
|
||||
let tasks = &mut cx.tasks;
|
||||
let progressed = tasks.summary != form.summary;
|
||||
tasks.summary = form.summary;
|
||||
|
||||
// If the task manager is visible, update the snaps with a full render.
|
||||
if tasks.visible {
|
||||
let new = tasks.paginate();
|
||||
if tasks.snaps != new {
|
||||
tasks.snaps = new;
|
||||
act!(tasks:arrow, cx)?;
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
||||
if !progressed {
|
||||
succ!()
|
||||
} else if tasks.summary.total == 0 {
|
||||
succ!(render!())
|
||||
} else {
|
||||
succ!(render_partial!())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::ArrowForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::Scrollable;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Arrow;
|
||||
|
||||
impl Actor for Arrow {
|
||||
type Form = ArrowForm;
|
||||
|
||||
const NAME: &str = "arrow";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
succ!(render!(cx.cmp.scroll(form.step)));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
use std::mem;
|
||||
|
||||
use anyhow::Result;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::cmp::CloseForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::input::parser::CompleteOpt;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Close;
|
||||
|
||||
impl Actor for Close {
|
||||
type Form = CloseForm;
|
||||
|
||||
const NAME: &str = "close";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
if form.submit && cx.cmp.visible {
|
||||
Self::flush_last_input(cx)?;
|
||||
}
|
||||
|
||||
let cmp = &mut cx.cmp;
|
||||
if let Some(item) = cmp.selected().filter(|_| form.submit).cloned() {
|
||||
return act!(input:complete, cx, CompleteOpt { name: item.name, is_dir: item.is_dir, ticket: cmp.ticket });
|
||||
}
|
||||
|
||||
cmp.caches.clear();
|
||||
cmp.ticket = Default::default();
|
||||
cmp.handle.take().map(|h| h.abort());
|
||||
succ!(render!(mem::replace(&mut cmp.visible, false)));
|
||||
}
|
||||
}
|
||||
|
||||
impl Close {
|
||||
fn flush_last_input(cx: &mut Ctx) -> Result<Data> {
|
||||
let Some(guard) = cx.input.lock() else { succ!() };
|
||||
if cx.cmp.ticket == guard.ticket.current() {
|
||||
succ!();
|
||||
}
|
||||
|
||||
let before = guard.partition().0.to_owned();
|
||||
drop(guard);
|
||||
|
||||
act!(cmp:trigger, cx, before)
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
yazi_macro::mod_flat!(arrow close show trigger);
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
use std::{mem, ops::ControlFlow};
|
||||
|
||||
use anyhow::Result;
|
||||
use yazi_core::cmp::CmpItem;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::cmp::ShowForm;
|
||||
use yazi_shared::{data::Data, path::{DynPath, PathDyn}, strand::StrandLike};
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
const LIMIT: usize = 30;
|
||||
|
||||
pub struct Show;
|
||||
|
||||
impl Actor for Show {
|
||||
type Form = ShowForm;
|
||||
|
||||
const NAME: &str = "show";
|
||||
|
||||
fn act(cx: &mut Ctx, Self::Form { opt }: Self::Form) -> Result<Data> {
|
||||
let cmp = &mut cx.cmp;
|
||||
if cmp.ticket != opt.ticket {
|
||||
succ!();
|
||||
}
|
||||
|
||||
if !opt.cache.is_empty() {
|
||||
cmp.caches.insert(opt.cache_name.clone(), opt.cache);
|
||||
}
|
||||
let Some(cache) = cmp.caches.get(&opt.cache_name) else {
|
||||
succ!();
|
||||
};
|
||||
|
||||
cmp.matches = Self::match_candidates(opt.word.dyn_path(), cache);
|
||||
if cmp.matches.is_empty() {
|
||||
succ!(render!(mem::replace(&mut cmp.visible, false)));
|
||||
}
|
||||
|
||||
cmp.offset = 0;
|
||||
cmp.cursor = 0;
|
||||
cmp.visible = true;
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
||||
impl Show {
|
||||
fn match_candidates(word: PathDyn, cache: &[CmpItem]) -> Vec<CmpItem> {
|
||||
let smart = !word.encoded_bytes().iter().any(|&b| b.is_ascii_uppercase());
|
||||
|
||||
let flow = cache.iter().try_fold((Vec::new(), Vec::new()), |(mut exact, mut fuzzy), item| {
|
||||
let starts_with = if smart {
|
||||
item.name.starts_with_ignore_ascii_case(word)
|
||||
} else {
|
||||
item.name.starts_with(word)
|
||||
};
|
||||
|
||||
if starts_with {
|
||||
exact.push(item);
|
||||
if exact.len() >= LIMIT {
|
||||
return ControlFlow::Break((exact, fuzzy));
|
||||
}
|
||||
} else if fuzzy.len() < LIMIT - exact.len() && item.name.contains(word) {
|
||||
// Here we don't break the control flow, since we want more exact matching.
|
||||
fuzzy.push(item)
|
||||
}
|
||||
ControlFlow::Continue((exact, fuzzy))
|
||||
});
|
||||
|
||||
let (exact, fuzzy) = match flow {
|
||||
ControlFlow::Continue(v) => v,
|
||||
ControlFlow::Break(v) => v,
|
||||
};
|
||||
|
||||
let it = fuzzy.into_iter().take(LIMIT - exact.len());
|
||||
exact.into_iter().chain(it).cloned().collect()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
use std::{io, mem};
|
||||
|
||||
use anyhow::Result;
|
||||
use yazi_core::cmp::{CmpItem, CmpOpt};
|
||||
use yazi_fs::{engine::{DirReader, FileHolder}, path::clean_url};
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::cmp::TriggerForm;
|
||||
use yazi_proxy::CmpProxy;
|
||||
use yazi_shared::{AnyAsciiChar, BytePredictor, data::Data, natsort, path::{DynPath, PathBufDyn, PathLike}, spec::Spec, strand::{AsStrand, StrandLike}, url::{UrlBuf, UrlCow, UrlLike}};
|
||||
use yazi_vfs::engine;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Trigger;
|
||||
|
||||
impl Actor for Trigger {
|
||||
type Form = TriggerForm;
|
||||
|
||||
const NAME: &str = "trigger";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
if form.ticket.is_some_and(|t| t != cx.cmp.ticket) {
|
||||
succ!();
|
||||
} else if form.ticket.is_none() {
|
||||
cx.cmp.ticket = cx.input.lock().map(|g| g.ticket.current()).unwrap_or_default();
|
||||
}
|
||||
|
||||
cx.cmp.handle.take().map(|h| h.abort());
|
||||
let Some((parent, word)) = Self::split_url(&form.word) else {
|
||||
return act!(cmp:close, cx, false);
|
||||
};
|
||||
|
||||
let ticket = cx.cmp.ticket;
|
||||
if cx.cmp.caches.contains_key(&parent) {
|
||||
return act!(cmp:show, cx, CmpOpt { cache: vec![], cache_name: parent, word, ticket });
|
||||
}
|
||||
|
||||
cx.cmp.handle = Some(tokio::spawn(async move {
|
||||
let mut dir = engine::read_dir(&parent).await?;
|
||||
let mut cache = vec![];
|
||||
|
||||
// "/" is both a directory separator and the root directory per se
|
||||
// As there's no parent directory for the FS root, it is a special case
|
||||
if parent.loc() == "/" {
|
||||
cache.push(CmpItem { name: Default::default(), is_dir: true });
|
||||
}
|
||||
|
||||
while let Ok(Some(ent)) = dir.next().await {
|
||||
if let Ok(ft) = ent.file_type().await {
|
||||
cache.push(CmpItem { name: ent.name().into_owned(), is_dir: ft.is_dir() });
|
||||
}
|
||||
}
|
||||
|
||||
if !cache.is_empty() {
|
||||
cache
|
||||
.sort_unstable_by(|a, b| natsort(a.name.encoded_bytes(), b.name.encoded_bytes(), true));
|
||||
CmpProxy::show(CmpOpt { cache, cache_name: parent, word, ticket });
|
||||
}
|
||||
|
||||
Ok::<_, io::Error>(())
|
||||
}));
|
||||
|
||||
succ!(render!(mem::replace(&mut cx.cmp.visible, false)));
|
||||
}
|
||||
}
|
||||
|
||||
impl Trigger {
|
||||
fn split_url(s: &str) -> Option<(UrlBuf, PathBufDyn)> {
|
||||
let (spec, path) = Spec::parse(s.as_bytes()).ok()?;
|
||||
if path.is_empty() && !AnyAsciiChar::SEP.predicate(s.bytes().last()?) {
|
||||
return None; // We don't complete a `sftp://test`, but `sftp://test/`
|
||||
}
|
||||
|
||||
// Spec
|
||||
let spec = spec.zeroed();
|
||||
if spec.kind.is_local() && path.as_strand() == "~" {
|
||||
return None; // We don't complete a `~`, but `~/`
|
||||
}
|
||||
|
||||
// Child
|
||||
let child = path.rsplit_pred(AnyAsciiChar::SEP).map_or(path.dyn_path(), |(_, c)| c).to_owned();
|
||||
|
||||
// Parent
|
||||
let url = UrlCow::try_from((spec.clone().zeroed(), path)).ok()?;
|
||||
let abs = if let Some(u) = engine::try_absolute(&url) { u } else { url };
|
||||
let parent = abs.loc().try_strip_suffix(&child).ok()?;
|
||||
|
||||
Some((clean_url(UrlCow::try_from((spec, parent)).ok()?), child))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use yazi_fs::CWD;
|
||||
use yazi_shared::url::UrlLike;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn compare(s: &str, parent: &str, child: &str) {
|
||||
let (mut p, c) = Trigger::split_url(s).unwrap();
|
||||
if let Ok(u) = p.try_strip_prefix(yazi_fs::CWD.load().as_ref()) {
|
||||
p = UrlBuf::Regular(u.as_os().unwrap().into());
|
||||
}
|
||||
assert_eq!((p, c.to_str().unwrap()), (parent.parse().unwrap(), child));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_split() {
|
||||
yazi_shared::init_tests();
|
||||
yazi_config::init_tests();
|
||||
yazi_fs::init();
|
||||
|
||||
assert_eq!(Trigger::split_url(""), None);
|
||||
assert_eq!(Trigger::split_url("sftp://vps"), None);
|
||||
compare(" ", "", " ");
|
||||
|
||||
compare("/", "/", "");
|
||||
compare("//", "/", "");
|
||||
compare("///", "/", "");
|
||||
|
||||
compare("/foo", "/", "foo");
|
||||
compare("//foo", "/", "foo");
|
||||
compare("///foo", "/", "foo");
|
||||
|
||||
compare("/foo/", "/foo/", "");
|
||||
compare("//foo/", "/foo/", "");
|
||||
compare("/foo/bar", "/foo/", "bar");
|
||||
compare("///foo/bar", "/foo/", "bar");
|
||||
|
||||
CWD.set(&"sftp://vps".parse::<UrlBuf>().unwrap(), || {});
|
||||
compare("sftp://vps/a", "sftp://vps/.", "a");
|
||||
compare("sftp://vps//a", "sftp://vps//", "a");
|
||||
compare("test-scope://aws/a", "test-scope://aws/.", "a");
|
||||
compare("test-scope://aws//a", "test-scope://aws//", "a");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn test_split() {
|
||||
yazi_shared::init_tests();
|
||||
yazi_config::init_tests();
|
||||
yazi_fs::init();
|
||||
compare("foo", "", "foo");
|
||||
|
||||
compare(r"foo\", r"foo\", "");
|
||||
compare(r"foo\bar", r"foo\", "bar");
|
||||
compare(r"foo\bar\", r"foo\bar\", "");
|
||||
|
||||
compare(r"C:\", r"C:\", "");
|
||||
compare(r"C:\foo", r"C:\", "foo");
|
||||
compare(r"C:\foo\", r"C:\foo\", "");
|
||||
compare(r"C:\foo\bar", r"C:\foo\", "bar");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::ArrowForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Arrow;
|
||||
|
||||
impl Actor for Arrow {
|
||||
type Form = ArrowForm;
|
||||
|
||||
const NAME: &str = "arrow";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let confirm = &mut cx.core.confirm;
|
||||
|
||||
let area = cx.core.mgr.area(confirm.position);
|
||||
let len = confirm.list.line_count(area.width);
|
||||
|
||||
let old = confirm.offset;
|
||||
confirm.offset = form.step.add(confirm.offset, len, area.height as _, 0, 0);
|
||||
|
||||
succ!(render!(old != confirm.offset));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::confirm::CloseForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Close;
|
||||
|
||||
impl Actor for Close {
|
||||
type Form = CloseForm;
|
||||
|
||||
const NAME: &str = "close";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
cx.confirm.token.complete(form.submit);
|
||||
cx.confirm.visible = false;
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
yazi_macro::mod_flat!(arrow close show);
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::confirm::ShowForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Show;
|
||||
|
||||
impl Actor for Show {
|
||||
type Form = ShowForm;
|
||||
|
||||
const NAME: &str = "show";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
act!(confirm:close, cx)?;
|
||||
|
||||
let confirm = &mut cx.confirm;
|
||||
confirm.title = form.cfg.title;
|
||||
confirm.body = form.cfg.body;
|
||||
confirm.list = form.cfg.list;
|
||||
|
||||
confirm.position = form.cfg.position;
|
||||
confirm.offset = 0;
|
||||
|
||||
confirm.token = form.token;
|
||||
confirm.visible = true;
|
||||
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
use yazi_core::{Core, mgr::Tabs, tab::{Folder, Tab}};
|
||||
use yazi_fs::file::File;
|
||||
use yazi_shared::{Source, event::Action, id::Id, url::UrlBuf};
|
||||
use yazi_tui::Raterm;
|
||||
|
||||
pub struct Ctx<'a> {
|
||||
pub core: &'a mut Core,
|
||||
pub term: &'a mut Option<Raterm>,
|
||||
pub tab: usize,
|
||||
pub level: usize,
|
||||
pub source: Source,
|
||||
#[cfg(debug_assertions)]
|
||||
pub backtrace: Vec<&'static str>,
|
||||
}
|
||||
|
||||
impl Deref for Ctx<'_> {
|
||||
type Target = Core;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.core }
|
||||
}
|
||||
|
||||
impl DerefMut for Ctx<'_> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target { self.core }
|
||||
}
|
||||
|
||||
impl<'a> Ctx<'a> {
|
||||
pub fn new(action: &Action, core: &'a mut Core, term: &'a mut Option<Raterm>) -> Result<Self> {
|
||||
let tab = if let Ok(id) = action.get::<Id>("tab") {
|
||||
core
|
||||
.mgr
|
||||
.tabs
|
||||
.iter()
|
||||
.position(|t| t.id == id)
|
||||
.ok_or_else(|| anyhow!("Tab with id {id} not found"))?
|
||||
} else {
|
||||
core.mgr.tabs.cursor
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
core,
|
||||
term,
|
||||
tab,
|
||||
level: 0,
|
||||
source: action.source,
|
||||
#[cfg(debug_assertions)]
|
||||
backtrace: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn renew<'b>(cx: &'a mut Ctx<'b>) -> Self {
|
||||
let tab = cx.core.mgr.tabs.cursor;
|
||||
Self {
|
||||
core: cx.core,
|
||||
term: cx.term,
|
||||
tab,
|
||||
level: cx.level,
|
||||
source: cx.source,
|
||||
#[cfg(debug_assertions)]
|
||||
backtrace: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn active(core: &'a mut Core, term: &'a mut Option<Raterm>) -> Self {
|
||||
let tab = core.mgr.tabs.cursor;
|
||||
Self {
|
||||
core,
|
||||
term,
|
||||
tab,
|
||||
level: 0,
|
||||
source: Source::Unknown,
|
||||
#[cfg(debug_assertions)]
|
||||
backtrace: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Ctx<'a> {
|
||||
#[inline]
|
||||
pub fn tabs(&self) -> &Tabs { &self.mgr.tabs }
|
||||
|
||||
#[inline]
|
||||
pub fn tabs_mut(&mut self) -> &mut Tabs { &mut self.mgr.tabs }
|
||||
|
||||
#[inline]
|
||||
pub fn tab(&self) -> &Tab { &self.tabs()[self.tab] }
|
||||
|
||||
#[inline]
|
||||
pub fn tab_mut(&mut self) -> &mut Tab { &mut self.core.mgr.tabs[self.tab] }
|
||||
|
||||
#[inline]
|
||||
pub fn cwd(&self) -> &UrlBuf { self.tab().cwd() }
|
||||
|
||||
#[inline]
|
||||
pub fn parent(&self) -> Option<&Folder> { self.tab().parent.as_ref() }
|
||||
|
||||
#[inline]
|
||||
pub fn parent_mut(&mut self) -> Option<&mut Folder> { self.tab_mut().parent.as_mut() }
|
||||
|
||||
#[inline]
|
||||
pub fn current(&self) -> &Folder { &self.tab().current }
|
||||
|
||||
#[inline]
|
||||
pub fn current_mut(&mut self) -> &mut Folder { &mut self.tab_mut().current }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered(&self) -> Option<&File> { self.tab().hovered() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_url(&self) -> Option<&UrlBuf> { self.tab().hovered_url() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_folder(&self) -> Option<&Folder> { self.tab().hovered_folder() }
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_folder_mut(&mut self) -> Option<&mut Folder> {
|
||||
self.tab_mut().hovered_folder_mut()
|
||||
}
|
||||
|
||||
pub fn source(&self) -> Source { if self.level != 1 { Source::Ind } else { self.source } }
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
yazi_macro::mod_flat!(preflight);
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use mlua::{ErrorContext, ExternalError, IntoLua, Value};
|
||||
use yazi_binding::runtime_scope;
|
||||
use yazi_dds::LOCAL;
|
||||
use yazi_parser::spark::{Spark, SparkKind};
|
||||
use yazi_plugin::LUA;
|
||||
|
||||
use crate::{Ctx, lives::Lives};
|
||||
|
||||
pub struct Preflight;
|
||||
|
||||
impl Preflight {
|
||||
pub fn act<'a>(cx: &mut Ctx, opt: (SparkKind, Spark<'a>)) -> Result<Spark<'a>> {
|
||||
let kind = opt.0;
|
||||
let Some(handlers) = LOCAL.read().get(kind.into()).filter(|&m| !m.is_empty()).cloned() else {
|
||||
return Ok(opt.1);
|
||||
};
|
||||
|
||||
Ok(Lives::scope(cx.core, |_| {
|
||||
let mut body = opt.1.into_lua(&LUA)?;
|
||||
for (id, cb) in handlers {
|
||||
match runtime_scope!(LUA, &id, cb.call::<Value>(&body)) {
|
||||
Ok(Value::Nil) => {
|
||||
Err(format!("`{kind}` event cancelled by `{id}` plugin on preflight").into_lua_err())?
|
||||
}
|
||||
Ok(v) => body = v,
|
||||
Err(e) => Err(
|
||||
format!("Failed to run `{kind}` event handler in `{id}` plugin: {e}").into_lua_err(),
|
||||
)?,
|
||||
};
|
||||
}
|
||||
|
||||
Spark::from_lua(&LUA, kind, body)
|
||||
.with_context(|e| format!("Unexpected return type from `{kind}` event handlers: {e}"))
|
||||
})?)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::ArrowForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::Scrollable;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Arrow;
|
||||
|
||||
impl Actor for Arrow {
|
||||
type Form = ArrowForm;
|
||||
|
||||
const NAME: &str = "arrow";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
succ!(render!(cx.help.scroll(form.step)));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{emit, render, succ};
|
||||
use yazi_parser::help::CloseForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Close;
|
||||
|
||||
impl Actor for Close {
|
||||
type Form = CloseForm;
|
||||
|
||||
const NAME: &str = "close";
|
||||
|
||||
fn act(cx: &mut Ctx, opt: Self::Form) -> Result<Data> {
|
||||
let help = &mut cx.help;
|
||||
|
||||
if let Some(chord) = help.bindings.get(help.cursor).filter(|_| opt.submit) {
|
||||
emit!(Seq(chord.to_seq(help.layer)));
|
||||
}
|
||||
|
||||
help.visible = false;
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::input::InputMode;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Escape;
|
||||
|
||||
impl Actor for Escape {
|
||||
type Form = VoidForm;
|
||||
|
||||
const NAME: &str = "escape";
|
||||
|
||||
fn act(cx: &mut Ctx, _: Self::Form) -> Result<Data> {
|
||||
if cx.help.input.mode() == InputMode::Normal {
|
||||
return act!(help:close, cx);
|
||||
}
|
||||
|
||||
act!(escape, cx.help.input)?;
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
yazi_macro::mod_flat!(arrow close escape toggle);
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use ratatui_core::layout::Margin;
|
||||
use yazi_config::popup::Help;
|
||||
use yazi_macro::{render, succ};
|
||||
use yazi_parser::help::ToggleForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::input::Input;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Toggle;
|
||||
|
||||
impl Actor for Toggle {
|
||||
type Form = ToggleForm;
|
||||
|
||||
const NAME: &str = "toggle";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let position = Help::position();
|
||||
let area = cx.mgr.area(position);
|
||||
let input_area = area.inner(Margin::new(1, 1));
|
||||
|
||||
let help = &mut cx.help;
|
||||
help.visible = true;
|
||||
help.layer = form.layer;
|
||||
help.position = position;
|
||||
help.height = area.height;
|
||||
|
||||
help.input = Input::default();
|
||||
help.input.repos(input_area);
|
||||
|
||||
help.keyword.clear();
|
||||
help.offset = 0;
|
||||
help.cursor = 0;
|
||||
help.filter_apply();
|
||||
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::input::InputMutGuard;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::{input::CloseForm, spark::SparkKind};
|
||||
use yazi_shared::{Source, data::Data};
|
||||
use yazi_widgets::input::InputEvent;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Close;
|
||||
|
||||
impl Actor for Close {
|
||||
type Form = CloseForm;
|
||||
|
||||
const NAME: &str = "close";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let Some(mut guard) = cx.input.lock_mut() else {
|
||||
succ!();
|
||||
};
|
||||
|
||||
guard.ticket.next();
|
||||
if let Some(cb) = guard.cb.take() {
|
||||
let value = guard.value().to_owned();
|
||||
cb(if form.submit { InputEvent::Submit(value) } else { InputEvent::Cancel(value) });
|
||||
}
|
||||
|
||||
if form.submit
|
||||
&& let InputMutGuard::Main(input) = guard
|
||||
{
|
||||
input.histories.remember(&input.main.history.name, input.main.value());
|
||||
}
|
||||
|
||||
cx.input.main.visible = false;
|
||||
|
||||
act!(cmp:close, cx)?;
|
||||
succ!(render!());
|
||||
}
|
||||
|
||||
fn hook(cx: &Ctx, _form: &Self::Form) -> Option<SparkKind> {
|
||||
match cx.source() {
|
||||
Source::Key => Some(SparkKind::KeyInputClose),
|
||||
Source::Ind => Some(SparkKind::IndInputClose),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{act, succ};
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::input::parser::CompleteOpt;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Complete;
|
||||
|
||||
impl Actor for Complete {
|
||||
type Form = CompleteOpt;
|
||||
|
||||
const NAME: &str = "complete";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let Some(mut guard) = cx.input.lock_mut() else {
|
||||
succ!();
|
||||
};
|
||||
|
||||
if guard.ticket.current() != form.ticket {
|
||||
succ!();
|
||||
}
|
||||
|
||||
act!(complete, guard, form)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_widgets::input::InputOp;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Escape;
|
||||
|
||||
impl Actor for Escape {
|
||||
type Form = VoidForm;
|
||||
|
||||
const NAME: &str = "escape";
|
||||
|
||||
fn act(cx: &mut Ctx, _: Self::Form) -> Result<Data> {
|
||||
use yazi_widgets::input::InputMode as M;
|
||||
let Some(mut guard) = cx.input.lock_mut() else {
|
||||
succ!();
|
||||
};
|
||||
|
||||
let (mode, op) = (guard.snap().mode, guard.snap().op);
|
||||
act!(escape, guard)?;
|
||||
|
||||
drop(guard);
|
||||
match mode {
|
||||
M::Normal if op == InputOp::None => act!(input:close, cx),
|
||||
M::Insert => act!(cmp:close, cx),
|
||||
M::Normal | M::Replace => Ok(().into()),
|
||||
}?;
|
||||
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
yazi_macro::mod_flat!(close complete escape recall remember show);
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::input::InputMutGuard;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::input::RecallForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Recall;
|
||||
|
||||
impl Actor for Recall {
|
||||
type Form = RecallForm;
|
||||
|
||||
const NAME: &str = "recall";
|
||||
|
||||
fn act(cx: &mut Ctx, form: Self::Form) -> Result<Data> {
|
||||
let Some(input) = cx.input.lock_mut() else {
|
||||
succ!();
|
||||
};
|
||||
|
||||
match input {
|
||||
InputMutGuard::Main(input) => {
|
||||
let entries = input.histories.get(&input.main.history.name);
|
||||
input.main.recall(entries, form.step)
|
||||
}
|
||||
InputMutGuard::Alt(input, mut guard) => {
|
||||
let entries = input.histories.get(&guard.history.name);
|
||||
guard.recall(entries, form.step)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
use anyhow::Result;
|
||||
use yazi_core::input::InputMutGuard;
|
||||
use yazi_macro::succ;
|
||||
use yazi_parser::VoidForm;
|
||||
use yazi_shared::data::Data;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Remember;
|
||||
|
||||
impl Actor for Remember {
|
||||
type Form = VoidForm;
|
||||
|
||||
const NAME: &str = "remember";
|
||||
|
||||
fn act(cx: &mut Ctx, _: Self::Form) -> Result<Data> {
|
||||
let Some(mut input) = cx.input.lock_mut() else {
|
||||
succ!();
|
||||
};
|
||||
|
||||
match &mut input {
|
||||
InputMutGuard::Main(input) => {
|
||||
input.histories.remember(&input.main.history.name, input.main.value());
|
||||
}
|
||||
InputMutGuard::Alt(input, guard) => {
|
||||
input.histories.remember(&guard.history.name, guard.value());
|
||||
}
|
||||
}
|
||||
|
||||
input.history.take();
|
||||
succ!();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
use std::ops::DerefMut;
|
||||
|
||||
use anyhow::Result;
|
||||
use yazi_config::{THEME, YAZI};
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::input::ShowForm;
|
||||
use yazi_shared::data::Data;
|
||||
use yazi_shim::ratatui::Padable;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
||||
pub struct Show;
|
||||
|
||||
impl Actor for Show {
|
||||
type Form = ShowForm;
|
||||
|
||||
const NAME: &str = "show";
|
||||
|
||||
fn act(cx: &mut Ctx, Self::Form { mut opt }: Self::Form) -> Result<Data> {
|
||||
act!(input:close, cx)?;
|
||||
|
||||
let area = cx.mgr.area(opt.position).padding(cx.input.padding());
|
||||
let input = &mut cx.input;
|
||||
input.main.name = opt.name.clone();
|
||||
input.main.title = opt.title.clone();
|
||||
input.main.position = opt.position;
|
||||
input.main.visible = true;
|
||||
|
||||
opt.styles = (&THEME.input).into();
|
||||
opt.blinking = YAZI.input.cursor_blink;
|
||||
*input.main.deref_mut() = yazi_widgets::input::Input::new(opt)?;
|
||||
input.main.repos(area);
|
||||
|
||||
succ!(render!());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
extern crate self as yazi_actor;
|
||||
|
||||
yazi_macro::mod_pub!(app cmp confirm core help input lives mgr notify pick spot tasks which);
|
||||
|
||||
yazi_macro::mod_flat!(actor context);
|
||||
|
||||
pub fn init() { lives::init(); }
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataMethods};
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Behavior {
|
||||
inner: PtrCell<yazi_scheduler::Behavior>,
|
||||
}
|
||||
|
||||
impl Deref for Behavior {
|
||||
type Target = yazi_scheduler::Behavior;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Behavior {
|
||||
pub(super) fn make(inner: &yazi_scheduler::Behavior) -> mlua::Result<AnyUserData> {
|
||||
let inner = PtrCell::from(inner);
|
||||
|
||||
Lives::scoped_userdata(Self { inner })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Behavior {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_method("reset", |_, me, ()| Ok(me.reset()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, LuaString, MetaMethod, UserData, UserDataMethods, UserDataRef, Value};
|
||||
use paste::paste;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) type CoreRef = UserDataRef<Core>;
|
||||
|
||||
pub(super) struct Core {
|
||||
inner: PtrCell<yazi_core::Core>,
|
||||
|
||||
c_active: Option<Value>,
|
||||
c_tabs: Option<Value>,
|
||||
c_tasks: Option<Value>,
|
||||
c_yanked: Option<Value>,
|
||||
c_input: Option<Value>,
|
||||
c_which: Option<Value>,
|
||||
c_layer: Option<Value>,
|
||||
}
|
||||
|
||||
impl Deref for Core {
|
||||
type Target = yazi_core::Core;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Core {
|
||||
pub(super) fn make(inner: &yazi_core::Core) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self {
|
||||
inner: inner.into(),
|
||||
|
||||
c_active: None,
|
||||
c_tabs: None,
|
||||
c_tasks: None,
|
||||
c_yanked: None,
|
||||
c_input: None,
|
||||
c_which: None,
|
||||
c_layer: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Core {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method_mut(MetaMethod::Index, |lua, me, key: LuaString| {
|
||||
macro_rules! reuse {
|
||||
($key:ident, $value:expr) => {
|
||||
match paste! { &me.[<c_ $key>] } {
|
||||
Some(v) => v.clone(),
|
||||
None => {
|
||||
let v = $value?.into_lua(lua)?;
|
||||
paste! { me.[<c_ $key>] = Some(v.clone()); };
|
||||
v
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Ok(match &*key.as_bytes() {
|
||||
b"active" => reuse!(active, super::Tab::make(me.active())),
|
||||
b"tabs" => reuse!(tabs, super::Tabs::make(&me.mgr.tabs)),
|
||||
b"tasks" => reuse!(tasks, super::Tasks::make(&me.tasks)),
|
||||
b"yanked" => reuse!(yanked, super::Yanked::make(&me.mgr.yanked)),
|
||||
b"input" => reuse!(input, super::Input::make(&me.input)),
|
||||
b"which" => reuse!(which, super::Which::make(&me.which)),
|
||||
b"layer" => reuse!(layer, Ok::<_, mlua::Error>(me.layer())),
|
||||
_ => Value::Nil,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
use std::ops::{Deref, Range};
|
||||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use super::{File, Filter, Lives, PtrCell};
|
||||
|
||||
pub(super) struct Entries {
|
||||
window: Range<usize>,
|
||||
folder: PtrCell<yazi_core::tab::Folder>,
|
||||
tab: PtrCell<yazi_core::tab::Tab>,
|
||||
}
|
||||
|
||||
impl Deref for Entries {
|
||||
type Target = yazi_fs::Entries;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.folder.entries }
|
||||
}
|
||||
|
||||
impl Entries {
|
||||
pub(super) fn make(
|
||||
window: Range<usize>,
|
||||
folder: &yazi_core::tab::Folder,
|
||||
tab: &yazi_core::tab::Tab,
|
||||
) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { window, folder: folder.into(), tab: tab.into() })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Entries {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_static_field("filter", |_, me| me.filter().map(Filter::make).transpose());
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.window.end - me.window.start));
|
||||
|
||||
methods.add_meta_method(MetaMethod::Index, |_, me, mut idx: usize| {
|
||||
idx += me.window.start;
|
||||
if idx > me.window.end || idx == 0 {
|
||||
Ok(None)
|
||||
} else {
|
||||
Some(File::make(idx - 1, &me.folder, &me.tab)).transpose()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
use std::{ops::Deref, ptr};
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods};
|
||||
use yazi_binding::{Range, style::Style};
|
||||
use yazi_config::THEME;
|
||||
use yazi_fs::file::FileInventory;
|
||||
use yazi_shared::{path::DynPath, url::UrlLike};
|
||||
|
||||
use super::{FILE_CACHE, Lives};
|
||||
use crate::lives::{CoreRef, PtrCell};
|
||||
|
||||
pub(super) struct File {
|
||||
idx: usize,
|
||||
folder: PtrCell<yazi_core::tab::Folder>,
|
||||
tab: PtrCell<yazi_core::tab::Tab>,
|
||||
}
|
||||
|
||||
impl Deref for File {
|
||||
type Target = yazi_fs::file::File;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.folder.entries[self.idx] }
|
||||
}
|
||||
|
||||
impl AsRef<yazi_fs::file::File> for File {
|
||||
fn as_ref(&self) -> &yazi_fs::file::File { self }
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub(super) fn make(
|
||||
idx: usize,
|
||||
folder: &yazi_core::tab::Folder,
|
||||
tab: &yazi_core::tab::Tab,
|
||||
) -> mlua::Result<AnyUserData> {
|
||||
use hashbrown::hash_map::Entry;
|
||||
|
||||
Ok(
|
||||
match unsafe { (*FILE_CACHE.get()).assume_init_mut() }.entry(PtrCell(&folder.entries[idx])) {
|
||||
Entry::Occupied(oe) => oe.into_mut().clone(),
|
||||
Entry::Vacant(ve) => {
|
||||
let ud = Lives::scoped_userdata(Self { idx, folder: folder.into(), tab: tab.into() })?;
|
||||
ve.insert(ud.clone());
|
||||
ud
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_hovered(&self) -> bool { self.idx == self.folder.cursor }
|
||||
}
|
||||
|
||||
impl UserData for File {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
yazi_binding::impl_file_fields!(fields);
|
||||
|
||||
fields.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
|
||||
fields.add_field_method_get("is_hovered", |_, me| Ok(me.is_hovered()));
|
||||
fields.add_field_method_get("in_current", |_, me| Ok(ptr::eq(&*me.folder, &me.tab.current)));
|
||||
fields.add_field_method_get("in_preview", |_, me| {
|
||||
Ok(me.idx == me.folder.cursor && me.tab.hovered().is_some_and(|f| f.url == me.folder.url))
|
||||
});
|
||||
}
|
||||
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
yazi_binding::impl_file_methods!(methods);
|
||||
|
||||
methods.add_method("icon", |lua, me, ()| {
|
||||
yazi_binding::deprecate!(
|
||||
lua,
|
||||
"{}: `File:icon()` is deprecated, use `th.icon:match(file)` instead"
|
||||
);
|
||||
// TODO: use a cache
|
||||
Ok(yazi_config::THEME.icon.matches(me, me.is_hovered()))
|
||||
});
|
||||
methods.add_method("size", |_, me, ()| {
|
||||
Ok(if me.is_dir() {
|
||||
me.folder.entries.sizes.get(&me.entry_key()).copied()
|
||||
} else {
|
||||
Some(me.len)
|
||||
})
|
||||
});
|
||||
methods.add_method("mime", |lua, me, ()| {
|
||||
let core: CoreRef = lua.named_registry_value("cx")?;
|
||||
core.mgr.mimetype.get(&me.url).map(|s| lua.create_string(s)).transpose()
|
||||
});
|
||||
methods.add_method("prefix", |lua, me, ()| {
|
||||
if !me.url.has_trail() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut comp = me.url.try_strip_prefix(me.url.trail()).unwrap_or(me.url.loc()).components();
|
||||
comp.next_back();
|
||||
Some(lua.create_string(comp.dyn_path().encoded_bytes())).transpose()
|
||||
});
|
||||
methods.add_method("style", |lua, me, ()| {
|
||||
let core: CoreRef = lua.named_registry_value("cx")?;
|
||||
let mime = core.mgr.mimetype.get(&me.url).unwrap_or_default();
|
||||
Ok(THEME.filetype.match_style(me, mime).map(Style::from))
|
||||
});
|
||||
methods.add_method("is_yanked", |lua, me, ()| {
|
||||
let core: CoreRef = lua.named_registry_value("cx")?;
|
||||
Ok(if !core.mgr.yanked.contains(&me.url) {
|
||||
0u8
|
||||
} else if core.mgr.yanked.cut {
|
||||
2u8
|
||||
} else {
|
||||
1u8
|
||||
})
|
||||
});
|
||||
methods.add_method("is_marked", |_, me, ()| {
|
||||
let Some(visual) = me.tab.mode.visual() else {
|
||||
return Ok(0u8);
|
||||
};
|
||||
if !visual.contains(me.idx, me.tab.current.cursor, me.folder.entries.len()) {
|
||||
return Ok(0u8);
|
||||
}
|
||||
if me.folder.url != me.tab.current.url {
|
||||
return Ok(0u8);
|
||||
}
|
||||
Ok(if me.tab.mode.is_select() { 1u8 } else { 2u8 })
|
||||
});
|
||||
methods.add_method("is_selected", |_, me, ()| Ok(me.tab.selected.contains(&me.url)));
|
||||
methods.add_method("found", |lua, me, ()| {
|
||||
let core: CoreRef = lua.named_registry_value("cx")?;
|
||||
let Some(finder) = &core.active().finder else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let Some(idx) = finder.matched_idx(&me.folder, me.entry_key()) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
lua.create_sequence_from([idx.into_lua(lua)?, finder.matched.len().into_lua(lua)?]).map(Some)
|
||||
});
|
||||
methods.add_method("highlights", |lua, me, ()| {
|
||||
let core: CoreRef = lua.named_registry_value("cx")?;
|
||||
let Some(finder) = &core.active().finder else {
|
||||
return Ok(None);
|
||||
};
|
||||
if me.folder.url != me.tab.current.url {
|
||||
return Ok(None);
|
||||
}
|
||||
let Some(Some(h)) = me.url.name().map(|s| finder.filter.highlighted(s)) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
lua.create_sequence_from(h.into_iter().map(Range::from)).map(Some)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
inventory::submit! {
|
||||
FileInventory {
|
||||
register: |_| {},
|
||||
borrow: |ud, f| f(&*ud.borrow::<File>()?),
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataMethods};
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Filter {
|
||||
inner: PtrCell<yazi_fs::Filter>,
|
||||
}
|
||||
|
||||
impl Deref for Filter {
|
||||
type Target = yazi_fs::Filter;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Filter {
|
||||
pub(super) fn make(inner: &yazi_fs::Filter) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Filter {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, MetaMethod, UserData, UserDataMethods};
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct Finder {
|
||||
inner: PtrCell<yazi_core::tab::Finder>,
|
||||
}
|
||||
|
||||
impl Deref for Finder {
|
||||
type Target = yazi_core::tab::Finder;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Finder {
|
||||
pub(super) fn make(inner: &yazi_core::tab::Finder) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Finder {
|
||||
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.filter.to_string()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
use std::ops::{Deref, Range};
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use super::{Entries, File, Lives, PtrCell};
|
||||
|
||||
pub(super) struct Folder {
|
||||
window: Range<usize>,
|
||||
inner: PtrCell<yazi_core::tab::Folder>,
|
||||
tab: PtrCell<yazi_core::tab::Tab>,
|
||||
}
|
||||
|
||||
impl Deref for Folder {
|
||||
type Target = yazi_core::tab::Folder;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Folder {
|
||||
pub(super) fn make(
|
||||
window: Option<Range<usize>>,
|
||||
inner: &yazi_core::tab::Folder,
|
||||
tab: &yazi_core::tab::Tab,
|
||||
) -> mlua::Result<AnyUserData> {
|
||||
let window = match window {
|
||||
Some(w) => w,
|
||||
None => {
|
||||
let limit = LAYOUT.get().preview.height as usize;
|
||||
inner.offset..inner.entries.len().min(inner.offset + limit)
|
||||
}
|
||||
};
|
||||
|
||||
Lives::scoped_userdata(Self { window, inner: inner.into(), tab: tab.into() })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Folder {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_cached_field("cwd", |_, me| Ok(me.url.clone()));
|
||||
fields.add_static_field("files", |_, me| Entries::make(0..me.entries.len(), me, &me.tab));
|
||||
fields.add_cached_field("stage", |_, me| Ok(me.stage.clone()));
|
||||
fields.add_static_field("window", |_, me| Entries::make(me.window.clone(), me, &me.tab));
|
||||
|
||||
fields.add_field_method_get("offset", |_, me| Ok(me.offset));
|
||||
fields.add_field_method_get("cursor", |_, me| Ok(me.cursor));
|
||||
fields.add_static_field("hovered", |_, me| {
|
||||
me.hovered().map(|_| File::make(me.cursor, me, &me.tab)).transpose()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
use crate::lives::InputAlt;
|
||||
|
||||
pub(super) struct Input {
|
||||
inner: PtrCell<yazi_core::input::Input>,
|
||||
}
|
||||
|
||||
impl Deref for Input {
|
||||
type Target = yazi_core::input::Input;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub(super) fn make(inner: &yazi_core::input::Input) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self { inner: inner.into() })
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for Input {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_cached_field("alt", |_, me| me.alt.as_ref().map(InputAlt::make).transpose());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, UserData, UserDataFields};
|
||||
use yazi_shim::mlua::UserDataFieldsExt;
|
||||
|
||||
use super::{Lives, PtrCell};
|
||||
|
||||
pub(super) struct InputAlt(PtrCell<yazi_core::input::InputAlt>);
|
||||
|
||||
impl Deref for InputAlt {
|
||||
type Target = yazi_core::input::InputAlt;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
impl InputAlt {
|
||||
pub(super) fn make(inner: &yazi_core::input::InputAlt) -> mlua::Result<AnyUserData> {
|
||||
Lives::scoped_userdata(Self(inner.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl UserData for InputAlt {
|
||||
fn add_fields<F: UserDataFields<Self>>(fields: &mut F) {
|
||||
fields.add_cached_field("value", |lua, me| lua.create_string(me.lock().value()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
use std::mem::MaybeUninit;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use mlua::{AnyUserData, UserData};
|
||||
use scopeguard::defer;
|
||||
use tracing::error;
|
||||
use yazi_plugin::LUA;
|
||||
|
||||
use super::{Core, PtrCell};
|
||||
use crate::lives::MutCell;
|
||||
|
||||
pub(super) static TO_DESTROY: MutCell<Vec<AnyUserData>> = MutCell::new(Vec::new());
|
||||
pub(super) static FILE_CACHE: MutCell<
|
||||
MaybeUninit<HashMap<PtrCell<yazi_fs::file::File>, AnyUserData>>,
|
||||
> = MutCell::new(MaybeUninit::uninit());
|
||||
|
||||
pub struct Lives;
|
||||
|
||||
impl Lives {
|
||||
pub fn scope<T, F>(core: &mut yazi_core::Core, f: F) -> mlua::Result<T>
|
||||
where
|
||||
F: FnOnce(&mut yazi_core::Core) -> mlua::Result<T>,
|
||||
{
|
||||
defer! {
|
||||
unsafe {
|
||||
(*FILE_CACHE.get()).assume_init_mut().clear();
|
||||
for ud in (*TO_DESTROY.get()).drain(..) {
|
||||
ud.destroy().expect("failed to destruct scoped userdata");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LUA.set_named_registry_value("cx", Core::make(core)?)?;
|
||||
LUA.globals().raw_set("cx", Core::make(core)?)?;
|
||||
let result = f(core);
|
||||
|
||||
if let Err(ref e) = result {
|
||||
error!("{e}");
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub(crate) fn scoped_userdata<T>(data: T) -> mlua::Result<AnyUserData>
|
||||
where
|
||||
T: UserData + 'static,
|
||||
{
|
||||
let ud = LUA.create_userdata(data)?;
|
||||
unsafe { &mut *TO_DESTROY.get() }.push(ud.clone());
|
||||
Ok(ud)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
yazi_macro::mod_flat!(behavior core entries file filter finder folder input input_alt lives mode mut_cell preference preview ptr selected tab tabs task tasks which yanked);
|
||||
|
||||
pub(super) fn init() {
|
||||
unsafe { FILE_CACHE.get().write(std::mem::MaybeUninit::new(<_>::default())) };
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue