Skip to content

Commit cd2e7ff

Browse files
committed
feat: re-implement zoxide as a built-in plugin (#881)
1 parent 0650aff commit cd2e7ff

File tree

11 files changed

+149
-48
lines changed

11 files changed

+149
-48
lines changed

.github/workflows/lock.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
pull-requests: write
1717
discussions: write
1818
steps:
19-
- uses: dessant/lock-threads@v4
19+
- uses: dessant/lock-threads@v5
2020
with:
2121
issue-inactive-days: "30"
2222
issue-comment: >

yazi-config/preset/keymap.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ keymap = [
8181
{ on = [ "s" ], run = "search fd", desc = "Search files by name using fd" },
8282
{ on = [ "S" ], run = "search rg", desc = "Search files by content using ripgrep" },
8383
{ on = [ "<C-s>" ], run = "search none", desc = "Cancel the ongoing search" },
84-
{ on = [ "z" ], run = "jump zoxide", desc = "Jump to a directory using zoxide" },
84+
{ on = [ "z" ], run = "plugin zoxide", desc = "Jump to a directory using zoxide" },
8585
{ on = [ "Z" ], run = "jump fzf", desc = "Jump to a directory, or reveal a file using fzf" },
8686

8787
# Linemode

yazi-core/src/tab/commands/jump.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use yazi_plugin::external::{self, FzfOpt, ZoxideOpt};
2-
use yazi_proxy::{AppProxy, TabProxy, HIDER};
3-
use yazi_shared::{event::Cmd, fs::ends_with_slash, Defer};
1+
use std::time::Duration;
2+
3+
use yazi_plugin::external::{self, FzfOpt};
4+
use yazi_proxy::{options::{NotifyLevel, NotifyOpt}, AppProxy, TabProxy, HIDER};
5+
use yazi_shared::{emit, event::Cmd, fs::ends_with_slash, Defer, Layer};
46

57
use crate::tab::Tab;
68

@@ -34,6 +36,21 @@ impl Tab {
3436
return;
3537
}
3638

39+
// TODO: Remove this once Yazi v0.2.7 is released
40+
if opt.type_ == OptType::Zoxide {
41+
AppProxy::notify(NotifyOpt {
42+
title: "Jump".to_owned(),
43+
content: r#"The `jump zoxide` command has been deprecated in Yazi v0.2.5. Please replace it with `plugin zoxide` in your `keymap.toml`.
44+
45+
See https://github.com/sxyazi/yazi/issues/865 for more details."#.to_owned(),
46+
level: NotifyLevel::Warn,
47+
timeout: Duration::from_secs(15),
48+
});
49+
50+
emit!(Call(Cmd::args("plugin", vec!["zoxide".to_owned()]), Layer::App));
51+
return;
52+
}
53+
3754
let cwd = self.current.cwd.clone();
3855
tokio::spawn(async move {
3956
let _permit = HIDER.acquire().await.unwrap();
@@ -43,7 +60,7 @@ impl Tab {
4360
let result = if opt.type_ == OptType::Fzf {
4461
external::fzf(FzfOpt { cwd }).await
4562
} else {
46-
external::zoxide(ZoxideOpt { cwd }).await
63+
unreachable!()
4764
};
4865

4966
let Ok(url) = result else {

yazi-fm/src/notify/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl<'a> Layout<'a> {
1616

1717
pub(crate) fn available(area: Rect) -> Rect {
1818
let chunks =
19-
layout::Layout::horizontal([Constraint::Fill(1), Constraint::Length(40), Constraint::Max(1)])
19+
layout::Layout::horizontal([Constraint::Fill(1), Constraint::Length(80), Constraint::Max(1)])
2020
.split(area);
2121

2222
let chunks =
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
local state = ya.sync(function(st)
2+
return {
3+
cwd = tostring(cx.active.current.cwd),
4+
empty = st.empty,
5+
}
6+
end)
7+
8+
local set_state = ya.sync(function(st, empty) st.empty = empty end)
9+
10+
local function notify(s, ...)
11+
ya.notify { title = "Zoxide", content = string.format(s, ...), timeout = 5, level = "error" }
12+
end
13+
14+
local function head(cwd)
15+
local child = Command("zoxide"):args({ "query", "-l" }):stdout(Command.PIPED):spawn()
16+
if not child then
17+
return 0
18+
end
19+
20+
local n = 0
21+
repeat
22+
local next, event = child:read_line()
23+
if event ~= 0 then
24+
break
25+
elseif cwd ~= next:gsub("\n$", "") then
26+
n = n + 1
27+
end
28+
until n >= 2
29+
30+
child:start_kill()
31+
return n
32+
end
33+
34+
local function setup(_, opts)
35+
opts = opts or {}
36+
37+
if opts.update_db then
38+
ps.sub(
39+
"cd",
40+
function()
41+
ya.manager_emit("shell", {
42+
confirm = true,
43+
"zoxide add " .. ya.quote(tostring(cx.active.current.cwd)),
44+
})
45+
end
46+
)
47+
end
48+
end
49+
50+
local function entry()
51+
local st = state()
52+
if st.empty == true then
53+
return notify("No directory history in the database, check out the `zoxide` docs to set it up.")
54+
elseif st.empty == nil and head(st.cwd) < 2 then
55+
set_state(true)
56+
return notify("No directory history in the database, check out the `zoxide` docs to set it up.")
57+
end
58+
59+
local _permit = ya.hide()
60+
local child, err = Command("zoxide")
61+
:args({ "query", "-i", "--exclude" })
62+
:arg(st.cwd)
63+
:stdin(Command.INHERIT)
64+
:stdout(Command.PIPED)
65+
:stderr(Command.INHERIT)
66+
:spawn()
67+
68+
if not child then
69+
return notify("Spawn `zoxide` failed with error code %s. Do you have it installed?", err)
70+
end
71+
72+
local output, err = child:wait_with_output()
73+
if not output then
74+
return notify("`zoxide` exited with error code %s", err)
75+
end
76+
ya.manager_emit("cd", { output.stdout:gsub("\n$", "") })
77+
end
78+
79+
return { setup = setup, entry = entry }

yazi-plugin/src/external/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ mod fzf;
33
mod highlighter;
44
mod lsar;
55
mod rg;
6-
mod zoxide;
76

87
pub use fd::*;
98
pub use fzf::*;
109
pub use highlighter::*;
1110
pub use lsar::*;
1211
pub use rg::*;
13-
pub use zoxide::*;

yazi-plugin/src/external/zoxide.rs

Lines changed: 0 additions & 26 deletions
This file was deleted.

yazi-plugin/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ pub use opt::*;
2323
pub use runtime::*;
2424

2525
pub fn init() {
26-
crate::init_lua();
2726
crate::loader::init();
27+
crate::init_lua();
2828
}

yazi-plugin/src/loader/loader.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ impl Loader {
3535
"noop" => include_bytes!("../../preset/plugins/noop.lua"),
3636
"pdf" => include_bytes!("../../preset/plugins/pdf.lua"),
3737
"video" => include_bytes!("../../preset/plugins/video.lua"),
38+
"zoxide" => include_bytes!("../../preset/plugins/zoxide.lua"),
3839
_ => bail!("plugin not found: {name}"),
3940
}))
4041
})?;

yazi-plugin/src/loader/require.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use mlua::{ExternalResult, Function, IntoLua, Lua, MetaMethod, Table, TableExt, UserData, Value, Variadic};
1+
use mlua::{ExternalResult, IntoLua, Lua, MetaMethod, Table, TableExt, UserData, Value, Variadic};
22

3+
use super::LOADER;
34
use crate::RtRef;
45

56
pub(super) struct Require;
@@ -8,15 +9,16 @@ impl Require {
89
pub(super) fn install(lua: &'static Lua) -> mlua::Result<()> {
910
let globals = lua.globals();
1011

11-
let require = globals.raw_get::<_, Function>("require")?;
1212
globals.raw_set(
1313
"require",
14-
lua.create_function(move |lua, name: mlua::String| {
15-
lua.named_registry_value::<RtRef>("rt")?.swap(name.to_str()?);
16-
let mod_: Table = require.call(&name)?;
14+
lua.create_function(|lua, name: mlua::String| {
15+
let s = name.to_str()?;
16+
futures::executor::block_on(LOADER.ensure(s)).into_lua_err()?;
17+
18+
lua.named_registry_value::<RtRef>("rt")?.swap(s);
19+
let mod_ = LOADER.load(s)?;
1720
lua.named_registry_value::<RtRef>("rt")?.reset();
1821

19-
mod_.raw_set("_name", &name)?;
2022
Self::create_mt(lua, name, mod_)
2123
})?,
2224
)?;

0 commit comments

Comments
 (0)