mirror of
https://github.com/zellij-org/zellij.git
synced 2024-12-28 11:42:41 +03:00
refactor(ansi-codes): treat ansi codes properly and also make things clearer (#85)
This commit is contained in:
parent
576876b475
commit
94d6f3dbf6
@ -1,3 +1,4 @@
|
||||
use crate::utils::logging::debug_log_to_file;
|
||||
use ::std::fmt::{self, Debug, Display, Formatter};
|
||||
|
||||
pub const EMPTY_TERMINAL_CHARACTER: TerminalCharacter = TerminalCharacter {
|
||||
@ -297,6 +298,114 @@ impl CharacterStyles {
|
||||
self.hidden = Some(AnsiCode::Reset);
|
||||
self.strike = Some(AnsiCode::Reset);
|
||||
}
|
||||
pub fn add_style_from_ansi_params(&mut self, ansi_params: &[i64]) {
|
||||
let mut params_used = 1; // if there's a parameter, it is always used
|
||||
if ansi_params.is_empty() || ansi_params[0] == 0 {
|
||||
self.reset_all();
|
||||
} else if ansi_params[0] == 39 {
|
||||
*self = self.foreground(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 49 {
|
||||
*self = self.background(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 21 {
|
||||
*self = self.bold(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 22 {
|
||||
*self = self.bold(Some(AnsiCode::Reset));
|
||||
*self = self.dim(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 23 {
|
||||
*self = self.italic(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 24 {
|
||||
*self = self.underline(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 25 {
|
||||
*self = self.blink_slow(Some(AnsiCode::Reset));
|
||||
*self = self.blink_fast(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 27 {
|
||||
*self = self.reverse(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 28 {
|
||||
*self = self.hidden(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 29 {
|
||||
*self = self.strike(Some(AnsiCode::Reset));
|
||||
} else if ansi_params[0] == 38 {
|
||||
let ansi_code = AnsiCode::Code((
|
||||
ansi_params.get(1).map(|p| *p as u16),
|
||||
ansi_params.get(2).map(|p| *p as u16),
|
||||
));
|
||||
*self = self.foreground(Some(ansi_code));
|
||||
if ansi_params.len() > 2 {
|
||||
params_used += ansi_params.len() - 1;
|
||||
}
|
||||
} else if ansi_params[0] == 48 {
|
||||
let ansi_code = AnsiCode::Code((
|
||||
ansi_params.get(1).map(|p| *p as u16),
|
||||
ansi_params.get(2).map(|p| *p as u16),
|
||||
));
|
||||
*self = self.background(Some(ansi_code));
|
||||
if ansi_params.get(1).is_some() {
|
||||
params_used += 1;
|
||||
}
|
||||
if ansi_params.get(2).is_some() {
|
||||
params_used += 1;
|
||||
}
|
||||
} else if ansi_params[0] == 1 {
|
||||
*self = self.bold(Some(AnsiCode::Code((Some(1), None))));
|
||||
} else if ansi_params[0] == 2 {
|
||||
*self = self.dim(Some(AnsiCode::Code((Some(2), None))));
|
||||
} else if ansi_params[0] == 3 {
|
||||
*self = self.italic(Some(AnsiCode::Code((Some(3), None))));
|
||||
} else if ansi_params[0] == 4 {
|
||||
*self = self.underline(Some(AnsiCode::Code((Some(4), None))));
|
||||
} else if ansi_params[0] == 5 {
|
||||
*self = self.blink_slow(Some(AnsiCode::Code((Some(5), None))));
|
||||
} else if ansi_params[0] == 6 {
|
||||
*self = self.blink_fast(Some(AnsiCode::Code((Some(6), None))));
|
||||
} else if ansi_params[0] == 7 {
|
||||
*self = self.reverse(Some(AnsiCode::Code((Some(7), None))));
|
||||
} else if ansi_params[0] == 8 {
|
||||
*self = self.hidden(Some(AnsiCode::Code((Some(8), None))));
|
||||
} else if ansi_params[0] == 9 {
|
||||
*self = self.strike(Some(AnsiCode::Code((Some(9), None))));
|
||||
} else if ansi_params[0] == 30 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Black)));
|
||||
} else if ansi_params[0] == 31 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Red)));
|
||||
} else if ansi_params[0] == 32 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Green)));
|
||||
} else if ansi_params[0] == 33 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Yellow)));
|
||||
} else if ansi_params[0] == 34 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Blue)));
|
||||
} else if ansi_params[0] == 35 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Magenta)));
|
||||
} else if ansi_params[0] == 36 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::Cyan)));
|
||||
} else if ansi_params[0] == 37 {
|
||||
*self = self.foreground(Some(AnsiCode::NamedColor(NamedColor::White)));
|
||||
} else if ansi_params[0] == 40 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::Black)));
|
||||
} else if ansi_params[0] == 41 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::Red)));
|
||||
} else if ansi_params[0] == 42 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::Green)));
|
||||
} else if ansi_params[0] == 43 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::Yellow)));
|
||||
} else if ansi_params[0] == 44 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::Blue)));
|
||||
} else if ansi_params[0] == 45 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::Magenta)));
|
||||
} else if ansi_params[0] == 46 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::Cyan)));
|
||||
} else if ansi_params[0] == 47 {
|
||||
*self = self.background(Some(AnsiCode::NamedColor(NamedColor::White)));
|
||||
} else {
|
||||
// if this happens, it's a bug
|
||||
let _ = debug_log_to_file(format!("unhandled csi m code {:?}", ansi_params));
|
||||
return;
|
||||
}
|
||||
if let Some(next_params) = ansi_params.get(params_used..) {
|
||||
if next_params.len() > 0 {
|
||||
self.add_style_from_ansi_params(next_params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for CharacterStyles {
|
||||
|
@ -9,7 +9,7 @@ use crate::terminal_pane::terminal_character::{
|
||||
AnsiCode, CharacterStyles, NamedColor, TerminalCharacter,
|
||||
};
|
||||
use crate::terminal_pane::Scroll;
|
||||
use crate::utils::logging::{debug_log_to_file, debug_log_to_file_pid_3};
|
||||
use crate::utils::logging::debug_log_to_file;
|
||||
use crate::VteEvent;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
@ -398,340 +398,7 @@ impl vte::Perform for TerminalPane {
|
||||
|
||||
fn csi_dispatch(&mut self, params: &[i64], _intermediates: &[u8], _ignore: bool, c: char) {
|
||||
if c == 'm' {
|
||||
if params.is_empty() || params[0] == 0 {
|
||||
// reset all
|
||||
self.pending_styles.reset_all();
|
||||
if let Some(param1) = params.get(1) {
|
||||
// TODO: this is a case currently found in eg. htop where we get two different
|
||||
// csi 'm' codes in one event.
|
||||
// We should understand why these are happening and then make a more generic
|
||||
// solution for them
|
||||
if *param1 == 1 {
|
||||
// bold
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.bold(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
}
|
||||
} else if params[0] == 39 {
|
||||
self.pending_styles = self.pending_styles.foreground(Some(AnsiCode::Reset));
|
||||
if let Some(param1) = params.get(1) {
|
||||
// TODO: this is a case currently found in eg. htop where we get two different
|
||||
// csi 'm' codes in one event.
|
||||
// We should understand why these are happening and then make a more generic
|
||||
// solution for them
|
||||
if *param1 == 49 {
|
||||
// TODO: if we need this to fix the bug, we need to make collecting the
|
||||
// second argument in such cases generic
|
||||
self.pending_styles = self.pending_styles.background(Some(AnsiCode::Reset));
|
||||
}
|
||||
}
|
||||
} else if params[0] == 49 {
|
||||
self.pending_styles = self.pending_styles.background(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 21 {
|
||||
// reset bold
|
||||
self.pending_styles = self.pending_styles.bold(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 22 {
|
||||
// reset bold and dim
|
||||
self.pending_styles = self.pending_styles.bold(Some(AnsiCode::Reset));
|
||||
self.pending_styles = self.pending_styles.dim(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 23 {
|
||||
// reset italic
|
||||
self.pending_styles = self.pending_styles.italic(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 24 {
|
||||
// reset underline
|
||||
self.pending_styles = self.pending_styles.underline(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 25 {
|
||||
// reset blink
|
||||
self.pending_styles = self.pending_styles.blink_slow(Some(AnsiCode::Reset));
|
||||
self.pending_styles = self.pending_styles.blink_fast(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 27 {
|
||||
// reset reverse
|
||||
self.pending_styles = self.pending_styles.reverse(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 28 {
|
||||
// reset hidden
|
||||
self.pending_styles = self.pending_styles.hidden(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 29 {
|
||||
// reset strike
|
||||
self.pending_styles = self.pending_styles.strike(Some(AnsiCode::Reset));
|
||||
} else if params[0] == 38 {
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.foreground(Some(AnsiCode::Code(
|
||||
(Some(*param1 as u16), Some(*param2 as u16)),
|
||||
)));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 48 {
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.background(Some(AnsiCode::Code(
|
||||
(Some(*param1 as u16), Some(*param2 as u16)),
|
||||
)));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 1 {
|
||||
// bold
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.bold(Some(AnsiCode::Code((
|
||||
Some(*param1 as u16),
|
||||
Some(*param2 as u16),
|
||||
))));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.bold(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles =
|
||||
self.pending_styles.bold(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 2 {
|
||||
// dim
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.dim(Some(AnsiCode::Code((
|
||||
Some(*param1 as u16),
|
||||
Some(*param2 as u16),
|
||||
))));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.dim(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles =
|
||||
self.pending_styles.dim(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 3 {
|
||||
// italic
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.italic(Some(AnsiCode::Code((
|
||||
Some(*param1 as u16),
|
||||
Some(*param2 as u16),
|
||||
))));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.italic(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.italic(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 4 {
|
||||
// underline
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.underline(Some(AnsiCode::Code(
|
||||
(Some(*param1 as u16), Some(*param2 as u16)),
|
||||
)));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.underline(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.underline(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 5 {
|
||||
// blink slow
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.blink_slow(Some(AnsiCode::Code(
|
||||
(Some(*param1 as u16), Some(*param2 as u16)),
|
||||
)));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.blink_slow(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.blink_slow(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 6 {
|
||||
// blink fast
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.blink_fast(Some(AnsiCode::Code(
|
||||
(Some(*param1 as u16), Some(*param2 as u16)),
|
||||
)));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.blink_fast(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.blink_fast(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 7 {
|
||||
// reverse
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.reverse(Some(AnsiCode::Code((
|
||||
Some(*param1 as u16),
|
||||
Some(*param2 as u16),
|
||||
))));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.reverse(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.reverse(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 8 {
|
||||
// hidden
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.hidden(Some(AnsiCode::Code((
|
||||
Some(*param1 as u16),
|
||||
Some(*param2 as u16),
|
||||
))));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.hidden(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.hidden(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 9 {
|
||||
// strike
|
||||
match (params.get(1), params.get(2)) {
|
||||
(Some(param1), Some(param2)) => {
|
||||
self.pending_styles = self.pending_styles.strike(Some(AnsiCode::Code((
|
||||
Some(*param1 as u16),
|
||||
Some(*param2 as u16),
|
||||
))));
|
||||
}
|
||||
(Some(param1), None) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.strike(Some(AnsiCode::Code((Some(*param1 as u16), None))));
|
||||
}
|
||||
(_, _) => {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.strike(Some(AnsiCode::Code((None, None))));
|
||||
}
|
||||
};
|
||||
} else if params[0] == 30 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::Black)));
|
||||
} else if params[0] == 31 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::Red)));
|
||||
} else if params[0] == 32 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::Green)));
|
||||
} else if params[0] == 33 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::Yellow)));
|
||||
} else if params[0] == 34 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::Blue)));
|
||||
} else if params[0] == 35 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::Magenta)));
|
||||
} else if params[0] == 36 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::Cyan)));
|
||||
} else if params[0] == 37 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.foreground(Some(AnsiCode::NamedColor(NamedColor::White)));
|
||||
} else if params[0] == 40 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::Black)));
|
||||
} else if params[0] == 41 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::Red)));
|
||||
} else if params[0] == 42 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::Green)));
|
||||
} else if params[0] == 43 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::Yellow)));
|
||||
} else if params[0] == 44 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::Blue)));
|
||||
} else if params[0] == 45 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::Magenta)));
|
||||
} else if params[0] == 46 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::Cyan)));
|
||||
} else if params[0] == 47 {
|
||||
self.pending_styles = self
|
||||
.pending_styles
|
||||
.background(Some(AnsiCode::NamedColor(NamedColor::White)));
|
||||
} else {
|
||||
let _ = debug_log_to_file(format!("unhandled csi m code {:?}", params));
|
||||
}
|
||||
self.pending_styles.add_style_from_ansi_params(params);
|
||||
} else if c == 'C' {
|
||||
// move cursor forward
|
||||
let move_by = if params[0] == 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user