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)
|
* 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)
|
* 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::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
|
## [0.32.0] - 2022-10-25
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,17 +16,23 @@ use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
|
use zellij_utils::errors::prelude::*;
|
||||||
use zellij_utils::pane_size::PaneGeom;
|
use zellij_utils::pane_size::PaneGeom;
|
||||||
use zellij_utils::pane_size::SizeInPixels;
|
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!(
|
write!(
|
||||||
vte_output,
|
vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m",
|
"\u{1b}[{};{}H\u{1b}[m",
|
||||||
y_coords + 1, // + 1 because VTE is 1 indexed
|
y_coords + 1, // + 1 because VTE is 1 indexed
|
||||||
x_coords + 1,
|
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(
|
fn adjust_styles_for_possible_selection(
|
||||||
|
|
@ -56,18 +62,21 @@ fn write_changed_styles(
|
||||||
chunk_changed_colors: Option<[Option<AnsiCode>; 256]>,
|
chunk_changed_colors: Option<[Option<AnsiCode>; 256]>,
|
||||||
link_handler: Option<&std::cell::Ref<LinkHandler>>,
|
link_handler: Option<&std::cell::Ref<LinkHandler>>,
|
||||||
vte_output: &mut String,
|
vte_output: &mut String,
|
||||||
) {
|
) -> Result<()> {
|
||||||
|
let err_context = "failed to format changed styles to VTE string";
|
||||||
|
|
||||||
if let Some(new_styles) =
|
if let Some(new_styles) =
|
||||||
character_styles.update_and_return_diff(¤t_character_styles, chunk_changed_colors)
|
character_styles.update_and_return_diff(¤t_character_styles, chunk_changed_colors)
|
||||||
{
|
{
|
||||||
if let Some(osc8_link) =
|
if let Some(osc8_link) =
|
||||||
link_handler.and_then(|l_h| l_h.output_osc8(new_styles.link_anchor))
|
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 {
|
} else {
|
||||||
write!(vte_output, "{}", new_styles).unwrap();
|
write!(vte_output, "{}", new_styles).context(err_context)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_chunks(
|
fn serialize_chunks(
|
||||||
|
|
@ -75,14 +84,17 @@ fn serialize_chunks(
|
||||||
sixel_chunks: Option<&Vec<SixelImageChunk>>,
|
sixel_chunks: Option<&Vec<SixelImageChunk>>,
|
||||||
link_handler: Option<&mut Rc<RefCell<LinkHandler>>>,
|
link_handler: Option<&mut Rc<RefCell<LinkHandler>>>,
|
||||||
sixel_image_store: &mut SixelImageStore,
|
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 vte_output = String::new();
|
||||||
let mut sixel_vte: Option<String> = None;
|
let mut sixel_vte: Option<String> = None;
|
||||||
let link_handler = link_handler.map(|l_h| l_h.borrow());
|
let link_handler = link_handler.map(|l_h| l_h.borrow());
|
||||||
for character_chunk in character_chunks {
|
for character_chunk in character_chunks {
|
||||||
let chunk_changed_colors = character_chunk.changed_colors();
|
let chunk_changed_colors = character_chunk.changed_colors();
|
||||||
let mut character_styles = CharacterStyles::new();
|
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;
|
let mut chunk_width = character_chunk.x;
|
||||||
for t_character in character_chunk.terminal_characters.iter() {
|
for t_character in character_chunk.terminal_characters.iter() {
|
||||||
let current_character_styles = adjust_styles_for_possible_selection(
|
let current_character_styles = adjust_styles_for_possible_selection(
|
||||||
|
|
@ -97,7 +109,8 @@ fn serialize_chunks(
|
||||||
chunk_changed_colors,
|
chunk_changed_colors,
|
||||||
link_handler.as_ref(),
|
link_handler.as_ref(),
|
||||||
&mut vte_output,
|
&mut vte_output,
|
||||||
);
|
)
|
||||||
|
.with_context(err_context)?;
|
||||||
chunk_width += t_character.width;
|
chunk_width += t_character.width;
|
||||||
vte_output.push(t_character.character);
|
vte_output.push(t_character.character);
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +127,8 @@ fn serialize_chunks(
|
||||||
);
|
);
|
||||||
if let Some(serialized_sixel_image) = serialized_sixel_image {
|
if let Some(serialized_sixel_image) = serialized_sixel_image {
|
||||||
let sixel_vte = sixel_vte.get_or_insert_with(String::new);
|
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);
|
sixel_vte.push_str(&serialized_sixel_image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +143,7 @@ fn serialize_chunks(
|
||||||
vte_output.push_str(sixel_vte);
|
vte_output.push_str(sixel_vte);
|
||||||
vte_output.push_str(restore_cursor_position);
|
vte_output.push_str(restore_cursor_position);
|
||||||
}
|
}
|
||||||
vte_output
|
Ok(vte_output)
|
||||||
}
|
}
|
||||||
|
|
||||||
type AbsoluteMiddleStart = usize;
|
type AbsoluteMiddleStart = usize;
|
||||||
|
|
@ -140,12 +154,19 @@ fn adjust_middle_segment_for_wide_chars(
|
||||||
middle_start: usize,
|
middle_start: usize,
|
||||||
middle_end: usize,
|
middle_end: usize,
|
||||||
terminal_characters: &[TerminalCharacter],
|
terminal_characters: &[TerminalCharacter],
|
||||||
) -> (
|
) -> Result<(
|
||||||
AbsoluteMiddleStart,
|
AbsoluteMiddleStart,
|
||||||
AbsoluteMiddleEnd,
|
AbsoluteMiddleEnd,
|
||||||
PadLeftEndBy,
|
PadLeftEndBy,
|
||||||
PadRightStartBy,
|
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_start_index = None;
|
||||||
let mut absolute_middle_end_index = None;
|
let mut absolute_middle_end_index = None;
|
||||||
let mut current_x = 0;
|
let mut current_x = 0;
|
||||||
|
|
@ -168,12 +189,12 @@ fn adjust_middle_segment_for_wide_chars(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
Ok((
|
||||||
absolute_middle_start_index.unwrap(),
|
absolute_middle_start_index.with_context(err_context)?,
|
||||||
absolute_middle_end_index.unwrap(),
|
absolute_middle_end_index.with_context(err_context)?,
|
||||||
pad_left_end_by,
|
pad_left_end_by,
|
||||||
pad_right_start_by,
|
pad_right_start_by,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
|
|
@ -216,27 +237,33 @@ impl Output {
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
mut character_chunks: Vec<CharacterChunk>,
|
mut character_chunks: Vec<CharacterChunk>,
|
||||||
z_index: Option<usize>,
|
z_index: Option<usize>,
|
||||||
) {
|
) -> Result<()> {
|
||||||
if let Some(client_character_chunks) = self.client_character_chunks.get_mut(&client_id) {
|
if let Some(client_character_chunks) = self.client_character_chunks.get_mut(&client_id) {
|
||||||
if let Some(floating_panes_stack) = &self.floating_panes_stack {
|
if let Some(floating_panes_stack) = &self.floating_panes_stack {
|
||||||
let mut visible_character_chunks =
|
let mut visible_character_chunks = floating_panes_stack
|
||||||
floating_panes_stack.visible_character_chunks(character_chunks, z_index);
|
.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);
|
client_character_chunks.append(&mut visible_character_chunks);
|
||||||
} else {
|
} else {
|
||||||
client_character_chunks.append(&mut character_chunks);
|
client_character_chunks.append(&mut character_chunks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn add_character_chunks_to_multiple_clients(
|
pub fn add_character_chunks_to_multiple_clients(
|
||||||
&mut self,
|
&mut self,
|
||||||
character_chunks: Vec<CharacterChunk>,
|
character_chunks: Vec<CharacterChunk>,
|
||||||
client_ids: impl Iterator<Item = ClientId>,
|
client_ids: impl Iterator<Item = ClientId>,
|
||||||
z_index: Option<usize>,
|
z_index: Option<usize>,
|
||||||
) {
|
) -> Result<()> {
|
||||||
for client_id in client_ids {
|
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?
|
// TODO: forgo clone by adding an all_clients thing?
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn add_post_vte_instruction_to_multiple_clients(
|
pub fn add_post_vte_instruction_to_multiple_clients(
|
||||||
&mut self,
|
&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();
|
let mut serialized_render_instructions = HashMap::new();
|
||||||
|
|
||||||
for (client_id, client_character_chunks) in self.client_character_chunks.drain() {
|
for (client_id, client_character_chunks) in self.client_character_chunks.drain() {
|
||||||
|
|
@ -344,12 +373,15 @@ impl Output {
|
||||||
}
|
}
|
||||||
|
|
||||||
// append the actual vte
|
// append the actual vte
|
||||||
client_serialized_render_instructions.push_str(&serialize_chunks(
|
client_serialized_render_instructions.push_str(
|
||||||
client_character_chunks,
|
&serialize_chunks(
|
||||||
self.sixel_chunks.get(&client_id),
|
client_character_chunks,
|
||||||
self.link_handler.as_mut(),
|
self.sixel_chunks.get(&client_id),
|
||||||
&mut self.sixel_image_store.borrow_mut(),
|
self.link_handler.as_mut(),
|
||||||
)); // TODO: less allocations?
|
&mut self.sixel_image_store.borrow_mut(),
|
||||||
|
)
|
||||||
|
.with_context(err_context)?,
|
||||||
|
); // TODO: less allocations?
|
||||||
|
|
||||||
// append post-vte instructions for this client
|
// append post-vte instructions for this client
|
||||||
if let Some(post_vte_instructions_for_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.insert(client_id, client_serialized_render_instructions);
|
||||||
}
|
}
|
||||||
serialized_render_instructions
|
Ok(serialized_render_instructions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,7 +412,14 @@ impl FloatingPanesStack {
|
||||||
&self,
|
&self,
|
||||||
mut character_chunks: Vec<CharacterChunk>,
|
mut character_chunks: Vec<CharacterChunk>,
|
||||||
z_index: Option<usize>,
|
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 z_index = z_index.unwrap_or(0);
|
||||||
let mut chunks_to_check: Vec<CharacterChunk> = character_chunks.drain(..).collect();
|
let mut chunks_to_check: Vec<CharacterChunk> = character_chunks.drain(..).collect();
|
||||||
let mut visible_chunks = vec![];
|
let mut visible_chunks = vec![];
|
||||||
|
|
@ -389,7 +428,9 @@ impl FloatingPanesStack {
|
||||||
Some(mut c_chunk) => {
|
Some(mut c_chunk) => {
|
||||||
let panes_to_check = self.layers.iter().skip(z_index);
|
let panes_to_check = self.layers.iter().skip(z_index);
|
||||||
for pane_geom in panes_to_check {
|
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 {
|
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
|
// 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
|
// 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(
|
pub fn visible_sixel_image_chunks(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -433,7 +474,14 @@ impl FloatingPanesStack {
|
||||||
&self,
|
&self,
|
||||||
pane_geom: &PaneGeom,
|
pane_geom: &PaneGeom,
|
||||||
c_chunk: &mut CharacterChunk,
|
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_top_edge = pane_geom.y;
|
||||||
let pane_left_edge = pane_geom.x;
|
let pane_left_edge = pane_geom.x;
|
||||||
let pane_bottom_edge = pane_geom.y + pane_geom.rows.as_usize().saturating_sub(1);
|
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 {
|
if pane_left_edge <= c_chunk_left_side && pane_right_edge >= c_chunk_right_side {
|
||||||
// pane covers chunk completely
|
// pane covers chunk completely
|
||||||
drop(c_chunk.terminal_characters.drain(..));
|
drop(c_chunk.terminal_characters.drain(..));
|
||||||
return None;
|
return Ok(None);
|
||||||
} else if pane_right_edge > c_chunk_left_side
|
} else if pane_right_edge > c_chunk_left_side
|
||||||
&& pane_right_edge < c_chunk_right_side
|
&& pane_right_edge < c_chunk_right_side
|
||||||
&& pane_left_edge <= c_chunk_left_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);
|
let covered_part = c_chunk.drain_by_width(pane_right_edge + 1 - c_chunk_left_side);
|
||||||
drop(covered_part);
|
drop(covered_part);
|
||||||
c_chunk.x = pane_right_edge + 1;
|
c_chunk.x = pane_right_edge + 1;
|
||||||
return None;
|
return Ok(None);
|
||||||
} else if pane_left_edge > c_chunk_left_side
|
} else if pane_left_edge > c_chunk_left_side
|
||||||
&& pane_left_edge < c_chunk_right_side
|
&& pane_left_edge < c_chunk_right_side
|
||||||
&& pane_right_edge >= c_chunk_right_side
|
&& pane_right_edge >= c_chunk_right_side
|
||||||
{
|
{
|
||||||
// pane covers chunk partially to the right
|
// pane covers chunk partially to the right
|
||||||
c_chunk.retain_by_width(pane_left_edge - c_chunk_left_side);
|
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 {
|
} else if pane_left_edge >= c_chunk_left_side && pane_right_edge <= c_chunk_right_side {
|
||||||
// pane covers chunk middle
|
// pane covers chunk middle
|
||||||
let (left_chunk_characters, right_chunk_characters) = c_chunk.cut_middle_out(
|
let (left_chunk_characters, right_chunk_characters) = c_chunk
|
||||||
pane_left_edge - c_chunk_left_side,
|
.cut_middle_out(
|
||||||
(pane_right_edge + 1) - c_chunk_left_side,
|
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 left_chunk_x = c_chunk_left_side;
|
||||||
let right_chunk_x = pane_right_edge + 1;
|
let right_chunk_x = pane_right_edge + 1;
|
||||||
let left_chunk =
|
let left_chunk =
|
||||||
CharacterChunk::new(left_chunk_characters, left_chunk_x, c_chunk.y);
|
CharacterChunk::new(left_chunk_characters, left_chunk_x, c_chunk.y);
|
||||||
c_chunk.x = right_chunk_x;
|
c_chunk.x = right_chunk_x;
|
||||||
c_chunk.terminal_characters = right_chunk_characters;
|
c_chunk.terminal_characters = right_chunk_characters;
|
||||||
return Some(left_chunk);
|
return Ok(Some(left_chunk));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
None
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn remove_covered_sixel_parts(
|
fn remove_covered_sixel_parts(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -732,7 +782,9 @@ impl CharacterChunk {
|
||||||
&mut self,
|
&mut self,
|
||||||
middle_start: usize,
|
middle_start: usize,
|
||||||
middle_end: 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 (
|
let (
|
||||||
absolute_middle_start_index,
|
absolute_middle_start_index,
|
||||||
absolute_middle_end_index,
|
absolute_middle_end_index,
|
||||||
|
|
@ -742,7 +794,8 @@ impl CharacterChunk {
|
||||||
middle_start,
|
middle_start,
|
||||||
middle_end,
|
middle_end,
|
||||||
&self.terminal_characters,
|
&self.terminal_characters,
|
||||||
);
|
)
|
||||||
|
.with_context(err_context)?;
|
||||||
let mut terminal_characters: Vec<TerminalCharacter> =
|
let mut terminal_characters: Vec<TerminalCharacter> =
|
||||||
self.terminal_characters.drain(..).collect();
|
self.terminal_characters.drain(..).collect();
|
||||||
let mut characters_on_the_right: Vec<TerminalCharacter> = terminal_characters
|
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_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<()> {
|
pub fn render(&mut self, output: &mut Output, floating_panes_are_visible: bool) -> Result<()> {
|
||||||
let err_context = || "failed to render tiled panes";
|
let err_context = || "failed to render tiled panes";
|
||||||
|
|
||||||
let connected_clients: Vec<ClientId> =
|
let connected_clients: Vec<ClientId> =
|
||||||
{ self.connected_clients.borrow().iter().copied().collect() };
|
{ self.connected_clients.borrow().iter().copied().collect() };
|
||||||
let multiple_users_exist_in_session = { self.connected_clients_in_app.borrow().len() > 1 };
|
let multiple_users_exist_in_session = { self.connected_clients_in_app.borrow().len() > 1 };
|
||||||
|
|
@ -450,11 +451,13 @@ impl TiledPanes {
|
||||||
// render boundaries if needed
|
// render boundaries if needed
|
||||||
for (client_id, boundaries) in &mut client_id_to_boundaries {
|
for (client_id, boundaries) in &mut client_id_to_boundaries {
|
||||||
// TODO: add some conditional rendering here so this isn't rendered for every character
|
// TODO: add some conditional rendering here so this isn't rendered for every character
|
||||||
output.add_character_chunks_to_client(
|
output
|
||||||
*client_id,
|
.add_character_chunks_to_client(
|
||||||
boundaries.render().with_context(err_context)?,
|
*client_id,
|
||||||
None,
|
boundaries.render().with_context(err_context)?,
|
||||||
);
|
None,
|
||||||
|
)
|
||||||
|
.with_context(err_context)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -746,7 +746,7 @@ impl Screen {
|
||||||
for tab_index in tabs_to_close {
|
for tab_index in tabs_to_close {
|
||||||
self.close_tab_at_index(tab_index).context(err_context)?;
|
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
|
self.bus
|
||||||
.senders
|
.senders
|
||||||
.send_to_server(ServerInstruction::Render(Some(serialized_output)))
|
.send_to_server(ServerInstruction::Render(Some(serialized_output)))
|
||||||
|
|
|
||||||
|
|
@ -2471,6 +2471,8 @@ impl Tab {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_selection_to_clipboard(&self, selection: &str) -> Result<()> {
|
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 mut output = Output::default();
|
||||||
let connected_clients: HashSet<ClientId> =
|
let connected_clients: HashSet<ClientId> =
|
||||||
{ self.connected_clients.borrow().iter().copied().collect() };
|
{ self.connected_clients.borrow().iter().copied().collect() };
|
||||||
|
|
@ -2481,15 +2483,20 @@ impl Tab {
|
||||||
.clipboard_provider
|
.clipboard_provider
|
||||||
.set_content(selection, &mut output, client_ids)
|
.set_content(selection, &mut output, client_ids)
|
||||||
{
|
{
|
||||||
Ok(_) => {
|
Ok(_) => output
|
||||||
let serialized_output = output.serialize();
|
.serialize()
|
||||||
self.senders
|
.and_then(|serialized_output| {
|
||||||
.send_to_server(ServerInstruction::Render(Some(serialized_output)))
|
self.senders
|
||||||
.context("failed to write selection to clipboard")?;
|
.send_to_server(ServerInstruction::Render(Some(serialized_output)))
|
||||||
Event::CopyToClipboard(self.clipboard_provider.as_copy_destination())
|
})
|
||||||
},
|
.and_then(|_| {
|
||||||
|
Ok(Event::CopyToClipboard(
|
||||||
|
self.clipboard_provider.as_copy_destination(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.with_context(err_context)?,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("could not write selection to clipboard: {}", err);
|
Err::<(), _>(err).with_context(err_context).non_fatal();
|
||||||
Event::SystemClipboardFailure
|
Event::SystemClipboardFailure
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -535,7 +535,7 @@ fn new_floating_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -567,7 +567,7 @@ fn floating_panes_persist_across_toggles() {
|
||||||
tab.toggle_floating_panes(client_id, None).unwrap();
|
tab.toggle_floating_panes(client_id, None).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -596,7 +596,7 @@ fn toggle_floating_panes_off() {
|
||||||
tab.toggle_floating_panes(client_id, None).unwrap();
|
tab.toggle_floating_panes(client_id, None).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -626,7 +626,7 @@ fn toggle_floating_panes_on() {
|
||||||
tab.toggle_floating_panes(client_id, None).unwrap();
|
tab.toggle_floating_panes(client_id, None).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -674,7 +674,7 @@ fn five_new_floating_panes() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -703,7 +703,7 @@ fn increase_floating_pane_size() {
|
||||||
tab.resize_increase(client_id);
|
tab.resize_increase(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -732,7 +732,7 @@ fn decrease_floating_pane_size() {
|
||||||
tab.resize_decrease(client_id);
|
tab.resize_decrease(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -761,7 +761,7 @@ fn resize_floating_pane_left() {
|
||||||
tab.resize_left(client_id);
|
tab.resize_left(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -790,7 +790,7 @@ fn resize_floating_pane_right() {
|
||||||
tab.resize_right(client_id);
|
tab.resize_right(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -819,7 +819,7 @@ fn resize_floating_pane_up() {
|
||||||
tab.resize_up(client_id);
|
tab.resize_up(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -848,7 +848,7 @@ fn resize_floating_pane_down() {
|
||||||
tab.resize_down(client_id);
|
tab.resize_down(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -897,7 +897,7 @@ fn move_floating_pane_focus_left() {
|
||||||
tab.move_focus_left(client_id);
|
tab.move_focus_left(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -953,7 +953,7 @@ fn move_floating_pane_focus_right() {
|
||||||
tab.move_focus_right(client_id);
|
tab.move_focus_right(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1008,7 +1008,7 @@ fn move_floating_pane_focus_up() {
|
||||||
tab.move_focus_up(client_id);
|
tab.move_focus_up(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1064,7 +1064,7 @@ fn move_floating_pane_focus_down() {
|
||||||
tab.move_focus_down(client_id);
|
tab.move_focus_down(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1122,7 +1122,7 @@ fn move_floating_pane_focus_with_mouse() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1180,7 +1180,7 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1238,7 +1238,7 @@ fn drag_pane_with_mouse() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1304,7 +1304,7 @@ fn mark_text_inside_floating_pane() {
|
||||||
);
|
);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1362,7 +1362,7 @@ fn resize_tab_with_floating_panes() {
|
||||||
});
|
});
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
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.resize_whole_tab(Size { cols: 50, rows: 10 });
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
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();
|
tab.render(&mut output, None).unwrap();
|
||||||
let (snapshot, _cursor_coordinates) = take_snapshot_and_cursor_position(
|
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.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1496,7 +1496,7 @@ fn embed_floating_pane() {
|
||||||
tab.toggle_pane_embed_or_floating(client_id).unwrap();
|
tab.toggle_pane_embed_or_floating(client_id).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1524,7 +1524,7 @@ fn float_embedded_pane() {
|
||||||
tab.toggle_pane_embed_or_floating(client_id).unwrap();
|
tab.toggle_pane_embed_or_floating(client_id).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1549,7 +1549,7 @@ fn cannot_float_only_embedded_pane() {
|
||||||
tab.toggle_pane_embed_or_floating(client_id).unwrap();
|
tab.toggle_pane_embed_or_floating(client_id).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1573,7 +1573,7 @@ fn replacing_existing_wide_characters() {
|
||||||
tab.handle_pty_bytes(1, pane_content).unwrap();
|
tab.handle_pty_bytes(1, pane_content).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1599,7 +1599,7 @@ fn rename_embedded_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1629,7 +1629,7 @@ fn rename_floating_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1651,7 +1651,7 @@ fn wide_characters_in_left_title_side() {
|
||||||
tab.handle_pty_bytes(1, pane_content).unwrap();
|
tab.handle_pty_bytes(1, pane_content).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1678,7 +1678,7 @@ fn save_cursor_position_across_resizes() {
|
||||||
|
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1714,7 +1714,7 @@ fn move_floating_pane_with_sixel_image() {
|
||||||
|
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot_with_sixel(
|
let snapshot = take_snapshot_with_sixel(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1752,7 +1752,7 @@ fn floating_pane_above_sixel_image() {
|
||||||
|
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot_with_sixel(
|
let snapshot = take_snapshot_with_sixel(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1777,7 +1777,7 @@ fn suppress_tiled_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1805,7 +1805,7 @@ fn suppress_floating_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1831,7 +1831,7 @@ fn close_suppressing_tiled_pane() {
|
||||||
tab.close_pane(new_pane_id, false);
|
tab.close_pane(new_pane_id, false);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1862,7 +1862,7 @@ fn close_suppressing_floating_pane() {
|
||||||
tab.close_pane(editor_pane_id, false);
|
tab.close_pane(editor_pane_id, false);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1889,7 +1889,7 @@ fn suppress_tiled_pane_float_it_and_close() {
|
||||||
tab.close_pane(new_pane_id, false);
|
tab.close_pane(new_pane_id, false);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1921,7 +1921,7 @@ fn suppress_floating_pane_embed_it_and_close_it() {
|
||||||
tab.close_pane(editor_pane_id, false);
|
tab.close_pane(editor_pane_id, false);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1948,7 +1948,7 @@ fn resize_whole_tab_while_tiled_pane_is_suppressed() {
|
||||||
});
|
});
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -1980,7 +1980,7 @@ fn resize_whole_tab_while_floting_pane_is_suppressed() {
|
||||||
});
|
});
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2005,7 +2005,7 @@ fn enter_search_pane() {
|
||||||
tab.handle_pty_bytes(1, pane_content).unwrap();
|
tab.handle_pty_bytes(1, pane_content).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2019,7 +2019,7 @@ fn enter_search_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2032,7 +2032,7 @@ fn enter_search_pane() {
|
||||||
tab.toggle_search_case_sensitivity(client_id);
|
tab.toggle_search_case_sensitivity(client_id);
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2046,7 +2046,7 @@ fn enter_search_pane() {
|
||||||
|
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2076,7 +2076,7 @@ fn enter_search_floating_pane() {
|
||||||
tab.handle_pty_bytes(2, pane_content).unwrap();
|
tab.handle_pty_bytes(2, pane_content).unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2088,7 +2088,7 @@ fn enter_search_floating_pane() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2366,7 +2366,7 @@ fn tab_with_basic_layout() {
|
||||||
let mut output = Output::default();
|
let mut output = Output::default();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2406,7 +2406,7 @@ fn tab_with_nested_layout() {
|
||||||
let mut output = Output::default();
|
let mut output = Output::default();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
@ -2440,7 +2440,7 @@ fn tab_with_nested_uneven_layout() {
|
||||||
let mut output = Output::default();
|
let mut output = Output::default();
|
||||||
tab.render(&mut output, None).unwrap();
|
tab.render(&mut output, None).unwrap();
|
||||||
let snapshot = take_snapshot(
|
let snapshot = take_snapshot(
|
||||||
output.serialize().get(&client_id).unwrap(),
|
output.serialize().unwrap().get(&client_id).unwrap(),
|
||||||
size.rows,
|
size.rows,
|
||||||
size.cols,
|
size.cols,
|
||||||
Palette::default(),
|
Palette::default(),
|
||||||
|
|
|
||||||
|
|
@ -46,17 +46,19 @@ impl<'a> PaneContentsAndUi<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
clients: impl Iterator<Item = ClientId>,
|
clients: impl Iterator<Item = ClientId>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if let Some((character_chunks, raw_vte_output, sixel_image_chunks)) = self
|
let err_context = "failed to render pane contents to multiple clients";
|
||||||
.pane
|
|
||||||
.render(None)
|
if let Some((character_chunks, raw_vte_output, sixel_image_chunks)) =
|
||||||
.context("failed to render pane contents to multiple clients")?
|
self.pane.render(None).context(err_context)?
|
||||||
{
|
{
|
||||||
let clients: Vec<ClientId> = clients.collect();
|
let clients: Vec<ClientId> = clients.collect();
|
||||||
self.output.add_character_chunks_to_multiple_clients(
|
self.output
|
||||||
character_chunks,
|
.add_character_chunks_to_multiple_clients(
|
||||||
clients.iter().copied(),
|
character_chunks,
|
||||||
self.z_index,
|
clients.iter().copied(),
|
||||||
);
|
self.z_index,
|
||||||
|
)
|
||||||
|
.context(err_context)?;
|
||||||
self.output.add_sixel_image_chunks_to_multiple_clients(
|
self.output.add_sixel_image_chunks_to_multiple_clients(
|
||||||
sixel_image_chunks,
|
sixel_image_chunks,
|
||||||
clients.iter().copied(),
|
clients.iter().copied(),
|
||||||
|
|
@ -77,13 +79,16 @@ impl<'a> PaneContentsAndUi<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn render_pane_contents_for_client(&mut self, client_id: ClientId) -> Result<()> {
|
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
|
if let Some((character_chunks, raw_vte_output, sixel_image_chunks)) = self
|
||||||
.pane
|
.pane
|
||||||
.render(Some(client_id))
|
.render(Some(client_id))
|
||||||
.with_context(|| format!("failed to render pane contents for client {client_id}"))?
|
.with_context(err_context)?
|
||||||
{
|
{
|
||||||
self.output
|
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(
|
self.output.add_sixel_image_chunks_to_client(
|
||||||
client_id,
|
client_id,
|
||||||
sixel_image_chunks,
|
sixel_image_chunks,
|
||||||
|
|
@ -150,6 +155,7 @@ impl<'a> PaneContentsAndUi<'a> {
|
||||||
session_is_mirrored: bool,
|
session_is_mirrored: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let err_context = || format!("failed to render pane frame for client {client_id}");
|
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 pane_focused_for_client_id = self.focused_clients.contains(&client_id);
|
||||||
let other_focused_clients: Vec<ClientId> = self
|
let other_focused_clients: Vec<ClientId> = self
|
||||||
.focused_clients
|
.focused_clients
|
||||||
|
|
@ -186,16 +192,15 @@ impl<'a> PaneContentsAndUi<'a> {
|
||||||
other_cursors_exist_in_session: self.multiple_users_exist_in_session,
|
other_cursors_exist_in_session: self.multiple_users_exist_in_session,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((frame_terminal_characters, vte_output)) = self
|
if let Some((frame_terminal_characters, vte_output)) = self
|
||||||
.pane
|
.pane
|
||||||
.render_frame(client_id, frame_params, client_mode)
|
.render_frame(client_id, frame_params, client_mode)
|
||||||
.with_context(err_context)?
|
.with_context(err_context)?
|
||||||
{
|
{
|
||||||
self.output.add_character_chunks_to_client(
|
self.output
|
||||||
client_id,
|
.add_character_chunks_to_client(client_id, frame_terminal_characters, self.z_index)
|
||||||
frame_terminal_characters,
|
.with_context(err_context)?;
|
||||||
self.z_index,
|
|
||||||
);
|
|
||||||
if let Some(vte_output) = vte_output {
|
if let Some(vte_output) = vte_output {
|
||||||
self.output
|
self.output
|
||||||
.add_post_vte_instruction_to_client(client_id, &vte_output);
|
.add_post_vte_instruction_to_client(client_id, &vte_output);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue