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:
parent
60322e969f
commit
417b4a4ec5
7 changed files with 193 additions and 124 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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(¤t_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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue