diff --git a/yazi-actor/src/pick/mod.rs b/yazi-actor/src/pick/mod.rs index e0fc92ad5..08e6405a2 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 show select); diff --git a/yazi-actor/src/pick/select.rs b/yazi-actor/src/pick/select.rs new file mode 100644 index 000000000..7adb1a175 --- /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::SelectOpt; +use yazi_shared::data::Data; + +use crate::{Actor, Ctx}; + +pub struct Select; + +impl Actor for Select { + type Options = SelectOpt; + + const NAME: &str = "select"; + + fn act(cx: &mut Ctx, opt: Self::Options) -> Result { + let pick = &mut cx.pick; + if opt.index >= pick.items.len() { + succ!(); + } + + if let Some(cb) = pick.callback.take() { + _ = cb.send(Ok(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 dee02f005..3ef6b0d33 100644 --- a/yazi-config/preset/keymap-default.toml +++ b/yazi-config/preset/keymap-default.toml @@ -219,6 +219,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 6c42dde30..4d1c09f83 100644 --- a/yazi-config/preset/yazi-default.toml +++ b/yazi-config/preset/yazi-default.toml @@ -228,6 +228,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-dds/src/spark/spark.rs b/yazi-dds/src/spark/spark.rs index 8d8853f07..760549b18 100644 --- a/yazi-dds/src/spark/spark.rs +++ b/yazi-dds/src/spark/spark.rs @@ -102,6 +102,7 @@ pub enum Spark<'a> { // Pick PickClose(yazi_parser::pick::CloseOpt), PickShow(yazi_parser::pick::ShowOpt), + PickSelect(yazi_parser::pick::SelectOpt), // Spot SpotCopy(yazi_parser::spot::CopyOpt), @@ -224,6 +225,7 @@ impl<'a> IntoLua for Spark<'a> { // Pick Self::PickClose(b) => b.into_lua(lua), Self::PickShow(b) => b.into_lua(lua), + Self::PickSelect(b) => b.into_lua(lua), // Spot Self::SpotCopy(b) => b.into_lua(lua), @@ -320,6 +322,7 @@ try_from_spark!(mgr::YankOpt, mgr:yank); try_from_spark!(notify::TickOpt, notify:tick); try_from_spark!(pick::CloseOpt, pick:close); try_from_spark!(pick::ShowOpt, pick:show); +try_from_spark!(pick::SelectOpt, pick:select); try_from_spark!(spot::CopyOpt, spot:copy); try_from_spark!(tasks::ProcessOpenOpt, tasks:process_open); try_from_spark!(tasks::UpdateSucceedOpt, tasks:update_succeed); diff --git a/yazi-fm/src/executor.rs b/yazi-fm/src/executor.rs index 905f73eee..48cc70773 100644 --- a/yazi-fm/src/executor.rs +++ b/yazi-fm/src/executor.rs @@ -215,6 +215,7 @@ impl<'a> Executor<'a> { on!(show); on!(close); on!(arrow); + on!(select); match cmd.name.as_ref() { // Help 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..53a4115b2 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 show select); diff --git a/yazi-parser/src/pick/select.rs b/yazi-parser/src/pick/select.rs new file mode 100644 index 000000000..2a4474b41 --- /dev/null +++ b/yazi-parser/src/pick/select.rs @@ -0,0 +1,23 @@ +use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; +use yazi_shared::event::CmdCow; + +#[derive(Debug)] +pub struct SelectOpt { + pub index: usize, +} + +impl From for SelectOpt { + fn from(c: CmdCow) -> Self { Self { index: c.first().unwrap_or(0) } } +} + +impl From for SelectOpt { + fn from(index: usize) -> Self { Self { index } } +} + +impl FromLua for SelectOpt { + fn from_lua(_: Value, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } +} + +impl IntoLua for SelectOpt { + fn into_lua(self, _: &Lua) -> mlua::Result { Err("unsupported".into_lua_err()) } +}