mirror of
https://github.com/sxyazi/yazi.git
synced 2024-10-05 14:47:19 +03:00
Merge 903336d4a2
into 11547eefe0
This commit is contained in:
commit
5560079502
25
.github/ISSUE_TEMPLATE/bug.yml
vendored
25
.github/ISSUE_TEMPLATE/bug.yml
vendored
@ -13,6 +13,8 @@ body:
|
||||
- macOS
|
||||
- Windows
|
||||
- Windows WSL
|
||||
- FreeBSD X11
|
||||
- FreeBSD Wayland
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
@ -22,31 +24,32 @@ body:
|
||||
placeholder: "ex: kitty v0.32.2"
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: tried_main
|
||||
attributes:
|
||||
label: Did you try the latest code to see if this problem got fixed?
|
||||
options:
|
||||
- Tried, but the problem still
|
||||
- Not tried, and I'll explain why below
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: debug
|
||||
attributes:
|
||||
label: "`yazi --debug` output"
|
||||
description: Please do a `yazi --debug` and paste the output here.
|
||||
description: Please run `yazi --debug` and paste the debug information here.
|
||||
value: |
|
||||
<details>
|
||||
|
||||
<!-- Paste the output between the backticks below: -->
|
||||
```sh
|
||||
<!-- ↓↓↓ Paste the output here: ↓↓↓ -->
|
||||
|
||||
|
||||
```
|
||||
|
||||
</details>
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: tried_main
|
||||
attributes:
|
||||
label: Did you try the latest nightly build to see if the problem got fixed?
|
||||
options:
|
||||
- Yes, and I updated the debug information above (`yazi --debug`) to the nightly that I tried
|
||||
- No, and I'll explain why below
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
|
44
Cargo.lock
generated
44
Cargo.lock
generated
@ -206,9 +206,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
@ -303,9 +303,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.7"
|
||||
version = "4.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
|
||||
checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@ -313,9 +313,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.7"
|
||||
version = "4.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
|
||||
checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@ -325,9 +325,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.6"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58"
|
||||
checksum = "1d598e88f6874d4b888ed40c71efbcbf4076f1dfbae128a08a8c9e45f710605d"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
@ -354,9 +354,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.5"
|
||||
version = "4.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
|
||||
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@ -480,7 +480,7 @@ version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"crossterm_winapi",
|
||||
"futures-core",
|
||||
"libc",
|
||||
@ -1110,7 +1110,7 @@ version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -1282,7 +1282,7 @@ version = "6.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"filetime",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
@ -1366,7 +1366,7 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"block2",
|
||||
"libc",
|
||||
"objc2",
|
||||
@ -1588,7 +1588,7 @@ version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"crossterm",
|
||||
@ -1638,7 +1638,7 @@ version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1699,7 +1699,7 @@ version = "0.38.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
@ -1765,9 +1765,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.117"
|
||||
version = "1.0.120"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@ -2796,7 +2796,7 @@ version = "0.2.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"crossterm",
|
||||
"globset",
|
||||
"indexmap",
|
||||
@ -2812,7 +2812,7 @@ name = "yazi-core"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"crossterm",
|
||||
"dirs",
|
||||
"futures",
|
||||
@ -2962,7 +2962,7 @@ name = "yazi-shared"
|
||||
version = "0.2.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"crossterm",
|
||||
"dirs",
|
||||
"futures",
|
||||
|
@ -15,12 +15,12 @@ yazi-config = { path = "../yazi-config", version = "0.2.5" }
|
||||
yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||
|
||||
# External dependencies
|
||||
clap = { version = "4.5.7", features = [ "derive" ] }
|
||||
clap = { version = "4.5.8", features = [ "derive" ] }
|
||||
serde = { version = "1.0.203", features = [ "derive" ] }
|
||||
|
||||
[build-dependencies]
|
||||
clap = { version = "4.5.7", features = [ "derive" ] }
|
||||
clap_complete = "4.5.6"
|
||||
clap = { version = "4.5.8", features = [ "derive" ] }
|
||||
clap_complete = "4.5.7"
|
||||
clap_complete_nushell = "4.5.2"
|
||||
clap_complete_fig = "4.5.1"
|
||||
vergen = { version = "8.3.1", features = [ "build", "git", "gitcl" ] }
|
||||
|
@ -14,20 +14,20 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = "1.0.86"
|
||||
clap = { version = "4.5.7", features = [ "derive" ] }
|
||||
clap = { version = "4.5.8", features = [ "derive" ] }
|
||||
crossterm = "0.27.0"
|
||||
md-5 = "0.10.6"
|
||||
serde_json = "1.0.117"
|
||||
serde_json = "1.0.120"
|
||||
tokio = { version = "1.38.0", features = [ "full" ] }
|
||||
toml_edit = "0.22.14"
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.86"
|
||||
clap = { version = "4.5.7", features = [ "derive" ] }
|
||||
clap_complete = "4.5.6"
|
||||
clap = { version = "4.5.8", features = [ "derive" ] }
|
||||
clap_complete = "4.5.7"
|
||||
clap_complete_fig = "4.5.1"
|
||||
clap_complete_nushell = "4.5.2"
|
||||
serde_json = "1.0.117"
|
||||
serde_json = "1.0.120"
|
||||
vergen = { version = "8.3.1", features = [ "build", "git", "gitcl" ] }
|
||||
|
||||
[[bin]]
|
||||
|
@ -14,7 +14,7 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||
# External dependencies
|
||||
anyhow = "1.0.86"
|
||||
arc-swap = "1.7.1"
|
||||
bitflags = "2.5.0"
|
||||
bitflags = "2.6.0"
|
||||
crossterm = "0.27.0"
|
||||
globset = "0.4.14"
|
||||
indexmap = "2.2.6"
|
||||
|
@ -20,7 +20,7 @@ yazi-shared = { path = "../yazi-shared", version = "0.2.5" }
|
||||
|
||||
# External dependencies
|
||||
anyhow = "1.0.86"
|
||||
bitflags = "2.5.0"
|
||||
bitflags = "2.6.0"
|
||||
crossterm = "0.27.0"
|
||||
dirs = "5.0.1"
|
||||
futures = "0.3.30"
|
||||
|
@ -21,7 +21,7 @@ anyhow = "1.0.86"
|
||||
mlua = { version = "0.9.9", features = [ "lua54" ] }
|
||||
parking_lot = "0.12.3"
|
||||
serde = { version = "1.0.203", features = [ "derive" ] }
|
||||
serde_json = "1.0.117"
|
||||
serde_json = "1.0.120"
|
||||
tokio = { version = "1.38.0", features = [ "full" ] }
|
||||
tokio-stream = "0.1.15"
|
||||
tokio-util = "0.7.11"
|
||||
|
@ -49,7 +49,7 @@ impl App {
|
||||
if matches!(event.kind, MouseEventKind::Down(_) if MANAGER.mouse_events.draggable()) {
|
||||
let evt = yazi_plugin::bindings::MouseEvent::cast(&LUA, event);
|
||||
if let (Ok(evt), Ok(root)) = (evt, LUA.globals().raw_get::<_, Table>("Root")) {
|
||||
root.raw_set("drag_start", evt).ok();
|
||||
root.raw_set("_drag_start", evt).ok();
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ impl App {
|
||||
}
|
||||
|
||||
if let Err(e) = Lives::scope(&self.cx, move |_| f(event)) {
|
||||
error!("{:?}", e);
|
||||
error!("{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,9 @@
|
||||
use crossterm::event::MouseEventKind;
|
||||
use mlua::{Table, TableExt};
|
||||
use ratatui::{buffer::Buffer, widgets::Widget};
|
||||
use tracing::error;
|
||||
use yazi_plugin::{bindings::{Cast, MouseEvent}, elements::{render_widgets, Rect}, LUA};
|
||||
use yazi_plugin::{bindings::{Cast, MouseEvent}, LUA};
|
||||
|
||||
pub(crate) struct Header;
|
||||
|
||||
impl Widget for Header {
|
||||
fn render(self, area: ratatui::layout::Rect, buf: &mut Buffer) {
|
||||
let mut f = || {
|
||||
let area = Rect::cast(&LUA, area)?;
|
||||
let comp: Table = LUA.globals().raw_get("Header")?;
|
||||
render_widgets(comp.call_method("render", area)?, buf);
|
||||
Ok::<_, anyhow::Error>(())
|
||||
};
|
||||
if let Err(e) = f() {
|
||||
error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Header {
|
||||
pub(crate) fn mouse(event: crossterm::event::MouseEvent) -> mlua::Result<()> {
|
||||
let evt = MouseEvent::cast(&LUA, event)?;
|
||||
|
@ -1,20 +0,0 @@
|
||||
use mlua::{Table, TableExt};
|
||||
use ratatui::{buffer::Buffer, widgets::Widget};
|
||||
use tracing::error;
|
||||
use yazi_plugin::{bindings::Cast, elements::{render_widgets, Rect}, LUA};
|
||||
|
||||
pub(crate) struct Manager;
|
||||
|
||||
impl Widget for Manager {
|
||||
fn render(self, area: ratatui::layout::Rect, buf: &mut Buffer) {
|
||||
let mut f = || {
|
||||
let area = Rect::cast(&LUA, area)?;
|
||||
let comp: Table = LUA.globals().raw_get("Manager")?;
|
||||
render_widgets(comp.call_method("render", area)?, buf);
|
||||
Ok::<_, anyhow::Error>(())
|
||||
};
|
||||
if let Err(e) = f() {
|
||||
error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
|
||||
mod current;
|
||||
mod header;
|
||||
mod manager;
|
||||
mod parent;
|
||||
mod preview;
|
||||
mod progress;
|
||||
@ -10,7 +9,6 @@ mod status;
|
||||
|
||||
pub(super) use current::*;
|
||||
pub(super) use header::*;
|
||||
pub(super) use manager::*;
|
||||
pub(super) use parent::*;
|
||||
pub(super) use preview::*;
|
||||
pub(super) use progress::*;
|
||||
|
@ -34,7 +34,7 @@ impl Progress {
|
||||
};
|
||||
|
||||
if let Err(e) = f() {
|
||||
error!("{:?}", e);
|
||||
error!("{e}");
|
||||
}
|
||||
patches
|
||||
}
|
||||
|
@ -1,25 +1,9 @@
|
||||
use crossterm::event::MouseEventKind;
|
||||
use mlua::{Table, TableExt};
|
||||
use ratatui::widgets::Widget;
|
||||
use tracing::error;
|
||||
use yazi_plugin::{bindings::{Cast, MouseEvent}, elements::{render_widgets, Rect}, LUA};
|
||||
use yazi_plugin::{bindings::{Cast, MouseEvent}, LUA};
|
||||
|
||||
pub(crate) struct Status;
|
||||
|
||||
impl Widget for Status {
|
||||
fn render(self, area: ratatui::layout::Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||
let mut f = || {
|
||||
let area = Rect::cast(&LUA, area)?;
|
||||
let comp: Table = LUA.globals().raw_get("Status")?;
|
||||
render_widgets(comp.call_method("render", area)?, buf);
|
||||
Ok::<_, anyhow::Error>(())
|
||||
};
|
||||
if let Err(e) = f() {
|
||||
error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Status {
|
||||
pub(crate) fn mouse(event: crossterm::event::MouseEvent) -> mlua::Result<()> {
|
||||
let evt = MouseEvent::cast(&LUA, event)?;
|
||||
|
@ -55,11 +55,11 @@ impl Lives {
|
||||
let ret = f(scope)?;
|
||||
|
||||
LAYOUT.store(Arc::new(yazi_config::Layout {
|
||||
header: *globals.raw_get::<_, Table>("Header")?.raw_get::<_, RectRef>("area")?,
|
||||
parent: *globals.raw_get::<_, Table>("Parent")?.raw_get::<_, RectRef>("area")?,
|
||||
current: *globals.raw_get::<_, Table>("Current")?.raw_get::<_, RectRef>("area")?,
|
||||
preview: *globals.raw_get::<_, Table>("Preview")?.raw_get::<_, RectRef>("area")?,
|
||||
status: *globals.raw_get::<_, Table>("Status")?.raw_get::<_, RectRef>("area")?,
|
||||
header: *globals.raw_get::<_, Table>("Header")?.raw_get::<_, RectRef>("_area")?,
|
||||
parent: *globals.raw_get::<_, Table>("Parent")?.raw_get::<_, RectRef>("_area")?,
|
||||
current: *globals.raw_get::<_, Table>("Current")?.raw_get::<_, RectRef>("_area")?,
|
||||
preview: *globals.raw_get::<_, Table>("Preview")?.raw_get::<_, RectRef>("_area")?,
|
||||
status: *globals.raw_get::<_, Table>("Status")?.raw_get::<_, RectRef>("_area")?,
|
||||
}));
|
||||
|
||||
Ok(ret)
|
||||
|
@ -53,7 +53,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
yazi_dds::init();
|
||||
|
||||
yazi_plugin::init();
|
||||
yazi_plugin::init()?;
|
||||
|
||||
yazi_core::init();
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crossterm::event::MouseEventKind;
|
||||
use mlua::{Table, TableExt};
|
||||
use ratatui::{buffer::Buffer, layout::{Constraint, Layout, Rect}, widgets::Widget};
|
||||
use yazi_plugin::{bindings::{Cast, MouseEvent}, LUA};
|
||||
use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget};
|
||||
use tracing::error;
|
||||
use yazi_plugin::{bindings::{Cast, MouseEvent}, elements::render_widgets, LUA};
|
||||
|
||||
use super::{completion, input, select, tasks, which};
|
||||
use crate::{components, help, Ctx};
|
||||
@ -16,13 +17,16 @@ impl<'a> Root<'a> {
|
||||
|
||||
impl<'a> Widget for Root<'a> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let chunks =
|
||||
Layout::vertical([Constraint::Length(1), Constraint::Fill(1), Constraint::Length(1)])
|
||||
.split(area);
|
||||
let mut f = || {
|
||||
let area = yazi_plugin::elements::Rect::cast(&LUA, area)?;
|
||||
let root: Table = LUA.globals().raw_get("Root")?;
|
||||
render_widgets(root.call_method("render", area)?, buf);
|
||||
Ok::<_, mlua::Error>(())
|
||||
};
|
||||
if let Err(e) = f() {
|
||||
error!("Lua method `Root:render()` call failed:\n{e}");
|
||||
}
|
||||
|
||||
components::Header.render(chunks[0], buf);
|
||||
components::Manager.render(chunks[1], buf);
|
||||
components::Status.render(chunks[2], buf);
|
||||
components::Preview::new(self.cx).render(area, buf);
|
||||
|
||||
if self.cx.tasks.visible {
|
||||
|
@ -1,8 +1,13 @@
|
||||
Current = {
|
||||
area = ui.Rect.default,
|
||||
}
|
||||
Current = {}
|
||||
|
||||
function Current:empty(area)
|
||||
function Current:new(area, tab)
|
||||
return setmetatable({
|
||||
_area = area,
|
||||
_tab = tab,
|
||||
}, { __index = self })
|
||||
end
|
||||
|
||||
function Current:empty()
|
||||
local folder = Folder:by_kind(Folder.CURRENT)
|
||||
|
||||
local line
|
||||
@ -13,21 +18,19 @@ function Current:empty(area)
|
||||
end
|
||||
|
||||
return {
|
||||
ui.Paragraph(area, { line }):align(ui.Paragraph.CENTER),
|
||||
ui.Paragraph(self._area, { line }):align(ui.Paragraph.CENTER),
|
||||
}
|
||||
end
|
||||
|
||||
function Current:render(area)
|
||||
self.area = area
|
||||
|
||||
function Current:render()
|
||||
local files = Folder:by_kind(Folder.CURRENT).window
|
||||
if #files == 0 then
|
||||
return self:empty(area)
|
||||
return self:empty()
|
||||
end
|
||||
|
||||
local items, markers = {}, {}
|
||||
for i, f in ipairs(files) do
|
||||
items[#items + 1] = ui.ListItem(ui.Line(File:full(f))):style(File:style(f))
|
||||
items[#items + 1] = ui.ListItem(File:children_render(f)):style(File:style(f))
|
||||
|
||||
-- Yanked/marked/selected files
|
||||
local marker = File:marker(f)
|
||||
@ -37,9 +40,9 @@ function Current:render(area)
|
||||
end
|
||||
|
||||
return ya.flat {
|
||||
ui.List(area, items),
|
||||
Folder:linemode(area, files),
|
||||
Folder:markers(area, markers),
|
||||
ui.List(self._area, items),
|
||||
Folder:linemode(self._area, files),
|
||||
Folder:markers(self._area, markers),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -1,76 +1,6 @@
|
||||
File = {}
|
||||
|
||||
function File:icon(file)
|
||||
local icon = file:icon()
|
||||
if not icon then
|
||||
return {}
|
||||
elseif file:is_hovered() then
|
||||
return { ui.Span(" " .. icon.text .. " ") }
|
||||
else
|
||||
return { ui.Span(" " .. icon.text .. " "):style(icon.style) }
|
||||
end
|
||||
end
|
||||
|
||||
function File:prefix(file)
|
||||
local prefix = file:prefix() or ""
|
||||
return prefix == "" and {} or { ui.Span(prefix .. "/") }
|
||||
end
|
||||
|
||||
function File:highlights(file)
|
||||
local name = file.name:gsub("\r", "?", 1)
|
||||
local highlights = file:highlights()
|
||||
if not highlights or #highlights == 0 then
|
||||
return { ui.Span(name) }
|
||||
end
|
||||
|
||||
local spans, last = {}, 0
|
||||
for _, h in ipairs(highlights) do
|
||||
if h[1] > last then
|
||||
spans[#spans + 1] = ui.Span(name:sub(last + 1, h[1]))
|
||||
end
|
||||
spans[#spans + 1] = ui.Span(name:sub(h[1] + 1, h[2])):style(THEME.manager.find_keyword)
|
||||
last = h[2]
|
||||
end
|
||||
if last < #name then
|
||||
spans[#spans + 1] = ui.Span(name:sub(last + 1))
|
||||
end
|
||||
return spans
|
||||
end
|
||||
|
||||
function File:found(file)
|
||||
if not file:is_hovered() then
|
||||
return {}
|
||||
end
|
||||
|
||||
local found = file:found()
|
||||
if not found then
|
||||
return {}
|
||||
end
|
||||
|
||||
return {
|
||||
ui.Span(" "),
|
||||
ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position),
|
||||
}
|
||||
end
|
||||
|
||||
function File:symlink(file)
|
||||
if not MANAGER.show_symlink then
|
||||
return {}
|
||||
end
|
||||
|
||||
local to = file.link_to
|
||||
return to and { ui.Span(" -> " .. tostring(to)):italic() } or {}
|
||||
end
|
||||
|
||||
function File:full(file)
|
||||
return ya.flat {
|
||||
self:icon(file),
|
||||
self:prefix(file),
|
||||
self:highlights(file),
|
||||
self:found(file),
|
||||
self:symlink(file),
|
||||
}
|
||||
end
|
||||
File = {
|
||||
_inc = 1000,
|
||||
}
|
||||
|
||||
function File:style(file)
|
||||
local style = file:style()
|
||||
@ -97,3 +27,98 @@ function File:marker(file)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function File:icon(file)
|
||||
local icon = file:icon()
|
||||
if not icon then
|
||||
return ui.Line("")
|
||||
elseif file:is_hovered() then
|
||||
return ui.Line(" " .. icon.text .. " ")
|
||||
else
|
||||
return ui.Line(" " .. icon.text .. " "):style(icon.style)
|
||||
end
|
||||
end
|
||||
|
||||
function File:prefix(file)
|
||||
local prefix = file:prefix() or ""
|
||||
return ui.Line(prefix ~= "" and prefix .. "/" or "")
|
||||
end
|
||||
|
||||
function File:highlights(file)
|
||||
local name = file.name:gsub("\r", "?", 1)
|
||||
local highlights = file:highlights()
|
||||
if not highlights or #highlights == 0 then
|
||||
return ui.Line(name)
|
||||
end
|
||||
|
||||
local spans, last = {}, 0
|
||||
for _, h in ipairs(highlights) do
|
||||
if h[1] > last then
|
||||
spans[#spans + 1] = ui.Span(name:sub(last + 1, h[1]))
|
||||
end
|
||||
spans[#spans + 1] = ui.Span(name:sub(h[1] + 1, h[2])):style(THEME.manager.find_keyword)
|
||||
last = h[2]
|
||||
end
|
||||
if last < #name then
|
||||
spans[#spans + 1] = ui.Span(name:sub(last + 1))
|
||||
end
|
||||
return ui.Line(spans)
|
||||
end
|
||||
|
||||
function File:found(file)
|
||||
if not file:is_hovered() then
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
local found = file:found()
|
||||
if not found then
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
return ui.Line {
|
||||
ui.Span(" "),
|
||||
ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position),
|
||||
}
|
||||
end
|
||||
|
||||
function File:symlink(file)
|
||||
if not MANAGER.show_symlink then
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
local to = file.link_to
|
||||
return ui.Line(to and { ui.Span(" -> " .. tostring(to)):italic() } or {})
|
||||
end
|
||||
|
||||
-- Initialize children
|
||||
File._children = {
|
||||
{ File.icon, id = 1, order = 1000 },
|
||||
{ File.prefix, id = 2, order = 2000 },
|
||||
{ File.highlights, id = 3, order = 3000 },
|
||||
{ File.found, id = 4, order = 4000 },
|
||||
{ File.symlink, id = 5, order = 5000 },
|
||||
}
|
||||
|
||||
function File:children_add(fn, order)
|
||||
self._inc = self._inc + 1
|
||||
self._children[#self._children + 1] = { fn, id = self._inc, order = order }
|
||||
table.sort(self._children, function(a, b) return a.order < b.order end)
|
||||
return self._inc
|
||||
end
|
||||
|
||||
function File:children_remove(id)
|
||||
for i, child in ipairs(self._children) do
|
||||
if child.id == id then
|
||||
table.remove(self._children, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function File:children_render(file)
|
||||
local lines = {}
|
||||
for _, child in ipairs(self._children) do
|
||||
lines[#lines + 1] = child[1](self, file)
|
||||
end
|
||||
return ui.Line(lines)
|
||||
end
|
||||
|
@ -1,6 +1,10 @@
|
||||
Header = {
|
||||
area = ui.Rect.default,
|
||||
}
|
||||
Header = {}
|
||||
|
||||
function Header:new(area)
|
||||
return setmetatable({
|
||||
_area = area,
|
||||
}, { __index = self })
|
||||
end
|
||||
|
||||
function Header:cwd(max)
|
||||
local s = ya.readable_path(tostring(cx.active.current.cwd)) .. self:flags()
|
||||
@ -67,14 +71,12 @@ function Header:tabs()
|
||||
return ui.Line(spans)
|
||||
end
|
||||
|
||||
function Header:render(area)
|
||||
self.area = area
|
||||
|
||||
function Header:render()
|
||||
local right = ui.Line { self:count(), self:tabs() }
|
||||
local left = ui.Line { self:cwd(math.max(0, area.w - right:width())) }
|
||||
local left = ui.Line { self:cwd(math.max(0, self._area.w - right:width())) }
|
||||
return {
|
||||
ui.Paragraph(area, { left }),
|
||||
ui.Paragraph(area, { right }):align(ui.Paragraph.RIGHT),
|
||||
ui.Paragraph(self._area, { left }),
|
||||
ui.Paragraph(self._area, { right }):align(ui.Paragraph.RIGHT),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
Parent = {
|
||||
area = ui.Rect.default,
|
||||
}
|
||||
Parent = {}
|
||||
|
||||
function Parent:render(area)
|
||||
self.area = area
|
||||
function Parent:new(area, tab)
|
||||
return setmetatable({
|
||||
_area = area,
|
||||
_tab = tab,
|
||||
}, { __index = self })
|
||||
end
|
||||
|
||||
function Parent:render()
|
||||
local folder = Folder:by_kind(Folder.PARENT)
|
||||
if not folder then
|
||||
return {}
|
||||
@ -12,7 +15,7 @@ function Parent:render(area)
|
||||
|
||||
local items, markers = {}, {}
|
||||
for i, f in ipairs(folder.window) do
|
||||
items[#items + 1] = ui.ListItem(ui.Line(File:full(f))):style(File:style(f))
|
||||
items[#items + 1] = ui.ListItem(File:children_render(f)):style(File:style(f))
|
||||
|
||||
-- Yanked/marked/selected files
|
||||
local marker = File:marker(f)
|
||||
@ -22,8 +25,8 @@ function Parent:render(area)
|
||||
end
|
||||
|
||||
return ya.flat {
|
||||
ui.List(area, items),
|
||||
Folder:markers(area, markers),
|
||||
ui.List(self._area, items),
|
||||
Folder:markers(self._area, markers),
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
Preview = {
|
||||
area = ui.Rect.default,
|
||||
}
|
||||
Preview = {}
|
||||
|
||||
function Preview:render(area)
|
||||
self.area = area
|
||||
return {}
|
||||
function Preview:new(area, tab)
|
||||
return setmetatable({
|
||||
_area = area,
|
||||
_tab = tab,
|
||||
}, { __index = self })
|
||||
end
|
||||
|
||||
function Preview:render() return {} end
|
||||
|
||||
function Preview:click(event, up)
|
||||
if up or not event.is_left then
|
||||
return
|
||||
|
@ -1,9 +1,9 @@
|
||||
Progress = {
|
||||
area = ui.Rect.default,
|
||||
_area = ui.Rect.default, -- TODO: remove this
|
||||
}
|
||||
|
||||
function Progress:render(area, offset)
|
||||
self.area = ui.Rect {
|
||||
self._area = ui.Rect {
|
||||
x = math.max(0, area.w - offset - 21),
|
||||
y = area.y,
|
||||
w = ya.clamp(0, area.w - offset - 1, 20),
|
||||
@ -15,16 +15,13 @@ end
|
||||
-- Progress bars usually need frequent updates to report the latest task progress.
|
||||
-- We use `partial_render()` to partially render it when there is progress change,
|
||||
-- which has almost no cost compared to a full render by `render()`.
|
||||
--
|
||||
-- However, at this time, we can only access `cx.tasks`. If you need certain data from the complete `cx`,
|
||||
-- just cache it to `self` during `render()`, and read it in `partial_render()` - this process is referred to as "composition".
|
||||
function Progress:partial_render()
|
||||
local progress = cx.tasks.progress
|
||||
if progress.total == 0 then
|
||||
return { ui.Paragraph(self.area, {}) }
|
||||
return { ui.Paragraph(self._area, {}) }
|
||||
end
|
||||
|
||||
local gauge = ui.Gauge(self.area)
|
||||
local gauge = ui.Gauge(self._area)
|
||||
if progress.fail == 0 then
|
||||
gauge = gauge:gauge_style(THEME.status.progress_normal)
|
||||
else
|
||||
|
@ -1,7 +1,28 @@
|
||||
Root = {
|
||||
drag_start = ui.Rect.default,
|
||||
_drag_start = ui.Rect.default,
|
||||
}
|
||||
|
||||
function Root:layout(area)
|
||||
return ui.Layout()
|
||||
:direction(ui.Layout.VERTICAL)
|
||||
:constraints({
|
||||
ui.Constraint.Length(1),
|
||||
ui.Constraint.Fill(1),
|
||||
ui.Constraint.Length(1),
|
||||
})
|
||||
:split(area)
|
||||
end
|
||||
|
||||
function Root:render(area)
|
||||
local chunks = self:layout(area)
|
||||
|
||||
return ya.flat {
|
||||
ya.eval("Header:render", Header.render, Header:new(chunks[1])) or {},
|
||||
ya.eval("Tab:render", Tab.render, Tab:new(chunks[2], cx.active)) or {},
|
||||
ya.eval("Status:render", Status.render, Status:new(chunks[3])) or {},
|
||||
}
|
||||
end
|
||||
|
||||
function Root:move(event) end
|
||||
|
||||
function Root:drag(event) end
|
||||
|
@ -1,8 +1,17 @@
|
||||
Status = {
|
||||
area = ui.Rect.default,
|
||||
LEFT = 0,
|
||||
RIGHT = 1,
|
||||
|
||||
_inc = 1000,
|
||||
}
|
||||
|
||||
function Status.style()
|
||||
function Status:new(area)
|
||||
return setmetatable({
|
||||
_area = area,
|
||||
}, { __index = self })
|
||||
end
|
||||
|
||||
function Status:style()
|
||||
if cx.active.mode.is_select then
|
||||
return THEME.status.mode_select
|
||||
elseif cx.active.mode.is_unset then
|
||||
@ -18,7 +27,7 @@ function Status:mode()
|
||||
mode = "UN-SET"
|
||||
end
|
||||
|
||||
local style = self.style()
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(THEME.status.separator_open):fg(style.bg),
|
||||
ui.Span(" " .. mode .. " "):style(style),
|
||||
@ -31,7 +40,7 @@ function Status:size()
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
local style = self.style()
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(" " .. ya.readable_size(h:size() or h.cha.length) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg),
|
||||
ui.Span(THEME.status.separator_close):fg(THEME.status.separator_style.fg),
|
||||
@ -41,10 +50,10 @@ end
|
||||
function Status:name()
|
||||
local h = cx.active.current.hovered
|
||||
if not h then
|
||||
return ui.Span("")
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
return ui.Span(" " .. h.name)
|
||||
return ui.Line(" " .. h.name)
|
||||
end
|
||||
|
||||
function Status:permissions()
|
||||
@ -92,7 +101,7 @@ function Status:percentage()
|
||||
percent = string.format(" %3d%% ", percent)
|
||||
end
|
||||
|
||||
local style = self.style()
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(" " .. THEME.status.separator_open):fg(THEME.status.separator_style.fg),
|
||||
ui.Span(percent):fg(style.bg):bg(THEME.status.separator_style.bg),
|
||||
@ -103,27 +112,66 @@ function Status:position()
|
||||
local cursor = cx.active.current.cursor
|
||||
local length = #cx.active.current.files
|
||||
|
||||
local style = self.style()
|
||||
local style = self:style()
|
||||
return ui.Line {
|
||||
ui.Span(string.format(" %2d/%-2d ", cursor + 1, length)):style(style),
|
||||
ui.Span(THEME.status.separator_close):fg(style.bg),
|
||||
}
|
||||
end
|
||||
|
||||
function Status:render(area)
|
||||
self.area = area
|
||||
|
||||
local left = ui.Line { self:mode(), self:size(), self:name() }
|
||||
local right = ui.Line { self:permissions(), self:percentage(), self:position() }
|
||||
function Status:render()
|
||||
local left = self:children_render(self.LEFT)
|
||||
local right = self:children_render(self.RIGHT)
|
||||
return {
|
||||
ui.Paragraph(area, { left }),
|
||||
ui.Paragraph(area, { right }):align(ui.Paragraph.RIGHT),
|
||||
table.unpack(Progress:render(area, right:width())),
|
||||
ui.Paragraph(self._area, { left }),
|
||||
ui.Paragraph(self._area, { right }):align(ui.Paragraph.RIGHT),
|
||||
table.unpack(Progress:render(self._area, right:width())),
|
||||
}
|
||||
end
|
||||
|
||||
-- Mouse events
|
||||
function Status:click(event, up) end
|
||||
|
||||
function Status:scroll(event, step) end
|
||||
|
||||
function Status:touch(event, step) end
|
||||
|
||||
-- Initialize children
|
||||
Status._left = {
|
||||
{ Status.mode, id = 1, order = 1000 },
|
||||
{ Status.size, id = 2, order = 2000 },
|
||||
{ Status.name, id = 3, order = 3000 },
|
||||
}
|
||||
Status._right = {
|
||||
{ Status.permissions, id = 4, order = 1000 },
|
||||
{ Status.percentage, id = 5, order = 2000 },
|
||||
{ Status.position, id = 6, order = 3000 },
|
||||
}
|
||||
|
||||
function Status:children_add(fn, order, side)
|
||||
self._inc = self._inc + 1
|
||||
local children = side == self.RIGHT and self._right or self._left
|
||||
|
||||
children[#children + 1] = { fn, id = self._inc, order = order }
|
||||
table.sort(children, function(a, b) return a.order < b.order end)
|
||||
|
||||
return self._inc
|
||||
end
|
||||
|
||||
function Status:children_remove(id, side)
|
||||
local children = side == self.RIGHT and self._right or self._left
|
||||
for i, child in ipairs(children) do
|
||||
if child.id == id then
|
||||
table.remove(children, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Status:children_render(side)
|
||||
local lines = {}
|
||||
for _, child in ipairs(side == self.RIGHT and self._right or self._left) do
|
||||
lines[#lines + 1] = child[1](self)
|
||||
end
|
||||
return ui.Line(lines)
|
||||
end
|
||||
|
@ -1,10 +1,14 @@
|
||||
Manager = {
|
||||
area = ui.Rect.default,
|
||||
}
|
||||
Manager = {} -- TODO: remove this after 0.3.0 release
|
||||
Tab = {}
|
||||
|
||||
function Manager:layout(area)
|
||||
self.area = area
|
||||
function Tab:new(area, tab)
|
||||
return setmetatable({
|
||||
_area = area,
|
||||
_tab = tab,
|
||||
}, { __index = self })
|
||||
end
|
||||
|
||||
function Tab:layout()
|
||||
return ui.Layout()
|
||||
:direction(ui.Layout.HORIZONTAL)
|
||||
:constraints({
|
||||
@ -12,11 +16,11 @@ function Manager:layout(area)
|
||||
ui.Constraint.Ratio(MANAGER.ratio.current, MANAGER.ratio.all),
|
||||
ui.Constraint.Ratio(MANAGER.ratio.preview, MANAGER.ratio.all),
|
||||
})
|
||||
:split(area)
|
||||
:split(self._area)
|
||||
end
|
||||
|
||||
function Manager:render(area)
|
||||
local chunks = self:layout(area)
|
||||
function Tab:render()
|
||||
local chunks = self:layout()
|
||||
|
||||
return ya.flat {
|
||||
-- Borders
|
||||
@ -24,10 +28,10 @@ function Manager:render(area)
|
||||
ui.Bar(chunks[3], ui.Bar.LEFT):symbol(THEME.manager.border_symbol):style(THEME.manager.border_style),
|
||||
|
||||
-- Parent
|
||||
Parent:render(chunks[1]:padding(ui.Padding.x(1))),
|
||||
Parent:new(chunks[1]:padding(ui.Padding.x(1)), self._tab):render(),
|
||||
-- Current
|
||||
Current:render(chunks[2]),
|
||||
Current:new(chunks[2], self._tab):render(),
|
||||
-- Preview
|
||||
Preview:render(chunks[3]:padding(ui.Padding.x(1))),
|
||||
Preview:new(chunks[3]:padding(ui.Padding.x(1)), self._tab):render(),
|
||||
}
|
||||
end
|
@ -20,7 +20,7 @@ function M:peek()
|
||||
|
||||
local items, markers = {}, {}
|
||||
for i, f in ipairs(folder.window) do
|
||||
items[#items + 1] = ui.ListItem(ui.Line(File:full(f))):style(File:style(f))
|
||||
items[#items + 1] = ui.ListItem(File:children_render(f)):style(File:style(f))
|
||||
|
||||
-- Yanked/marked/selected files
|
||||
local marker = File:marker(f)
|
||||
|
@ -15,19 +15,29 @@ end
|
||||
function ya.round(x) return x >= 0 and math.floor(x + 0.5) or math.ceil(x - 0.5) end
|
||||
|
||||
function ya.flat(t)
|
||||
local r = {}
|
||||
for _, v in ipairs(t) do
|
||||
if type(v) == "table" then
|
||||
for _, v2 in ipairs(ya.flat(v)) do
|
||||
r[#r + 1] = v2
|
||||
local r, todo = {}, { t }
|
||||
while #todo > 0 do
|
||||
for _, v in ipairs(table.remove(todo)) do
|
||||
if type(v) == "table" then
|
||||
todo[#todo + 1] = v
|
||||
else
|
||||
r[#r + 1] = v
|
||||
end
|
||||
else
|
||||
r[#r + 1] = v
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function ya.eval(ctx, f, ...)
|
||||
local ok, res = xpcall(f, debug.traceback, ...)
|
||||
if ok then
|
||||
return res
|
||||
end
|
||||
|
||||
ya.raw_err(string.format("Failed to call `%s()`:\n%s", ctx, res))
|
||||
return nil
|
||||
end
|
||||
|
||||
function ya.basename(str) return string.gsub(str, "(.*[/\\])(.*)", "%2") end
|
||||
|
||||
function ya.readable_size(size)
|
||||
|
@ -7,6 +7,18 @@ impl Constraint {
|
||||
pub fn install(lua: &Lua, ui: &Table) -> mlua::Result<()> {
|
||||
let constraint = lua.create_table()?;
|
||||
|
||||
constraint.raw_set(
|
||||
"Min",
|
||||
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Min(n))))?,
|
||||
)?;
|
||||
constraint.raw_set(
|
||||
"Max",
|
||||
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Max(n))))?,
|
||||
)?;
|
||||
constraint.raw_set(
|
||||
"Length",
|
||||
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Length(n))))?,
|
||||
)?;
|
||||
constraint.raw_set(
|
||||
"Percentage",
|
||||
lua
|
||||
@ -19,16 +31,8 @@ impl Constraint {
|
||||
})?,
|
||||
)?;
|
||||
constraint.raw_set(
|
||||
"Length",
|
||||
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Length(n))))?,
|
||||
)?;
|
||||
constraint.raw_set(
|
||||
"Max",
|
||||
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Max(n))))?,
|
||||
)?;
|
||||
constraint.raw_set(
|
||||
"Min",
|
||||
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Min(n))))?,
|
||||
"Fill",
|
||||
lua.create_function(|_, n: u16| Ok(Constraint(ratatui::layout::Constraint::Fill(n))))?,
|
||||
)?;
|
||||
|
||||
ui.raw_set("Constraint", constraint)
|
||||
|
@ -23,7 +23,11 @@ impl TryFrom<Table<'_>> for Line {
|
||||
if let Ok(span) = ud.take::<Span>() {
|
||||
spans.push(span.0);
|
||||
} else if let Ok(line) = ud.take::<Line>() {
|
||||
spans.extend(line.0.spans.into_iter().collect::<Vec<_>>());
|
||||
let style = line.0.style;
|
||||
spans.extend(line.0.spans.into_iter().map(|mut span| {
|
||||
span.style = style.patch(span.style);
|
||||
span
|
||||
}));
|
||||
} else {
|
||||
return Err("expected a table of Spans or Lines".into_lua_err());
|
||||
}
|
||||
@ -83,9 +87,9 @@ impl UserData for Line {
|
||||
{
|
||||
let mut me = ud.borrow_mut::<Self>()?;
|
||||
me.0.style = match value {
|
||||
Value::Nil => me.0.style.patch(ratatui::style::Style::reset()),
|
||||
Value::Table(tb) => me.0.style.patch(Style::try_from(tb)?.0),
|
||||
Value::UserData(ud) => me.0.style.patch(ud.borrow::<Style>()?.0),
|
||||
Value::Nil => ratatui::style::Style::default(),
|
||||
Value::Table(tb) => Style::try_from(tb)?.0,
|
||||
Value::UserData(ud) => ud.borrow::<Style>()?.0,
|
||||
_ => return Err("expected a Style or Table or nil".into_lua_err()),
|
||||
};
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub async fn entry(name: String, args: Vec<Data>) -> mlua::Result<()> {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let lua = slim_lua(&name)?;
|
||||
let plugin: Table = if let Some(b) = LOADER.read().get(&name) {
|
||||
lua.load(b.as_ref()).call(())?
|
||||
lua.load(b.as_ref()).set_name(name).call(())?
|
||||
} else {
|
||||
return Err("unloaded plugin".into_lua_err());
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ pub async fn fetch(name: &str, files: Vec<yazi_shared::fs::File>) -> mlua::Resul
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let lua = slim_lua(&name)?;
|
||||
let plugin: Table = if let Some(b) = LOADER.read().get(&name) {
|
||||
lua.load(b.as_ref()).call(())?
|
||||
lua.load(b.as_ref()).set_name(name).call(())?
|
||||
} else {
|
||||
return Err("unloaded plugin".into_lua_err());
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
use mlua::Lua;
|
||||
use mlua::{Lua, StdLib};
|
||||
|
||||
use crate::{elements, runtime::Runtime};
|
||||
|
||||
pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
|
||||
let lua = Lua::new();
|
||||
let lua = unsafe { Lua::unsafe_new_with(StdLib::ALL_SAFE | StdLib::DEBUG, Default::default()) };
|
||||
lua.set_named_registry_value("rt", Runtime::new(name))?;
|
||||
|
||||
// Base
|
||||
@ -16,7 +16,7 @@ pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
|
||||
crate::process::install(&lua)?;
|
||||
crate::utils::install_isolate(&lua)?;
|
||||
crate::Config::new(&lua).install_preview()?;
|
||||
lua.load(include_str!("../../preset/ya.lua")).exec()?;
|
||||
lua.load(include_str!("../../preset/ya.lua")).set_name("ya.lua").exec()?;
|
||||
|
||||
// Elements
|
||||
let ui = lua.create_table()?;
|
||||
|
@ -26,7 +26,7 @@ pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> Cancellation
|
||||
);
|
||||
|
||||
let plugin: Table = if let Some(b) = LOADER.read().get(&name) {
|
||||
lua.load(b.as_ref()).call(())?
|
||||
lua.load(b.as_ref()).set_name(name).call(())?
|
||||
} else {
|
||||
return Err("unloaded plugin".into_lua_err());
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ pub async fn preload(name: &str, file: yazi_shared::fs::File) -> mlua::Result<u8
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let lua = slim_lua(&name)?;
|
||||
let plugin: Table = if let Some(b) = LOADER.read().get(&name) {
|
||||
lua.load(b.as_ref()).call(())?
|
||||
lua.load(b.as_ref()).set_name(name).call(())?
|
||||
} else {
|
||||
return Err("unloaded plugin".into_lua_err());
|
||||
};
|
||||
|
@ -26,9 +26,10 @@ pub use lua::*;
|
||||
pub use opt::*;
|
||||
pub use runtime::*;
|
||||
|
||||
pub fn init() {
|
||||
pub fn init() -> anyhow::Result<()> {
|
||||
CLIPBOARD.with(Default::default);
|
||||
|
||||
crate::loader::init();
|
||||
crate::init_lua();
|
||||
crate::init_lua()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ impl Loader {
|
||||
}
|
||||
|
||||
let t: Table = match self.read().get(name) {
|
||||
Some(b) => LUA.load(b.as_ref()).call(())?,
|
||||
Some(b) => LUA.load(b.as_ref()).set_name(name).call(())?,
|
||||
None => Err(format!("plugin `{name}` not found").into_lua_err())?,
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use mlua::Lua;
|
||||
use anyhow::{Context, Result};
|
||||
use mlua::{Lua, StdLib};
|
||||
use yazi_boot::BOOT;
|
||||
use yazi_shared::RoCell;
|
||||
|
||||
@ -7,11 +7,12 @@ use crate::runtime::Runtime;
|
||||
|
||||
pub static LUA: RoCell<Lua> = RoCell::new();
|
||||
|
||||
pub(super) fn init_lua() {
|
||||
LUA.init(Lua::new());
|
||||
pub(super) fn init_lua() -> Result<()> {
|
||||
LUA.init(unsafe { Lua::unsafe_new_with(StdLib::ALL_SAFE | StdLib::DEBUG, Default::default()) });
|
||||
|
||||
stage_1(&LUA).expect("Lua setup failed");
|
||||
stage_2(&LUA).expect("Lua runtime failed");
|
||||
stage_1(&LUA).context("Lua setup failed")?;
|
||||
stage_2(&LUA).context("Lua runtime failed")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stage_1(lua: &'static Lua) -> Result<()> {
|
||||
@ -20,7 +21,7 @@ fn stage_1(lua: &'static Lua) -> Result<()> {
|
||||
|
||||
// Base
|
||||
lua.set_named_registry_value("rt", Runtime::default())?;
|
||||
lua.load(include_str!("../preset/ya.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/ya.lua")).set_name("ya.lua").exec()?;
|
||||
crate::bindings::Icon::register(lua)?;
|
||||
crate::bindings::MouseEvent::register(lua)?;
|
||||
crate::elements::pour(lua)?;
|
||||
@ -31,25 +32,25 @@ fn stage_1(lua: &'static Lua) -> Result<()> {
|
||||
crate::url::pour(lua)?;
|
||||
|
||||
// Components
|
||||
lua.load(include_str!("../preset/components/current.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/file.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/folder.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/header.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/manager.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/parent.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/preview.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/progress.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/root.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/status.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/components/current.lua")).set_name("current.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/file.lua")).set_name("file.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/folder.lua")).set_name("folder.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/header.lua")).set_name("header.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/parent.lua")).set_name("parent.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/preview.lua")).set_name("preview.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/progress.lua")).set_name("progress.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/root.lua")).set_name("root.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/status.lua")).set_name("status.lua").exec()?;
|
||||
lua.load(include_str!("../preset/components/tab.lua")).set_name("tab.lua").exec()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stage_2(lua: &'static Lua) -> mlua::Result<()> {
|
||||
lua.load(include_str!("../preset/setup.lua")).exec()?;
|
||||
lua.load(include_str!("../preset/setup.lua")).set_name("setup.lua").exec()?;
|
||||
|
||||
if let Ok(b) = std::fs::read(BOOT.config_dir.join("init.lua")) {
|
||||
lua.load(b).exec()?;
|
||||
lua.load(b).set_name("init.lua").exec()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -21,6 +21,11 @@ impl Utils {
|
||||
})?,
|
||||
)?;
|
||||
|
||||
ya.raw_set(
|
||||
"raw_err",
|
||||
lua.create_function(|_, s: mlua::String| Ok(error!("{}", s.to_string_lossy())))?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ rust-version = "1.78.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
bitflags = "2.5.0"
|
||||
bitflags = "2.6.0"
|
||||
crossterm = "0.27.0"
|
||||
dirs = "5.0.1"
|
||||
futures = "0.3.30"
|
||||
|
Loading…
Reference in New Issue
Block a user