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: make Input and Select positions customizable #361

Merged
merged 16 commits into from
Nov 17, 2023
56 changes: 56 additions & 0 deletions yazi-config/preset/yazi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,61 @@ bizarre_retry = 5
[plugins]
preload = []

[input]
# cd
cd_title = "Change directory:"
cd_origin = "top-center"
cd_offset = [ 0, 2, 50, 3 ]

# create
create_title = "Create:"
create_origin = "top-center"
create_offset = [ 0, 2, 50, 3 ]

# rename
rename_title = "Rename:"
rename_origin = "hovered"
rename_offset = [ 0, 1, 50, 3 ]

# trash
trash_title = "Move {n} selected file{s} to trash? (y/N)"
trash_origin = "top-center"
trash_offset = [ 0, 2, 50, 3 ]

# delete
delete_title = "Delete {n} selected file{s} permanently? (y/N)"
delete_origin = "top-center"
delete_offset = [ 0, 2, 50, 3 ]

# find
find_title = [ "Find next:", "Find previous:" ]
find_origin = "top-center"
find_offset = [ 0, 2, 50, 3 ]

# search
search_title = "Search:"
search_origin = "top-center"
search_offset = [ 0, 2, 50, 3 ]

# shell
shell_title = [ "Shell:", "Shell (block):" ]
shell_origin = "top-center"
shell_offset = [ 0, 2, 50, 3 ]

# overwrite
overwrite_title = "Overwrite an existing file? (y/N)"
overwrite_origin = "top-center"
overwrite_offset = [ 0, 2, 50, 3 ]

# quit
quit_title = "{n} task{s} running, sure to quit? (y/N)"
quit_origin = "top-center"
quit_offset = [ 0, 2, 50, 3 ]

[select]
open_title = "Open with:"
open_origin = "hovered"
open_offset = [ 0, 1, 50, 7 ]

[log]
enabled = false
5 changes: 5 additions & 0 deletions yazi-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod manager;
pub mod open;
mod pattern;
pub mod plugins;
pub mod popup;
mod preset;
pub mod preview;
mod tasks;
Expand All @@ -32,6 +33,8 @@ pub static PLUGINS: RoCell<plugins::Plugins> = RoCell::new();
pub static PREVIEW: RoCell<preview::Preview> = RoCell::new();
pub static TASKS: RoCell<tasks::Tasks> = RoCell::new();
pub static THEME: RoCell<theme::Theme> = RoCell::new();
pub static INPUT: RoCell<popup::Input> = RoCell::new();
pub static SELECT: RoCell<popup::Select> = RoCell::new();

pub static BOOT: RoCell<boot::Boot> = RoCell::new();

Expand All @@ -48,6 +51,8 @@ pub fn init() {
PREVIEW.with(Default::default);
TASKS.with(Default::default);
THEME.with(Default::default);
INPUT.with(Default::default);
SELECT.with(Default::default);

BOOT.with(Default::default);
}
73 changes: 73 additions & 0 deletions yazi-config/src/popup/input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use serde::Deserialize;

use super::{Offset, Origin};
use crate::MERGED_YAZI;

#[derive(Deserialize)]
pub struct Input {
// cd
pub cd_title: String,
pub cd_origin: Origin,
pub cd_offset: Offset,

// create
pub create_title: String,
pub create_origin: Origin,
pub create_offset: Offset,

// rename
pub rename_title: String,
pub rename_origin: Origin,
pub rename_offset: Offset,

// trash
pub trash_title: String,
pub trash_origin: Origin,
pub trash_offset: Offset,

// delete
pub delete_title: String,
pub delete_origin: Origin,
pub delete_offset: Offset,

// find
pub find_title: [String; 2],
pub find_origin: Origin,
pub find_offset: Offset,

// search
pub search_title: String,
pub search_origin: Origin,
pub search_offset: Offset,

// shell
pub shell_title: [String; 2],
pub shell_origin: Origin,
pub shell_offset: Offset,

// overwrite
pub overwrite_title: String,
pub overwrite_origin: Origin,
pub overwrite_offset: Offset,

// quit
pub quit_title: String,
pub quit_origin: Origin,
pub quit_offset: Offset,
}

impl Default for Input {
fn default() -> Self {
#[derive(Deserialize)]
struct Outer {
input: Input,
}

toml::from_str::<Outer>(&MERGED_YAZI).unwrap().input
}
}

impl Input {
#[inline]
pub const fn border(&self) -> u16 { 2 }
}
13 changes: 13 additions & 0 deletions yazi-config/src/popup/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
mod input;
mod offset;
mod options;
mod origin;
mod position;
mod select;

pub use input::*;
pub use offset::*;
pub use options::*;
pub use origin::*;
pub use position::*;
pub use select::*;
34 changes: 34 additions & 0 deletions yazi-config/src/popup/offset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use anyhow::bail;
use serde::Deserialize;

