mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
ec42b42ce6
The zerowidth characters were conventionally stored in a [char; 5]. This creates problems both by limiting the maximum number of zerowidth characters and by increasing the cell size beyond what is necessary even when no zerowidth characters are used. Instead of storing zerowidth characters as a slice, a new CellExtra struct is introduced which can store arbitrary optional cell data that is rarely required. Since this is stored behind an optional pointer (Option<Box<CellExtra>>), the initialization and dropping in the case of no extra data are extremely cheap and the size penalty to cells without this extra data is limited to 8 instead of 20 bytes. The most noticible difference with this PR should be a reduction in memory size of up to at least 30% (1.06G -> 733M, 100k scrollback, 72 lines, 280 columns). Since the zerowidth characters are now stored dynamically, the limit of 5 per cell is also no longer present.
138 lines
3.5 KiB
Rust
138 lines
3.5 KiB
Rust
use serde::Deserialize;
|
|
use serde_json as json;
|
|
|
|
use std::fs::{self, File};
|
|
use std::io::{self, Read};
|
|
use std::path::Path;
|
|
|
|
use alacritty_terminal::ansi;
|
|
use alacritty_terminal::config::MockConfig;
|
|
use alacritty_terminal::event::{Event, EventListener};
|
|
use alacritty_terminal::grid::{Dimensions, Grid};
|
|
use alacritty_terminal::index::Column;
|
|
use alacritty_terminal::term::cell::Cell;
|
|
use alacritty_terminal::term::{SizeInfo, Term};
|
|
|
|
macro_rules! ref_tests {
|
|
($($name:ident)*) => {
|
|
$(
|
|
#[test]
|
|
fn $name() {
|
|
let test_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/ref"));
|
|
let test_path = test_dir.join(stringify!($name));
|
|
ref_test(&test_path);
|
|
}
|
|
)*
|
|
}
|
|
}
|
|
|
|
ref_tests! {
|
|
csi_rep
|
|
fish_cc
|
|
indexed_256_colors
|
|
issue_855
|
|
ll
|
|
newline_with_cursor_beyond_scroll_region
|
|
tab_rendering
|
|
tmux_git_log
|
|
tmux_htop
|
|
vim_24bitcolors_bce
|
|
vim_large_window_scroll
|
|
vim_simple_edit
|
|
vttest_cursor_movement_1
|
|
vttest_insert
|
|
vttest_origin_mode_1
|
|
vttest_origin_mode_2
|
|
vttest_scroll
|
|
vttest_tab_clear_set
|
|
zsh_tab_completion
|
|
history
|
|
grid_reset
|
|
row_reset
|
|
zerowidth
|
|
selective_erasure
|
|
colored_reset
|
|
delete_lines
|
|
delete_chars_reset
|
|
alt_reset
|
|
deccolm_reset
|
|
decaln_reset
|
|
insert_blank_reset
|
|
erase_chars_reset
|
|
scroll_up_reset
|
|
clear_underline
|
|
region_scroll_down
|
|
wrapline_alt_toggle
|
|
saved_cursor
|
|
saved_cursor_alt
|
|
sgr
|
|
underline
|
|
}
|
|
|
|
fn read_u8<P>(path: P) -> Vec<u8>
|
|
where
|
|
P: AsRef<Path>,
|
|
{
|
|
let mut res = Vec::new();
|
|
File::open(path.as_ref()).unwrap().read_to_end(&mut res).unwrap();
|
|
|
|
res
|
|
}
|
|
|
|
#[derive(Deserialize, Default)]
|
|
struct RefConfig {
|
|
history_size: u32,
|
|
}
|
|
|
|
struct Mock;
|
|
impl EventListener for Mock {
|
|
fn send_event(&self, _event: Event) {}
|
|
}
|
|
|
|
fn ref_test(dir: &Path) {
|
|
let recording = read_u8(dir.join("alacritty.recording"));
|
|
let serialized_size = fs::read_to_string(dir.join("size.json")).unwrap();
|
|
let serialized_grid = fs::read_to_string(dir.join("grid.json")).unwrap();
|
|
let serialized_cfg = fs::read_to_string(dir.join("config.json")).unwrap();
|
|
|
|
let size: SizeInfo = json::from_str(&serialized_size).unwrap();
|
|
let grid: Grid<Cell> = json::from_str(&serialized_grid).unwrap();
|
|
let ref_config: RefConfig = json::from_str(&serialized_cfg).unwrap();
|
|
|
|
let mut config = MockConfig::default();
|
|
config.scrolling.set_history(ref_config.history_size);
|
|
|
|
let mut terminal = Term::new(&config, size, Mock);
|
|
let mut parser = ansi::Processor::new();
|
|
|
|
for byte in recording {
|
|
parser.advance(&mut terminal, byte, &mut io::sink());
|
|
}
|
|
|
|
// Truncate invisible lines from the grid.
|
|
let mut term_grid = terminal.grid().clone();
|
|
term_grid.initialize_all();
|
|
term_grid.truncate();
|
|
|
|
if grid != term_grid {
|
|
for i in 0..grid.total_lines() {
|
|
for j in 0..grid.cols().0 {
|
|
let cell = &term_grid[i][Column(j)];
|
|
let original_cell = &grid[i][Column(j)];
|
|
if original_cell != cell {
|
|
println!(
|
|
"[{i}][{j}] {original:?} => {now:?}",
|
|
i = i,
|
|
j = j,
|
|
original = original_cell,
|
|
now = cell,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
panic!("Ref test failed; grid doesn't match");
|
|
}
|
|
|
|
assert_eq!(grid, term_grid);
|
|
}
|