Skip to content

Commit 28870ad

Browse files
authored
feat: customizing the number of columns of "which key" component (#571)
1 parent a19e263 commit 28870ad

File tree

7 files changed

+84
-71
lines changed

7 files changed

+84
-71
lines changed

yazi-config/preset/theme.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ hovered = { underline = true }
113113
# : Which {{{
114114

115115
[which]
116+
cols = 3
116117
mask = { bg = "black" }
117118
cand = { fg = "lightcyan" }
118119
rest = { fg = "darkgray" }

yazi-config/src/theme/theme.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ pub struct Tasks {
9595
pub hovered: Style,
9696
}
9797

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

141143
check_validation(theme.manager.validate());
144+
check_validation(theme.which.validate());
142145

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

yazi-fm/src/which/cand.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use ratatui::{buffer::Buffer, layout::Rect, text::{Line, Span}, widgets::{Paragraph, Widget}};
2+
use yazi_config::{keymap::Control, THEME};
3+
4+
pub(super) struct Cand<'a> {
5+
cand: &'a Control,
6+
times: usize,
7+
}
8+
9+
impl<'a> Cand<'a> {
10+
pub(super) fn new(cand: &'a Control, times: usize) -> Self { Self { times, cand } }
11+
12+
fn keys(&self) -> Vec<String> {
13+
self.cand.on[self.times..].iter().map(ToString::to_string).collect()
14+
}
15+
}
16+
17+
impl Widget for Cand<'_> {
18+
fn render(self, area: Rect, buf: &mut Buffer) {
19+
let keys = self.keys();
20+
let mut spans = Vec::with_capacity(10);
21+
22+
// Padding
23+
spans.push(Span::raw(" ".repeat(10usize.saturating_sub(keys.join("").len()))));
24+
25+
// First key
26+
spans.push(Span::styled(keys[0].clone(), THEME.which.cand.into()));
27+
28+
// Rest keys
29+
spans.extend(keys.iter().skip(1).map(|k| Span::styled(k, THEME.which.rest.into())));
30+
31+
// Separator
32+
spans.push(Span::styled(&THEME.which.separator, THEME.which.separator_style.into()));
33+
34+
// Description
35+
spans.push(Span::styled(self.cand.desc_or_exec(), THEME.which.desc.into()));
36+
37+
Paragraph::new(Line::from(spans)).render(area, buf);
38+
}
39+
}

yazi-fm/src/which/layout.rs

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use ratatui::{buffer::Buffer, layout, layout::{Constraint, Direction, Rect}, widgets::{Block, Widget}};
22
use yazi_config::THEME;
33

4-
use super::Side;
4+
use super::Cand;
55
use crate::{widgets, Ctx};
66

7+
const PADDING_X: u16 = 1;
8+
const PADDING_Y: u16 = 1;
9+
710
pub(crate) struct Which<'a> {
811
cx: &'a Ctx,
912
}
@@ -15,31 +18,42 @@ impl<'a> Which<'a> {
1518
impl Widget for Which<'_> {
1619
fn render(self, area: Rect, buf: &mut Buffer) {
1720
let which = &self.cx.which;
18-
let mut cands: (Vec<_>, Vec<_>, Vec<_>) = Default::default();
19-
for (i, &c) in which.cands.iter().enumerate() {
20-
match i % 3 {
21-
0 => cands.0.push(c),
22-
1 => cands.1.push(c),
23-
2 => cands.2.push(c),
24-
_ => unreachable!(),
25-
}
26-
}
21+
let cols = THEME.which.cols as usize;
2722

28-
let height = area.height.min(cands.0.len() as u16 + 2);
29-
let y = area.height.saturating_sub(height + 2);
30-
let area = Rect { x: area.width.min(1), y, width: area.width.saturating_sub(2), height };
23+
let height = area.height.min(which.cands.len().div_ceil(cols) as u16 + PADDING_Y * 2);
24+
let area = Rect {
25+
x: PADDING_X.min(area.width),
26+
y: area.height.saturating_sub(height + PADDING_Y * 2),
27+
width: area.width.saturating_sub(PADDING_X * 2),
28+
height,
29+
};
30+
31+
// Don't render if there's no space
32+
if area.height <= PADDING_Y * 2 {
33+
return;
34+
}
3135

32-
let chunks = layout::Layout::new(Direction::Horizontal, [
33-
Constraint::Ratio(1, 3),
34-
Constraint::Ratio(1, 3),
35-
Constraint::Ratio(1, 3),
36-
])
37-
.split(area);
36+
let chunks = {
37+
use Constraint::*;
38+
layout::Layout::new(Direction::Horizontal, match cols {
39+
1 => &[Ratio(1, 1)] as &[Constraint],
40+
2 => &[Ratio(1, 2), Ratio(1, 2)],
41+
_ => &[Ratio(1, 3), Ratio(1, 3), Ratio(1, 3)],
42+
})
43+
.split(area)
44+
};
3845

3946
widgets::Clear.render(area, buf);
4047
Block::new().style(THEME.which.mask.into()).render(area, buf);
41-
Side::new(which.times, cands.0).render(chunks[0], buf);
42-
Side::new(which.times, cands.1).render(chunks[1], buf);
43-
Side::new(which.times, cands.2).render(chunks[2], buf);
48+
49+
for y in 0..area.height {
50+
for (x, chunk) in chunks.iter().enumerate() {
51+
let Some(&cand) = which.cands.get(y as usize * cols + x) else {
52+
break;
53+
};
54+
55+
Cand::new(cand, which.times).render(Rect { y: chunk.y + y + 1, height: 1, ..*chunk }, buf);
56+
}
57+
}
4458
}
4559
}

yazi-fm/src/which/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
mod cand;
12
mod layout;
2-
mod side;
33

4+
use cand::*;
45
pub(super) use layout::*;
5-
use side::*;

yazi-fm/src/which/side.rs

Lines changed: 0 additions & 44 deletions
This file was deleted.

yazi-plugin/preset/components/progress.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ function Progress:render(area, offset)
66
self.area = ui.Rect {
77
x = math.max(0, area.w - offset - 21),
88
y = area.y,
9-
w = math.max(0, math.min(20, area.w - offset - 1)),
10-
h = 1,
9+
w = ya.clamp(0, area.w - offset - 1, 20),
10+
h = math.min(1, area.h),
1111
}
1212
return self:partial_render()
1313
end

0 commit comments

Comments
 (0)