mirror of
https://github.com/wez/wezterm.git
synced 2024-11-27 12:23:46 +03:00
termwiz: add flag to force use of standard ANSI SGR codes
With a TERM of "screen-256color" or "screen", common attributes such as bold are rendered with a \x0f AKA ^O AKA \017 code that makes pagers such as less and streampager grumpy. In particular, streampager renders as inverted "<0F>" and less as inverted "^O". Add a new flag force_terminfo_render_to_use_ansi_sgr which makes the TerminfoRenderer ignore the terminfo entries for common attributes, instead using the standard ANSI/ECMA-48 sequences.
This commit is contained in:
parent
f898c15c9b
commit
1dcec5e5ae
@ -107,6 +107,13 @@ builder! {
|
||||
|
||||
/// Whether mouse support is present and should be used
|
||||
mouse_reporting: Option<bool>,
|
||||
|
||||
/// When true, rather than using the terminfo `sgr` or `sgr0` entries,
|
||||
/// assume that the terminal is ANSI/ECMA-48 compliant for the
|
||||
/// common SGR attributes of bold, dim, reverse, underline, blink,
|
||||
/// invisible and reset, and directly emit those sequences.
|
||||
/// This can improve rendered text compatibility with pagers.
|
||||
force_terminfo_render_to_use_ansi_sgr: Option<bool>,
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +161,7 @@ pub struct Capabilities {
|
||||
terminfo_db: Option<terminfo::Database>,
|
||||
bracketed_paste: bool,
|
||||
mouse_reporting: bool,
|
||||
force_terminfo_render_to_use_ansi_sgr: bool,
|
||||
}
|
||||
|
||||
impl Capabilities {
|
||||
@ -282,6 +290,9 @@ impl Capabilities {
|
||||
let bracketed_paste = hints.bracketed_paste.unwrap_or(true);
|
||||
let mouse_reporting = hints.mouse_reporting.unwrap_or(true);
|
||||
|
||||
let force_terminfo_render_to_use_ansi_sgr =
|
||||
hints.force_terminfo_render_to_use_ansi_sgr.unwrap_or(false);
|
||||
|
||||
Ok(Self {
|
||||
color_level,
|
||||
sixel,
|
||||
@ -291,6 +302,7 @@ impl Capabilities {
|
||||
terminfo_db,
|
||||
bracketed_paste,
|
||||
mouse_reporting,
|
||||
force_terminfo_render_to_use_ansi_sgr,
|
||||
})
|
||||
}
|
||||
|
||||
@ -336,6 +348,12 @@ impl Capabilities {
|
||||
pub fn mouse_reporting(&self) -> bool {
|
||||
self.mouse_reporting
|
||||
}
|
||||
|
||||
/// Whether to emit standard ANSI/ECMA-48 codes, overriding any
|
||||
/// SGR terminfo capabilities.
|
||||
pub fn force_terminfo_render_to_use_ansi_sgr(&self) -> bool {
|
||||
self.force_terminfo_render_to_use_ansi_sgr
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -50,13 +50,18 @@ impl TerminfoRenderer {
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))]
|
||||
fn flush_pending_attr<W: RenderTty + Write>(&mut self, out: &mut W) -> Result<()> {
|
||||
macro_rules! attr_on {
|
||||
($cap:ident, $sgr:expr) => {
|
||||
if let Some(attr) = self.get_capability::<cap::$cap>() {
|
||||
($cap:ident, $sgr:expr) => {{
|
||||
let cap = if self.caps.force_terminfo_render_to_use_ansi_sgr() {
|
||||
None
|
||||
} else {
|
||||
self.get_capability::<cap::$cap>()
|
||||
};
|
||||
if let Some(attr) = cap {
|
||||
attr.expand().to(out.by_ref())?;
|
||||
} else {
|
||||
write!(out, "{}", CSI::Sgr($sgr))?;
|
||||
}
|
||||
};
|
||||
}};
|
||||
($sgr:expr) => {
|
||||
write!(out, "{}", CSI::Sgr($sgr))?;
|
||||
};
|
||||
@ -71,8 +76,13 @@ impl TerminfoRenderer {
|
||||
current_foreground = ColorAttribute::Default;
|
||||
current_background = ColorAttribute::Default;
|
||||
|
||||
let sgr = if self.caps.force_terminfo_render_to_use_ansi_sgr() {
|
||||
None
|
||||
} else {
|
||||
self.get_capability::<cap::SetAttributes>()
|
||||
};
|
||||
// The SetAttributes capability can only handle single underline and slow blink.
|
||||
if let Some(sgr) = self.get_capability::<cap::SetAttributes>() {
|
||||
if let Some(sgr) = sgr {
|
||||
sgr.expand()
|
||||
.bold(attr.intensity() == Intensity::Bold)
|
||||
.dim(attr.intensity() == Intensity::Half)
|
||||
@ -706,10 +716,14 @@ mod test {
|
||||
|
||||
/// Return Capabilities loaded from the included xterm terminfo data
|
||||
fn xterm_terminfo() -> Capabilities {
|
||||
xterm_terminfo_with_hints(ProbeHints::default())
|
||||
}
|
||||
|
||||
fn xterm_terminfo_with_hints(hints: ProbeHints) -> Capabilities {
|
||||
// Load our own compiled data so that the tests have an
|
||||
// environment that doesn't vary machine by machine.
|
||||
let data = include_bytes!("../../data/xterm-256color");
|
||||
Capabilities::new_with_hints(ProbeHints::default().terminfo_db(Some(
|
||||
Capabilities::new_with_hints(hints.terminfo_db(Some(
|
||||
terminfo::Database::from_buffer(data.as_ref()).unwrap(),
|
||||
)))
|
||||
.unwrap()
|
||||
@ -915,6 +929,37 @@ mod test {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Sanity that force_terminfo_render_to_use_ansi_sgr does something.
|
||||
fn bold_text_force_ansi_sgr() {
|
||||
let mut out = FakeTerm::new(xterm_terminfo_with_hints(
|
||||
ProbeHints::default().force_terminfo_render_to_use_ansi_sgr(Some(true)),
|
||||
));
|
||||
out.render(&[
|
||||
Change::Text("not ".into()),
|
||||
AttributeChange::Intensity(Intensity::Bold).into(),
|
||||
Change::Text("foo".into()),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
let result = out.parse();
|
||||
assert_eq!(
|
||||
result,
|
||||
vec![
|
||||
// Same as bold_text() above, but without the "(B" from srg/sgr0.
|
||||
Action::Print('n'),
|
||||
Action::Print('o'),
|
||||
Action::Print('t'),
|
||||
Action::Print(' '),
|
||||
Action::CSI(CSI::Sgr(Sgr::Reset)),
|
||||
Action::CSI(CSI::Sgr(Sgr::Intensity(Intensity::Bold))),
|
||||
Action::Print('f'),
|
||||
Action::Print('o'),
|
||||
Action::Print('o'),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clear_screen() {
|
||||
let mut out = FakeTerm::new_with_size(xterm_terminfo(), 4, 3);
|
||||
|
Loading…
Reference in New Issue
Block a user