Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Mount manager #1977

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions yazi-config/preset/keymap.toml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ keymap = [
# Tasks
{ on = "w", run = "tasks_show", desc = "Show task manager" },

# Mount manager
{ on = "M", run = "mount_show", desc = "Show mount manager" },

# Help
{ on = "~", run = "help", desc = "Open help" },
{ on = "<F1>", run = "help", desc = "Open help" },
Expand Down Expand Up @@ -178,6 +181,28 @@ keymap = [
{ on = "<F1>", run = "help", desc = "Open help" },
]

[mount]

keymap = [
{ on = "<Esc>", run = "close", desc = "Close mount manager" },
{ on = "<C-[>", run = "close", desc = "Close mount manager" },
{ on = "<C-c>", run = "close", desc = "Close mount manager" },
{ on = "M", run = "close", desc = "Close mount manager" },

{ on = "k", run = "arrow -1", desc = "Move cursor up" },
{ on = "j", run = "arrow 1", desc = "Move cursor down" },

{ on = "<Up>", run = "arrow -1", desc = "Move cursor up" },
{ on = "<Down>", run = "arrow 1", desc = "Move cursor down" },

{ on = "<Enter>", run = "mountpoint_cd", desc = "Change directory to selected mountpoint" },
{ on = "l", run = "mountpoint_cd", desc = "Change directory to selected mountpoint" },

# Help
{ on = "~", run = "help", desc = "Open help" },
{ on = "<F1>", run = "help", desc = "Open help" },
]

[spot]

keymap = [
Expand Down
5 changes: 5 additions & 0 deletions yazi-config/src/keymap/keymap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct Keymap {
pub confirm: Vec<Chord>,
pub help: Vec<Chord>,
pub completion: Vec<Chord>,
pub mount: Vec<Chord>,
}

impl Keymap {
Expand All @@ -34,6 +35,7 @@ impl Keymap {
Layer::Help => &self.help,
Layer::Completion => &self.completion,
Layer::Which => unreachable!(),
Layer::Mount => &self.mount,
}
}
}
Expand Down Expand Up @@ -61,6 +63,7 @@ impl<'de> Deserialize<'de> for Keymap {
confirm: Inner,
help: Inner,
completion: Inner,
mount: Inner,
}
#[derive(Deserialize)]
struct Inner {
Expand Down Expand Up @@ -104,6 +107,8 @@ impl<'de> Deserialize<'de> for Keymap {
help: mix(shadow.help.prepend_keymap, shadow.help.keymap, shadow.help.append_keymap),
#[rustfmt::skip]
completion: mix(shadow.completion.prepend_keymap, shadow.completion.keymap, shadow.completion.append_keymap),
#[rustfmt::skip]
mount: mix(shadow.mount.prepend_keymap, shadow.mount.keymap, shadow.mount.append_keymap),
})
}
}
2 changes: 1 addition & 1 deletion yazi-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
clippy::unit_arg
)]

yazi_macro::mod_pub!(completion confirm help input manager notify pick spot tab tasks which);
yazi_macro::mod_pub!(completion confirm help input manager notify pick spot tab tasks which mount);

