errors: Don't unwrap in zellij_server::output (#1878)

* server/output: Don't unwrap

and return `Result` types where appropriate instead.

* server: Handle new `Result`s from `output`

* server/tab/unit: Unwrap new `Result`s

* changelog: Add PR #1878

Don't unwrap in `zellij_server::output`.
This commit is contained in:
har7an 2022-10-30 06:02:03 +00:00 committed by GitHub
parent 60322e969f
commit 417b4a4ec5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 193 additions and 124 deletions

View file

@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* debugging: Remove calls to unwrap in `zellij_server::pty_writer` (https://github.com/zellij-org/zellij/pull/1872)
* docs(example): update the format of the themes for the example directory (https://github.com/zellij-org/zellij/pull/1877)
* debugging: Remove calls to unwrap in `zellij_server::terminal_bytes` (https://github.com/zellij-org/zellij/pull/1876)
* debugging: Remove calls to unwrap in `zellij_server::output` (https://github.com/zellij-org/zellij/pull/1878)
## [0.32.0] - 2022-10-25

View file

@ -16,17 +16,23 @@ use std::{
collections::{HashMap, HashSet},
str,
};
use zellij_utils::errors::prelude::*;
use zellij_utils::pane_size::PaneGeom;
use zellij_utils::pane_size::SizeInPixels;
fn vte_goto_instruction(x_coords: usize, y_coords: usize, vte_output: &mut String) {
fn vte_goto_instruction(x_coords: usize, y_coords: usize, vte_output: &mut String) -> Result<()> {
write!(
vte_output,
"\u{1b}[{};{}H\u{1b}[m",
y_coords + 1, // + 1 because VTE is 1 indexed
x_coords + 1,
)
.unwrap();
.with_context(|| {
format!(
"failed to execute VTE instruction to go to ({}, {})",
x_coords, y_coords
)
})
}
fn adjust_styles_for_possible_selection(
@ -56,18 +62,21 @@ fn write_changed_styles(
chunk_changed_colors: Option<[Option<AnsiCode>; 256]>,
link_handler: Option<&std::cell::Ref<LinkHandler>>,
vte_output: &mut String,
) {
) -> Result<()> {
let err_context = "failed to format changed styles to VTE string";
if let Some(new_styles) =
character_styles.update_and_return_diff(&current_character_styles, chunk_changed_colors)
{
if let Some(osc8_link) =
link_handler.and_then(|l_h| l_h.output_osc8(new_styles.link_anchor))
{
write!(vte_output, "{}{}", new_styles, osc8_link).unwrap();
write!(vte_output, "{}{}", new_styles, osc8_link).context(err_context)?;
} else {
write!(vte_output, "{}", new_styles).unwrap();
write!(vte_output, "{}", new_styles).context(err_context)?;
}
}
Ok(())
}
fn serialize_chunks(
@ -75,14 +84,17 @@ fn serialize_chunks(
sixel_chunks: Option<&Vec<SixelImageChunk>>,
link_handler: Option<&mut Rc<RefCell<LinkHandler>>>,
sixel_image_store: &mut SixelImageStore,
) -> String {
) -> Result<String> {
let err_context = || "failed to serialize input chunks".to_string();
let mut vte_output = String::new();
let mut sixel_vte: Option<String> = None;
let link_handler = link_handler.map(|l_h| l_h.borrow());
for character_chunk in character_chunks {
let chunk_changed_colors = character_chunk.changed_colors();
let mut character_styles = CharacterStyles::new();
vte_goto_instruction(character_chunk.x, character_chunk.y, &mut vte_output);
vte_goto_instruction(character_chunk.x, character_chunk.y, &mut vte_output)
.with_context(err_context)?;
let mut chunk_width = character_chunk.x;
for t_character in character_chunk.terminal_characters.iter() {
let current_character_styles = adjust_styles_for_possible_selection(
@ -97,7 +109,8 @@ fn serialize_chunks(
chunk_changed_colors,
link_handler.as_ref(),
&mut vte_output,
);
)
.with_context(err_context)?;
chunk_width += t_character.width;
vte_output.push(t_character.character);
}
@ -114,7 +127,8 @@ fn serialize_chunks(
);
if let Some(serialized_sixel_image) = serialized_sixel_image {
let sixel_vte = sixel_vte.get_or_insert_with(String::new);
vte_goto_instruction(sixel_chunk.cell_x, sixel_chunk.cell_y, sixel_vte);
vte_goto_instruction(sixel_chunk.cell_x, sixel_chunk.cell_y, sixel_vte)
.with_context(err_context)?;
sixel_vte.push_str(&serialized_sixel_image);
}
}
@ -129,7 +143,7 @@ fn serialize_chunks(
vte_output.push_str(sixel_vte);
vte_output.push_str(restore_cursor_position);
}
vte_output
Ok(vte_output)
}
type AbsoluteMiddleStart = usize;
@ -140,12 +154,19 @@ fn adjust_middle_segment_for_wide_chars(
middle_start: usize,
middle_end: usize,
terminal_characters: &[TerminalCharacter],
) -> (
) -> Result<(
AbsoluteMiddleStart,
AbsoluteMiddleEnd,
PadLeftEndBy,
PadRightStartBy,
) {
)> {
let err_context = || {
format!(
"failed to adjust middle segment (from {} to {}) for wide chars: '{:?}'",
middle_start, middle_end, terminal_characters
)
};
let mut absolute_middle_start_index = None;
let mut absolute_middle_end_index = None;
let mut current_x = 0;
@ -168,12 +189,12 @@ fn adjust_middle_segment_for_wide_chars(
}
}
}
(
absolute_middle_start_index.unwrap(),
absolute_middle_end_index.unwrap(),
Ok((
absolute_middle_start_index.with_context(err_context)?,
absolute_middle_end_index.with_context(err_context)?,
pad_left_end_by,
pad_right_start_by,
)
))
}
#[derive(Clone, Debug, Default)]
@ -216,27 +237,33 @@ impl Output {
client_id: ClientId,
mut character_chunks: Vec<CharacterChunk>,
z_index: Option<usize>,
) {
) -> Result<()> {
if let Some(client_character_chunks) = self.client_character_chunks.get_mut(&client_id) {
if let Some(floating_panes_stack) = &self.floating_panes_stack {
let mut visible_character_chunks =
floating_panes_stack.visible_character_chunks(character_chunks, z_index);
let mut visible_character_chunks = floating_panes_stack
.visible_character_chunks(character_chunks, z_index)
.with_context(|| {
format!("failed to add character chunks for client {}", client_id)
})?;
client_character_chunks.append(&mut visible_character_chunks);
} else {
client_character_chunks.append(&mut character_chunks);
}
}
Ok(())
}
pub fn add_character_chunks_to_multiple_clients(
&mut self,
character_chunks: Vec<CharacterChunk>,
client_ids: impl Iterator<Item = ClientId>,
z_index: Option<usize>,
) {
) -> Result<()> {
for client_id in client_ids {
self.add_character_chunks_to_client(client_id, character_chunks.clone(), z_index);
self.add_character_chunks_to_client(client_id, character_chunks.clone(), z_index)
.context("failed to add character chunks for multiple clients")?;
// TODO: forgo clone by adding an all_clients thing?
}
Ok(())
}
pub fn add_post_vte_instruction_to_multiple_clients(
&mut self,
@ -328,7 +355,9 @@ impl Output {
}
}
}
pub fn serialize(&mut self) -> HashMap<ClientId, String> {
pub fn serialize(&mut self) -> Result<HashMap<ClientId, String>> {
let err_context = || "failed to serialize output to clients".to_string();
let mut serialized_render_instructions = HashMap::new();
for (client_id, client_character_chunks) in self.client_character_chunks.drain() {
@ -344,12 +373,15 @@ impl Output {
}
// append the actual vte
client_serialized_render_instructions.push_str(&serialize_chunks(
client_character_chunks,
self.sixel_chunks.get(&client_id),
self.link_handler.as_mut(),
&mut self.sixel_image_store.borrow_mut(),
)); // TODO: less allocations?
client_serialized_render_instructions.push_str(
&serialize_chunks(
client_character_chunks,
self.sixel_chunks.get(&client_id),
self.link_handler.as_mut(),
&mut self.sixel_image_store.borrow_mut(),
)
.with_context(err_context)?,
); // TODO: less allocations?
// append post-vte instructions for this client
if let Some(post_vte_instructions_for_client) =
@ -362,7 +394,7 @@ impl Output {
serialized_render_instructions.insert(client_id, client_serialized_render_instructions);
}
serialized_render_instructions
Ok(serialized_render_instructions)
}
}
@ -380,7 +412,14 @@ impl FloatingPanesStack {
&self,
mut character_chunks: Vec<CharacterChunk>,
z_index: Option<usize>,
) -> Vec<CharacterChunk> {
) -> Result<Vec<CharacterChunk>> {
let err_context = || {
format!(
"failed to determine visible character chunks at z-index {:?}",
z_index
)
};
let z_index = z_index.unwrap_or(0);
let mut chunks_to_check: Vec<CharacterChunk> = character_chunks.drain(..).collect();
let mut visible_chunks = vec![];
@ -389,7 +428,9 @@ impl FloatingPanesStack {
Some(mut c_chunk) => {
let panes_to_check = self.layers.iter().skip(z_index);
for pane_geom in panes_to_check {
let new_chunk_to_check = self.remove_covered_parts(pane_geom, &mut c_chunk);
let new_chunk_to_check = self
.remove_covered_parts(pane_geom, &mut c_chunk)
.with_context(err_context)?;
if let Some(new_chunk_to_check) = new_chunk_to_check {
// this happens when the pane covers the middle of the chunk, and so we
// end up with an extra chunk we need to check (eg. against panes above
@ -407,7 +448,7 @@ impl FloatingPanesStack {
},
}
}
visible_chunks
Ok(visible_chunks)
}
pub fn visible_sixel_image_chunks(
&self,
@ -433,7 +474,14 @@ impl FloatingPanesStack {
&self,
pane_geom: &PaneGeom,
c_chunk: &mut CharacterChunk,
) -> Option<CharacterChunk> {
) -> Result<Option<CharacterChunk>> {
let err_context = || {
format!(
"failed to remove covered parts from floating panes: {:#?}",
self
)
};
let pane_top_edge = pane_geom.y;
let pane_left_edge = pane_geom.x;
let pane_bottom_edge = pane_geom.y + pane_geom.rows.as_usize().saturating_sub(1);
@ -444,7 +492,7 @@ impl FloatingPanesStack {
if pane_left_edge <= c_chunk_left_side && pane_right_edge >= c_chunk_right_side {
// pane covers chunk completely
drop(c_chunk.terminal_characters.drain(..));
return None;
return Ok(None);
} else if pane_right_edge > c_chunk_left_side
&& pane_right_edge < c_chunk_right_side
&& pane_left_edge <= c_chunk_left_side
@ -453,30 +501,32 @@ impl FloatingPanesStack {
let covered_part = c_chunk.drain_by_width(pane_right_edge + 1 - c_chunk_left_side);
drop(covered_part);
c_chunk.x = pane_right_edge + 1;
return None;
return Ok(None);
} else if pane_left_edge > c_chunk_left_side
&& pane_left_edge < c_chunk_right_side
&& pane_right_edge >= c_chunk_right_side
{
// pane covers chunk partially to the right
c_chunk.retain_by_width(pane_left_edge - c_chunk_left_side);
return None;
return Ok(None);
} else if pane_left_edge >= c_chunk_left_side && pane_right_edge <= c_chunk_right_side {
// pane covers chunk middle
let (left_chunk_characters, right_chunk_characters) = c_chunk.cut_middle_out(
pane_left_edge - c_chunk_left_side,
(pane_right_edge + 1) - c_chunk_left_side,
);
let (left_chunk_characters, right_chunk_characters) = c_chunk
.cut_middle_out(
pane_left_edge - c_chunk_left_side,
(pane_right_edge + 1) - c_chunk_left_side,
)
.with_context(err_context)?;
let left_chunk_x = c_chunk_left_side;
let right_chunk_x = pane_right_edge + 1;
let left_chunk =
CharacterChunk::new(left_chunk_characters, left_chunk_x, c_chunk.y);
c_chunk.x = right_chunk_x;
c_chunk.terminal_characters = right_chunk_characters;
return Some(left_chunk);
return Ok(Some(left_chunk));
}
};
None
Ok(None)
}
fn remove_covered_sixel_parts(
&self,
@ -732,7 +782,9 @@ impl CharacterChunk {
&mut self,
middle_start: usize,
middle_end: usize,
) -> (Vec<TerminalCharacter>, Vec<TerminalCharacter>) {
) -> Result<(Vec<TerminalCharacter>, Vec<TerminalCharacter>)> {
let err_context = || "failed to cut middle out of character chunk".to_string();
let (
absolute_middle_start_index,
absolute_middle_end_index,
@ -742,7 +794,8 @@ impl CharacterChunk {
middle_start,
middle_end,
&self.terminal_characters,
);
)
.with_context(err_context)?;
let mut terminal_characters: Vec<TerminalCharacter> =
self.terminal_characters.drain(..).collect();
let mut characters_on_the_right: Vec<TerminalCharacter> = terminal_characters
@ -759,7 +812,7 @@ impl CharacterChunk {
characters_on_the_right.insert(0, EMPTY_TERMINAL_CHARACTER);
}
}
(characters_on_the_left, characters_on_the_right)
Ok((characters_on_the_left, characters_on_the_right))
}
}

View file

@ -381,6 +381,7 @@ impl TiledPanes {
}
pub fn render(&mut self, output: &mut Output, floating_panes_are_visible: bool) -> Result<()> {
let err_context = || "failed to render tiled panes";
let connected_clients: Vec<ClientId> =
{ self.connected_clients.borrow().iter().copied().collect() };
let multiple_users_exist_in_session = { self.connected_clients_in_app.borrow().len() > 1 };
@ -450,11 +451,13 @@ impl TiledPanes {
// render boundaries if needed
for (client_id, boundaries) in &mut client_id_to_boundaries {
// TODO: add some conditional rendering here so this isn't rendered for every character
output.add_character_chunks_to_client(
*client_id,
boundaries.render().with_context(err_context)?,
None,
);
output
.add_character_chunks_to_client(
*client_id,
boundaries.render().with_context(err_context)?,
None,
)
.with_context(err_context)?;
}
Ok(())
}

View file

@ -746,7 +746,7 @@ impl Screen {
for tab_index in tabs_to_close {
self.close_tab_at_index(tab_index).context(err_context)?;
}
let serialized_output = output.serialize();
let serialized_output = output.serialize().context(err_context)?;
self.bus
.senders
.send_to_server(ServerInstruction::Render(Some(serialized_output)))

View file

@ -2471,6 +2471,8 @@ impl Tab {
}
fn write_selection_to_clipboard(&self, selection: &str) -> Result<()> {
let err_context = || format!("failed to write selection to clipboard: '{}'", selection);
let mut output = Output::default();
let connected_clients: HashSet<ClientId> =
{ self.connected_clients.borrow().iter().copied().collect() };
@ -2481,15 +2483,20 @@ impl Tab {
.clipboard_provider
.set_content(selection, &mut output, client_ids)
{
Ok(_) => {
let serialized_output = output.serialize();
self.senders
.send_to_server(ServerInstruction::Render(Some(serialized_output)))
.context("failed to write selection to clipboard")?;
Event::CopyToClipboard(self.clipboard_provider.as_copy_destination())
},
Ok(_) => output
.serialize()
.and_then(|serialized_output| {
self.senders
.send_to_server(ServerInstruction::Render(Some(serialized_output)))
})
.and_then(|_| {
Ok(Event::CopyToClipboard(
self.clipboard_provider.as_copy_destination(),
))
})
.with_context(err_context)?,
Err(err) => {
log::error!("could not write selection to clipboard: {}", err);
Err::<(), _>(err).with_context(err_context).non_fatal();
Event::SystemClipboardFailure
},
};

View file

@ -535,7 +535,7 @@ fn new_floating_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -567,7 +567,7 @@ fn floating_panes_persist_across_toggles() {
tab.toggle_floating_panes(client_id, None).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -596,7 +596,7 @@ fn toggle_floating_panes_off() {
tab.toggle_floating_panes(client_id, None).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -626,7 +626,7 @@ fn toggle_floating_panes_on() {
tab.toggle_floating_panes(client_id, None).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -674,7 +674,7 @@ fn five_new_floating_panes() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -703,7 +703,7 @@ fn increase_floating_pane_size() {
tab.resize_increase(client_id);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -732,7 +732,7 @@ fn decrease_floating_pane_size() {
tab.resize_decrease(client_id);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -761,7 +761,7 @@ fn resize_floating_pane_left() {
tab.resize_left(client_id);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -790,7 +790,7 @@ fn resize_floating_pane_right() {
tab.resize_right(client_id);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -819,7 +819,7 @@ fn resize_floating_pane_up() {
tab.resize_up(client_id);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -848,7 +848,7 @@ fn resize_floating_pane_down() {
tab.resize_down(client_id);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -897,7 +897,7 @@ fn move_floating_pane_focus_left() {
tab.move_focus_left(client_id);
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -953,7 +953,7 @@ fn move_floating_pane_focus_right() {
tab.move_focus_right(client_id);
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1008,7 +1008,7 @@ fn move_floating_pane_focus_up() {
tab.move_focus_up(client_id);
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1064,7 +1064,7 @@ fn move_floating_pane_focus_down() {
tab.move_focus_down(client_id);
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1122,7 +1122,7 @@ fn move_floating_pane_focus_with_mouse() {
.unwrap();
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1180,7 +1180,7 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1238,7 +1238,7 @@ fn drag_pane_with_mouse() {
.unwrap();
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1304,7 +1304,7 @@ fn mark_text_inside_floating_pane() {
);
tab.render(&mut output, None).unwrap();
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1362,7 +1362,7 @@ fn resize_tab_with_floating_panes() {
});
tab.render(&mut output, None).unwrap();
let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1412,7 +1412,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() {
tab.resize_whole_tab(Size { cols: 50, rows: 10 });
tab.render(&mut output, None).unwrap();
let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1466,7 +1466,7 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b
});
tab.render(&mut output, None).unwrap();
let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1496,7 +1496,7 @@ fn embed_floating_pane() {
tab.toggle_pane_embed_or_floating(client_id).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1524,7 +1524,7 @@ fn float_embedded_pane() {
tab.toggle_pane_embed_or_floating(client_id).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1549,7 +1549,7 @@ fn cannot_float_only_embedded_pane() {
tab.toggle_pane_embed_or_floating(client_id).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1573,7 +1573,7 @@ fn replacing_existing_wide_characters() {
tab.handle_pty_bytes(1, pane_content).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1599,7 +1599,7 @@ fn rename_embedded_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1629,7 +1629,7 @@ fn rename_floating_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1651,7 +1651,7 @@ fn wide_characters_in_left_title_side() {
tab.handle_pty_bytes(1, pane_content).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1678,7 +1678,7 @@ fn save_cursor_position_across_resizes() {
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1714,7 +1714,7 @@ fn move_floating_pane_with_sixel_image() {
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot_with_sixel(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1752,7 +1752,7 @@ fn floating_pane_above_sixel_image() {
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot_with_sixel(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1777,7 +1777,7 @@ fn suppress_tiled_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1805,7 +1805,7 @@ fn suppress_floating_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1831,7 +1831,7 @@ fn close_suppressing_tiled_pane() {
tab.close_pane(new_pane_id, false);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1862,7 +1862,7 @@ fn close_suppressing_floating_pane() {
tab.close_pane(editor_pane_id, false);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1889,7 +1889,7 @@ fn suppress_tiled_pane_float_it_and_close() {
tab.close_pane(new_pane_id, false);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1921,7 +1921,7 @@ fn suppress_floating_pane_embed_it_and_close_it() {
tab.close_pane(editor_pane_id, false);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1948,7 +1948,7 @@ fn resize_whole_tab_while_tiled_pane_is_suppressed() {
});
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -1980,7 +1980,7 @@ fn resize_whole_tab_while_floting_pane_is_suppressed() {
});
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2005,7 +2005,7 @@ fn enter_search_pane() {
tab.handle_pty_bytes(1, pane_content).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2019,7 +2019,7 @@ fn enter_search_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2032,7 +2032,7 @@ fn enter_search_pane() {
tab.toggle_search_case_sensitivity(client_id);
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2046,7 +2046,7 @@ fn enter_search_pane() {
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2076,7 +2076,7 @@ fn enter_search_floating_pane() {
tab.handle_pty_bytes(2, pane_content).unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2088,7 +2088,7 @@ fn enter_search_floating_pane() {
.unwrap();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2366,7 +2366,7 @@ fn tab_with_basic_layout() {
let mut output = Output::default();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2406,7 +2406,7 @@ fn tab_with_nested_layout() {
let mut output = Output::default();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),
@ -2440,7 +2440,7 @@ fn tab_with_nested_uneven_layout() {
let mut output = Output::default();
tab.render(&mut output, None).unwrap();
let snapshot = take_snapshot(
output.serialize().get(&client_id).unwrap(),
output.serialize().unwrap().get(&client_id).unwrap(),
size.rows,
size.cols,
Palette::default(),

View file

@ -46,17 +46,19 @@ impl<'a> PaneContentsAndUi<'a> {
&mut self,
clients: impl Iterator<Item = ClientId>,
) -> Result<()> {
if let Some((character_chunks, raw_vte_output, sixel_image_chunks)) = self
.pane
.render(None)
.context("failed to render pane contents to multiple clients")?
let err_context = "failed to render pane contents to multiple clients";
if let Some((character_chunks, raw_vte_output, sixel_image_chunks)) =
self.pane.render(None).context(err_context)?
{
let clients: Vec<ClientId> = clients.collect();
self.output.add_character_chunks_to_multiple_clients(
character_chunks,
clients.iter().copied(),
self.z_index,
);
self.output
.add_character_chunks_to_multiple_clients(
character_chunks,
clients.iter().copied(),
self.z_index,
)
.context(err_context)?;
self.output.add_sixel_image_chunks_to_multiple_clients(
sixel_image_chunks,
clients.iter().copied(),
@ -77,13 +79,16 @@ impl<'a> PaneContentsAndUi<'a> {
Ok(())
}
pub fn render_pane_contents_for_client(&mut self, client_id: ClientId) -> Result<()> {
let err_context = || format!("failed to render pane contents for client {client_id}");
if let Some((character_chunks, raw_vte_output, sixel_image_chunks)) = self
.pane
.render(Some(client_id))
.with_context(|| format!("failed to render pane contents for client {client_id}"))?
.with_context(err_context)?
{
self.output
.add_character_chunks_to_client(client_id, character_chunks, self.z_index);
.add_character_chunks_to_client(client_id, character_chunks, self.z_index)
.with_context(err_context)?;
self.output.add_sixel_image_chunks_to_client(
client_id,
sixel_image_chunks,
@ -150,6 +155,7 @@ impl<'a> PaneContentsAndUi<'a> {
session_is_mirrored: bool,
) -> Result<()> {
let err_context = || format!("failed to render pane frame for client {client_id}");
let pane_focused_for_client_id = self.focused_clients.contains(&client_id);
let other_focused_clients: Vec<ClientId> = self
.focused_clients
@ -186,16 +192,15 @@ impl<'a> PaneContentsAndUi<'a> {
other_cursors_exist_in_session: self.multiple_users_exist_in_session,
}
};
if let Some((frame_terminal_characters, vte_output)) = self
.pane
.render_frame(client_id, frame_params, client_mode)
.with_context(err_context)?
{
self.output.add_character_chunks_to_client(
client_id,
frame_terminal_characters,
self.z_index,
);
self.output
.add_character_chunks_to_client(client_id, frame_terminal_characters, self.z_index)
.with_context(err_context)?;
if let Some(vte_output) = vte_output {
self.output
.add_post_vte_instruction_to_client(client_id, &vte_output);