mirror of
https://github.com/zellij-org/zellij.git
synced 2024-11-23 08:57:14 +03:00
fix(resurrection): log failure instead of crashing in some edge cases (#2851)
* fix(resurrection): log failure instead of crashing in some edge cases * style(fmt): rustfmt
This commit is contained in:
parent
a6ab09cbb0
commit
404608e7e3
@ -535,23 +535,43 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box<Layout>) -> Result<()> {
|
||||
PtyInstruction::DumpLayout(mut session_layout_metadata, client_id) => {
|
||||
let err_context = || format!("Failed to dump layout");
|
||||
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
||||
let (kdl_layout, _pane_contents) =
|
||||
session_serialization::serialize_session_layout(session_layout_metadata.into());
|
||||
pty.bus
|
||||
.senders
|
||||
.send_to_server(ServerInstruction::Log(vec![kdl_layout], client_id))
|
||||
.with_context(err_context)
|
||||
.non_fatal();
|
||||
match session_serialization::serialize_session_layout(
|
||||
session_layout_metadata.into(),
|
||||
) {
|
||||
Ok((kdl_layout, _pane_contents)) => {
|
||||
pty.bus
|
||||
.senders
|
||||
.send_to_server(ServerInstruction::Log(vec![kdl_layout], client_id))
|
||||
.with_context(err_context)
|
||||
.non_fatal();
|
||||
},
|
||||
Err(e) => {
|
||||
pty.bus
|
||||
.senders
|
||||
.send_to_server(ServerInstruction::Log(vec![e.to_owned()], client_id))
|
||||
.with_context(err_context)
|
||||
.non_fatal();
|
||||
},
|
||||
}
|
||||
},
|
||||
PtyInstruction::LogLayoutToHd(mut session_layout_metadata) => {
|
||||
let err_context = || format!("Failed to dump layout");
|
||||
pty.populate_session_layout_metadata(&mut session_layout_metadata);
|
||||
let kdl_layout =
|
||||
session_serialization::serialize_session_layout(session_layout_metadata.into());
|
||||
pty.bus
|
||||
.senders
|
||||
.send_to_background_jobs(BackgroundJob::ReportLayoutInfo(kdl_layout))
|
||||
.with_context(err_context)?;
|
||||
match session_serialization::serialize_session_layout(
|
||||
session_layout_metadata.into(),
|
||||
) {
|
||||
Ok(kdl_layout_and_pane_contents) => {
|
||||
pty.bus
|
||||
.senders
|
||||
.send_to_background_jobs(BackgroundJob::ReportLayoutInfo(
|
||||
kdl_layout_and_pane_contents,
|
||||
))
|
||||
.with_context(err_context)?;
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Failed to log layout to HD: {}", e);
|
||||
},
|
||||
}
|
||||
},
|
||||
PtyInstruction::Exit => break,
|
||||
}
|
||||
|
@ -64,16 +64,18 @@ pub struct PaneLayoutManifest {
|
||||
|
||||
pub fn serialize_session_layout(
|
||||
global_layout_manifest: GlobalLayoutManifest,
|
||||
) -> (String, BTreeMap<String, String>) {
|
||||
) -> Result<(String, BTreeMap<String, String>), &'static str> {
|
||||
// BTreeMap is the pane contents and their file names
|
||||
let mut kdl_string = String::from("layout {\n");
|
||||
let mut pane_contents = BTreeMap::new();
|
||||
stringify_global_cwd(&global_layout_manifest.global_cwd, &mut kdl_string);
|
||||
stringify_multiple_tabs(
|
||||
if let Err(e) = stringify_multiple_tabs(
|
||||
global_layout_manifest.tabs,
|
||||
&mut pane_contents,
|
||||
&mut kdl_string,
|
||||
);
|
||||
) {
|
||||
return Err(e);
|
||||
}
|
||||
stringify_new_tab_template(
|
||||
global_layout_manifest.default_layout.template,
|
||||
&mut pane_contents,
|
||||
@ -90,7 +92,7 @@ pub fn serialize_session_layout(
|
||||
&mut kdl_string,
|
||||
);
|
||||
kdl_string.push_str("}");
|
||||
(kdl_string, pane_contents)
|
||||
Ok((kdl_string, pane_contents))
|
||||
}
|
||||
|
||||
fn stringify_tab(
|
||||
@ -100,31 +102,38 @@ fn stringify_tab(
|
||||
tiled_panes: &Vec<PaneLayoutManifest>,
|
||||
floating_panes: &Vec<PaneLayoutManifest>,
|
||||
pane_contents: &mut BTreeMap<String, String>,
|
||||
) -> String {
|
||||
) -> Option<String> {
|
||||
let mut kdl_string = String::new();
|
||||
let tiled_panes_layout = get_tiled_panes_layout_from_panegeoms(tiled_panes, None);
|
||||
let floating_panes_layout = get_floating_panes_layout_from_panegeoms(floating_panes);
|
||||
let tiled_panes = if &tiled_panes_layout.children_split_direction != &SplitDirection::default()
|
||||
{
|
||||
vec![tiled_panes_layout]
|
||||
} else {
|
||||
tiled_panes_layout.children
|
||||
};
|
||||
let mut tab_attributes = vec![format!("name=\"{}\"", tab_name,)];
|
||||
if is_focused {
|
||||
tab_attributes.push(format!("focus=true"));
|
||||
// let tiled_panes_layout = get_tiled_panes_layout_from_panegeoms(tiled_panes, None);
|
||||
match get_tiled_panes_layout_from_panegeoms(tiled_panes, None) {
|
||||
Some(tiled_panes_layout) => {
|
||||
let floating_panes_layout = get_floating_panes_layout_from_panegeoms(floating_panes);
|
||||
let tiled_panes =
|
||||
if &tiled_panes_layout.children_split_direction != &SplitDirection::default() {
|
||||
vec![tiled_panes_layout]
|
||||
} else {
|
||||
tiled_panes_layout.children
|
||||
};
|
||||
let mut tab_attributes = vec![format!("name=\"{}\"", tab_name,)];
|
||||
if is_focused {
|
||||
tab_attributes.push(format!("focus=true"));
|
||||
}
|
||||
if hide_floating_panes {
|
||||
tab_attributes.push(format!("hide_floating_panes=true"));
|
||||
}
|
||||
kdl_string.push_str(&kdl_string_from_tab(
|
||||
&tiled_panes,
|
||||
&floating_panes_layout,
|
||||
tab_attributes,
|
||||
None,
|
||||
pane_contents,
|
||||
));
|
||||
Some(kdl_string)
|
||||
},
|
||||
None => {
|
||||
return None;
|
||||
},
|
||||
}
|
||||
if hide_floating_panes {
|
||||
tab_attributes.push(format!("hide_floating_panes=true"));
|
||||
}
|
||||
kdl_string.push_str(&kdl_string_from_tab(
|
||||
&tiled_panes,
|
||||
&floating_panes_layout,
|
||||
tab_attributes,
|
||||
None,
|
||||
pane_contents,
|
||||
));
|
||||
kdl_string
|
||||
}
|
||||
|
||||
/// Redundant with `geoms_to_kdl_tab`
|
||||
@ -507,23 +516,29 @@ fn stringify_multiple_tabs(
|
||||
tabs: Vec<(String, TabLayoutManifest)>,
|
||||
pane_contents: &mut BTreeMap<String, String>,
|
||||
kdl_string: &mut String,
|
||||
) {
|
||||
) -> Result<(), &'static str> {
|
||||
for (tab_name, tab_layout_manifest) in tabs {
|
||||
let tiled_panes = tab_layout_manifest.tiled_panes;
|
||||
let floating_panes = tab_layout_manifest.floating_panes;
|
||||
let hide_floating_panes = tab_layout_manifest.hide_floating_panes;
|
||||
kdl_string.push_str(&indent(
|
||||
&stringify_tab(
|
||||
tab_name.clone(),
|
||||
tab_layout_manifest.is_focused,
|
||||
hide_floating_panes,
|
||||
&tiled_panes,
|
||||
&floating_panes,
|
||||
pane_contents,
|
||||
),
|
||||
INDENT,
|
||||
));
|
||||
let stringified = stringify_tab(
|
||||
tab_name.clone(),
|
||||
tab_layout_manifest.is_focused,
|
||||
hide_floating_panes,
|
||||
&tiled_panes,
|
||||
&floating_panes,
|
||||
pane_contents,
|
||||
);
|
||||
match stringified {
|
||||
Some(stringified) => {
|
||||
kdl_string.push_str(&indent(&stringified, INDENT));
|
||||
},
|
||||
None => {
|
||||
return Err("Failed to stringify tab");
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn kdl_string_from_floating_pane(
|
||||
@ -592,10 +607,15 @@ fn tiled_pane_layout_from_manifest(
|
||||
fn get_tiled_panes_layout_from_panegeoms(
|
||||
geoms: &Vec<PaneLayoutManifest>,
|
||||
split_size: Option<SplitSize>,
|
||||
) -> TiledPaneLayout {
|
||||
) -> Option<TiledPaneLayout> {
|
||||
let (children_split_direction, splits) = match get_splits(&geoms) {
|
||||
Some(x) => x,
|
||||
None => return tiled_pane_layout_from_manifest(geoms.iter().next(), split_size),
|
||||
None => {
|
||||
return Some(tiled_pane_layout_from_manifest(
|
||||
geoms.iter().next(),
|
||||
split_size,
|
||||
))
|
||||
},
|
||||
};
|
||||
let mut children = Vec::new();
|
||||
let mut remaining_geoms = geoms.clone();
|
||||
@ -614,29 +634,38 @@ fn get_tiled_panes_layout_from_panegeoms(
|
||||
.into_iter()
|
||||
.partition(|g| g.geom.x + g.geom.cols.as_usize() <= v_max),
|
||||
};
|
||||
let constraint =
|
||||
get_domain_constraint(&subgeoms, &children_split_direction, (v_min, v_max));
|
||||
new_geoms.push(subgeoms);
|
||||
new_constraints.push(constraint);
|
||||
match get_domain_constraint(&subgeoms, &children_split_direction, (v_min, v_max)) {
|
||||
Some(constraint) => {
|
||||
new_geoms.push(subgeoms);
|
||||
new_constraints.push(constraint);
|
||||
},
|
||||
None => {
|
||||
return None;
|
||||
},
|
||||
}
|
||||
}
|
||||
let new_split_sizes = get_split_sizes(&new_constraints);
|
||||
for (subgeoms, subsplit_size) in new_geoms.iter().zip(new_split_sizes) {
|
||||
children.push(get_tiled_panes_layout_from_panegeoms(
|
||||
&subgeoms,
|
||||
subsplit_size,
|
||||
));
|
||||
match get_tiled_panes_layout_from_panegeoms(&subgeoms, subsplit_size) {
|
||||
Some(child) => {
|
||||
children.push(child);
|
||||
},
|
||||
None => {
|
||||
return None;
|
||||
},
|
||||
}
|
||||
}
|
||||
let children_are_stacked = children_split_direction == SplitDirection::Horizontal
|
||||
&& new_geoms
|
||||
.iter()
|
||||
.all(|c| c.iter().all(|c| c.geom.is_stacked));
|
||||
TiledPaneLayout {
|
||||
Some(TiledPaneLayout {
|
||||
children_split_direction,
|
||||
split_size,
|
||||
children,
|
||||
children_are_stacked,
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn get_floating_panes_layout_from_panegeoms(
|
||||
@ -789,7 +818,7 @@ fn get_domain_constraint(
|
||||
geoms: &Vec<PaneLayoutManifest>,
|
||||
split_direction: &SplitDirection,
|
||||
(v_min, v_max): (usize, usize),
|
||||
) -> Constraint {
|
||||
) -> Option<Constraint> {
|
||||
match split_direction {
|
||||
SplitDirection::Horizontal => get_domain_row_constraint(&geoms, (v_min, v_max)),
|
||||
SplitDirection::Vertical => get_domain_col_constraint(&geoms, (v_min, v_max)),
|
||||
@ -800,21 +829,28 @@ fn get_domain_constraint(
|
||||
fn get_domain_col_constraint(
|
||||
geoms: &Vec<PaneLayoutManifest>,
|
||||
(x_min, x_max): (usize, usize),
|
||||
) -> Constraint {
|
||||
) -> Option<Constraint> {
|
||||
let mut percent = 0.0;
|
||||
let mut x = x_min;
|
||||
while x != x_max {
|
||||
// we only look at one (ie the last) geom that has value `x` for `g.x`
|
||||
let geom = geoms.iter().filter(|g| g.geom.x == x).last().unwrap();
|
||||
if let Some(size) = geom.geom.cols.as_percent() {
|
||||
percent += size;
|
||||
let geom = geoms.iter().filter(|g| g.geom.x == x).last();
|
||||
match geom {
|
||||
Some(geom) => {
|
||||
if let Some(size) = geom.geom.cols.as_percent() {
|
||||
percent += size;
|
||||
}
|
||||
x += geom.geom.cols.as_usize();
|
||||
},
|
||||
None => {
|
||||
return None;
|
||||
},
|
||||
}
|
||||
x += geom.geom.cols.as_usize();
|
||||
}
|
||||
if percent == 0.0 {
|
||||
Constraint::Fixed(x_max - x_min)
|
||||
Some(Constraint::Fixed(x_max - x_min))
|
||||
} else {
|
||||
Constraint::Percent(percent)
|
||||
Some(Constraint::Percent(percent))
|
||||
}
|
||||
}
|
||||
|
||||
@ -822,21 +858,28 @@ fn get_domain_col_constraint(
|
||||
fn get_domain_row_constraint(
|
||||
geoms: &Vec<PaneLayoutManifest>,
|
||||
(y_min, y_max): (usize, usize),
|
||||
) -> Constraint {
|
||||
) -> Option<Constraint> {
|
||||
let mut percent = 0.0;
|
||||
let mut y = y_min;
|
||||
while y != y_max {
|
||||
// we only look at one (ie the last) geom that has value `y` for `g.y`
|
||||
let geom = geoms.iter().filter(|g| g.geom.y == y).last().unwrap();
|
||||
if let Some(size) = geom.geom.rows.as_percent() {
|
||||
percent += size;
|
||||
let geom = geoms.iter().filter(|g| g.geom.y == y).last();
|
||||
match geom {
|
||||
Some(geom) => {
|
||||
if let Some(size) = geom.geom.rows.as_percent() {
|
||||
percent += size;
|
||||
}
|
||||
y += geom.geom.rows.as_usize();
|
||||
},
|
||||
None => {
|
||||
return None;
|
||||
},
|
||||
}
|
||||
y += geom.geom.rows.as_usize();
|
||||
}
|
||||
if percent == 0.0 {
|
||||
Constraint::Fixed(y_max - y_min)
|
||||
Some(Constraint::Fixed(y_max - y_min))
|
||||
} else {
|
||||
Constraint::Percent(percent)
|
||||
Some(Constraint::Percent(percent))
|
||||
}
|
||||
}
|
||||
|
||||
@ -932,7 +975,7 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
// let kdl = kdl_string_from_panegeoms(&geoms);
|
||||
let kdl = serialize_session_layout(global_layout_manifest);
|
||||
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||
expect![[r#"layout {
|
||||
tab name="Tab #1" {
|
||||
pane size=1
|
||||
@ -958,7 +1001,7 @@ mod tests {
|
||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||
..Default::default()
|
||||
};
|
||||
let kdl = serialize_session_layout(global_layout_manifest);
|
||||
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||
expect![[r#"layout {
|
||||
tab name="Tab #1" {
|
||||
pane
|
||||
@ -986,7 +1029,7 @@ mod tests {
|
||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||
..Default::default()
|
||||
};
|
||||
let kdl = serialize_session_layout(global_layout_manifest);
|
||||
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||
expect![[r#"layout {
|
||||
tab name="Tab #1" {
|
||||
pane size=10 split_direction="vertical" {
|
||||
@ -1022,7 +1065,7 @@ mod tests {
|
||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||
..Default::default()
|
||||
};
|
||||
let kdl = serialize_session_layout(global_layout_manifest);
|
||||
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||
expect![[r#"layout {
|
||||
tab name="Tab #1" {
|
||||
pane split_direction="vertical" {
|
||||
@ -1059,7 +1102,7 @@ mod tests {
|
||||
tabs: vec![("Tab #1".to_owned(), tab_layout_manifest)],
|
||||
..Default::default()
|
||||
};
|
||||
let kdl = serialize_session_layout(global_layout_manifest);
|
||||
let kdl = serialize_session_layout(global_layout_manifest).unwrap();
|
||||
expect![[r#"layout {
|
||||
tab name="Tab #1" {
|
||||
pane size=5
|
||||
|
Loading…
Reference in New Issue
Block a user