#[derive(Clone, Copy, Default, Deserialize)]
#[serde(try_from = "Vec<i16>")]
pub struct Offset {
pub x: i16,
pub y: i16,
pub width: u16,
pub height: u16,
}

impl TryFrom<Vec<i16>> for Offset {
type Error = anyhow::Error;

fn try_from(values: Vec<i16>) -> Result<Self, Self::Error> {
if values.len() != 4 {
bail!("offset must have 4 values: {:?}", values);
}
if values[2] < 0 || values[3] < 0 {
bail!("offset width and height must be positive: {:?}", values);
}
if values[3] < 3 {
bail!("offset height must be at least 3: {:?}", values);
}

Ok(Self {
x: values[0],
y: values[1],
width: values[2] as u16,
height: values[3] as u16,
})
}
}
143 changes: 143 additions & 0 deletions yazi-config/src/popup/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use super::{Offset, Position};
use crate::{INPUT, SELECT};

#[derive(Default)]
pub struct InputOpt {
pub title: String,
pub value: String,
pub position: Position,
pub realtime: bool,
pub completion: bool,
pub highlight: bool,
}

#[derive(Default)]
pub struct SelectOpt {
pub title: String,
pub items: Vec<String>,
pub position: Position,
}

impl InputOpt {
#[inline]
pub fn cd() -> Self {
Self {
title: INPUT.cd_title.to_owned(),
position: Position::new(INPUT.cd_origin, INPUT.cd_offset),
completion: true,
..Default::default()
}
}

#[inline]
pub fn create() -> Self {
Self {
title: INPUT.create_title.to_owned(),
position: Position::new(INPUT.create_origin, INPUT.create_offset),
..Default::default()
}
}

#[inline]
pub fn rename() -> Self {
Self {
title: INPUT.rename_title.to_owned(),
position: Position::new(INPUT.rename_origin, INPUT.rename_offset),
..Default::default()
}
}

#[inline]
pub fn trash(n: usize) -> Self {
let title = INPUT.trash_title.replace("{n}", &n.to_string());
Self {
title: title.replace("{s}", if n > 1 { "s" } else { "" }),
position: Position::new(INPUT.trash_origin, INPUT.trash_offset),
..Default::default()
}
}

#[inline]
pub fn delete(n: usize) -> Self {
let title = INPUT.delete_title.replace("{n}", &n.to_string());
Self {
title: title.replace("{s}", if n > 1 { "s" } else { "" }),
position: Position::new(INPUT.delete_origin, INPUT.delete_offset),
..Default::default()
}
}

#[inline]
pub fn find(prev: bool) -> Self {
Self {
title: INPUT.find_title[prev as usize].to_owned(),
position: Position::new(INPUT.find_origin, INPUT.find_offset),
realtime: true,
..Default::default()
}
}

#[inline]
pub fn search() -> Self {
Self {
title: INPUT.search_title.to_owned(),
position: Position::new(INPUT.search_origin, INPUT.search_offset),
..Default::default()
}
}

#[inline]
pub fn shell(block: bool) -> Self {
Self {
title: INPUT.shell_title[block as usize].to_owned(),
position: Position::new(INPUT.shell_origin, INPUT.shell_offset),
highlight: true,
..Default::default()
}
}

#[inline]
pub fn overwrite() -> Self {
Self {
title: INPUT.overwrite_title.to_owned(),
position: Position::new(INPUT.overwrite_origin, INPUT.overwrite_offset),
..Default::default()
}
}

#[inline]
pub fn quit(n: usize) -> Self {
let title = INPUT.quit_title.replace("{n}", &n.to_string());
Self {
title: title.replace("{s}", if n > 1 { "s" } else { "" }),
position: Position::new(INPUT.quit_origin, INPUT.quit_offset),
..Default::default()
}
}

#[inline]
pub fn with_value(mut self, value: impl Into<String>) -> Self {
self.value = value.into();
self
}
}

impl SelectOpt {
#[inline]
fn max_height(len: usize) -> u16 {
SELECT.open_offset.height.min(SELECT.border().saturating_add(len as u16))
}

#[inline]
pub fn open(items: Vec<String>) -> Self {
let max_height = Self::max_height(items.len());
Self {
title: SELECT.open_title.to_owned(),
items,
position: Position::new(SELECT.open_origin, Offset {
height: max_height,
..SELECT.open_offset
}),
}
}
}
24 changes: 24 additions & 0 deletions yazi-config/src/popup/origin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use serde::Deserialize;

#[derive(Clone, Copy, Default, Deserialize, PartialEq, Eq)]
pub enum Origin {
#[default]
#[serde(rename = "top-left")]
TopLeft,
#[serde(rename = "top-center")]
TopCenter,
#[serde(rename = "top-right")]
TopRight,

#[serde(rename = "bottom-left")]
BottomLeft,
#[serde(rename = "bottom-center")]
BottomCenter,
#[serde(rename = "bottom-right")]
BottomRight,

#[serde(rename = "center")]
Center,
#[serde(rename = "hovered")]
Hovered,
}
Loading