pub fn init() {
manager::WATCHED.with(<_>::default);
Expand Down
37 changes: 37 additions & 0 deletions yazi-core/src/mount/commands/arrow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use yazi_macro::render;
use yazi_shared::event::{CmdCow, Data};

use crate::mount::Mount;

struct Opt {
step: isize,
}

impl From<CmdCow> for Opt {
fn from(c: CmdCow) -> Self {
Self { step: c.first().and_then(Data::as_isize).unwrap_or(0) }
}
}

impl From<isize> for Opt {
fn from(step: isize) -> Self {
Self { step }
}
}

impl Mount {
#[yazi_codegen::command]
pub fn arrow(&mut self, opt: Opt) {
self.update();
let old = self.cursor;
if opt.step > 0 {
self.cursor += 1;
} else {
self.cursor = self.cursor.saturating_sub(1);
}

let max = Self::limit().min(self.points.len());
self.cursor = self.cursor.min(max.saturating_sub(1));
render!(self.cursor != old);
}
}
1 change: 1 addition & 0 deletions yazi-core/src/mount/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yazi_macro::mod_flat!(arrow toggle mountpoint_cd);
14 changes: 14 additions & 0 deletions yazi-core/src/mount/commands/mountpoint_cd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use yazi_macro::emit;
use yazi_proxy::options::ProcessExecOpt;
use yazi_shared::{Layer, event::Cmd, fs::Url};

use crate::mount::Mount;

impl Mount {
pub fn mountpoint_cd(&mut self, _opt: impl TryInto<ProcessExecOpt>) {
if let Some(target) = self.points.get(self.cursor) {
let url: Url = target.path.clone().into();
emit!(Call(Cmd::args("cd", &[url]), Layer::Manager));
}
}
}
26 changes: 26 additions & 0 deletions yazi-core/src/mount/commands/toggle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use yazi_macro::render;
use yazi_shared::event::CmdCow;

use crate::mount::Mount;

struct Opt;

impl From<CmdCow> for Opt {
fn from(_: CmdCow) -> Self { Self }
}
impl From<()> for Opt {
fn from(_: ()) -> Self { Self }
}

impl Mount {
#[yazi_codegen::command]
pub fn toggle(&mut self, _: Opt) {
self.visible = !self.visible;

if self.visible {
self.arrow(0);
}

render!();
}
}
7 changes: 7 additions & 0 deletions yazi-core/src/mount/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
yazi_macro::mod_pub!(commands);

yazi_macro::mod_flat!(mount);

pub const MOUNT_BORDER: u16 = 2;
pub const MOUNT_PADDING: u16 = 2;
pub const MOUNT_PERCENT: u16 = 80;
53 changes: 53 additions & 0 deletions yazi-core/src/mount/mount.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use std::{io::BufRead, path::PathBuf, sync::Arc, time::Duration};

use parking_lot::Mutex;
use yazi_adapter::Dimension;
use yazi_scheduler::{Ongoing, TaskSummary};

use super::{MOUNT_BORDER, MOUNT_PADDING, MOUNT_PERCENT};

#[derive(Debug)]
pub struct MountPoint {
pub dev: String,
pub path: PathBuf,
pub fs: String,
pub opts: String,
}

#[derive(Default)]
pub struct Mount {
pub visible: bool,
pub cursor: usize,

pub points: Vec<MountPoint>,
}

impl Mount {
pub fn update(&mut self) {
let points =
std::io::BufReader::new(std::fs::File::open(PathBuf::from("/proc/mounts")).unwrap())
.lines()
.map_while(Result::ok)
.filter_map(|l| {
let mut parts = l.trim_end_matches(" 0 0").split(' ');
Some(MountPoint {
dev: parts.next()?.into(),
path: parts.next()?.into(),
fs: parts.next()?.into(),
opts: parts.next()?.into(),
})
})
.filter(|p| !p.path.starts_with("/sys"))
.filter(|p| !p.path.starts_with("/tmp"))
.filter(|p| !p.path.starts_with("/run"))
.filter(|p| !p.path.starts_with("/dev"))
.filter(|p| !p.path.starts_with("/proc"));
self.points = points.collect();
}

#[inline]
pub fn limit() -> usize {
(Dimension::available().rows * MOUNT_PERCENT / 100).saturating_sub(MOUNT_BORDER + MOUNT_PADDING)
as usize
}
}
20 changes: 11 additions & 9 deletions yazi-fm/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ratatui::layout::Rect;
use yazi_core::{completion::Completion, confirm::Confirm, help::Help, input::Input, manager::Manager, notify::Notify, pick::Pick, tab::Tab, tasks::Tasks, which::Which};
use yazi_core::{completion::Completion, confirm::Confirm, help::Help, input::Input, manager::Manager, notify::Notify, pick::Pick, tab::Tab, tasks::Tasks, which::Which, mount::Mount};
use yazi_fs::Folder;

pub struct Ctx {
Expand All @@ -12,20 +12,22 @@ pub struct Ctx {
pub completion: Completion,
pub which: Which,
pub notify: Notify,
pub mount: Mount,
}

impl Ctx {
pub fn make() -> Self {
Self {
manager: Manager::make(),
tasks: Tasks::serve(),
pick: Default::default(),
input: Default::default(),
confirm: Default::default(),
help: Default::default(),
manager: Manager::make(),
tasks: Tasks::serve(),
pick: Default::default(),
input: Default::default(),
confirm: Default::default(),
help: Default::default(),
completion: Default::default(),
which: Default::default(),
notify: Default::default(),
which: Default::default(),
notify: Default::default(),
mount: Default::default(),
}
}

Expand Down
30 changes: 30 additions & 0 deletions yazi-fm/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl<'a> Executor<'a> {
Layer::Help => self.help(cmd),
Layer::Completion => self.completion(cmd),
Layer::Which => self.which(cmd),
Layer::Mount => self.mount(cmd),
}
}

Expand Down Expand Up @@ -145,6 +146,8 @@ impl<'a> Executor<'a> {
match cmd.name.as_str() {
// Tasks
"tasks_show" => self.app.cx.tasks.toggle(()),
// Mount
"mount_show" => self.app.cx.mount.toggle(()),
// Help
"help" => self.app.cx.help.toggle(Layer::Manager),
// Plugin
Expand Down Expand Up @@ -355,4 +358,31 @@ impl<'a> Executor<'a> {
on!(show);
on!(callback);
}

fn mount(&mut self, cmd: CmdCow) {
macro_rules! on {
($name:ident) => {
if cmd.name == stringify!($name) {
return self.app.cx.mount.$name(cmd);
}
};
($name:ident, $alias:literal) => {
if cmd.name == $alias {
return self.app.cx.mount.$name(cmd);
}
};
}

on!(toggle, "close");
on!(arrow);
on!(mountpoint_cd);

match cmd.name.as_str() {
// Help
"help" => self.app.cx.help.toggle(Layer::Mount),
// Plugin
"plugin" => self.app.plugin(cmd),
_ => {}
}
}
}
4 changes: 4 additions & 0 deletions yazi-fm/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ impl Widget for Root<'_> {
tasks::Tasks::new(self.cx).render(area, buf);
}

if self.cx.mount.visible {
tasks::Mount::new(self.cx).render(area, buf);
}

if self.cx.active().spot.visible() {
spot::Spot::new(self.cx).render(area, buf);
}
Expand Down
2 changes: 2 additions & 0 deletions yazi-fm/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ impl<'a> Router<'a> {
self.matches(Layer::Spot, key)
} else if cx.tasks.visible {
self.matches(Layer::Tasks, key)
} else if cx.mount.visible {
self.matches(Layer::Mount, key)
} else {
self.matches(Layer::Manager, key)
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-fm/src/tasks/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
yazi_macro::mod_flat!(progress tasks);
yazi_macro::mod_flat!(progress tasks mount);
Loading
Loading