tlc: implement split ratio adjustment (SplitMore/SplitLess)

Alt-Shift-Right grows left panel 5%, Alt-Shift-Left shrinks 5%.
Alt-= resets to 50/50. Range clamped to 10-90%.
panel_areas() uses split_ratio when equal_split is false.
3 new tests. 976 tests total, 0 failures.
This commit is contained in:
2026-06-19 10:23:38 +03:00
parent 8aa02e1ed0
commit 2bcaba5340
@@ -124,6 +124,9 @@ pub struct FileManager {
pub active: Active,
/// Layout mode (horizontal = side-by-side, vertical = stacked).
pub layout: LayoutMode,
/// Left panel width as a percentage (1-99). Used when `equal_split` is false.
/// Adjusted by SplitMore (Alt-Shift-Right) and SplitLess (Alt-Shift-Left).
pub split_ratio: u16,
/// Active theme.
pub theme: Theme,
/// Bottom status line.
@@ -332,6 +335,7 @@ impl FileManager {
} else {
LayoutMode::Horizontal
},
split_ratio: 50,
theme,
status: StatusLine::default(),
cfg: cfg.filemanager.clone(),
@@ -714,7 +718,7 @@ impl FileManager {
}
Cmd::EqualSplit => {
self.runtime.equal_split = Some(true);
self.status.set_message("Equal split".to_string());
self.split_ratio = 50;
Ok(true)
}
Cmd::DirSize => {
@@ -748,12 +752,14 @@ impl FileManager {
self.cmdline.insert_text(&name);
Ok(true)
}
Cmd::SplitLess | Cmd::SplitMore => {
Cmd::SplitLess => {
self.runtime.equal_split = Some(false);
self.status.set_message(
"Manual split-ratio adjust needs a split field; equal-split toggled off"
.to_string(),
);
self.split_ratio = self.split_ratio.saturating_sub(5).max(10);
Ok(true)
}
Cmd::SplitMore => {
self.runtime.equal_split = Some(false);
self.split_ratio = self.split_ratio.saturating_add(5).min(90);
Ok(true)
}
Cmd::Jobs => {
@@ -2238,18 +2244,30 @@ impl FileManager {
}
fn panel_areas(&self, area: Rect) -> (Rect, Rect) {
let left_pct = if self.runtime.equal_split.unwrap_or(true) {
50
} else {
self.split_ratio.clamp(1, 99)
};
let right_pct = 100u16.saturating_sub(left_pct);
match self.layout {
LayoutMode::Horizontal => {
let chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
.constraints([
Constraint::Percentage(left_pct),
Constraint::Percentage(right_pct),
])
.split(area);
(chunks[0], chunks[1])
}
LayoutMode::Vertical => {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
.constraints([
Constraint::Percentage(left_pct),
Constraint::Percentage(right_pct),
])
.split(area);
(chunks[0], chunks[1])
}
@@ -3474,4 +3492,43 @@ mod tests {
assert_eq!(lines, vec!["Binary file, cannot display"]);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn split_more_increases_left_ratio() {
let dir = std::env::temp_dir().join("tlc-fm-split-more");
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).unwrap();
let mut fm = FileManager::new(&dir, &empty_cfg()).unwrap();
assert_eq!(fm.split_ratio, 50);
fm.dispatch(Cmd::SplitMore).unwrap();
assert_eq!(fm.split_ratio, 55);
assert_eq!(fm.runtime.equal_split, Some(false));
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn split_less_decreases_left_ratio() {
let dir = std::env::temp_dir().join("tlc-fm-split-less");
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).unwrap();
let mut fm = FileManager::new(&dir, &empty_cfg()).unwrap();
fm.split_ratio = 60;
fm.dispatch(Cmd::SplitLess).unwrap();
assert_eq!(fm.split_ratio, 55);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn equal_split_resets_ratio() {
let dir = std::env::temp_dir().join("tlc-fm-split-equal");
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).unwrap();
let mut fm = FileManager::new(&dir, &empty_cfg()).unwrap();
fm.split_ratio = 70;
fm.runtime.equal_split = Some(false);
fm.dispatch(Cmd::EqualSplit).unwrap();
assert_eq!(fm.split_ratio, 50);
assert_eq!(fm.runtime.equal_split, Some(true));
let _ = fs::remove_dir_all(&dir);
}
}