feat: configure interchangeable top and bottom bars

This commit is contained in:
Valdemar Lorenzen
2026-10-12 11:47:31 +02:00
parent 4cfd068f1c
commit 0d3fbc01f8
12 changed files with 776 additions and 340 deletions
+44 -26
View File
@@ -1351,8 +1351,8 @@ pub struct Editor {
owned_system_clipboard: Option<(String, Vec<String>, bool)>,
last_edit: Option<EditRecipe>,
message: String,
tabline: ChromeLine,
statusline: ChromeLine,
top_bar: ChromeLine,
bottom_bar: ChromeLine,
labels: BTreeMap<String, String>,
quit: bool,
capabilities: Vec<String>,
@@ -1439,8 +1439,8 @@ impl Editor {
owned_system_clipboard: None,
last_edit: None,
message: String::new(),
tabline: ChromeLine::tabline(),
statusline: ChromeLine::statusline(),
top_bar: ChromeLine::top(),
bottom_bar: ChromeLine::bottom(),
labels: BTreeMap::new(),
quit: false,
capabilities,
@@ -3831,11 +3831,11 @@ impl Editor {
pub fn message(&self) -> &str {
&self.message
}
pub fn tabline_config(&self) -> &ChromeLine {
&self.tabline
pub fn top_bar_config(&self) -> &ChromeLine {
&self.top_bar
}
pub fn statusline_config(&self) -> &ChromeLine {
&self.statusline
pub fn bottom_bar_config(&self) -> &ChromeLine {
&self.bottom_bar
}
pub fn label(&self, name: &str) -> &str {
self.labels.get(name).map_or("", String::as_str)
@@ -3881,12 +3881,12 @@ impl Editor {
pub fn set_chrome_config(
&mut self,
mut tabline: ChromeLine,
mut statusline: ChromeLine,
mut top: ChromeLine,
mut bottom: ChromeLine,
labels: BTreeMap<String, String>,
) -> Result<(), String> {
tabline.validate(true)?;
statusline.validate(false)?;
top.validate()?;
bottom.validate()?;
let mut total = 0usize;
for (name, text) in &labels {
validate_label(name, text)?;
@@ -3898,8 +3898,8 @@ impl Editor {
return Err("Labels exceed 4 MiB".into());
}
}
self.tabline = tabline;
self.statusline = statusline;
self.top_bar = top;
self.bottom_bar = bottom;
self.labels = labels
.into_iter()
.map(|(name, text)| (name, sanitize_label(text)))
@@ -17749,9 +17749,11 @@ mod tests {
fn chrome_installation_and_invalid_label_batches_are_atomic() {
let mut editor = editor();
editor.set_label("battery".into(), "ready".into()).unwrap();
let mut top = ChromeLine::tabline();
let mut top = ChromeLine::top();
top.left = vec!["mode".into(), "language".into()];
top.center.push("workspace".into());
let bottom = ChromeLine::statusline();
let mut bottom = ChromeLine::bottom();
bottom.left = vec!["tabs".into()];
editor
.set_chrome_config(
top.clone(),
@@ -17764,18 +17766,34 @@ mod tests {
.unwrap();
assert_eq!(editor.label("workspace"), "tools�");
assert_eq!(
editor.tabline_config().segment("workspace"),
editor.top_bar_config().segment("workspace"),
&crate::chrome::SegmentConfig::default()
);
let installed = editor.tabline_config().clone();
top.segments.get_mut("tabs").unwrap().title = "{missing}".into();
assert!(
editor
.set_chrome_config(top, bottom, BTreeMap::new())
.is_err()
);
assert_eq!(editor.tabline_config(), &installed);
assert_eq!(editor.label("battery"), "ready");
let installed_top = editor.top_bar_config().clone();
let installed_bottom = editor.bottom_bar_config().clone();
assert_eq!(installed_top.left, ["mode", "language"]);
assert_eq!(installed_bottom.left, ["tabs"]);
top.right.push("uninstalled".into());
bottom.center.push("uninstalled".into());
let mut invalid_top = top.clone();
invalid_top.segments.get_mut("tabs").unwrap().title = "{missing}".into();
let mut invalid_bottom = bottom.clone();
invalid_bottom.segments.get_mut("mode").unwrap().padding = 65;
for (top, bottom, labels) in [
(invalid_top, bottom.clone(), BTreeMap::new()),
(top.clone(), invalid_bottom, BTreeMap::new()),
(
top,
bottom,
BTreeMap::from([("bad-name".into(), "invalid".into())]),
),
] {
assert!(editor.set_chrome_config(top, bottom, labels).is_err());
assert_eq!(editor.top_bar_config(), &installed_top);
assert_eq!(editor.bottom_bar_config(), &installed_bottom);
assert_eq!(editor.label("battery"), "ready");
assert_eq!(editor.label("workspace"), "tools�");
}
assert!(
editor
.apply(vec![