fix(style): various internal refactorings
This commit is contained in:
parent
d34e624010
commit
56e85f87d6
39 changed files with 358 additions and 360 deletions
|
|
@ -93,7 +93,7 @@ fn selected_mode_shortcut(
|
||||||
) -> LinePart {
|
) -> LinePart {
|
||||||
let prefix_separator = palette.selected_prefix_separator.paint(separator);
|
let prefix_separator = palette.selected_prefix_separator.paint(separator);
|
||||||
let char_left_separator = palette.selected_char_left_separator.paint(" <".to_string());
|
let char_left_separator = palette.selected_char_left_separator.paint(" <".to_string());
|
||||||
let char_shortcut = palette.selected_char_shortcut.paint(format!("{}", letter));
|
let char_shortcut = palette.selected_char_shortcut.paint(letter.to_string());
|
||||||
let char_right_separator = palette.selected_char_right_separator.paint(">".to_string());
|
let char_right_separator = palette.selected_char_right_separator.paint(">".to_string());
|
||||||
let styled_text = palette.selected_styled_text.paint(format!("{} ", text));
|
let styled_text = palette.selected_styled_text.paint(format!("{} ", text));
|
||||||
let suffix_separator = palette.selected_suffix_separator.paint(separator);
|
let suffix_separator = palette.selected_suffix_separator.paint(separator);
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ impl ZellijPlugin for State {
|
||||||
let first_line = format!("{}{}", superkey, ctrl_keys);
|
let first_line = format!("{}{}", superkey, ctrl_keys);
|
||||||
|
|
||||||
let mut second_line = LinePart::default();
|
let mut second_line = LinePart::default();
|
||||||
for t in self.tabs.iter_mut() {
|
for t in &mut self.tabs {
|
||||||
if t.active {
|
if t.active {
|
||||||
match self.mode_info.mode {
|
match self.mode_info.mode {
|
||||||
InputMode::Normal => {
|
InputMode::Normal => {
|
||||||
|
|
|
||||||
|
|
@ -31,16 +31,14 @@ fn full_length_shortcut(
|
||||||
let description = Style::new().fg(white_color).bold().paint(description);
|
let description = Style::new().fg(white_color).bold().paint(description);
|
||||||
let len = shortcut_len + description_len + separator.chars().count();
|
let len = shortcut_len + description_len + separator.chars().count();
|
||||||
LinePart {
|
LinePart {
|
||||||
part: format!(
|
part: ANSIStrings(&[
|
||||||
"{}",
|
separator,
|
||||||
ANSIStrings(&[
|
shortcut_left_separator,
|
||||||
separator,
|
shortcut,
|
||||||
shortcut_left_separator,
|
shortcut_right_separator,
|
||||||
shortcut,
|
description,
|
||||||
shortcut_right_separator,
|
])
|
||||||
description
|
.to_string(),
|
||||||
])
|
|
||||||
),
|
|
||||||
len,
|
len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,16 +71,14 @@ fn first_word_shortcut(
|
||||||
.paint(description_first_word);
|
.paint(description_first_word);
|
||||||
let len = shortcut_len + description_first_word_length + separator.chars().count();
|
let len = shortcut_len + description_first_word_length + separator.chars().count();
|
||||||
LinePart {
|
LinePart {
|
||||||
part: format!(
|
part: ANSIStrings(&[
|
||||||
"{}",
|
separator,
|
||||||
ANSIStrings(&[
|
shortcut_left_separator,
|
||||||
separator,
|
shortcut,
|
||||||
shortcut_left_separator,
|
shortcut_right_separator,
|
||||||
shortcut,
|
description_first_word,
|
||||||
shortcut_right_separator,
|
])
|
||||||
description_first_word,
|
.to_string(),
|
||||||
])
|
|
||||||
),
|
|
||||||
len,
|
len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +280,7 @@ fn locked_interface_indication(palette: Palette) -> LinePart {
|
||||||
};
|
};
|
||||||
let locked_styled_text = Style::new().fg(white_color).bold().paint(locked_text);
|
let locked_styled_text = Style::new().fg(white_color).bold().paint(locked_text);
|
||||||
LinePart {
|
LinePart {
|
||||||
part: format!("{}", locked_styled_text),
|
part: locked_styled_text.to_string(),
|
||||||
len: locked_text_len,
|
len: locked_text_len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -310,16 +306,14 @@ fn select_pane_shortcut(is_first_shortcut: bool, palette: Palette) -> LinePart {
|
||||||
let description = Style::new().fg(white_color).bold().paint(description);
|
let description = Style::new().fg(white_color).bold().paint(description);
|
||||||
let len = shortcut_len + description_len + separator.chars().count();
|
let len = shortcut_len + description_len + separator.chars().count();
|
||||||
LinePart {
|
LinePart {
|
||||||
part: format!(
|
part: ANSIStrings(&[
|
||||||
"{}",
|
separator,
|
||||||
ANSIStrings(&[
|
shortcut_left_separator,
|
||||||
separator,
|
shortcut,
|
||||||
shortcut_left_separator,
|
shortcut_right_separator,
|
||||||
shortcut,
|
description,
|
||||||
shortcut_right_separator,
|
])
|
||||||
description
|
.to_string(),
|
||||||
])
|
|
||||||
),
|
|
||||||
len,
|
len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -422,7 +416,7 @@ pub fn text_copied_hint(palette: &Palette) -> LinePart {
|
||||||
PaletteColor::EightBit(color) => Fixed(color),
|
PaletteColor::EightBit(color) => Fixed(color),
|
||||||
};
|
};
|
||||||
LinePart {
|
LinePart {
|
||||||
part: format!("{}", Style::new().fg(green_color).bold().paint(hint)),
|
part: Style::new().fg(green_color).bold().paint(hint).to_string(),
|
||||||
len: hint.len(),
|
len: hint.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,8 @@ fn left_more_message(tab_count_to_the_left: usize, palette: Palette, separator:
|
||||||
.bold()
|
.bold()
|
||||||
.paint(more_text);
|
.paint(more_text);
|
||||||
let right_separator = style!(palette.orange, palette.gray).paint(separator);
|
let right_separator = style!(palette.orange, palette.gray).paint(separator);
|
||||||
let more_styled_text = format!(
|
let more_styled_text =
|
||||||
"{}",
|
ANSIStrings(&[left_separator, more_styled_text, right_separator]).to_string();
|
||||||
ANSIStrings(&[left_separator, more_styled_text, right_separator,])
|
|
||||||
);
|
|
||||||
LinePart {
|
LinePart {
|
||||||
part: more_styled_text,
|
part: more_styled_text,
|
||||||
len: more_text_len,
|
len: more_text_len,
|
||||||
|
|
@ -137,10 +135,8 @@ fn right_more_message(
|
||||||
.bold()
|
.bold()
|
||||||
.paint(more_text);
|
.paint(more_text);
|
||||||
let right_separator = style!(palette.orange, palette.gray).paint(separator);
|
let right_separator = style!(palette.orange, palette.gray).paint(separator);
|
||||||
let more_styled_text = format!(
|
let more_styled_text =
|
||||||
"{}",
|
ANSIStrings(&[left_separator, more_styled_text, right_separator]).to_string();
|
||||||
ANSIStrings(&[left_separator, more_styled_text, right_separator,])
|
|
||||||
);
|
|
||||||
LinePart {
|
LinePart {
|
||||||
part: more_styled_text,
|
part: more_styled_text,
|
||||||
len: more_text_len,
|
len: more_text_len,
|
||||||
|
|
@ -155,7 +151,7 @@ fn tab_line_prefix(session_name: Option<&str>, palette: Palette, cols: usize) ->
|
||||||
.bold()
|
.bold()
|
||||||
.paint(prefix_text);
|
.paint(prefix_text);
|
||||||
let mut parts = vec![LinePart {
|
let mut parts = vec![LinePart {
|
||||||
part: format!("{}", prefix_styled_text),
|
part: prefix_styled_text.to_string(),
|
||||||
len: prefix_text_len,
|
len: prefix_text_len,
|
||||||
}];
|
}];
|
||||||
if let Some(name) = session_name {
|
if let Some(name) = session_name {
|
||||||
|
|
@ -164,7 +160,7 @@ fn tab_line_prefix(session_name: Option<&str>, palette: Palette, cols: usize) ->
|
||||||
let name_part_styled_text = style!(palette.white, palette.gray).bold().paint(name_part);
|
let name_part_styled_text = style!(palette.white, palette.gray).bold().paint(name_part);
|
||||||
if cols.saturating_sub(prefix_text_len) >= name_part_len {
|
if cols.saturating_sub(prefix_text_len) >= name_part_len {
|
||||||
parts.push(LinePart {
|
parts.push(LinePart {
|
||||||
part: format!("{}", name_part_styled_text),
|
part: name_part_styled_text.to_string(),
|
||||||
len: name_part_len,
|
len: name_part_len,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ impl ZellijPlugin for State {
|
||||||
Event::ModeUpdate(mode_info) => self.mode_info = mode_info,
|
Event::ModeUpdate(mode_info) => self.mode_info = mode_info,
|
||||||
Event::TabUpdate(tabs) => {
|
Event::TabUpdate(tabs) => {
|
||||||
// tabs are indexed starting from 1 so we need to add 1
|
// tabs are indexed starting from 1 so we need to add 1
|
||||||
self.active_tab_idx = (&tabs).iter().position(|t| t.active).unwrap() + 1;
|
self.active_tab_idx = tabs.iter().position(|t| t.active).unwrap() + 1;
|
||||||
self.tabs = tabs;
|
self.tabs = tabs;
|
||||||
}
|
}
|
||||||
Event::Mouse(me) => match me {
|
Event::Mouse(me) => match me {
|
||||||
|
|
@ -69,7 +69,7 @@ impl ZellijPlugin for State {
|
||||||
}
|
}
|
||||||
let mut all_tabs: Vec<LinePart> = vec![];
|
let mut all_tabs: Vec<LinePart> = vec![];
|
||||||
let mut active_tab_index = 0;
|
let mut active_tab_index = 0;
|
||||||
for t in self.tabs.iter_mut() {
|
for t in &mut self.tabs {
|
||||||
let mut tabname = t.name.clone();
|
let mut tabname = t.name.clone();
|
||||||
if t.active && self.mode_info.mode == InputMode::RenameTab {
|
if t.active && self.mode_info.mode == InputMode::RenameTab {
|
||||||
if tabname.is_empty() {
|
if tabname.is_empty() {
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,8 @@ pub fn active_tab(text: String, palette: Palette, separator: &str) -> LinePart {
|
||||||
.bold()
|
.bold()
|
||||||
.paint(format!(" {} ", text));
|
.paint(format!(" {} ", text));
|
||||||
let right_separator = style!(palette.green, palette.gray).paint(separator);
|
let right_separator = style!(palette.green, palette.gray).paint(separator);
|
||||||
let tab_styled_text = format!(
|
let tab_styled_text =
|
||||||
"{}",
|
ANSIStrings(&[left_separator, tab_styled_text, right_separator]).to_string();
|
||||||
ANSIStrings(&[left_separator, tab_styled_text, right_separator,])
|
|
||||||
);
|
|
||||||
LinePart {
|
LinePart {
|
||||||
part: tab_styled_text,
|
part: tab_styled_text,
|
||||||
len: tab_text_len,
|
len: tab_text_len,
|
||||||
|
|
@ -28,10 +26,8 @@ pub fn non_active_tab(text: String, palette: Palette, separator: &str) -> LinePa
|
||||||
.bold()
|
.bold()
|
||||||
.paint(format!(" {} ", text));
|
.paint(format!(" {} ", text));
|
||||||
let right_separator = style!(palette.fg, palette.gray).paint(separator);
|
let right_separator = style!(palette.fg, palette.gray).paint(separator);
|
||||||
let tab_styled_text = format!(
|
let tab_styled_text =
|
||||||
"{}",
|
ANSIStrings(&[left_separator, tab_styled_text, right_separator]).to_string();
|
||||||
ANSIStrings(&[left_separator, tab_styled_text, right_separator,])
|
|
||||||
);
|
|
||||||
LinePart {
|
LinePart {
|
||||||
part: tab_styled_text,
|
part: tab_styled_text,
|
||||||
len: tab_text_len,
|
len: tab_text_len,
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ pub(crate) fn kill_all_sessions(yes: bool) {
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for session in sessions.iter() {
|
for session in &sessions {
|
||||||
kill_session_impl(session);
|
kill_session_impl(session);
|
||||||
}
|
}
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
|
|
@ -131,7 +131,7 @@ fn attach_with_session_name(
|
||||||
config_options: Options,
|
config_options: Options,
|
||||||
create: bool,
|
create: bool,
|
||||||
) -> ClientInfo {
|
) -> ClientInfo {
|
||||||
match session_name.as_ref() {
|
match &session_name {
|
||||||
Some(session) if create => {
|
Some(session) if create => {
|
||||||
if !session_exists(session).unwrap() {
|
if !session_exists(session).unwrap() {
|
||||||
ClientInfo::New(session_name.unwrap())
|
ClientInfo::New(session_name.unwrap())
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use zellij_utils::{pane_size::Size, position::Position};
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use super::remote_runner::{RemoteRunner, RemoteTerminal, Step};
|
use super::remote_runner::{RemoteRunner, RemoteTerminal, Step};
|
||||||
|
|
@ -231,26 +232,26 @@ pub fn scrolling_inside_a_pane() {
|
||||||
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() {
|
if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() {
|
||||||
// cursor is in the newly opened second pane
|
// cursor is in the newly opened second pane
|
||||||
let mut content_to_send = String::new();
|
let mut content_to_send = String::new();
|
||||||
content_to_send.push_str(&format!("{:0<56}", "line1 "));
|
write!(&mut content_to_send, "{:0<56}", "line1 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line2 "));
|
write!(&mut content_to_send, "{:0<58}", "line2 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line3 "));
|
write!(&mut content_to_send, "{:0<58}", "line3 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line4 "));
|
write!(&mut content_to_send, "{:0<58}", "line4 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line5 "));
|
write!(&mut content_to_send, "{:0<58}", "line5 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line6 "));
|
write!(&mut content_to_send, "{:0<58}", "line6 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line7 "));
|
write!(&mut content_to_send, "{:0<58}", "line7 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line8 "));
|
write!(&mut content_to_send, "{:0<58}", "line8 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line9 "));
|
write!(&mut content_to_send, "{:0<58}", "line9 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line10 "));
|
write!(&mut content_to_send, "{:0<58}", "line10 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line11 "));
|
write!(&mut content_to_send, "{:0<58}", "line11 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line12 "));
|
write!(&mut content_to_send, "{:0<58}", "line12 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line13 "));
|
write!(&mut content_to_send, "{:0<58}", "line13 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line14 "));
|
write!(&mut content_to_send, "{:0<58}", "line14 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line15 "));
|
write!(&mut content_to_send, "{:0<58}", "line15 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line16 "));
|
write!(&mut content_to_send, "{:0<58}", "line16 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line17 "));
|
write!(&mut content_to_send, "{:0<58}", "line17 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line18 "));
|
write!(&mut content_to_send, "{:0<58}", "line18 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<58}", "line19 "));
|
write!(&mut content_to_send, "{:0<58}", "line19 ").unwrap();
|
||||||
content_to_send.push_str(&format!("{:0<57}", "line20 "));
|
write!(&mut content_to_send, "{:0<57}", "line20 ").unwrap();
|
||||||
|
|
||||||
remote_terminal.send_key(content_to_send.as_bytes());
|
remote_terminal.send_key(content_to_send.as_bytes());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,14 +45,12 @@ fn setup_remote_environment(channel: &mut ssh2::Channel, win_size: Size) {
|
||||||
.request_pty("xterm", None, Some((columns, rows, 0, 0)))
|
.request_pty("xterm", None, Some((columns, rows, 0, 0)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
channel.shell().unwrap();
|
channel.shell().unwrap();
|
||||||
channel.write_all("export PS1=\"$ \"\n".as_bytes()).unwrap();
|
channel.write_all(b"export PS1=\"$ \"\n").unwrap();
|
||||||
channel.flush().unwrap();
|
channel.flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop_zellij(channel: &mut ssh2::Channel) {
|
fn stop_zellij(channel: &mut ssh2::Channel) {
|
||||||
channel
|
channel.write_all(b"killall -KILL zellij\n").unwrap();
|
||||||
.write_all("killall -KILL zellij\n".as_bytes())
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_zellij(channel: &mut ssh2::Channel) {
|
fn start_zellij(channel: &mut ssh2::Channel) {
|
||||||
|
|
|
||||||
|
|
@ -299,9 +299,9 @@ pub fn start_client(
|
||||||
os_input.send_to_server(ClientToServerMsg::ClientExited);
|
os_input.send_to_server(ClientToServerMsg::ClientExited);
|
||||||
|
|
||||||
if let ExitReason::Error(_) = reason {
|
if let ExitReason::Error(_) = reason {
|
||||||
handle_error(format!("{}", reason));
|
handle_error(reason.to_string());
|
||||||
}
|
}
|
||||||
exit_msg = format!("{}", reason);
|
exit_msg = reason.to_string();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ClientInstruction::Error(backtrace) => {
|
ClientInstruction::Error(backtrace) => {
|
||||||
|
|
|
||||||
|
|
@ -66,14 +66,14 @@ pub(crate) fn stdin_loop(
|
||||||
&& stdin_buffer
|
&& stdin_buffer
|
||||||
.iter()
|
.iter()
|
||||||
.take(bracketed_paste_start.len())
|
.take(bracketed_paste_start.len())
|
||||||
.eq(bracketed_paste_start.iter()))
|
.eq(&bracketed_paste_start))
|
||||||
{
|
{
|
||||||
match bracketed_paste_end_position(&stdin_buffer) {
|
match bracketed_paste_end_position(&stdin_buffer) {
|
||||||
Some(paste_end_position) => {
|
Some(paste_end_position) => {
|
||||||
let starts_with_bracketed_paste_start = stdin_buffer
|
let starts_with_bracketed_paste_start = stdin_buffer
|
||||||
.iter()
|
.iter()
|
||||||
.take(bracketed_paste_start.len())
|
.take(bracketed_paste_start.len())
|
||||||
.eq(bracketed_paste_start.iter());
|
.eq(&bracketed_paste_start);
|
||||||
|
|
||||||
let ends_with_bracketed_paste_end = true;
|
let ends_with_bracketed_paste_end = true;
|
||||||
|
|
||||||
|
|
@ -97,7 +97,7 @@ pub(crate) fn stdin_loop(
|
||||||
let starts_with_bracketed_paste_start = stdin_buffer
|
let starts_with_bracketed_paste_start = stdin_buffer
|
||||||
.iter()
|
.iter()
|
||||||
.take(bracketed_paste_start.len())
|
.take(bracketed_paste_start.len())
|
||||||
.eq(bracketed_paste_start.iter());
|
.eq(&bracketed_paste_start);
|
||||||
if starts_with_bracketed_paste_start {
|
if starts_with_bracketed_paste_start {
|
||||||
drop(stdin_buffer.drain(..6)); // bracketed paste start
|
drop(stdin_buffer.drain(..6)); // bracketed paste start
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -451,9 +451,8 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, socket_path: PathBuf) {
|
||||||
// Here the output is of the type Option<String> sent by screen thread.
|
// Here the output is of the type Option<String> sent by screen thread.
|
||||||
// If `Some(_)`- unwrap it and forward it to the clients to render.
|
// If `Some(_)`- unwrap it and forward it to the clients to render.
|
||||||
// If `None`- Send an exit instruction. This is the case when a user closes the last Tab/Pane.
|
// If `None`- Send an exit instruction. This is the case when a user closes the last Tab/Pane.
|
||||||
if let Some(op) = output.as_mut() {
|
if let Some(op) = &mut output {
|
||||||
for (client_id, client_render_instruction) in
|
for (client_id, client_render_instruction) in &mut op.client_render_instructions
|
||||||
op.client_render_instructions.iter_mut()
|
|
||||||
{
|
{
|
||||||
os_input.send_to_client(
|
os_input.send_to_client(
|
||||||
*client_id,
|
*client_id,
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ mod logging_pipe_test {
|
||||||
fn write_without_endl_does_not_consume_buffer_after_flush() {
|
fn write_without_endl_does_not_consume_buffer_after_flush() {
|
||||||
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
||||||
|
|
||||||
let test_buffer = "Testing write".as_bytes();
|
let test_buffer = b"Testing write";
|
||||||
|
|
||||||
pipe.write_all(test_buffer).expect("Err write");
|
pipe.write_all(test_buffer).expect("Err write");
|
||||||
pipe.flush().expect("Err flush");
|
pipe.flush().expect("Err flush");
|
||||||
|
|
@ -159,7 +159,7 @@ mod logging_pipe_test {
|
||||||
fn write_with_single_endl_at_the_end_consumes_whole_buffer_after_flush() {
|
fn write_with_single_endl_at_the_end_consumes_whole_buffer_after_flush() {
|
||||||
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
||||||
|
|
||||||
let test_buffer = "Testing write \n".as_bytes();
|
let test_buffer = b"Testing write \n";
|
||||||
|
|
||||||
pipe.write_all(test_buffer).expect("Err write");
|
pipe.write_all(test_buffer).expect("Err write");
|
||||||
pipe.flush().expect("Err flush");
|
pipe.flush().expect("Err flush");
|
||||||
|
|
@ -171,8 +171,8 @@ mod logging_pipe_test {
|
||||||
fn write_with_endl_in_the_middle_consumes_buffer_up_to_endl_after_flush() {
|
fn write_with_endl_in_the_middle_consumes_buffer_up_to_endl_after_flush() {
|
||||||
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
||||||
|
|
||||||
let test_buffer = "Testing write \n".as_bytes();
|
let test_buffer = b"Testing write \n";
|
||||||
let test_buffer2 = "And the rest".as_bytes();
|
let test_buffer2: &[_] = b"And the rest";
|
||||||
|
|
||||||
pipe.write_all(
|
pipe.write_all(
|
||||||
[
|
[
|
||||||
|
|
@ -195,7 +195,7 @@ mod logging_pipe_test {
|
||||||
fn write_with_many_endl_consumes_whole_buffer_after_flush() {
|
fn write_with_many_endl_consumes_whole_buffer_after_flush() {
|
||||||
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
||||||
|
|
||||||
let test_buffer = "Testing write \n".as_bytes();
|
let test_buffer: &[_] = b"Testing write \n";
|
||||||
|
|
||||||
pipe.write_all(
|
pipe.write_all(
|
||||||
[
|
[
|
||||||
|
|
@ -235,7 +235,7 @@ mod logging_pipe_test {
|
||||||
#[test]
|
#[test]
|
||||||
fn write_with_many_endls_consumes_everything_after_flush() {
|
fn write_with_many_endls_consumes_everything_after_flush() {
|
||||||
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
let mut pipe = LoggingPipe::new("TestPipe", 0);
|
||||||
let test_buffer = "Testing write \n".as_bytes();
|
let test_buffer: &[_] = b"Testing write \n";
|
||||||
|
|
||||||
pipe.write_all(
|
pipe.write_all(
|
||||||
[test_buffer, test_buffer, b"\n", b"\n", b"\n"]
|
[test_buffer, test_buffer, b"\n", b"\n", b"\n"]
|
||||||
|
|
|
||||||
|
|
@ -456,16 +456,14 @@ impl Grid {
|
||||||
self.output_buffer.update_line(line_index);
|
self.output_buffer.update_line(line_index);
|
||||||
}
|
}
|
||||||
pub fn advance_to_next_tabstop(&mut self, styles: CharacterStyles) {
|
pub fn advance_to_next_tabstop(&mut self, styles: CharacterStyles) {
|
||||||
let mut next_tabstop = None;
|
let next_tabstop = self
|
||||||
for tabstop in self.horizontal_tabstops.iter() {
|
.horizontal_tabstops
|
||||||
if *tabstop > self.cursor.x {
|
.iter()
|
||||||
next_tabstop = Some(tabstop);
|
.copied()
|
||||||
break;
|
.find(|&tabstop| tabstop > self.cursor.x);
|
||||||
}
|
|
||||||
}
|
|
||||||
match next_tabstop {
|
match next_tabstop {
|
||||||
Some(tabstop) => {
|
Some(tabstop) => {
|
||||||
self.cursor.x = *tabstop;
|
self.cursor.x = tabstop;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.cursor.x = self.width.saturating_sub(1);
|
self.cursor.x = self.width.saturating_sub(1);
|
||||||
|
|
@ -477,16 +475,15 @@ impl Grid {
|
||||||
self.output_buffer.update_line(self.cursor.y);
|
self.output_buffer.update_line(self.cursor.y);
|
||||||
}
|
}
|
||||||
pub fn move_to_previous_tabstop(&mut self) {
|
pub fn move_to_previous_tabstop(&mut self) {
|
||||||
let mut previous_tabstop = None;
|
let previous_tabstop = self
|
||||||
for tabstop in self.horizontal_tabstops.iter() {
|
.horizontal_tabstops
|
||||||
if *tabstop >= self.cursor.x {
|
.iter()
|
||||||
break;
|
.rev()
|
||||||
}
|
.copied()
|
||||||
previous_tabstop = Some(tabstop);
|
.find(|&tabstop| tabstop < self.cursor.x);
|
||||||
}
|
|
||||||
match previous_tabstop {
|
match previous_tabstop {
|
||||||
Some(tabstop) => {
|
Some(tabstop) => {
|
||||||
self.cursor.x = *tabstop;
|
self.cursor.x = tabstop;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.cursor.x = 0;
|
self.cursor.x = 0;
|
||||||
|
|
@ -506,7 +503,7 @@ impl Grid {
|
||||||
|
|
||||||
fn recalculate_scrollback_buffer_count(&self) -> usize {
|
fn recalculate_scrollback_buffer_count(&self) -> usize {
|
||||||
let mut scrollback_buffer_count = 0;
|
let mut scrollback_buffer_count = 0;
|
||||||
for row in self.lines_above.iter() {
|
for row in &self.lines_above {
|
||||||
let row_width = row.width();
|
let row_width = row.width();
|
||||||
// rows in lines_above are unwrapped, so we need to account for that
|
// rows in lines_above are unwrapped, so we need to account for that
|
||||||
if row_width > self.width {
|
if row_width > self.width {
|
||||||
|
|
@ -531,7 +528,7 @@ impl Grid {
|
||||||
self.saved_cursor_position = Some(self.cursor.clone());
|
self.saved_cursor_position = Some(self.cursor.clone());
|
||||||
}
|
}
|
||||||
fn restore_cursor_position(&mut self) {
|
fn restore_cursor_position(&mut self) {
|
||||||
if let Some(saved_cursor_position) = self.saved_cursor_position.as_ref() {
|
if let Some(saved_cursor_position) = &self.saved_cursor_position {
|
||||||
self.cursor = saved_cursor_position.clone();
|
self.cursor = saved_cursor_position.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -701,7 +698,7 @@ impl Grid {
|
||||||
|
|
||||||
// trim lines after the last empty space that has no following character, because
|
// trim lines after the last empty space that has no following character, because
|
||||||
// terminals don't trim empty lines
|
// terminals don't trim empty lines
|
||||||
for line in viewport_canonical_lines.iter_mut() {
|
for line in &mut viewport_canonical_lines {
|
||||||
let mut trim_at = None;
|
let mut trim_at = None;
|
||||||
for (index, character) in line.columns.iter().enumerate() {
|
for (index, character) in line.columns.iter().enumerate() {
|
||||||
if character.character != EMPTY_TERMINAL_CHARACTER.character {
|
if character.character != EMPTY_TERMINAL_CHARACTER.character {
|
||||||
|
|
@ -1134,7 +1131,7 @@ impl Grid {
|
||||||
pub fn clear_all(&mut self, replace_with: TerminalCharacter) {
|
pub fn clear_all(&mut self, replace_with: TerminalCharacter) {
|
||||||
let replace_with_columns = VecDeque::from(vec![replace_with; self.width]);
|
let replace_with_columns = VecDeque::from(vec![replace_with; self.width]);
|
||||||
self.replace_characters_in_line_after_cursor(replace_with);
|
self.replace_characters_in_line_after_cursor(replace_with);
|
||||||
for row in self.viewport.iter_mut() {
|
for row in &mut self.viewport {
|
||||||
row.replace_columns(replace_with_columns.clone());
|
row.replace_columns(replace_with_columns.clone());
|
||||||
}
|
}
|
||||||
self.output_buffer.update_all_lines();
|
self.output_buffer.update_all_lines();
|
||||||
|
|
@ -1481,7 +1478,7 @@ impl Grid {
|
||||||
if self.title_stack.len() > MAX_TITLE_STACK_SIZE {
|
if self.title_stack.len() > MAX_TITLE_STACK_SIZE {
|
||||||
self.title_stack.remove(0);
|
self.title_stack.remove(0);
|
||||||
}
|
}
|
||||||
if let Some(title) = self.title.as_ref() {
|
if let Some(title) = &self.title {
|
||||||
self.title_stack.push(title.clone());
|
self.title_stack.push(title.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1793,7 +1790,7 @@ impl Perform for Grid {
|
||||||
alternative_lines_above,
|
alternative_lines_above,
|
||||||
alternative_viewport,
|
alternative_viewport,
|
||||||
alternative_cursor,
|
alternative_cursor,
|
||||||
)) = self.alternative_lines_above_viewport_and_cursor.as_mut()
|
)) = &mut self.alternative_lines_above_viewport_and_cursor
|
||||||
{
|
{
|
||||||
std::mem::swap(&mut self.lines_above, alternative_lines_above);
|
std::mem::swap(&mut self.lines_above, alternative_lines_above);
|
||||||
std::mem::swap(&mut self.viewport, alternative_viewport);
|
std::mem::swap(&mut self.viewport, alternative_viewport);
|
||||||
|
|
@ -2159,7 +2156,7 @@ impl Row {
|
||||||
Row::new(width)
|
Row::new(width)
|
||||||
} else {
|
} else {
|
||||||
let mut first_row = rows.remove(0);
|
let mut first_row = rows.remove(0);
|
||||||
for row in rows.iter_mut() {
|
for row in &mut rows {
|
||||||
first_row.append(&mut row.columns);
|
first_row.append(&mut row.columns);
|
||||||
}
|
}
|
||||||
first_row
|
first_row
|
||||||
|
|
@ -2175,14 +2172,14 @@ impl Row {
|
||||||
}
|
}
|
||||||
pub fn width(&self) -> usize {
|
pub fn width(&self) -> usize {
|
||||||
let mut width = 0;
|
let mut width = 0;
|
||||||
for terminal_character in self.columns.iter() {
|
for terminal_character in &self.columns {
|
||||||
width += terminal_character.width;
|
width += terminal_character.width;
|
||||||
}
|
}
|
||||||
width
|
width
|
||||||
}
|
}
|
||||||
pub fn excess_width(&self) -> usize {
|
pub fn excess_width(&self) -> usize {
|
||||||
let mut acc = 0;
|
let mut acc = 0;
|
||||||
for terminal_character in self.columns.iter() {
|
for terminal_character in &self.columns {
|
||||||
if terminal_character.width > 1 {
|
if terminal_character.width > 1 {
|
||||||
acc += terminal_character.width - 1;
|
acc += terminal_character.width - 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn dispatch_osc8_link_end() {
|
fn dispatch_osc8_link_end() {
|
||||||
let mut link_handler = LinkHandler::default();
|
let mut link_handler = LinkHandler::default();
|
||||||
let params = vec!["8".as_bytes(), &[], &[]];
|
let params: Vec<&[_]> = vec![b"8", b"", b""];
|
||||||
|
|
||||||
let anchor = link_handler.dispatch_osc8(¶ms);
|
let anchor = link_handler.dispatch_osc8(¶ms);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::fmt::Write;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::unimplemented;
|
use std::unimplemented;
|
||||||
|
|
@ -165,12 +166,14 @@ impl Pane for PluginPane {
|
||||||
.concat()
|
.concat()
|
||||||
};
|
};
|
||||||
|
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
&mut vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
self.get_content_y() + 1 + index,
|
self.get_content_y() + 1 + index,
|
||||||
self.get_content_x() + 1,
|
self.get_content_x() + 1,
|
||||||
line_to_print,
|
line_to_print,
|
||||||
)); // goto row/col and reset styles
|
)
|
||||||
|
.unwrap(); // goto row/col and reset styles
|
||||||
let line_len = line_to_print.len();
|
let line_len = line_to_print.len();
|
||||||
if line_len < self.get_content_columns() {
|
if line_len < self.get_content_columns() {
|
||||||
// pad line
|
// pad line
|
||||||
|
|
@ -185,11 +188,13 @@ impl Pane for PluginPane {
|
||||||
for line_index in total_line_count..self.get_content_rows() {
|
for line_index in total_line_count..self.get_content_rows() {
|
||||||
let x = self.get_content_x();
|
let x = self.get_content_x();
|
||||||
let y = self.get_content_y();
|
let y = self.get_content_y();
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
&mut vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m",
|
"\u{1b}[{};{}H\u{1b}[m",
|
||||||
y + line_index + 1,
|
y + line_index + 1,
|
||||||
x + 1
|
x + 1
|
||||||
)); // goto row/col and reset styles
|
)
|
||||||
|
.unwrap(); // goto row/col and reset styles
|
||||||
for _col_index in 0..self.get_content_columns() {
|
for _col_index in 0..self.get_content_columns() {
|
||||||
vte_output.push(' ');
|
vte_output.push(' ');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,44 +68,48 @@ pub enum NamedColor {
|
||||||
|
|
||||||
impl NamedColor {
|
impl NamedColor {
|
||||||
fn to_foreground_ansi_code(self) -> String {
|
fn to_foreground_ansi_code(self) -> String {
|
||||||
match self {
|
let v = match self {
|
||||||
NamedColor::Black => format!("{}", 30),
|
NamedColor::Black => 30,
|
||||||
NamedColor::Red => format!("{}", 31),
|
NamedColor::Red => 31,
|
||||||
NamedColor::Green => format!("{}", 32),
|
NamedColor::Green => 32,
|
||||||
NamedColor::Yellow => format!("{}", 33),
|
NamedColor::Yellow => 33,
|
||||||
NamedColor::Blue => format!("{}", 34),
|
NamedColor::Blue => 34,
|
||||||
NamedColor::Magenta => format!("{}", 35),
|
NamedColor::Magenta => 35,
|
||||||
NamedColor::Cyan => format!("{}", 36),
|
NamedColor::Cyan => 36,
|
||||||
NamedColor::White => format!("{}", 37),
|
NamedColor::White => 37,
|
||||||
NamedColor::BrightBlack => format!("{}", 90),
|
NamedColor::BrightBlack => 90,
|
||||||
NamedColor::BrightRed => format!("{}", 91),
|
NamedColor::BrightRed => 91,
|
||||||
NamedColor::BrightGreen => format!("{}", 92),
|
NamedColor::BrightGreen => 92,
|
||||||
NamedColor::BrightYellow => format!("{}", 93),
|
NamedColor::BrightYellow => 93,
|
||||||
NamedColor::BrightBlue => format!("{}", 94),
|
NamedColor::BrightBlue => 94,
|
||||||
NamedColor::BrightMagenta => format!("{}", 95),
|
NamedColor::BrightMagenta => 95,
|
||||||
NamedColor::BrightCyan => format!("{}", 96),
|
NamedColor::BrightCyan => 96,
|
||||||
NamedColor::BrightWhite => format!("{}", 97),
|
NamedColor::BrightWhite => 97,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
v.to_string()
|
||||||
}
|
}
|
||||||
fn to_background_ansi_code(self) -> String {
|
fn to_background_ansi_code(self) -> String {
|
||||||
match self {
|
let v = match self {
|
||||||
NamedColor::Black => format!("{}", 40),
|
NamedColor::Black => 40,
|
||||||
NamedColor::Red => format!("{}", 41),
|
NamedColor::Red => 41,
|
||||||
NamedColor::Green => format!("{}", 42),
|
NamedColor::Green => 42,
|
||||||
NamedColor::Yellow => format!("{}", 43),
|
NamedColor::Yellow => 43,
|
||||||
NamedColor::Blue => format!("{}", 44),
|
NamedColor::Blue => 44,
|
||||||
NamedColor::Magenta => format!("{}", 45),
|
NamedColor::Magenta => 45,
|
||||||
NamedColor::Cyan => format!("{}", 46),
|
NamedColor::Cyan => 46,
|
||||||
NamedColor::White => format!("{}", 47),
|
NamedColor::White => 47,
|
||||||
NamedColor::BrightBlack => format!("{}", 100),
|
NamedColor::BrightBlack => 100,
|
||||||
NamedColor::BrightRed => format!("{}", 101),
|
NamedColor::BrightRed => 101,
|
||||||
NamedColor::BrightGreen => format!("{}", 102),
|
NamedColor::BrightGreen => 102,
|
||||||
NamedColor::BrightYellow => format!("{}", 103),
|
NamedColor::BrightYellow => 103,
|
||||||
NamedColor::BrightBlue => format!("{}", 104),
|
NamedColor::BrightBlue => 104,
|
||||||
NamedColor::BrightMagenta => format!("{}", 105),
|
NamedColor::BrightMagenta => 105,
|
||||||
NamedColor::BrightCyan => format!("{}", 106),
|
NamedColor::BrightCyan => 106,
|
||||||
NamedColor::BrightWhite => format!("{}", 107),
|
NamedColor::BrightWhite => 107,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
v.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use crate::pty::VteBytes;
|
||||||
use crate::tab::Pane;
|
use crate::tab::Pane;
|
||||||
use crate::ClientId;
|
use crate::ClientId;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::fmt::Debug;
|
use std::fmt::{Debug, Write};
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
use std::time::{self, Instant};
|
use std::time::{self, Instant};
|
||||||
use zellij_utils::pane_size::Offset;
|
use zellij_utils::pane_size::Offset;
|
||||||
|
|
@ -93,8 +93,8 @@ impl Pane for TerminalPane {
|
||||||
self.reflow_lines();
|
self.reflow_lines();
|
||||||
}
|
}
|
||||||
fn handle_pty_bytes(&mut self, bytes: VteBytes) {
|
fn handle_pty_bytes(&mut self, bytes: VteBytes) {
|
||||||
for byte in bytes.iter() {
|
for &byte in &bytes {
|
||||||
self.vte_parser.advance(&mut self.grid, *byte);
|
self.vte_parser.advance(&mut self.grid, byte);
|
||||||
}
|
}
|
||||||
self.set_should_render(true);
|
self.set_should_render(true);
|
||||||
}
|
}
|
||||||
|
|
@ -191,11 +191,13 @@ impl Pane for TerminalPane {
|
||||||
let content_y = self.get_content_y();
|
let content_y = self.get_content_y();
|
||||||
if self.grid.clear_viewport_before_rendering {
|
if self.grid.clear_viewport_before_rendering {
|
||||||
for line_index in 0..self.grid.height {
|
for line_index in 0..self.grid.height {
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
&mut vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m",
|
"\u{1b}[{};{}H\u{1b}[m",
|
||||||
content_y + line_index + 1,
|
content_y + line_index + 1,
|
||||||
content_x + 1
|
content_x + 1
|
||||||
)); // goto row/col and reset styles
|
)
|
||||||
|
.unwrap(); // goto row/col and reset styles
|
||||||
for _col_index in 0..self.grid.width {
|
for _col_index in 0..self.grid.width {
|
||||||
vte_output.push(EMPTY_TERMINAL_CHARACTER.character);
|
vte_output.push(EMPTY_TERMINAL_CHARACTER.character);
|
||||||
}
|
}
|
||||||
|
|
@ -212,8 +214,14 @@ impl Pane for TerminalPane {
|
||||||
self.grid.update_line_for_rendering(y);
|
self.grid.update_line_for_rendering(y);
|
||||||
let x = content_x + x;
|
let x = content_x + x;
|
||||||
let y = content_y + y;
|
let y = content_y + y;
|
||||||
vte_output.push_str(&format!("\u{1b}[{};{}H\u{1b}[m", y + 1, x + 1));
|
write!(
|
||||||
vte_output.push(EMPTY_TERMINAL_CHARACTER.character);
|
&mut vte_output,
|
||||||
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
|
y + 1,
|
||||||
|
x + 1,
|
||||||
|
EMPTY_TERMINAL_CHARACTER.character
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
let max_width = self.get_content_columns();
|
let max_width = self.get_content_columns();
|
||||||
for character_chunk in self.grid.read_changes() {
|
for character_chunk in self.grid.read_changes() {
|
||||||
|
|
@ -222,11 +230,13 @@ impl Pane for TerminalPane {
|
||||||
let chunk_absolute_x = pane_x + character_chunk.x;
|
let chunk_absolute_x = pane_x + character_chunk.x;
|
||||||
let chunk_absolute_y = pane_y + character_chunk.y;
|
let chunk_absolute_y = pane_y + character_chunk.y;
|
||||||
let terminal_characters = character_chunk.terminal_characters;
|
let terminal_characters = character_chunk.terminal_characters;
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
&mut vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m",
|
"\u{1b}[{};{}H\u{1b}[m",
|
||||||
chunk_absolute_y + 1,
|
chunk_absolute_y + 1,
|
||||||
chunk_absolute_x + 1
|
chunk_absolute_x + 1
|
||||||
)); // goto row/col and reset styles
|
)
|
||||||
|
.unwrap(); // goto row/col and reset styles
|
||||||
|
|
||||||
let mut chunk_width = character_chunk.x;
|
let mut chunk_width = character_chunk.x;
|
||||||
for mut t_character in terminal_characters {
|
for mut t_character in terminal_characters {
|
||||||
|
|
@ -248,9 +258,13 @@ impl Pane for TerminalPane {
|
||||||
if let Some(new_styles) = character_styles
|
if let Some(new_styles) = character_styles
|
||||||
.update_and_return_diff(&t_character.styles, self.grid.changed_colors)
|
.update_and_return_diff(&t_character.styles, self.grid.changed_colors)
|
||||||
{
|
{
|
||||||
vte_output.push_str(&new_styles.to_string());
|
write!(
|
||||||
vte_output
|
&mut vte_output,
|
||||||
.push_str(&self.grid.link_handler.output_osc8(new_styles.link_anchor))
|
"{}{}",
|
||||||
|
new_styles,
|
||||||
|
self.grid.link_handler.output_osc8(new_styles.link_anchor)
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
vte_output.push(t_character.character);
|
vte_output.push(t_character.character);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ use ::insta::assert_snapshot;
|
||||||
use zellij_utils::pane_size::PaneGeom;
|
use zellij_utils::pane_size::PaneGeom;
|
||||||
use zellij_utils::zellij_tile::data::Palette;
|
use zellij_utils::zellij_tile::data::Palette;
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn scrolling_inside_a_pane() {
|
pub fn scrolling_inside_a_pane() {
|
||||||
let mut fake_win_size = PaneGeom::default();
|
let mut fake_win_size = PaneGeom::default();
|
||||||
|
|
@ -15,9 +17,9 @@ pub fn scrolling_inside_a_pane() {
|
||||||
let mut terminal_pane = TerminalPane::new(pid, fake_win_size, palette, 0); // 0 is the pane index
|
let mut terminal_pane = TerminalPane::new(pid, fake_win_size, palette, 0); // 0 is the pane index
|
||||||
let mut text_to_fill_pane = String::new();
|
let mut text_to_fill_pane = String::new();
|
||||||
for i in 0..30 {
|
for i in 0..30 {
|
||||||
text_to_fill_pane.push_str(&format!("\rline {}\n", i + 1));
|
writeln!(&mut text_to_fill_pane, "\rline {}", i + 1).unwrap();
|
||||||
}
|
}
|
||||||
terminal_pane.handle_pty_bytes(text_to_fill_pane.as_bytes().to_vec());
|
terminal_pane.handle_pty_bytes(text_to_fill_pane.into_bytes());
|
||||||
terminal_pane.scroll_up(10);
|
terminal_pane.scroll_up(10);
|
||||||
assert_snapshot!(format!("{:?}", terminal_pane.grid));
|
assert_snapshot!(format!("{:?}", terminal_pane.grid));
|
||||||
terminal_pane.scroll_down(3);
|
terminal_pane.scroll_down(3);
|
||||||
|
|
|
||||||
|
|
@ -284,13 +284,12 @@ impl Pty {
|
||||||
PaneId::Plugin(..) => None,
|
PaneId::Plugin(..) => None,
|
||||||
PaneId::Terminal(id) => self.id_to_child_pid.get(id),
|
PaneId::Terminal(id) => self.id_to_child_pid.get(id),
|
||||||
})
|
})
|
||||||
.and_then(|id| {
|
.and_then(|&id| {
|
||||||
self.bus
|
self.bus
|
||||||
.os_input
|
.os_input
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|input| input.get_cwd(Pid::from_raw(*id)))
|
.and_then(|input| input.get_cwd(Pid::from_raw(id)))
|
||||||
})
|
});
|
||||||
.flatten();
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ fn route_action(
|
||||||
.senders
|
.senders
|
||||||
.send_to_screen(ScreenInstruction::ClearScroll(client_id))
|
.send_to_screen(ScreenInstruction::ClearScroll(client_id))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let val = Vec::from(val.as_bytes());
|
let val = val.into_bytes();
|
||||||
session
|
session
|
||||||
.senders
|
.senders
|
||||||
.send_to_screen(ScreenInstruction::WriteCharacter(val, client_id))
|
.send_to_screen(ScreenInstruction::WriteCharacter(val, client_id))
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ impl Screen {
|
||||||
// currently all clients are just mirrors, so we perform the action for every entry in
|
// currently all clients are just mirrors, so we perform the action for every entry in
|
||||||
// tab_history
|
// tab_history
|
||||||
// TODO: receive a client_id and only do it for the client
|
// TODO: receive a client_id and only do it for the client
|
||||||
for (client_id, tab_history) in self.tab_history.iter_mut() {
|
for (client_id, tab_history) in &mut self.tab_history {
|
||||||
let old_active_index = self.active_tab_indices.remove(client_id).unwrap();
|
let old_active_index = self.active_tab_indices.remove(client_id).unwrap();
|
||||||
self.active_tab_indices.insert(*client_id, new_tab_index);
|
self.active_tab_indices.insert(*client_id, new_tab_index);
|
||||||
tab_history.retain(|&e| e != new_tab_pos);
|
tab_history.retain(|&e| e != new_tab_pos);
|
||||||
|
|
@ -348,7 +348,7 @@ impl Screen {
|
||||||
|
|
||||||
pub fn resize_to_screen(&mut self, new_screen_size: Size) {
|
pub fn resize_to_screen(&mut self, new_screen_size: Size) {
|
||||||
self.size = new_screen_size;
|
self.size = new_screen_size;
|
||||||
for (_, tab) in self.tabs.iter_mut() {
|
for tab in self.tabs.values_mut() {
|
||||||
tab.resize_whole_tab(new_screen_size);
|
tab.resize_whole_tab(new_screen_size);
|
||||||
tab.set_force_render();
|
tab.set_force_render();
|
||||||
}
|
}
|
||||||
|
|
@ -361,7 +361,7 @@ impl Screen {
|
||||||
let mut tabs_to_close = vec![];
|
let mut tabs_to_close = vec![];
|
||||||
let size = self.size;
|
let size = self.size;
|
||||||
let overlay = self.overlay.clone();
|
let overlay = self.overlay.clone();
|
||||||
for (tab_index, tab) in self.tabs.iter_mut() {
|
for (tab_index, tab) in &mut self.tabs {
|
||||||
if tab.has_active_panes() {
|
if tab.has_active_panes() {
|
||||||
let vte_overlay = overlay.generate_overlay(size);
|
let vte_overlay = overlay.generate_overlay(size);
|
||||||
tab.render(&mut output, Some(vte_overlay));
|
tab.render(&mut output, Some(vte_overlay));
|
||||||
|
|
@ -442,7 +442,7 @@ impl Screen {
|
||||||
let connected_clients = active_tab.drain_connected_clients();
|
let connected_clients = active_tab.drain_connected_clients();
|
||||||
tab.add_multiple_clients(&connected_clients);
|
tab.add_multiple_clients(&connected_clients);
|
||||||
}
|
}
|
||||||
for (client_id, tab_history) in self.tab_history.iter_mut() {
|
for (client_id, tab_history) in &mut self.tab_history {
|
||||||
let old_active_index = self.active_tab_indices.remove(client_id).unwrap();
|
let old_active_index = self.active_tab_indices.remove(client_id).unwrap();
|
||||||
self.active_tab_indices.insert(*client_id, tab_index);
|
self.active_tab_indices.insert(*client_id, tab_index);
|
||||||
tab_history.retain(|&e| e != tab_index);
|
tab_history.retain(|&e| e != tab_index);
|
||||||
|
|
@ -941,8 +941,8 @@ pub(crate) fn screen_thread_main(
|
||||||
screen.get_active_tab_mut(client_id).unwrap().close_pane(id);
|
screen.get_active_tab_mut(client_id).unwrap().close_pane(id);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
for (_index, tab) in screen.tabs.iter_mut() {
|
for tab in screen.tabs.values_mut() {
|
||||||
if tab.get_pane_ids().iter().any(|pid| *pid == id) {
|
if tab.get_pane_ids().contains(&id) {
|
||||||
tab.close_pane(id);
|
tab.close_pane(id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -962,7 +962,7 @@ pub(crate) fn screen_thread_main(
|
||||||
}
|
}
|
||||||
ScreenInstruction::TogglePaneFrames => {
|
ScreenInstruction::TogglePaneFrames => {
|
||||||
screen.draw_pane_frames = !screen.draw_pane_frames;
|
screen.draw_pane_frames = !screen.draw_pane_frames;
|
||||||
for (_, tab) in screen.tabs.iter_mut() {
|
for tab in screen.tabs.values_mut() {
|
||||||
tab.set_pane_frames(screen.draw_pane_frames);
|
tab.set_pane_frames(screen.draw_pane_frames);
|
||||||
}
|
}
|
||||||
screen.render();
|
screen.render();
|
||||||
|
|
|
||||||
|
|
@ -360,7 +360,7 @@ impl Tab {
|
||||||
let positions_in_layout = layout.position_panes_in_space(&free_space);
|
let positions_in_layout = layout.position_panes_in_space(&free_space);
|
||||||
|
|
||||||
let mut positions_and_size = positions_in_layout.iter();
|
let mut positions_and_size = positions_in_layout.iter();
|
||||||
for (pane_kind, terminal_pane) in self.panes.iter_mut() {
|
for (pane_kind, terminal_pane) in &mut self.panes {
|
||||||
// for now the layout only supports terminal panes
|
// for now the layout only supports terminal panes
|
||||||
if let PaneId::Terminal(pid) = pane_kind {
|
if let PaneId::Terminal(pid) = pane_kind {
|
||||||
match positions_and_size.next() {
|
match positions_and_size.next() {
|
||||||
|
|
@ -774,7 +774,7 @@ impl Tab {
|
||||||
if self.fullscreen_is_active {
|
if self.fullscreen_is_active {
|
||||||
let first_client_id = self.connected_clients.iter().next().unwrap(); // this is a temporary hack until we fix the ui for multiple clients
|
let first_client_id = self.connected_clients.iter().next().unwrap(); // this is a temporary hack until we fix the ui for multiple clients
|
||||||
let active_pane_id = self.active_panes.get(first_client_id).unwrap();
|
let active_pane_id = self.active_panes.get(first_client_id).unwrap();
|
||||||
for terminal_id in self.panes_to_hide.iter() {
|
for terminal_id in &self.panes_to_hide {
|
||||||
let pane = self.panes.get_mut(terminal_id).unwrap();
|
let pane = self.panes.get_mut(terminal_id).unwrap();
|
||||||
pane.set_should_render(true);
|
pane.set_should_render(true);
|
||||||
pane.set_should_render_boundaries(true);
|
pane.set_should_render_boundaries(true);
|
||||||
|
|
@ -908,11 +908,11 @@ impl Tab {
|
||||||
fn update_active_panes_in_pty_thread(&self) {
|
fn update_active_panes_in_pty_thread(&self) {
|
||||||
// this is a bit hacky and we should ideally not keep this state in two different places at
|
// this is a bit hacky and we should ideally not keep this state in two different places at
|
||||||
// some point
|
// some point
|
||||||
for connected_client in self.connected_clients.iter() {
|
for &connected_client in &self.connected_clients {
|
||||||
self.senders
|
self.senders
|
||||||
.send_to_pty(PtyInstruction::UpdateActivePane(
|
.send_to_pty(PtyInstruction::UpdateActivePane(
|
||||||
self.active_panes.get(connected_client).copied(),
|
self.active_panes.get(&connected_client).copied(),
|
||||||
*connected_client,
|
connected_client,
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
@ -936,28 +936,27 @@ impl Tab {
|
||||||
self.mode_info.mode,
|
self.mode_info.mode,
|
||||||
);
|
);
|
||||||
pane_contents_and_ui.render_pane_contents_for_all_clients();
|
pane_contents_and_ui.render_pane_contents_for_all_clients();
|
||||||
for client_id in self.connected_clients.iter() {
|
for &client_id in &self.connected_clients {
|
||||||
if self.draw_pane_frames {
|
if self.draw_pane_frames {
|
||||||
pane_contents_and_ui
|
pane_contents_and_ui.render_pane_frame(client_id, self.session_is_mirrored);
|
||||||
.render_pane_frame(*client_id, self.session_is_mirrored);
|
|
||||||
} else {
|
} else {
|
||||||
let boundaries = client_id_to_boundaries
|
let boundaries = client_id_to_boundaries
|
||||||
.entry(*client_id)
|
.entry(client_id)
|
||||||
.or_insert_with(|| Boundaries::new(self.viewport));
|
.or_insert_with(|| Boundaries::new(self.viewport));
|
||||||
pane_contents_and_ui.render_pane_boundaries(
|
pane_contents_and_ui.render_pane_boundaries(
|
||||||
*client_id,
|
client_id,
|
||||||
boundaries,
|
boundaries,
|
||||||
self.session_is_mirrored,
|
self.session_is_mirrored,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// this is done for panes that don't have their own cursor (eg. panes of
|
// this is done for panes that don't have their own cursor (eg. panes of
|
||||||
// another user)
|
// another user)
|
||||||
pane_contents_and_ui.render_fake_cursor_if_needed(*client_id);
|
pane_contents_and_ui.render_fake_cursor_if_needed(client_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// render boundaries if needed
|
// render boundaries if needed
|
||||||
for (client_id, boundaries) in client_id_to_boundaries.iter_mut() {
|
for (client_id, boundaries) in &mut client_id_to_boundaries {
|
||||||
output.push_to_client(*client_id, &boundaries.vte_output());
|
output.push_to_client(*client_id, &boundaries.vte_output());
|
||||||
}
|
}
|
||||||
// FIXME: Once clients can be distinguished
|
// FIXME: Once clients can be distinguished
|
||||||
|
|
@ -976,24 +975,24 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn render_cursor(&self, output: &mut Output) {
|
fn render_cursor(&self, output: &mut Output) {
|
||||||
for client_id in self.connected_clients.iter() {
|
for &client_id in &self.connected_clients {
|
||||||
match self.get_active_terminal_cursor_position(*client_id) {
|
match self.get_active_terminal_cursor_position(client_id) {
|
||||||
Some((cursor_position_x, cursor_position_y)) => {
|
Some((cursor_position_x, cursor_position_y)) => {
|
||||||
let show_cursor = "\u{1b}[?25h";
|
let show_cursor = "\u{1b}[?25h";
|
||||||
let change_cursor_shape =
|
let change_cursor_shape =
|
||||||
self.get_active_pane(*client_id).unwrap().cursor_shape_csi();
|
self.get_active_pane(client_id).unwrap().cursor_shape_csi();
|
||||||
let goto_cursor_position = &format!(
|
let goto_cursor_position = &format!(
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
cursor_position_y + 1,
|
cursor_position_y + 1,
|
||||||
cursor_position_x + 1,
|
cursor_position_x + 1,
|
||||||
change_cursor_shape
|
change_cursor_shape
|
||||||
); // goto row/col
|
); // goto row/col
|
||||||
output.push_to_client(*client_id, show_cursor);
|
output.push_to_client(client_id, show_cursor);
|
||||||
output.push_to_client(*client_id, goto_cursor_position);
|
output.push_to_client(client_id, goto_cursor_position);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let hide_cursor = "\u{1b}[?25l";
|
let hide_cursor = "\u{1b}[?25l";
|
||||||
output.push_to_client(*client_id, hide_cursor);
|
output.push_to_client(client_id, hide_cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1509,10 +1508,7 @@ impl Tab {
|
||||||
|
|
||||||
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
||||||
// above and below this one. This should be moved to a `can_resize` function eventually.
|
// above and below this one. This should be moved to a `can_resize` function eventually.
|
||||||
for terminal_id in terminals_to_the_left
|
for terminal_id in terminals_to_the_left.iter().chain(&terminals_to_the_right) {
|
||||||
.iter()
|
|
||||||
.chain(terminals_to_the_right.iter())
|
|
||||||
{
|
|
||||||
let pane = self.panes.get(terminal_id).unwrap();
|
let pane = self.panes.get(terminal_id).unwrap();
|
||||||
if pane.current_geom().rows.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
if pane.current_geom().rows.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1523,10 +1519,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_below {
|
for terminal_id in terminals_below {
|
||||||
self.increase_pane_height(&terminal_id, percent);
|
self.increase_pane_height(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_to_the_left
|
for terminal_id in terminals_to_the_left.iter().chain(&terminals_to_the_right) {
|
||||||
.iter()
|
|
||||||
.chain(terminals_to_the_right.iter())
|
|
||||||
{
|
|
||||||
self.reduce_pane_height(terminal_id, percent);
|
self.reduce_pane_height(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1548,10 +1541,7 @@ impl Tab {
|
||||||
|
|
||||||
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
||||||
// above and below this one. This should be moved to a `can_resize` function eventually.
|
// above and below this one. This should be moved to a `can_resize` function eventually.
|
||||||
for terminal_id in terminals_to_the_left
|
for terminal_id in terminals_to_the_left.iter().chain(&terminals_to_the_right) {
|
||||||
.iter()
|
|
||||||
.chain(terminals_to_the_right.iter())
|
|
||||||
{
|
|
||||||
let pane = self.panes.get(terminal_id).unwrap();
|
let pane = self.panes.get(terminal_id).unwrap();
|
||||||
if pane.current_geom().rows.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
if pane.current_geom().rows.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1562,10 +1552,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_above {
|
for terminal_id in terminals_above {
|
||||||
self.increase_pane_height(&terminal_id, percent);
|
self.increase_pane_height(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_to_the_left
|
for terminal_id in terminals_to_the_left.iter().chain(&terminals_to_the_right) {
|
||||||
.iter()
|
|
||||||
.chain(terminals_to_the_right.iter())
|
|
||||||
{
|
|
||||||
self.reduce_pane_height(terminal_id, percent);
|
self.reduce_pane_height(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1587,7 +1574,7 @@ impl Tab {
|
||||||
|
|
||||||
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
||||||
// above and below this one. This should be moved to a `can_resize` function eventually.
|
// above and below this one. This should be moved to a `can_resize` function eventually.
|
||||||
for terminal_id in terminals_above.iter().chain(terminals_below.iter()) {
|
for terminal_id in terminals_above.iter().chain(&terminals_below) {
|
||||||
let pane = self.panes.get(terminal_id).unwrap();
|
let pane = self.panes.get(terminal_id).unwrap();
|
||||||
if pane.current_geom().cols.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
if pane.current_geom().cols.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1598,7 +1585,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_to_the_left {
|
for terminal_id in terminals_to_the_left {
|
||||||
self.increase_pane_width(&terminal_id, percent);
|
self.increase_pane_width(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_above.iter().chain(terminals_below.iter()) {
|
for terminal_id in terminals_above.iter().chain(&terminals_below) {
|
||||||
self.reduce_pane_width(terminal_id, percent);
|
self.reduce_pane_width(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1620,7 +1607,7 @@ impl Tab {
|
||||||
|
|
||||||
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
// FIXME: This checks that we aren't violating the resize constraints of the aligned panes
|
||||||
// above and below this one. This should be moved to a `can_resize` function eventually.
|
// above and below this one. This should be moved to a `can_resize` function eventually.
|
||||||
for terminal_id in terminals_above.iter().chain(terminals_below.iter()) {
|
for terminal_id in terminals_above.iter().chain(&terminals_below) {
|
||||||
let pane = self.panes.get(terminal_id).unwrap();
|
let pane = self.panes.get(terminal_id).unwrap();
|
||||||
if pane.current_geom().cols.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
if pane.current_geom().cols.as_percent().unwrap() - percent < RESIZE_PERCENT {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1631,7 +1618,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_to_the_right {
|
for terminal_id in terminals_to_the_right {
|
||||||
self.increase_pane_width(&terminal_id, percent);
|
self.increase_pane_width(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_above.iter().chain(terminals_below.iter()) {
|
for terminal_id in terminals_above.iter().chain(&terminals_below) {
|
||||||
self.reduce_pane_width(terminal_id, percent);
|
self.reduce_pane_width(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1654,10 +1641,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_above {
|
for terminal_id in terminals_above {
|
||||||
self.reduce_pane_height(&terminal_id, percent);
|
self.reduce_pane_height(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_to_the_left
|
for terminal_id in terminals_to_the_left.iter().chain(&terminals_to_the_right) {
|
||||||
.iter()
|
|
||||||
.chain(terminals_to_the_right.iter())
|
|
||||||
{
|
|
||||||
self.increase_pane_height(terminal_id, percent);
|
self.increase_pane_height(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1680,10 +1664,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_below {
|
for terminal_id in terminals_below {
|
||||||
self.reduce_pane_height(&terminal_id, percent);
|
self.reduce_pane_height(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_to_the_left
|
for terminal_id in terminals_to_the_left.iter().chain(&terminals_to_the_right) {
|
||||||
.iter()
|
|
||||||
.chain(terminals_to_the_right.iter())
|
|
||||||
{
|
|
||||||
self.increase_pane_height(terminal_id, percent);
|
self.increase_pane_height(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1708,7 +1689,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_to_the_right {
|
for terminal_id in terminals_to_the_right {
|
||||||
self.reduce_pane_width(&terminal_id, percent);
|
self.reduce_pane_width(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_above.iter().chain(terminals_below.iter()) {
|
for terminal_id in terminals_above.iter().chain(&terminals_below) {
|
||||||
self.increase_pane_width(terminal_id, percent);
|
self.increase_pane_width(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1731,7 +1712,7 @@ impl Tab {
|
||||||
for terminal_id in terminals_to_the_left {
|
for terminal_id in terminals_to_the_left {
|
||||||
self.reduce_pane_width(&terminal_id, percent);
|
self.reduce_pane_width(&terminal_id, percent);
|
||||||
}
|
}
|
||||||
for terminal_id in terminals_above.iter().chain(terminals_below.iter()) {
|
for terminal_id in terminals_above.iter().chain(&terminals_below) {
|
||||||
self.increase_pane_width(terminal_id, percent);
|
self.increase_pane_width(terminal_id, percent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2180,7 +2161,7 @@ impl Tab {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn relayout_tab(&mut self, direction: Direction) {
|
pub fn relayout_tab(&mut self, direction: Direction) {
|
||||||
let mut resizer = PaneResizer::new(self.panes.iter_mut());
|
let mut resizer = PaneResizer::new(&mut self.panes);
|
||||||
let result = match direction {
|
let result = match direction {
|
||||||
Direction::Horizontal => resizer.layout(direction, self.display_area.cols),
|
Direction::Horizontal => resizer.layout(direction, self.display_area.cols),
|
||||||
Direction::Vertical => resizer.layout(direction, self.display_area.rows),
|
Direction::Vertical => resizer.layout(direction, self.display_area.rows),
|
||||||
|
|
@ -3119,12 +3100,12 @@ impl Tab {
|
||||||
fn grow_panes(&mut self, panes: &[PaneId], direction: Direction, (width, height): (f64, f64)) {
|
fn grow_panes(&mut self, panes: &[PaneId], direction: Direction, (width, height): (f64, f64)) {
|
||||||
match direction {
|
match direction {
|
||||||
Direction::Horizontal => {
|
Direction::Horizontal => {
|
||||||
for pane_id in panes.iter() {
|
for pane_id in panes {
|
||||||
self.increase_pane_width(pane_id, width);
|
self.increase_pane_width(pane_id, width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Direction::Vertical => {
|
Direction::Vertical => {
|
||||||
for pane_id in panes.iter() {
|
for pane_id in panes {
|
||||||
self.increase_pane_height(pane_id, height);
|
self.increase_pane_height(pane_id, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use zellij_utils::{pane_size::Viewport, zellij_tile};
|
||||||
use crate::tab::Pane;
|
use crate::tab::Pane;
|
||||||
use ansi_term::Colour::{Fixed, RGB};
|
use ansi_term::Colour::{Fixed, RGB};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Write;
|
||||||
use zellij_tile::data::PaletteColor;
|
use zellij_tile::data::PaletteColor;
|
||||||
use zellij_utils::shared::colors;
|
use zellij_utils::shared::colors;
|
||||||
|
|
||||||
|
|
@ -513,12 +514,14 @@ impl Boundaries {
|
||||||
pub fn vte_output(&self) -> String {
|
pub fn vte_output(&self) -> String {
|
||||||
let mut vte_output = String::new();
|
let mut vte_output = String::new();
|
||||||
for (coordinates, boundary_character) in &self.boundary_characters {
|
for (coordinates, boundary_character) in &self.boundary_characters {
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
&mut vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
coordinates.y + 1,
|
coordinates.y + 1,
|
||||||
coordinates.x + 1,
|
coordinates.x + 1,
|
||||||
boundary_character
|
boundary_character
|
||||||
)); // goto row/col + boundary character
|
)
|
||||||
|
.unwrap(); // goto row/col + boundary character
|
||||||
}
|
}
|
||||||
vte_output
|
vte_output
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ use zellij_utils::pane_size::Size;
|
||||||
use super::{Overlay, OverlayType, Overlayable};
|
use super::{Overlay, OverlayType, Overlayable};
|
||||||
use crate::{ClientId, ServerInstruction};
|
use crate::{ClientId, ServerInstruction};
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Prompt {
|
pub struct Prompt {
|
||||||
pub message: String,
|
pub message: String,
|
||||||
|
|
@ -37,7 +39,14 @@ impl Overlayable for Prompt {
|
||||||
let mut vte_output = self.message.clone();
|
let mut vte_output = self.message.clone();
|
||||||
Overlay::pad_cols(&mut vte_output, size.cols);
|
Overlay::pad_cols(&mut vte_output, size.cols);
|
||||||
for (x, h) in vte_output.chars().enumerate() {
|
for (x, h) in vte_output.chars().enumerate() {
|
||||||
output.push_str(&format!("\u{1b}[{};{}H\u{1b}[48;5;238m{}", rows, x + 1, h,));
|
write!(
|
||||||
|
&mut output,
|
||||||
|
"\u{1b}[{};{}H\u{1b}[48;5;238m{}",
|
||||||
|
rows,
|
||||||
|
x + 1,
|
||||||
|
h,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,29 +7,25 @@ use zellij_utils::zellij_tile::prelude::{Palette, PaletteColor};
|
||||||
|
|
||||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
fn color_string(character: &str, color: Option<PaletteColor>) -> String {
|
fn color_string(character: &str, color: Option<PaletteColor>) -> String {
|
||||||
match color {
|
match color {
|
||||||
Some(color) => match color {
|
Some(PaletteColor::Rgb((r, g, b))) => RGB(r, g, b).bold().paint(character).to_string(),
|
||||||
PaletteColor::Rgb((r, g, b)) => {
|
Some(PaletteColor::EightBit(color)) => Fixed(color).bold().paint(character).to_string(),
|
||||||
format!("{}", RGB(r, g, b).bold().paint(character))
|
None => Style::new().bold().paint(character).to_string(),
|
||||||
}
|
|
||||||
PaletteColor::EightBit(color) => {
|
|
||||||
format!("{}", Fixed(color).bold().paint(character))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => format!("{}", Style::new().bold().paint(character)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn background_color(character: &str, color: Option<PaletteColor>) -> String {
|
fn background_color(character: &str, color: Option<PaletteColor>) -> String {
|
||||||
match color {
|
match color {
|
||||||
Some(PaletteColor::Rgb((r, g, b))) => {
|
Some(PaletteColor::Rgb((r, g, b))) => {
|
||||||
format!("{}", Style::new().on(RGB(r, g, b)).paint(character))
|
Style::new().on(RGB(r, g, b)).paint(character).to_string()
|
||||||
}
|
}
|
||||||
Some(PaletteColor::EightBit(color)) => {
|
Some(PaletteColor::EightBit(color)) => {
|
||||||
format!("{}", Style::new().on(Fixed(color)).paint(character))
|
Style::new().on(Fixed(color)).paint(character).to_string()
|
||||||
}
|
}
|
||||||
None => String::from(character),
|
None => character.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -475,7 +471,7 @@ impl PaneFrame {
|
||||||
let mut left_side = self.render_title_left_side(length_of_each_side);
|
let mut left_side = self.render_title_left_side(length_of_each_side);
|
||||||
let mut right_side = self.render_title_right_side(length_of_each_side);
|
let mut right_side = self.render_title_right_side(length_of_each_side);
|
||||||
|
|
||||||
match (left_side.as_mut(), right_side.as_mut()) {
|
match (&mut left_side, &mut right_side) {
|
||||||
(Some((left_side, left_side_len)), Some((right_side, right_side_len))) => self
|
(Some((left_side, left_side_len)), Some((right_side, right_side_len))) => self
|
||||||
.three_part_title_line(
|
.three_part_title_line(
|
||||||
left_side,
|
left_side,
|
||||||
|
|
@ -511,23 +507,26 @@ impl PaneFrame {
|
||||||
fn render_title(&self, vte_output: &mut String) {
|
fn render_title(&self, vte_output: &mut String) {
|
||||||
let total_title_length = self.geom.cols.saturating_sub(2); // 2 for the left and right corners
|
let total_title_length = self.geom.cols.saturating_sub(2); // 2 for the left and right corners
|
||||||
|
|
||||||
if let Some((middle, middle_length)) = self.render_title_middle(total_title_length).as_mut()
|
if let Some((middle, middle_length)) = &self.render_title_middle(total_title_length) {
|
||||||
{
|
|
||||||
let title_text = self.title_line_with_middle(middle, middle_length);
|
let title_text = self.title_line_with_middle(middle, middle_length);
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
self.geom.y + 1, // +1 because goto is 1 indexed
|
self.geom.y + 1, // +1 because goto is 1 indexed
|
||||||
self.geom.x + 1, // +1 because goto is 1 indexed
|
self.geom.x + 1, // +1 because goto is 1 indexed
|
||||||
color_string(&title_text, self.color),
|
color_string(&title_text, self.color),
|
||||||
)); // goto row/col + boundary character
|
)
|
||||||
|
.unwrap(); // goto row/col + boundary character
|
||||||
} else {
|
} else {
|
||||||
let title_text = self.title_line_without_middle();
|
let title_text = self.title_line_without_middle();
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
self.geom.y + 1, // +1 because goto is 1 indexed
|
self.geom.y + 1, // +1 because goto is 1 indexed
|
||||||
self.geom.x + 1, // +1 because goto is 1 indexed
|
self.geom.x + 1, // +1 because goto is 1 indexed
|
||||||
color_string(&title_text, self.color),
|
color_string(&title_text, self.color),
|
||||||
)); // goto row/col + boundary character
|
)
|
||||||
|
.unwrap(); // goto row/col + boundary character
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn render(&self) -> String {
|
pub fn render(&self) -> String {
|
||||||
|
|
@ -539,44 +538,43 @@ impl PaneFrame {
|
||||||
} else if row == self.geom.y + self.geom.rows - 1 {
|
} else if row == self.geom.y + self.geom.rows - 1 {
|
||||||
// bottom row
|
// bottom row
|
||||||
for col in self.geom.x..(self.geom.x + self.geom.cols) {
|
for col in self.geom.x..(self.geom.x + self.geom.cols) {
|
||||||
if col == self.geom.x {
|
let boundary = if col == self.geom.x {
|
||||||
// bottom left corner
|
// bottom left corner
|
||||||
vte_output.push_str(&format!(
|
boundary_type::BOTTOM_LEFT
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
|
||||||
row + 1, // +1 because goto is 1 indexed
|
|
||||||
col + 1,
|
|
||||||
color_string(boundary_type::BOTTOM_LEFT, self.color),
|
|
||||||
)); // goto row/col + boundary character
|
|
||||||
} else if col == self.geom.x + self.geom.cols - 1 {
|
} else if col == self.geom.x + self.geom.cols - 1 {
|
||||||
// bottom right corner
|
// bottom right corner
|
||||||
vte_output.push_str(&format!(
|
boundary_type::BOTTOM_RIGHT
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
|
||||||
row + 1, // +1 because goto is 1 indexed
|
|
||||||
col + 1,
|
|
||||||
color_string(boundary_type::BOTTOM_RIGHT, self.color),
|
|
||||||
)); // goto row/col + boundary character
|
|
||||||
} else {
|
} else {
|
||||||
vte_output.push_str(&format!(
|
boundary_type::HORIZONTAL
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
};
|
||||||
row + 1, // +1 because goto is 1 indexed
|
|
||||||
col + 1,
|
let boundary_rendered = color_string(boundary, self.color);
|
||||||
color_string(boundary_type::HORIZONTAL, self.color),
|
write!(
|
||||||
)); // goto row/col + boundary character
|
&mut vte_output,
|
||||||
}
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
|
row + 1,
|
||||||
|
col + 1,
|
||||||
|
boundary_rendered
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vte_output.push_str(&format!(
|
write!(
|
||||||
|
&mut vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
row + 1, // +1 because goto is 1 indexed
|
row + 1, // +1 because goto is 1 indexed
|
||||||
self.geom.x + 1,
|
self.geom.x + 1,
|
||||||
color_string(boundary_type::VERTICAL, self.color),
|
color_string(boundary_type::VERTICAL, self.color),
|
||||||
)); // goto row/col + boundary character
|
)
|
||||||
vte_output.push_str(&format!(
|
.unwrap(); // goto row/col + boundary character
|
||||||
|
write!(
|
||||||
|
&mut vte_output,
|
||||||
"\u{1b}[{};{}H\u{1b}[m{}",
|
"\u{1b}[{};{}H\u{1b}[m{}",
|
||||||
row + 1, // +1 because goto is 1 indexed
|
row + 1, // +1 because goto is 1 indexed
|
||||||
self.geom.x + self.geom.cols,
|
self.geom.x + self.geom.cols,
|
||||||
color_string(boundary_type::VERTICAL, self.color),
|
color_string(boundary_type::VERTICAL, self.color),
|
||||||
)); // goto row/col + boundary character
|
)
|
||||||
|
.unwrap(); // goto row/col + boundary character
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vte_output
|
vte_output
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,14 @@ impl<'a> PaneContentsAndUi<'a> {
|
||||||
let pane_focused_for_different_client = self
|
let pane_focused_for_different_client = self
|
||||||
.focused_clients
|
.focused_clients
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|c_id| **c_id != client_id)
|
.filter(|&&c_id| c_id != client_id)
|
||||||
.count()
|
.count()
|
||||||
> 0;
|
> 0;
|
||||||
if pane_focused_for_different_client && !pane_focused_for_client_id {
|
if pane_focused_for_different_client && !pane_focused_for_client_id {
|
||||||
let fake_cursor_client_id = self
|
let fake_cursor_client_id = self
|
||||||
.focused_clients
|
.focused_clients
|
||||||
.iter()
|
.iter()
|
||||||
.find(|c_id| **c_id != client_id)
|
.find(|&&c_id| c_id != client_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let Some(colors) = client_id_to_colors(*fake_cursor_client_id, self.colors) {
|
if let Some(colors) = client_id_to_colors(*fake_cursor_client_id, self.colors) {
|
||||||
if let Some(vte_output) = self.pane.render_fake_cursor(colors.0, colors.1) {
|
if let Some(vte_output) = self.pane.render_fake_cursor(colors.0, colors.1) {
|
||||||
|
|
@ -84,7 +84,7 @@ impl<'a> PaneContentsAndUi<'a> {
|
||||||
let other_focused_clients: Vec<ClientId> = self
|
let other_focused_clients: Vec<ClientId> = self
|
||||||
.focused_clients
|
.focused_clients
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|c_id| **c_id != client_id)
|
.filter(|&&c_id| c_id != client_id)
|
||||||
.copied()
|
.copied()
|
||||||
.collect();
|
.collect();
|
||||||
let pane_focused_for_differet_client = !other_focused_clients.is_empty();
|
let pane_focused_for_differet_client = !other_focused_clients.is_empty();
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ struct Span {
|
||||||
type Grid = Vec<Vec<Span>>;
|
type Grid = Vec<Vec<Span>>;
|
||||||
|
|
||||||
impl<'a> PaneResizer<'a> {
|
impl<'a> PaneResizer<'a> {
|
||||||
pub fn new(panes: impl Iterator<Item = (&'a PaneId, &'a mut Box<dyn Pane>)>) -> Self {
|
pub fn new(panes: impl IntoIterator<Item = (&'a PaneId, &'a mut Box<dyn Pane>)>) -> Self {
|
||||||
let panes: HashMap<_, _> = panes.collect();
|
let panes: HashMap<_, _> = panes.into_iter().collect();
|
||||||
let mut vars = HashMap::new();
|
let mut vars = HashMap::new();
|
||||||
for &&k in panes.keys() {
|
for &&k in panes.keys() {
|
||||||
vars.insert(k, Variable::new());
|
vars.insert(k, Variable::new());
|
||||||
|
|
@ -84,7 +84,7 @@ impl<'a> PaneResizer<'a> {
|
||||||
|
|
||||||
// Round f64 pane sizes to usize without gaps or overlap
|
// Round f64 pane sizes to usize without gaps or overlap
|
||||||
let mut finalised = Vec::new();
|
let mut finalised = Vec::new();
|
||||||
for spans in grid.iter_mut() {
|
for spans in &mut grid {
|
||||||
let rounded_size: isize = spans.iter().map(|s| rounded_sizes[&s.size_var]).sum();
|
let rounded_size: isize = spans.iter().map(|s| rounded_sizes[&s.size_var]).sum();
|
||||||
let mut error = space as isize - rounded_size;
|
let mut error = space as isize - rounded_size;
|
||||||
let mut flex_spans: Vec<_> = spans
|
let mut flex_spans: Vec<_> = spans
|
||||||
|
|
@ -105,9 +105,9 @@ impl<'a> PaneResizer<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update span positions based on their rounded sizes
|
// Update span positions based on their rounded sizes
|
||||||
for spans in grid.iter_mut() {
|
for spans in &mut grid {
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
for span in spans.iter_mut() {
|
for span in spans {
|
||||||
span.pos = offset;
|
span.pos = offset;
|
||||||
let sz = rounded_sizes[&span.size_var];
|
let sz = rounded_sizes[&span.size_var];
|
||||||
if sz < 1 {
|
if sz < 1 {
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ pub fn toggle_to_previous_tab_create_tabs_only() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 1],
|
&[0, 1],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -319,7 +319,7 @@ pub fn toggle_to_previous_tab_create_tabs_only() {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 2],
|
&[0, 2],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -331,7 +331,7 @@ pub fn toggle_to_previous_tab_create_tabs_only() {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 1],
|
&[0, 1],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -358,7 +358,7 @@ pub fn toggle_to_previous_tab_delete() {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 1, 2],
|
&[0, 1, 2],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -370,7 +370,7 @@ pub fn toggle_to_previous_tab_delete() {
|
||||||
screen.toggle_tab(1);
|
screen.toggle_tab(1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 1, 3],
|
&[0, 1, 3],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -382,7 +382,7 @@ pub fn toggle_to_previous_tab_delete() {
|
||||||
screen.toggle_tab(1);
|
screen.toggle_tab(1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 1, 2],
|
&[0, 1, 2],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -394,7 +394,7 @@ pub fn toggle_to_previous_tab_delete() {
|
||||||
screen.switch_tab_prev(1);
|
screen.switch_tab_prev(1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 1, 3],
|
&[0, 1, 3],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -405,7 +405,7 @@ pub fn toggle_to_previous_tab_delete() {
|
||||||
screen.switch_tab_prev(1);
|
screen.switch_tab_prev(1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 3, 2],
|
&[0, 3, 2],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -417,7 +417,7 @@ pub fn toggle_to_previous_tab_delete() {
|
||||||
screen.close_tab(1);
|
screen.close_tab(1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 3],
|
&[0, 3],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -434,7 +434,7 @@ pub fn toggle_to_previous_tab_delete() {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
screen.tab_history.get(&1).unwrap(),
|
screen.tab_history.get(&1).unwrap(),
|
||||||
&vec![0, 2],
|
&[0, 2],
|
||||||
"Tab history is invalid"
|
"Tab history is invalid"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ pub(crate) fn wasm_thread_main(
|
||||||
let mut plugin_map = HashMap::new();
|
let mut plugin_map = HashMap::new();
|
||||||
let plugin_dir = data_dir.join("plugins/");
|
let plugin_dir = data_dir.join("plugins/");
|
||||||
let plugin_global_data_dir = plugin_dir.join("data");
|
let plugin_global_data_dir = plugin_dir.join("data");
|
||||||
fs::create_dir_all(plugin_global_data_dir.as_path()).unwrap();
|
fs::create_dir_all(&plugin_global_data_dir).unwrap();
|
||||||
|
|
||||||
for plugin in plugins.iter() {
|
for plugin in plugins.iter() {
|
||||||
if let PluginType::Headless = plugin.run {
|
if let PluginType::Headless = plugin.run {
|
||||||
|
|
@ -160,7 +160,7 @@ pub(crate) fn wasm_thread_main(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info!("wasm main thread exits");
|
info!("wasm main thread exits");
|
||||||
fs::remove_dir_all(plugin_global_data_dir.as_path()).unwrap();
|
fs::remove_dir_all(&plugin_global_data_dir).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_plugin(
|
fn start_plugin(
|
||||||
|
|
@ -210,7 +210,7 @@ fn start_plugin(
|
||||||
.env("CLICOLOR_FORCE", "1")
|
.env("CLICOLOR_FORCE", "1")
|
||||||
.map_dir("/host", ".")
|
.map_dir("/host", ".")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map_dir("/data", plugin_own_data_dir.as_path())
|
.map_dir("/data", &plugin_own_data_dir)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.stdin(Box::new(input))
|
.stdin(Box::new(input))
|
||||||
.stdout(Box::new(output))
|
.stdout(Box::new(output))
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,7 @@ lazy_static! {
|
||||||
sock_dir.push(envs::get_session_name().unwrap());
|
sock_dir.push(envs::get_session_name().unwrap());
|
||||||
sock_dir
|
sock_dir
|
||||||
};
|
};
|
||||||
pub static ref ZELLIJ_TMP_DIR: PathBuf =
|
pub static ref ZELLIJ_TMP_DIR: PathBuf = PathBuf::from(format!("/tmp/zellij-{}", *UID));
|
||||||
PathBuf::from("/tmp/zellij-".to_string() + &format!("{}", *UID));
|
|
||||||
pub static ref ZELLIJ_TMP_LOG_DIR: PathBuf = ZELLIJ_TMP_DIR.join("zellij-log");
|
pub static ref ZELLIJ_TMP_LOG_DIR: PathBuf = ZELLIJ_TMP_DIR.join("zellij-log");
|
||||||
pub static ref ZELLIJ_TMP_LOG_FILE: PathBuf = ZELLIJ_TMP_LOG_DIR.join("zellij.log");
|
pub static ref ZELLIJ_TMP_LOG_FILE: PathBuf = ZELLIJ_TMP_LOG_DIR.join("zellij.log");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,8 @@ impl ErrorContext {
|
||||||
|
|
||||||
/// Adds a call to this [`ErrorContext`]'s call stack representation.
|
/// Adds a call to this [`ErrorContext`]'s call stack representation.
|
||||||
pub fn add_call(&mut self, call: ContextType) {
|
pub fn add_call(&mut self, call: ContextType) {
|
||||||
for ctx in self.calls.iter_mut() {
|
for ctx in &mut self.calls {
|
||||||
if *ctx == ContextType::Empty {
|
if let ContextType::Empty = ctx {
|
||||||
*ctx = call;
|
*ctx = call;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ impl Config {
|
||||||
// once serde-yaml supports zero-copy
|
// once serde-yaml supports zero-copy
|
||||||
pub fn from_default_assets() -> ConfigResult {
|
pub fn from_default_assets() -> ConfigResult {
|
||||||
let cfg = String::from_utf8(setup::DEFAULT_CONFIG.to_vec())?;
|
let cfg = String::from_utf8(setup::DEFAULT_CONFIG.to_vec())?;
|
||||||
Self::from_yaml(cfg.as_str())
|
Self::from_yaml(&cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merges two Config structs into one Config struct
|
/// Merges two Config structs into one Config struct
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ impl Keybinds {
|
||||||
|
|
||||||
for mode in InputMode::iter() {
|
for mode in InputMode::iter() {
|
||||||
if let Some(keybinds) = keybinds_from_yaml.get(&mode) {
|
if let Some(keybinds) = keybinds_from_yaml.get(&mode) {
|
||||||
for keybind in keybinds.iter() {
|
for keybind in keybinds {
|
||||||
match keybind {
|
match keybind {
|
||||||
KeyActionUnbind::Unbind(unbind) => {
|
KeyActionUnbind::Unbind(unbind) => {
|
||||||
unbind_config.insert(mode, unbind.unbind.clone());
|
unbind_config.insert(mode, unbind.unbind.clone());
|
||||||
|
|
@ -242,8 +242,8 @@ impl From<KeybindsFromYaml> for Keybinds {
|
||||||
|
|
||||||
for mode in InputMode::iter() {
|
for mode in InputMode::iter() {
|
||||||
let mut mode_keybinds = ModeKeybinds::new();
|
let mut mode_keybinds = ModeKeybinds::new();
|
||||||
for key_action in keybinds_from_yaml.keybinds.get(&mode).iter() {
|
if let Some(key_action) = keybinds_from_yaml.keybinds.get(&mode) {
|
||||||
for keybind in key_action.iter() {
|
for keybind in key_action {
|
||||||
mode_keybinds = mode_keybinds.merge(ModeKeybinds::from(keybind.clone()));
|
mode_keybinds = mode_keybinds.merge(ModeKeybinds::from(keybind.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -254,8 +254,8 @@ impl LayoutFromYamlIntermediate {
|
||||||
) -> LayoutFromYamlIntermediateResult {
|
) -> LayoutFromYamlIntermediateResult {
|
||||||
match layout_dir {
|
match layout_dir {
|
||||||
Some(dir) => Self::from_path(&dir.join(layout))
|
Some(dir) => Self::from_path(&dir.join(layout))
|
||||||
.or_else(|_| LayoutFromYamlIntermediate::from_default_assets(layout.as_path())),
|
.or_else(|_| LayoutFromYamlIntermediate::from_default_assets(layout)),
|
||||||
None => LayoutFromYamlIntermediate::from_default_assets(layout.as_path()),
|
None => LayoutFromYamlIntermediate::from_default_assets(layout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Currently still needed but on nightly
|
// Currently still needed but on nightly
|
||||||
|
|
@ -277,19 +277,19 @@ impl LayoutFromYamlIntermediate {
|
||||||
// once serde-yaml supports zero-copy
|
// once serde-yaml supports zero-copy
|
||||||
pub fn default_from_assets() -> LayoutFromYamlIntermediateResult {
|
pub fn default_from_assets() -> LayoutFromYamlIntermediateResult {
|
||||||
let layout: LayoutFromYamlIntermediate =
|
let layout: LayoutFromYamlIntermediate =
|
||||||
serde_yaml::from_str(String::from_utf8(setup::DEFAULT_LAYOUT.to_vec())?.as_str())?;
|
serde_yaml::from_str(&String::from_utf8(setup::DEFAULT_LAYOUT.to_vec())?)?;
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn strider_from_assets() -> LayoutFromYamlIntermediateResult {
|
pub fn strider_from_assets() -> LayoutFromYamlIntermediateResult {
|
||||||
let layout: LayoutFromYamlIntermediate =
|
let layout: LayoutFromYamlIntermediate =
|
||||||
serde_yaml::from_str(String::from_utf8(setup::STRIDER_LAYOUT.to_vec())?.as_str())?;
|
serde_yaml::from_str(&String::from_utf8(setup::STRIDER_LAYOUT.to_vec())?)?;
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_status_from_assets() -> LayoutFromYamlIntermediateResult {
|
pub fn disable_status_from_assets() -> LayoutFromYamlIntermediateResult {
|
||||||
let layout: LayoutFromYamlIntermediate =
|
let layout: LayoutFromYamlIntermediate =
|
||||||
serde_yaml::from_str(String::from_utf8(setup::NO_STATUS_LAYOUT.to_vec())?.as_str())?;
|
serde_yaml::from_str(&String::from_utf8(setup::NO_STATUS_LAYOUT.to_vec())?)?;
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -331,9 +331,10 @@ impl LayoutFromYaml {
|
||||||
#[allow(clippy::ptr_arg)]
|
#[allow(clippy::ptr_arg)]
|
||||||
pub fn from_dir(layout: &PathBuf, layout_dir: Option<&PathBuf>) -> LayoutFromYamlResult {
|
pub fn from_dir(layout: &PathBuf, layout_dir: Option<&PathBuf>) -> LayoutFromYamlResult {
|
||||||
match layout_dir {
|
match layout_dir {
|
||||||
Some(dir) => Self::new(&dir.join(layout))
|
Some(dir) => {
|
||||||
.or_else(|_| Self::from_default_assets(layout.as_path())),
|
Self::new(&dir.join(layout)).or_else(|_| Self::from_default_assets(layout))
|
||||||
None => Self::from_default_assets(layout.as_path()),
|
}
|
||||||
|
None => Self::from_default_assets(layout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -372,19 +373,19 @@ impl LayoutFromYaml {
|
||||||
// once serde-yaml supports zero-copy
|
// once serde-yaml supports zero-copy
|
||||||
pub fn default_from_assets() -> LayoutFromYamlResult {
|
pub fn default_from_assets() -> LayoutFromYamlResult {
|
||||||
let layout: LayoutFromYaml =
|
let layout: LayoutFromYaml =
|
||||||
serde_yaml::from_str(String::from_utf8(setup::DEFAULT_LAYOUT.to_vec())?.as_str())?;
|
serde_yaml::from_str(&String::from_utf8(setup::DEFAULT_LAYOUT.to_vec())?)?;
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn strider_from_assets() -> LayoutFromYamlResult {
|
pub fn strider_from_assets() -> LayoutFromYamlResult {
|
||||||
let layout: LayoutFromYaml =
|
let layout: LayoutFromYaml =
|
||||||
serde_yaml::from_str(String::from_utf8(setup::STRIDER_LAYOUT.to_vec())?.as_str())?;
|
serde_yaml::from_str(&String::from_utf8(setup::STRIDER_LAYOUT.to_vec())?)?;
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disable_status_from_assets() -> LayoutFromYamlResult {
|
pub fn disable_status_from_assets() -> LayoutFromYamlResult {
|
||||||
let layout: LayoutFromYaml =
|
let layout: LayoutFromYaml =
|
||||||
serde_yaml::from_str(String::from_utf8(setup::NO_STATUS_LAYOUT.to_vec())?.as_str())?;
|
serde_yaml::from_str(&String::from_utf8(setup::NO_STATUS_LAYOUT.to_vec())?)?;
|
||||||
Ok(layout)
|
Ok(layout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -465,7 +466,7 @@ pub struct TabLayout {
|
||||||
|
|
||||||
impl TabLayout {
|
impl TabLayout {
|
||||||
fn check(&self) -> Result<TabLayout, ConfigError> {
|
fn check(&self) -> Result<TabLayout, ConfigError> {
|
||||||
for part in self.parts.iter() {
|
for part in &self.parts {
|
||||||
part.check()?;
|
part.check()?;
|
||||||
if !part.name.is_empty() {
|
if !part.name.is_empty() {
|
||||||
return Err(ConfigError::LayoutNameInTab(LayoutNameInTabError));
|
return Err(ConfigError::LayoutNameInTab(LayoutNameInTabError));
|
||||||
|
|
@ -479,7 +480,7 @@ impl Layout {
|
||||||
pub fn total_terminal_panes(&self) -> usize {
|
pub fn total_terminal_panes(&self) -> usize {
|
||||||
let mut total_panes = 0;
|
let mut total_panes = 0;
|
||||||
total_panes += self.parts.len();
|
total_panes += self.parts.len();
|
||||||
for part in self.parts.iter() {
|
for part in &self.parts {
|
||||||
match part.run {
|
match part.run {
|
||||||
Some(Run::Command(_)) | None => {
|
Some(Run::Command(_)) | None => {
|
||||||
total_panes += part.total_terminal_panes();
|
total_panes += part.total_terminal_panes();
|
||||||
|
|
@ -493,7 +494,7 @@ impl Layout {
|
||||||
pub fn total_borderless_panes(&self) -> usize {
|
pub fn total_borderless_panes(&self) -> usize {
|
||||||
let mut total_borderless_panes = 0;
|
let mut total_borderless_panes = 0;
|
||||||
total_borderless_panes += self.parts.iter().filter(|p| p.borderless).count();
|
total_borderless_panes += self.parts.iter().filter(|p| p.borderless).count();
|
||||||
for part in self.parts.iter() {
|
for part in &self.parts {
|
||||||
total_borderless_panes += part.total_borderless_panes();
|
total_borderless_panes += part.total_borderless_panes();
|
||||||
}
|
}
|
||||||
total_borderless_panes
|
total_borderless_panes
|
||||||
|
|
@ -503,7 +504,7 @@ impl Layout {
|
||||||
if self.parts.is_empty() {
|
if self.parts.is_empty() {
|
||||||
run_instructions.push(self.run.clone());
|
run_instructions.push(self.run.clone());
|
||||||
}
|
}
|
||||||
for part in self.parts.iter() {
|
for part in &self.parts {
|
||||||
let mut current_runnables = part.extract_run_instructions();
|
let mut current_runnables = part.extract_run_instructions();
|
||||||
run_instructions.append(&mut current_runnables);
|
run_instructions.append(&mut current_runnables);
|
||||||
}
|
}
|
||||||
|
|
@ -549,7 +550,7 @@ fn layout_size(direction: Direction, layout: &Layout) -> usize {
|
||||||
.parts
|
.parts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| child_layout_size(direction, layout.direction, p))
|
.map(|p| child_layout_size(direction, layout.direction, p))
|
||||||
.sum::<usize>();
|
.sum();
|
||||||
max(size, children_size)
|
max(size, children_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ pub use zellij_tile::data::PluginTag;
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref DEFAULT_CONFIG_PLUGINS: PluginsConfig = {
|
static ref DEFAULT_CONFIG_PLUGINS: PluginsConfig = {
|
||||||
let cfg = String::from_utf8(setup::DEFAULT_CONFIG.to_vec()).unwrap();
|
let cfg = String::from_utf8(setup::DEFAULT_CONFIG.to_vec()).unwrap();
|
||||||
let cfg_yaml: ConfigFromYaml = serde_yaml::from_str(cfg.as_str()).unwrap();
|
let cfg_yaml: ConfigFromYaml = serde_yaml::from_str(&cfg).unwrap();
|
||||||
PluginsConfig::try_from(cfg_yaml.plugins).unwrap()
|
PluginsConfig::try_from(cfg_yaml.plugins).unwrap()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +271,7 @@ mod tests {
|
||||||
)?;
|
)?;
|
||||||
let plugins = PluginsConfig::get_plugins_with_default(plugins.try_into()?);
|
let plugins = PluginsConfig::get_plugins_with_default(plugins.try_into()?);
|
||||||
|
|
||||||
assert_eq!(plugins.iter().collect::<Vec<_>>().len(), 4);
|
assert_eq!(plugins.iter().count(), 4);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ pub fn atomic_create_dir(dir_name: &Path) -> io::Result<()> {
|
||||||
pub fn debug_to_file(message: &[u8], pid: RawFd) -> io::Result<()> {
|
pub fn debug_to_file(message: &[u8], pid: RawFd) -> io::Result<()> {
|
||||||
let mut path = PathBuf::new();
|
let mut path = PathBuf::new();
|
||||||
path.push(&*ZELLIJ_TMP_LOG_DIR);
|
path.push(&*ZELLIJ_TMP_LOG_DIR);
|
||||||
path.push(format!("zellij-{}.log", pid.to_string()));
|
path.push(format!("zellij-{}.log", pid));
|
||||||
|
|
||||||
let mut file = fs::OpenOptions::new()
|
let mut file = fs::OpenOptions::new()
|
||||||
.append(true)
|
.append(true)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ use crate::{
|
||||||
};
|
};
|
||||||
use directories_next::BaseDirs;
|
use directories_next::BaseDirs;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{convert::TryFrom, io::Write, path::Path, path::PathBuf, process};
|
use std::{
|
||||||
|
convert::TryFrom, fmt::Write as FmtWrite, io::Write, path::Path, path::PathBuf, process,
|
||||||
|
};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
const CONFIG_LOCATION: &str = ".config/zellij";
|
const CONFIG_LOCATION: &str = ".config/zellij";
|
||||||
|
|
@ -47,7 +49,7 @@ fn default_config_dirs() -> Vec<Option<PathBuf>> {
|
||||||
/// Looks for an existing dir, uses that, else returns a
|
/// Looks for an existing dir, uses that, else returns a
|
||||||
/// dir matching the config spec.
|
/// dir matching the config spec.
|
||||||
pub fn get_default_data_dir() -> PathBuf {
|
pub fn get_default_data_dir() -> PathBuf {
|
||||||
vec![
|
[
|
||||||
xdg_data_dir(),
|
xdg_data_dir(),
|
||||||
Path::new(SYSTEM_DEFAULT_DATA_DIR_PREFIX).join("share/zellij"),
|
Path::new(SYSTEM_DEFAULT_DATA_DIR_PREFIX).join("share/zellij"),
|
||||||
]
|
]
|
||||||
|
|
@ -300,9 +302,9 @@ impl Setup {
|
||||||
|
|
||||||
let mut message = String::new();
|
let mut message = String::new();
|
||||||
|
|
||||||
message.push_str(&format!("[Version]: {:?}\n", VERSION));
|
writeln!(&mut message, "[Version]: {:?}", VERSION).unwrap();
|
||||||
if let Some(config_dir) = config_dir {
|
if let Some(config_dir) = config_dir {
|
||||||
message.push_str(&format!("[CONFIG DIR]: {:?}\n", config_dir));
|
writeln!(&mut message, "[CONFIG DIR]: {:?}", config_dir).unwrap();
|
||||||
} else {
|
} else {
|
||||||
message.push_str("[CONFIG DIR]: Not Found\n");
|
message.push_str("[CONFIG DIR]: Not Found\n");
|
||||||
let mut default_config_dirs = default_config_dirs()
|
let mut default_config_dirs = default_config_dirs()
|
||||||
|
|
@ -314,32 +316,34 @@ impl Setup {
|
||||||
" On your system zellij looks in the following config directories by default:\n",
|
" On your system zellij looks in the following config directories by default:\n",
|
||||||
);
|
);
|
||||||
for dir in default_config_dirs {
|
for dir in default_config_dirs {
|
||||||
message.push_str(&format!(" {:?}\n", dir));
|
writeln!(&mut message, " {:?}", dir).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(config_file) = config_file {
|
if let Some(config_file) = config_file {
|
||||||
message.push_str(&format!("[CONFIG FILE]: {:?}\n", config_file));
|
writeln!(&mut message, "[CONFIG FILE]: {:?}", config_file).unwrap();
|
||||||
match Config::new(&config_file) {
|
match Config::new(&config_file) {
|
||||||
Ok(_) => message.push_str("[CONFIG FILE]: Well defined.\n"),
|
Ok(_) => message.push_str("[CONFIG FILE]: Well defined.\n"),
|
||||||
Err(e) => message.push_str(&format!("[CONFIG ERROR]: {}\n", e)),
|
Err(e) => writeln!(&mut message, "[CONFIG ERROR]: {}", e).unwrap(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.push_str("[CONFIG FILE]: Not Found\n");
|
message.push_str("[CONFIG FILE]: Not Found\n");
|
||||||
message.push_str(&format!(
|
writeln!(
|
||||||
" By default zellij looks for a file called [{}] in the configuration directory\n",
|
&mut message,
|
||||||
|
" By default zellij looks for a file called [{}] in the configuration directory",
|
||||||
CONFIG_NAME
|
CONFIG_NAME
|
||||||
));
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
message.push_str(&format!("[DATA DIR]: {:?}\n", data_dir));
|
writeln!(&mut message, "[DATA DIR]: {:?}", data_dir).unwrap();
|
||||||
message.push_str(&format!("[PLUGIN DIR]: {:?}\n", plugin_dir));
|
message.push_str(&format!("[PLUGIN DIR]: {:?}\n", plugin_dir));
|
||||||
if let Some(layout_dir) = layout_dir {
|
if let Some(layout_dir) = layout_dir {
|
||||||
message.push_str(&format!("[LAYOUT DIR]: {:?}\n", layout_dir));
|
writeln!(&mut message, "[LAYOUT DIR]: {:?}", layout_dir).unwrap();
|
||||||
} else {
|
} else {
|
||||||
message.push_str("[LAYOUT DIR]: Not Found\n");
|
message.push_str("[LAYOUT DIR]: Not Found\n");
|
||||||
}
|
}
|
||||||
message.push_str(&format!("[SYSTEM DATA DIR]: {:?}\n", system_data_dir));
|
writeln!(&mut message, "[SYSTEM DATA DIR]: {:?}", system_data_dir).unwrap();
|
||||||
|
|
||||||
message.push_str(&format!("[ARROW SEPARATOR]: {}\n", ARROW_SEPARATOR));
|
writeln!(&mut message, "[ARROW SEPARATOR]: {}", ARROW_SEPARATOR).unwrap();
|
||||||
message.push_str(" Is the [ARROW_SEPARATOR] displayed correctly?\n");
|
message.push_str(" Is the [ARROW_SEPARATOR] displayed correctly?\n");
|
||||||
message.push_str(" If not you may want to either start zellij with a compatible mode: 'zellij options --simplified-ui true'\n");
|
message.push_str(" If not you may want to either start zellij with a compatible mode: 'zellij options --simplified-ui true'\n");
|
||||||
let mut hyperlink_compat = String::new();
|
let mut hyperlink_compat = String::new();
|
||||||
|
|
@ -348,22 +352,24 @@ impl Setup {
|
||||||
hyperlink_compat.push_str(hyperlink_mid);
|
hyperlink_compat.push_str(hyperlink_mid);
|
||||||
hyperlink_compat.push_str("https://zellij.dev/documentation/compatibility.html#the-status-bar-fonts-dont-render-correctly");
|
hyperlink_compat.push_str("https://zellij.dev/documentation/compatibility.html#the-status-bar-fonts-dont-render-correctly");
|
||||||
hyperlink_compat.push_str(hyperlink_end);
|
hyperlink_compat.push_str(hyperlink_end);
|
||||||
message.push_str(&format!(
|
write!(
|
||||||
|
&mut message,
|
||||||
" Or check the font that is in use:\n {}\n",
|
" Or check the font that is in use:\n {}\n",
|
||||||
hyperlink_compat
|
hyperlink_compat
|
||||||
));
|
)
|
||||||
|
.unwrap();
|
||||||
message.push_str("[MOUSE INTERACTION]: \n");
|
message.push_str("[MOUSE INTERACTION]: \n");
|
||||||
message.push_str(" Can be temporarily disabled through pressing the [SHIFT] key.\n");
|
message.push_str(" Can be temporarily disabled through pressing the [SHIFT] key.\n");
|
||||||
message.push_str(" If that doesn't fix any issues consider to disable the mouse handling of zellij: 'zellij options --disable-mouse-mode'\n");
|
message.push_str(" If that doesn't fix any issues consider to disable the mouse handling of zellij: 'zellij options --disable-mouse-mode'\n");
|
||||||
|
|
||||||
message.push_str(&format!("[FEATURES]: {:?}\n", FEATURES));
|
writeln!(&mut message, "[FEATURES]: {:?}", FEATURES).unwrap();
|
||||||
let mut hyperlink = String::new();
|
let mut hyperlink = String::new();
|
||||||
hyperlink.push_str(hyperlink_start);
|
hyperlink.push_str(hyperlink_start);
|
||||||
hyperlink.push_str("https://www.zellij.dev/documentation/");
|
hyperlink.push_str("https://www.zellij.dev/documentation/");
|
||||||
hyperlink.push_str(hyperlink_mid);
|
hyperlink.push_str(hyperlink_mid);
|
||||||
hyperlink.push_str("zellij.dev/documentation");
|
hyperlink.push_str("zellij.dev/documentation");
|
||||||
hyperlink.push_str(hyperlink_end);
|
hyperlink.push_str(hyperlink_end);
|
||||||
message.push_str(&format!("[DOCUMENTATION]: {}\n", hyperlink));
|
writeln!(&mut message, "[DOCUMENTATION]: {}", hyperlink).unwrap();
|
||||||
//printf '\e]8;;http://example.com\e\\This is a link\e]8;;\e\\\n'
|
//printf '\e]8;;http://example.com\e\\This is a link\e]8;;\e\\\n'
|
||||||
|
|
||||||
std::io::stdout().write_all(message.as_bytes())?;
|
std::io::stdout().write_all(message.as_bytes())?;
|
||||||
|
|
@ -371,14 +377,10 @@ impl Setup {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn generate_completion(shell: String) {
|
fn generate_completion(shell: String) {
|
||||||
let shell = match shell.as_ref() {
|
let shell = match shell.parse() {
|
||||||
"bash" => structopt::clap::Shell::Bash,
|
Ok(shell) => shell,
|
||||||
"fish" => structopt::clap::Shell::Fish,
|
_ => {
|
||||||
"zsh" => structopt::clap::Shell::Zsh,
|
eprintln!("Unsupported shell: {}", shell);
|
||||||
"powerShell" => structopt::clap::Shell::PowerShell,
|
|
||||||
"elvish" => structopt::clap::Shell::Elvish,
|
|
||||||
other => {
|
|
||||||
eprintln!("Unsupported shell: {}", other);
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -400,8 +402,8 @@ mod setup_test {
|
||||||
config: &str,
|
config: &str,
|
||||||
layout: &str,
|
layout: &str,
|
||||||
) -> Result<(Config, LayoutFromYamlIntermediate), ConfigError> {
|
) -> Result<(Config, LayoutFromYamlIntermediate), ConfigError> {
|
||||||
let config = Config::from_yaml(&config)?;
|
let config = Config::from_yaml(config)?;
|
||||||
let layout = LayoutFromYamlIntermediate::from_yaml(&layout)?;
|
let layout = LayoutFromYamlIntermediate::from_yaml(layout)?;
|
||||||
Ok((config, layout))
|
Ok((config, layout))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ pub fn set_permissions(path: &Path) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ansi_len(s: &str) -> usize {
|
pub fn ansi_len(s: &str) -> usize {
|
||||||
from_utf8(&strip(s.as_bytes()).unwrap()).unwrap().width()
|
from_utf8(&strip(s).unwrap()).unwrap().width()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn adjust_to_size(s: &str, rows: usize, columns: usize) -> String {
|
pub fn adjust_to_size(s: &str, rows: usize, columns: usize) -> String {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue