Skip to content
Merged
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
1 change: 1 addition & 0 deletions yazi-config/preset/theme.toml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ hovered = { underline = true }
# : Which {{{

[which]
cols = 3
mask = { bg = "black" }
cand = { fg = "lightcyan" }
rest = { fg = "darkgray" }
Expand Down
5 changes: 4 additions & 1 deletion yazi-config/src/theme/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,10 @@ pub struct Tasks {
pub hovered: Style,
}

#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, Validate)]
pub struct Which {
#[validate(range(min = 1, max = 3, message = "Must be between 1 and 3"))]
pub cols: u8,
pub mask: Style,
pub cand: Style,
pub rest: Style,
Expand Down Expand Up @@ -139,6 +141,7 @@ impl Default for Theme {
let mut theme: Self = toml::from_str(&MERGED_THEME).unwrap();

check_validation(theme.manager.validate());
check_validation(theme.which.validate());

theme.manager.syntect_theme = expand_path(&theme.manager.syntect_theme);

Expand Down
39 changes: 39 additions & 0 deletions yazi-fm/src/which/cand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use ratatui::{buffer::Buffer, layout::Rect, text::{Line, Span}, widgets::{Paragraph, Widget}};
use yazi_config::{keymap::Control, THEME};

pub(super) struct Cand<'a> {
cand: &'a Control,
times: usize,
}

impl<'a> Cand<'a> {
pub(super) fn new(cand: &'a Control, times: usize) -> Self { Self { times, cand } }

fn keys(&self) -> Vec<String> {
self.cand.on[self.times..].iter().map(ToString::to_string).collect()
}
}

impl Widget for Cand<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let keys = self.keys();
let mut spans = Vec::with_capacity(10);

// Padding
spans.push(Span::raw(" ".repeat(10usize.saturating_sub(keys.join("").len()))));

// First key
spans.push(Span::styled(keys[0].clone(), THEME.which.cand.into()));

// Rest keys
spans.extend(keys.iter().skip(1).map(|k| Span::styled(k, THEME.which.rest.into())));

// Separator
spans.push(Span::styled(&THEME.which.separator, THEME.which.separator_style.into()));

// Description
spans.push(Span::styled(self.cand.desc_or_exec(), THEME.which.desc.into()));

Paragraph::new(Line::from(spans)).render(area, buf);
}
}
58 changes: 36 additions & 22 deletions yazi-fm/src/which/layout.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use ratatui::{buffer::Buffer, layout, layout::{Constraint, Direction, Rect}, widgets::{Block, Widget}};
use yazi_config::THEME;

use super::Side;
use super::Cand;
use crate::{widgets, Ctx};

const PADDING_X: u16 = 1;
const PADDING_Y: u16 = 1;

pub(crate) struct Which<'a> {
cx: &'a Ctx,
}
Expand All @@ -15,31 +18,42 @@ impl<'a> Which<'a> {
impl Widget for Which<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let which = &self.cx.which;
let mut cands: (Vec<_>, Vec<_>, Vec<_>) = Default::default();
for (i, &c) in which.cands.iter().enumerate() {
match i % 3 {
0 => cands.0.push(c),
1 => cands.1.push(c),
2 => cands.2.push(c),
_ => unreachable!(),
}
}
let cols = THEME.which.cols as usize;

let height = area.height.min(cands.0.len() as u16 + 2);
let y = area.height.saturating_sub(height + 2);
let area = Rect { x: area.width.min(1), y, width: area.width.saturating_sub(2), height };
let height = area.height.min(which.cands.len().div_ceil(cols) as u16 + PADDING_Y * 2);
let area = Rect {
x: PADDING_X.min(area.width),
y: area.height.saturating_sub(height + PADDING_Y * 2),
width: area.width.saturating_sub(PADDING_X * 2),
height,
};

// Don't render if there's no space
if area.height <= PADDING_Y * 2 {
return;
}

let chunks = layout::Layout::new(Direction::Horizontal, [
Constraint::Ratio(1, 3),
Constraint::Ratio(1, 3),
Constraint::Ratio(1, 3),
])
.split(area);
let chunks = {
use Constraint::*;
layout::Layout::new(Direction::Horizontal, match cols {
1 => &[Ratio(1, 1)] as &[Constraint],
2 => &[Ratio(1, 2), Ratio(1, 2)],
_ => &[Ratio(1, 3), Ratio(1, 3), Ratio(1, 3)],
})
.split(area)
};

widgets::Clear.render(area, buf);
Block::new().style(THEME.which.mask.into()).render(area, buf);
Side::new(which.times, cands.0).render(chunks[0], buf);
Side::new(which.times, cands.1).render(chunks[1], buf);
Side::new(which.times, cands.2).render(chunks[2], buf);

for y in 0..area.height {
for (x, chunk) in chunks.iter().enumerate() {
let Some(&cand) = which.cands.get(y as usize * cols + x) else {
break;
};

Cand::new(cand, which.times).render(Rect { y: chunk.y + y + 1, height: 1, ..*chunk }, buf);
}
}
}
}
4 changes: 2 additions & 2 deletions yazi-fm/src/which/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod cand;
mod layout;
mod side;

use cand::*;
pub(super) use layout::*;
use side::*;
44 changes: 0 additions & 44 deletions yazi-fm/src/which/side.rs

This file was deleted.

4 changes: 2 additions & 2 deletions yazi-plugin/preset/components/progress.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ function Progress:render(area, offset)
self.area = ui.Rect {
x = math.max(0, area.w - offset - 21),
y = area.y,
w = math.max(0, math.min(20, area.w - offset - 1)),
h = 1,
w = ya.clamp(0, area.w - offset - 1, 20),
h = math.min(1, area.h),
}
return self:partial_render()
end
Expand Down