Add escape to report text area size

This implements the escapes `CSI 14 t` and `CSI 18 t` which report the
text area size in pixels and characters.
This commit is contained in:
Ayose Cazorla 2020-08-28 22:26:03 +00:00 committed by GitHub
parent ee2c5a6cdd
commit cdf5e51e74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 50 additions and 23 deletions

View file

@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Escapes for double underlines (`CSI 4 : 2 m`) and underline reset (`CSI 4 : 0 m`)
- Configuration file option for sourcing other files (`import`)
- CLI parameter `--option`/`-o` to override any configuration field
- Escape sequences to report text area size in pixels (`CSI 14 t`) and in characters (`CSI 18 t`)
### Changed

View file

@ -427,7 +427,7 @@ impl Display {
pty_resize_handle.on_resize(&pty_size);
// Resize terminal.
terminal.resize(&pty_size);
terminal.resize(pty_size);
// Resize renderer.
let physical = PhysicalSize::new(self.size_info.width as u32, self.size_info.height as u32);

View file

@ -1295,7 +1295,7 @@ mod tests {
let mut clipboard = Clipboard::new_nop();
let mut terminal = Term::new(&cfg, &size, MockEventProxy);
let mut terminal = Term::new(&cfg, size, MockEventProxy);
let mut mouse = Mouse::default();
mouse.click_state = $initial_state;

View file

@ -145,7 +145,7 @@ fn run(
// This object contains all of the state about what's being displayed. It's
// wrapped in a clonable mutex since both the I/O loop and display need to
// access it.
let terminal = Term::new(&config, &display.size_info, event_proxy.clone());
let terminal = Term::new(&config, display.size_info, event_proxy.clone());
let terminal = Arc::new(FairMutex::new(terminal));
// Create the PTY.

View file

@ -316,6 +316,12 @@ pub trait Handler {
/// Pop the last title from the stack.
fn pop_title(&mut self) {}
/// Report text area size in pixels.
fn text_area_size_pixels<W: io::Write>(&mut self, _: &mut W) {}
/// Report text area size in characters.
fn text_area_size_chars<W: io::Write>(&mut self, _: &mut W) {}
}
/// Describes shape of cursor.
@ -1080,6 +1086,8 @@ where
('s', None) => handler.save_cursor_position(),
('T', None) => handler.scroll_down(Line(next_param_or(1) as usize)),
('t', None) => match next_param_or(1) as usize {
14 => handler.text_area_size_pixels(writer),
18 => handler.text_area_size_chars(writer),
22 => handler.push_title(),
23 => handler.pop_title(),
_ => unhandled!(),

View file

@ -418,7 +418,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
Term::new(&MockConfig::default(), &size, Mock)
Term::new(&MockConfig::default(), size, Mock)
}
/// Test case of single cell selection.

View file

@ -745,6 +745,9 @@ pub struct Term<T> {
/// Current forward and backward buffer search regexes.
regex_search: Option<RegexSearch>,
/// Information about window dimensions.
size: SizeInfo,
}
impl<T> Term<T> {
@ -758,7 +761,7 @@ impl<T> Term<T> {
self.dirty = true;
}
pub fn new<C>(config: &Config<C>, size: &SizeInfo, event_proxy: T) -> Term<T> {
pub fn new<C>(config: &Config<C>, size: SizeInfo, event_proxy: T) -> Term<T> {
let num_cols = size.cols();
let num_lines = size.lines();
@ -795,6 +798,7 @@ impl<T> Term<T> {
title_stack: Vec::new(),
selection: None,
regex_search: None,
size,
}
}
@ -964,7 +968,9 @@ impl<T> Term<T> {
}
/// Resize terminal to new dimensions.
pub fn resize(&mut self, size: &SizeInfo) {
pub fn resize(&mut self, size: SizeInfo) {
self.size = size;
let old_cols = self.cols();
let old_lines = self.screen_lines();
let num_cols = max(size.cols(), Column(MIN_SIZE));
@ -2219,6 +2225,18 @@ impl<T: EventListener> Handler for Term<T> {
self.set_title(popped);
}
}
#[inline]
fn text_area_size_pixels<W: io::Write>(&mut self, writer: &mut W) {
let width = self.size.cell_width as usize * self.cols().0;
let height = self.size.cell_height as usize * self.screen_lines().0;
let _ = write!(writer, "\x1b[4;{};{}t", height, width);
}
#[inline]
fn text_area_size_chars<W: io::Write>(&mut self, writer: &mut W) {
let _ = write!(writer, "\x1b[8;{};{}t", self.screen_lines(), self.cols());
}
}
/// Terminal version for escape sequence reports.
@ -2342,7 +2360,7 @@ pub mod test {
padding_y: 0.,
dpr: 1.,
};
let mut term = Term::new(&Config::<()>::default(), &size, ());
let mut term = Term::new(&Config::<()>::default(), size, ());
// Fill terminal with content.
for (line, text) in lines.iter().rev().enumerate() {
@ -2399,7 +2417,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
let mut grid: Grid<Cell> = Grid::new(Line(3), Column(5), 0, Cell::default());
for i in 0..5 {
for j in 0..2 {
@ -2455,7 +2473,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
let mut grid: Grid<Cell> = Grid::new(Line(1), Column(5), 0, Cell::default());
for i in 0..5 {
grid[Line(0)][Column(i)].c = 'a';
@ -2484,7 +2502,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
let mut grid: Grid<Cell> = Grid::new(Line(3), Column(3), 0, Cell::default());
for l in 0..3 {
if l != 1 {
@ -2529,7 +2547,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
let cursor = Point::new(Line(0), Column(0));
term.configure_charset(CharsetIndex::G0, StandardCharset::SpecialCharacterAndLineDrawing);
term.input('a');
@ -2548,7 +2566,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
// Add one line of scrollback.
term.grid.scroll_up(&(Line(0)..Line(1)), Line(1), Cell::default());
@ -2578,7 +2596,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
// Create 10 lines of scrollback.
for _ in 0..19 {
@ -2589,7 +2607,7 @@ mod tests {
// Increase visible lines.
size.height = 30.;
term.resize(&size);
term.resize(size);
assert_eq!(term.history_size(), 0);
assert_eq!(term.grid.cursor.point, Point::new(Line(19), Column(0)));
@ -2606,7 +2624,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
// Create 10 lines of scrollback.
for _ in 0..19 {
@ -2620,7 +2638,7 @@ mod tests {
// Increase visible lines.
size.height = 30.;
term.resize(&size);
term.resize(size);
// Leave alt screen.
term.unset_mode(ansi::Mode::SwapScreenAndSetRestoreCursor);
@ -2640,7 +2658,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
// Create 10 lines of scrollback.
for _ in 0..19 {
@ -2651,7 +2669,7 @@ mod tests {
// Increase visible lines.
size.height = 5.;
term.resize(&size);
term.resize(size);
assert_eq!(term.history_size(), 15);
assert_eq!(term.grid.cursor.point, Point::new(Line(4), Column(0)));
@ -2668,7 +2686,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
// Create 10 lines of scrollback.
for _ in 0..19 {
@ -2682,7 +2700,7 @@ mod tests {
// Increase visible lines.
size.height = 5.;
term.resize(&size);
term.resize(size);
// Leave alt screen.
term.unset_mode(ansi::Mode::SwapScreenAndSetRestoreCursor);
@ -2702,7 +2720,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
let mut term = Term::new(&MockConfig::default(), &size, Mock);
let mut term = Term::new(&MockConfig::default(), size, Mock);
// Title None by default.
assert_eq!(term.title, None);

View file

@ -416,7 +416,7 @@ mod tests {
padding_y: 0.0,
dpr: 1.0,
};
Term::new(&MockConfig::default(), &size, Mock)
Term::new(&MockConfig::default(), size, Mock)
}
#[test]

View file

@ -102,7 +102,7 @@ fn ref_test(dir: &Path) {
let mut config = MockConfig::default();
config.scrolling.set_history(ref_config.history_size);
let mut terminal = Term::new(&config, &size, Mock);
let mut terminal = Term::new(&config, size, Mock);
let mut parser = ansi::Processor::new();
for byte in recording {