diff --git a/yazi-actor/src/pick/mod.rs b/yazi-actor/src/pick/mod.rs index e0fc92ad5..d95524dcf 100644 --- a/yazi-actor/src/pick/mod.rs +++ b/yazi-actor/src/pick/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(arrow close show); +yazi_macro::mod_flat!(arrow close select show); diff --git a/yazi-actor/src/pick/select.rs b/yazi-actor/src/pick/select.rs new file mode 100644 index 000000000..a2176ae66 --- /dev/null +++ b/yazi-actor/src/pick/select.rs @@ -0,0 +1,31 @@ +use anyhow::Result; +use yazi_macro::{render, succ}; +use yazi_parser::pick::SelectForm; +use yazi_shared::data::Data; + +use crate::{Actor, Ctx}; + +pub struct Select; + +impl Actor for Select { + type Form = SelectForm; + + const NAME: &str = "select"; + + fn act(cx: &mut Ctx, opt: Self::Form) -> Result { + let pick = &mut cx.pick; + if opt.index >= pick.items.len() { + succ!(); + } + + if let Some(cb) = pick.callback.take() { + _ = cb.send(Some(opt.index)); + } + + pick.cursor = 0; + pick.offset = 0; + pick.visible = false; + + succ!(render!()); + } +} diff --git a/yazi-config/preset/keymap-default.toml b/yazi-config/preset/keymap-default.toml index 447cb98e9..2cac38f5a 100644 --- a/yazi-config/preset/keymap-default.toml +++ b/yazi-config/preset/keymap-default.toml @@ -220,6 +220,16 @@ keymap = [ { on = "", run = "arrow prev", desc = "Previous option" }, { on = "", run = "arrow next", desc = "Next option" }, + { on = "1", run = "select 0", desc = "Select first option" }, + { on = "2", run = "select 1", desc = "Select second option" }, + { on = "3", run = "select 2", desc = "Select third option" }, + { on = "4", run = "select 3", desc = "Select fourth option" }, + { on = "5", run = "select 4", desc = "Select fifth option" }, + { on = "6", run = "select 5", desc = "Select sixth option" }, + { on = "7", run = "select 6", desc = "Select seventh option" }, + { on = "8", run = "select 7", desc = "Select eighth option" }, + { on = "9", run = "select 8", desc = "Select ninth option" }, + # Help { on = "~", run = "help", desc = "Open help" }, { on = "", run = "help", desc = "Open help" }, diff --git a/yazi-config/preset/yazi-default.toml b/yazi-config/preset/yazi-default.toml index c2276d550..785c509b5 100644 --- a/yazi-config/preset/yazi-default.toml +++ b/yazi-config/preset/yazi-default.toml @@ -238,6 +238,7 @@ quit_offset = [ 0, 0, 50, 15 ] open_title = "Open with:" open_origin = "hovered" open_offset = [ 0, 1, 50, 7 ] +line_numbers = true [which] sort_by = "none" diff --git a/yazi-config/src/popup/pick.rs b/yazi-config/src/popup/pick.rs index cd22be27d..af2f14589 100644 --- a/yazi-config/src/popup/pick.rs +++ b/yazi-config/src/popup/pick.rs @@ -6,9 +6,10 @@ use super::{Offset, Origin}; #[derive(Deserialize, DeserializeOver2)] pub struct Pick { // open - pub open_title: String, - pub open_origin: Origin, - pub open_offset: Offset, + pub open_title: String, + pub open_origin: Origin, + pub open_offset: Offset, + pub line_numbers: bool, } impl Pick { diff --git a/yazi-fm/src/executor.rs b/yazi-fm/src/executor.rs index 897d86dac..ceee0caf7 100644 --- a/yazi-fm/src/executor.rs +++ b/yazi-fm/src/executor.rs @@ -235,6 +235,7 @@ impl<'a> Executor<'a> { } on!(show); + on!(select); on!(close); on!(arrow); diff --git a/yazi-fm/src/pick/list.rs b/yazi-fm/src/pick/list.rs index b5c3367ac..793b2c390 100644 --- a/yazi-fm/src/pick/list.rs +++ b/yazi-fm/src/pick/list.rs @@ -1,5 +1,5 @@ use ratatui::{buffer::Buffer, layout::{Margin, Rect}, widgets::{ListItem, Scrollbar, ScrollbarOrientation, ScrollbarState, StatefulWidget, Widget}}; -use yazi_config::THEME; +use yazi_config::{THEME, YAZI}; use yazi_core::Core; use yazi_widgets::Scrollable; @@ -27,11 +27,16 @@ impl Widget for List<'_> { // List content let inner = area.inner(Margin::new(1, 0)); let items = pick.window().map(|(i, v)| { - if i == pick.cursor { - ListItem::new(format!(" {v}")).style(THEME.pick.active) + let (prefix, style) = + if i == pick.cursor { ("", THEME.pick.active) } else { (" ", THEME.pick.inactive) }; + + let index_str = if !YAZI.pick.line_numbers { + "".to_string() } else { - ListItem::new(format!(" {v}")).style(THEME.pick.inactive) - } + if i < 9 { format!("{:>2}", i + 1) } else { " ".to_string() } + }; + + ListItem::new(format!("{prefix}{index_str} {v}")).style(style) }); Widget::render(ratatui::widgets::List::new(items), inner, buf); } diff --git a/yazi-parser/src/pick/mod.rs b/yazi-parser/src/pick/mod.rs index 37e615146..6a96754c1 100644 --- a/yazi-parser/src/pick/mod.rs +++ b/yazi-parser/src/pick/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(close show); +yazi_macro::mod_flat!(close select show); diff --git a/yazi-parser/src/pick/select.rs b/yazi-parser/src/pick/select.rs new file mode 100644 index 000000000..9b20b2f76 --- /dev/null +++ b/yazi-parser/src/pick/select.rs @@ -0,0 +1,23 @@ +use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; +use yazi_shared::event::ActionCow; + +#[derive(Debug)] +pub struct SelectForm { + pub index: usize, +} + +impl From for SelectForm { + fn from(c: ActionCow) -> Self { Self { index: c.first().unwrap_or(0) } } +} + +impl From for SelectForm { + fn from(index: usize) -> Self { Self { index } } +} + +impl FromLua for SelectForm { + fn from_lua(_: Value, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } +} + +impl IntoLua for SelectForm { + fn into_lua(self, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } +} diff --git a/yazi-parser/src/spark/spark.rs b/yazi-parser/src/spark/spark.rs index c0f45c041..8ca95d79e 100644 --- a/yazi-parser/src/spark/spark.rs +++ b/yazi-parser/src/spark/spark.rs @@ -132,6 +132,7 @@ pub enum Spark<'a> { // Pick PickArrow(crate::ArrowForm), PickClose(crate::pick::CloseForm), + PickSelect(crate::pick::SelectForm), PickShow(crate::pick::ShowForm), // Spot @@ -316,6 +317,7 @@ impl<'a> IntoLua for Spark<'a> { // Pick Self::PickArrow(b) => b.into_lua(lua), Self::PickClose(b) => b.into_lua(lua), + Self::PickSelect(b) => b.into_lua(lua), Self::PickShow(b) => b.into_lua(lua), // Spot @@ -432,6 +434,7 @@ try_from_spark!(crate::mgr::YankForm, mgr:yank); try_from_spark!(crate::notify::PushForm, notify:push); try_from_spark!(crate::notify::TickForm, notify:tick); try_from_spark!(crate::pick::CloseForm, pick:close); +try_from_spark!(crate::pick::SelectForm, pick: select); try_from_spark!(crate::pick::ShowForm, pick:show); try_from_spark!(crate::spot::CopyForm, spot:copy); try_from_spark!(crate::tasks::ProcessOpenForm, tasks:process_open);