feat(compatibility): vim working!
This commit is contained in:
parent
1844816f47
commit
5cd365a73c
11 changed files with 452 additions and 1 deletions
|
|
@ -159,6 +159,7 @@ pub struct TerminalOutput {
|
||||||
cursor_position: usize,
|
cursor_position: usize,
|
||||||
newline_indices: Vec<usize>, // canonical line breaks we get from the vt interpreter
|
newline_indices: Vec<usize>, // canonical line breaks we get from the vt interpreter
|
||||||
linebreak_indices: Vec<usize>, // linebreaks from line wrapping
|
linebreak_indices: Vec<usize>, // linebreaks from line wrapping
|
||||||
|
scroll_region: (usize, usize), // top line index / bottom line index
|
||||||
reset_foreground_ansi_code: bool, // this is a performance optimization, rather than placing and looking for the ansi reset code in pending_ansi_codes
|
reset_foreground_ansi_code: bool, // this is a performance optimization, rather than placing and looking for the ansi reset code in pending_ansi_codes
|
||||||
reset_background_ansi_code: bool, // this is a performance optimization, rather than placing and looking for the ansi reset code in pending_ansi_codes
|
reset_background_ansi_code: bool, // this is a performance optimization, rather than placing and looking for the ansi reset code in pending_ansi_codes
|
||||||
reset_misc_ansi_code: bool, // this is a performance optimization, rather than placing and looking for the ansi reset code in pending_ansi_codes
|
reset_misc_ansi_code: bool, // this is a performance optimization, rather than placing and looking for the ansi reset code in pending_ansi_codes
|
||||||
|
|
@ -175,6 +176,7 @@ impl TerminalOutput {
|
||||||
cursor_position: 0,
|
cursor_position: 0,
|
||||||
newline_indices: Vec::new(),
|
newline_indices: Vec::new(),
|
||||||
linebreak_indices: Vec::new(),
|
linebreak_indices: Vec::new(),
|
||||||
|
scroll_region: (1, ws.ws_row as usize),
|
||||||
display_rows: ws.ws_row,
|
display_rows: ws.ws_row,
|
||||||
display_cols: ws.ws_col,
|
display_cols: ws.ws_col,
|
||||||
should_render: true,
|
should_render: true,
|
||||||
|
|
@ -440,21 +442,168 @@ impl TerminalOutput {
|
||||||
let last_linebreak_index = self.linebreak_indices.iter().rev().find(|&&l_i| l_i <= index_in_line).unwrap_or(&0);
|
let last_linebreak_index = self.linebreak_indices.iter().rev().find(|&&l_i| l_i <= index_in_line).unwrap_or(&0);
|
||||||
max(*last_newline_index, *last_linebreak_index)
|
max(*last_newline_index, *last_linebreak_index)
|
||||||
}
|
}
|
||||||
|
fn scroll_region_line_indices (&self) -> (usize, usize) {
|
||||||
|
let mut newline_indices = self.newline_indices.iter().rev();
|
||||||
|
let mut linebreak_indices = self.linebreak_indices.iter().rev();
|
||||||
|
|
||||||
|
let mut next_newline = newline_indices.next();
|
||||||
|
let mut next_linebreak = linebreak_indices.next();
|
||||||
|
|
||||||
|
let mut lines_from_end = 0;
|
||||||
|
|
||||||
|
let scroll_end_index_from_screen_bottom = self.display_rows as usize - self.scroll_region.1;
|
||||||
|
let scroll_start_index_from_screen_bottom = scroll_end_index_from_screen_bottom + (self.scroll_region.1 - self.scroll_region.0);
|
||||||
|
|
||||||
|
let mut scroll_region_start_index = None;
|
||||||
|
let mut scroll_region_end_index = None;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match max(next_newline, next_linebreak) {
|
||||||
|
Some(next_line_index) => {
|
||||||
|
if lines_from_end == scroll_start_index_from_screen_bottom {
|
||||||
|
scroll_region_start_index = Some(next_line_index);
|
||||||
|
}
|
||||||
|
if lines_from_end == scroll_end_index_from_screen_bottom {
|
||||||
|
scroll_region_end_index = Some(next_line_index);
|
||||||
|
}
|
||||||
|
if scroll_region_start_index.is_some() && scroll_region_end_index.is_some() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if Some(next_line_index) == next_newline {
|
||||||
|
next_newline = newline_indices.next();
|
||||||
|
} else if Some(next_line_index) == next_linebreak {
|
||||||
|
next_linebreak = linebreak_indices.next();
|
||||||
|
}
|
||||||
|
lines_from_end += 1;
|
||||||
|
},
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*scroll_region_start_index.unwrap_or(&0), *scroll_region_end_index.unwrap_or(&0))
|
||||||
|
}
|
||||||
|
fn index_of_next_line_after(&self, index_in_line: usize) -> usize {
|
||||||
|
let last_newline_index = self.newline_indices.iter().find(|&&n_i| n_i >= index_in_line).unwrap_or(&0);
|
||||||
|
let last_linebreak_index = self.linebreak_indices.iter().find(|&&l_i| l_i >= index_in_line).unwrap_or(&0);
|
||||||
|
max(*last_newline_index, *last_linebreak_index)
|
||||||
|
}
|
||||||
|
fn insert_empty_lines_at_cursor(&mut self, count: usize) {
|
||||||
|
for _ in 0..count {
|
||||||
|
self.delete_last_line_in_scroll_region();
|
||||||
|
let start_of_current_line = self.index_of_beginning_of_line(self.cursor_position);
|
||||||
|
let end_of_current_line = self.index_of_next_line_after(self.cursor_position);
|
||||||
|
for i in 0..end_of_current_line - start_of_current_line {
|
||||||
|
self.characters.insert(start_of_current_line + i, EMPTY_TERMINAL_CHARACTER.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
fn delete_last_line_in_scroll_region(&mut self) {
|
||||||
|
if let Some(newline_index_of_scroll_region_end) = self.get_line_position_on_screen(self.scroll_region.1) {
|
||||||
|
let end_of_last_scroll_region_line = self.get_line_position_on_screen(self.scroll_region.1 + 1).unwrap();
|
||||||
|
&self.characters.drain(newline_index_of_scroll_region_end..end_of_last_scroll_region_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn delete_first_line_in_scroll_region(&mut self) {
|
||||||
|
if let Some(newline_index_of_scroll_region_start) = self.get_line_position_on_screen(self.scroll_region.0) {
|
||||||
|
let end_of_first_scroll_region_line = self.get_line_position_on_screen(self.scroll_region.0 + 1).unwrap();
|
||||||
|
let removed_count = {
|
||||||
|
let removed_line = &self.characters.drain(newline_index_of_scroll_region_start..end_of_first_scroll_region_line);
|
||||||
|
removed_line.len()
|
||||||
|
};
|
||||||
|
let newline_index_of_scroll_region_end = self.get_line_position_on_screen(self.scroll_region.1).unwrap();
|
||||||
|
for i in 0..removed_count {
|
||||||
|
self.characters.insert(newline_index_of_scroll_region_end + i, EMPTY_TERMINAL_CHARACTER.clone())
|
||||||
|
}
|
||||||
|
// TODO: if removed_count is larger than the line it was inserted it, recalculate all
|
||||||
|
// newline_indices after it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_line_position_on_screen(&self, index_on_screen: usize) -> Option<usize> {
|
||||||
|
let mut newline_indices = self.newline_indices.iter().rev();
|
||||||
|
let mut linebreak_indices = self.linebreak_indices.iter().rev();
|
||||||
|
|
||||||
|
let mut next_newline = newline_indices.next();
|
||||||
|
let mut next_linebreak = linebreak_indices.next();
|
||||||
|
|
||||||
|
let mut lines_from_end = 0; // 1 because we're counting and not indexing TODO: fix this
|
||||||
|
loop {
|
||||||
|
match max(next_newline, next_linebreak) {
|
||||||
|
Some(next_line_index) => {
|
||||||
|
if index_on_screen == self.display_rows as usize - lines_from_end {
|
||||||
|
return Some(*next_line_index);
|
||||||
|
} else {
|
||||||
|
lines_from_end += 1;
|
||||||
|
}
|
||||||
|
if lines_from_end > self.display_rows as usize {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if Some(next_line_index) == next_newline {
|
||||||
|
next_newline = newline_indices.next();
|
||||||
|
} else if Some(next_line_index) == next_linebreak {
|
||||||
|
next_linebreak = linebreak_indices.next();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
if index_on_screen == self.display_rows as usize - lines_from_end {
|
||||||
|
return Some(0);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: better naming of these two functions
|
||||||
|
fn get_line_index_on_screen (&self, position_in_characters: usize) -> Option<usize> {
|
||||||
|
let mut newline_indices = self.newline_indices.iter().rev();
|
||||||
|
let mut linebreak_indices = self.linebreak_indices.iter().rev();
|
||||||
|
|
||||||
|
let mut next_newline = newline_indices.next();
|
||||||
|
let mut next_linebreak = linebreak_indices.next();
|
||||||
|
|
||||||
|
let mut lines_from_end = 0;
|
||||||
|
loop {
|
||||||
|
match max(next_newline, next_linebreak) {
|
||||||
|
Some(next_line_index) => {
|
||||||
|
if *next_line_index <= position_in_characters {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
lines_from_end += 1;
|
||||||
|
if Some(next_line_index) == next_newline {
|
||||||
|
next_newline = newline_indices.next();
|
||||||
|
} else if Some(next_line_index) == next_linebreak {
|
||||||
|
next_linebreak = linebreak_indices.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lines_from_end > self.display_rows as usize {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.display_rows as usize - lines_from_end)
|
||||||
|
}
|
||||||
|
}
|
||||||
fn add_newline (&mut self) {
|
fn add_newline (&mut self) {
|
||||||
let nearest_line_end = self.index_of_end_of_canonical_line(self.cursor_position);
|
let nearest_line_end = self.index_of_end_of_canonical_line(self.cursor_position);
|
||||||
|
let current_line_index_on_screen = self.get_line_index_on_screen(self.cursor_position);
|
||||||
if nearest_line_end == self.characters.len() {
|
if nearest_line_end == self.characters.len() {
|
||||||
self.newline_indices.push(nearest_line_end);
|
self.newline_indices.push(nearest_line_end);
|
||||||
self.cursor_position = nearest_line_end;
|
self.cursor_position = nearest_line_end;
|
||||||
|
} else if current_line_index_on_screen == Some(self.scroll_region.1) { // end of scroll region
|
||||||
|
// shift all lines in scroll region up
|
||||||
|
self.delete_first_line_in_scroll_region();
|
||||||
} else {
|
} else {
|
||||||
// we shouldn't add a new line in the middle of the text
|
// we shouldn't add a new line in the middle of the text
|
||||||
// in this case, we'll move to the next existing line and it
|
// in this case, we'll move to the next existing line and it
|
||||||
// will be overriden as we print on it
|
// will be overriden as we print on it
|
||||||
self.cursor_position = nearest_line_end;
|
self.cursor_position = nearest_line_end;
|
||||||
}
|
}
|
||||||
self.should_render = true;
|
|
||||||
self.pending_foreground_ansi_codes.clear();
|
self.pending_foreground_ansi_codes.clear();
|
||||||
self.pending_background_ansi_codes.clear();
|
self.pending_background_ansi_codes.clear();
|
||||||
self.pending_misc_ansi_codes.clear();
|
self.pending_misc_ansi_codes.clear();
|
||||||
|
self.should_render = true;
|
||||||
}
|
}
|
||||||
fn move_to_beginning_of_line (&mut self) {
|
fn move_to_beginning_of_line (&mut self) {
|
||||||
let last_newline_index = self.index_of_beginning_of_line(self.cursor_position);
|
let last_newline_index = self.index_of_beginning_of_line(self.cursor_position);
|
||||||
|
|
@ -463,8 +612,18 @@ impl TerminalOutput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn debug_log_to_file (message: String) {
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
let mut file = OpenOptions::new().append(true).create(true).open("/tmp/mosaic-log.txt").unwrap();
|
||||||
|
file.write_all(message.as_bytes()).unwrap();
|
||||||
|
file.write_all("\n".as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
impl vte::Perform for TerminalOutput {
|
impl vte::Perform for TerminalOutput {
|
||||||
fn print(&mut self, c: char) {
|
fn print(&mut self, c: char) {
|
||||||
|
|
||||||
|
|
||||||
// while not ideal that we separate the reset and actual code logic here,
|
// while not ideal that we separate the reset and actual code logic here,
|
||||||
// combining them is a question of rendering performance and not refactoring,
|
// combining them is a question of rendering performance and not refactoring,
|
||||||
// so will be addressed separately
|
// so will be addressed separately
|
||||||
|
|
@ -673,6 +832,29 @@ impl vte::Perform for TerminalOutput {
|
||||||
// TBD
|
// TBD
|
||||||
} else if c == 'h' {
|
} else if c == 'h' {
|
||||||
// TBD
|
// TBD
|
||||||
|
} else if c == 'r' {
|
||||||
|
debug_log_to_file(format!("\rparams {:?}", params));
|
||||||
|
if params.len() > 1 {
|
||||||
|
// TODO: why do we need this if? what does a 1 parameter 'r' mean?
|
||||||
|
self.scroll_region = (params[0] as usize, params[1] as usize);
|
||||||
|
}
|
||||||
|
} else if c == 't' {
|
||||||
|
// TBD - title?
|
||||||
|
} else if c == 'n' {
|
||||||
|
// TBD - device status report
|
||||||
|
} else if c == 'c' {
|
||||||
|
// TBD - identify terminal
|
||||||
|
} else if c == 'M' {
|
||||||
|
// delete lines if currently inside scroll region
|
||||||
|
let line_count_to_delete = params[0];
|
||||||
|
for _ in 0..line_count_to_delete {
|
||||||
|
// TODO: better, do this in bulk
|
||||||
|
self.delete_first_line_in_scroll_region()
|
||||||
|
}
|
||||||
|
} else if c == 'L' {
|
||||||
|
// insert blank lines if inside scroll region
|
||||||
|
let line_count_to_add = params[0];
|
||||||
|
self.insert_empty_lines_at_cursor(line_count_to_add as usize);
|
||||||
} else {
|
} else {
|
||||||
println!("unhandled csi: {:?}->{:?}", c, params);
|
println!("unhandled csi: {:?}->{:?}", c, params);
|
||||||
panic!("aaa!!!");
|
panic!("aaa!!!");
|
||||||
|
|
|
||||||
BIN
src/tests/fixtures/vim_ctrl_d
vendored
Normal file
BIN
src/tests/fixtures/vim_ctrl_d
vendored
Normal file
Binary file not shown.
BIN
src/tests/fixtures/vim_ctrl_u
vendored
Normal file
BIN
src/tests/fixtures/vim_ctrl_u
vendored
Normal file
Binary file not shown.
BIN
src/tests/fixtures/vim_scroll_region_down
vendored
Normal file
BIN
src/tests/fixtures/vim_scroll_region_down
vendored
Normal file
Binary file not shown.
|
|
@ -88,3 +88,80 @@ pub fn fish_select_tab_completion_options() {
|
||||||
assert_snapshot!(snapshot);
|
assert_snapshot!(snapshot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn vim_scroll_region_down () {
|
||||||
|
// here we test a case where vim defines the scroll region as lesser than the screen row count
|
||||||
|
// and then scrolls down
|
||||||
|
// the region is defined here by vim as 1-26 (there are 28 rows)
|
||||||
|
// then the cursor is moved to line 26 and a new line is added
|
||||||
|
// what should happen is that the first line in the scroll region (1) is deleted
|
||||||
|
// and an empty line is inserted in the last scroll region line (26)
|
||||||
|
// this tests also has other steps afterwards that fills the line with the next line in the
|
||||||
|
// file
|
||||||
|
// experience appear to the user
|
||||||
|
let fake_win_size = Winsize {
|
||||||
|
ws_col: 116,
|
||||||
|
ws_row: 28,
|
||||||
|
ws_xpixel: 0,
|
||||||
|
ws_ypixel: 0,
|
||||||
|
};
|
||||||
|
let fixture_name = "vim_scroll_region_down";
|
||||||
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
||||||
|
fake_input_output.add_terminal_input(&[17]); // quit (ctrl-q)
|
||||||
|
start(Box::new(fake_input_output.clone()));
|
||||||
|
let output_frames = fake_input_output.stdout_writer.output_frames.lock().unwrap();
|
||||||
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
||||||
|
for snapshot in snapshots {
|
||||||
|
assert_snapshot!(snapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn vim_ctrl_d() {
|
||||||
|
// in vim ctrl-d moves down half a page
|
||||||
|
// in this case, it sends the terminal the csi 'M' directive, which tells it to delete X (13 in
|
||||||
|
// this case) lines inside the scroll region and push the other lines up
|
||||||
|
// what happens here is that 13 lines are deleted and instead 13 empty lines are added at the
|
||||||
|
// end of the scroll region
|
||||||
|
// vim makes sure to fill these empty lines with the rest of the file
|
||||||
|
let fake_win_size = Winsize {
|
||||||
|
ws_col: 116,
|
||||||
|
ws_row: 28,
|
||||||
|
ws_xpixel: 0,
|
||||||
|
ws_ypixel: 0,
|
||||||
|
};
|
||||||
|
let fixture_name = "vim_ctrl_d";
|
||||||
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
||||||
|
fake_input_output.add_terminal_input(&[17]); // quit (ctrl-q)
|
||||||
|
start(Box::new(fake_input_output.clone()));
|
||||||
|
let output_frames = fake_input_output.stdout_writer.output_frames.lock().unwrap();
|
||||||
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
||||||
|
for snapshot in snapshots {
|
||||||
|
assert_snapshot!(snapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn vim_ctrl_u() {
|
||||||
|
// in vim ctrl-u moves up half a page
|
||||||
|
// in this case, it sends the terminal the csi 'L' directive, which tells it to insert X (13 in
|
||||||
|
// this case) lines at the cursor, pushing away (deleting) the last line in the scroll region
|
||||||
|
// this causes the effect of scrolling up X lines (vim replaces the lines with the ones in the
|
||||||
|
// file above the current content)
|
||||||
|
let fake_win_size = Winsize {
|
||||||
|
ws_col: 116,
|
||||||
|
ws_row: 28,
|
||||||
|
ws_xpixel: 0,
|
||||||
|
ws_ypixel: 0,
|
||||||
|
};
|
||||||
|
let fixture_name = "vim_ctrl_u";
|
||||||
|
let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name);
|
||||||
|
fake_input_output.add_terminal_input(&[17]); // quit (ctrl-q)
|
||||||
|
start(Box::new(fake_input_output.clone()));
|
||||||
|
let output_frames = fake_input_output.stdout_writer.output_frames.lock().unwrap();
|
||||||
|
let snapshots = get_output_frame_snapshots(&output_frames, &fake_win_size);
|
||||||
|
for snapshot in snapshots {
|
||||||
|
assert_snapshot!(snapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/tests/integration/compatibility.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
2 line15
|
||||||
|
1 line16
|
||||||
|
17 line17
|
||||||
|
1 line18
|
||||||
|
2 line19
|
||||||
|
3 line20
|
||||||
|
4 line21
|
||||||
|
5 line22
|
||||||
|
6 line23
|
||||||
|
7 line24
|
||||||
|
8 line25
|
||||||
|
9 line26
|
||||||
|
10 line27
|
||||||
|
11 line28
|
||||||
|
12 line29
|
||||||
|
13 line30
|
||||||
|
14 line31
|
||||||
|
15 line32
|
||||||
|
16 line33
|
||||||
|
17 line34
|
||||||
|
18 line35
|
||||||
|
19 line36
|
||||||
|
20 line37
|
||||||
|
21 line38
|
||||||
|
22 line39
|
||||||
|
NORMAL testfile.rs unix | utf-8 | rust 40% 17:1
|
||||||
|
"/tmp/testfile.rs" 42L, 285C
|
||||||
|
Bye from Mosaic!█
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/tests/integration/compatibility.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
3 line14
|
||||||
|
2 line15
|
||||||
|
1 line16
|
||||||
|
17 █ine17
|
||||||
|
1 line18
|
||||||
|
2 line19
|
||||||
|
3 line20
|
||||||
|
4 line21
|
||||||
|
5 line22
|
||||||
|
6 line23
|
||||||
|
7 line24
|
||||||
|
8 line25
|
||||||
|
9 line26
|
||||||
|
10 line27
|
||||||
|
11 line28
|
||||||
|
12 line29
|
||||||
|
13 line30
|
||||||
|
14 line31
|
||||||
|
15 line32
|
||||||
|
16 line33
|
||||||
|
17 line34
|
||||||
|
18 line35
|
||||||
|
19 line36
|
||||||
|
20 line37
|
||||||
|
21 line38
|
||||||
|
22 line39
|
||||||
|
NORMAL testfile.rs unix | utf-8 | rust 40% 17:1
|
||||||
|
"/tmp/testfile.rs" 42L, 285C
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/tests/integration/compatibility.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
21 line5
|
||||||
|
20 line6
|
||||||
|
19 line7
|
||||||
|
18 line8
|
||||||
|
17 line9
|
||||||
|
16 line10
|
||||||
|
15 line11
|
||||||
|
14 line12
|
||||||
|
13 line13
|
||||||
|
12 line14
|
||||||
|
11 line15
|
||||||
|
10 line16
|
||||||
|
9 line17
|
||||||
|
8 line18
|
||||||
|
7 line19
|
||||||
|
6 line20
|
||||||
|
5 line21
|
||||||
|
4 line22
|
||||||
|
3 line23
|
||||||
|
2 line24
|
||||||
|
1 line25
|
||||||
|
26 line26
|
||||||
|
1 line27
|
||||||
|
2 line28
|
||||||
|
3 line29
|
||||||
|
NORMAL testfile.rs unix | utf-8 | rust 61% 26:1
|
||||||
|
"/tmp/testfile.rs" 42L, 285C
|
||||||
|
Bye from Mosaic!█
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/tests/integration/compatibility.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
22 line4
|
||||||
|
21 line5
|
||||||
|
20 line6
|
||||||
|
19 line7
|
||||||
|
18 line8
|
||||||
|
17 line9
|
||||||
|
16 line10
|
||||||
|
15 line11
|
||||||
|
14 line12
|
||||||
|
13 line13
|
||||||
|
12 line14
|
||||||
|
11 line15
|
||||||
|
10 line16
|
||||||
|
9 line17
|
||||||
|
8 line18
|
||||||
|
7 line19
|
||||||
|
6 line20
|
||||||
|
5 line21
|
||||||
|
4 line22
|
||||||
|
3 line23
|
||||||
|
2 line24
|
||||||
|
1 line25
|
||||||
|
26 █ine26
|
||||||
|
1 line27
|
||||||
|
2 line28
|
||||||
|
3 line29
|
||||||
|
NORMAL testfile.rs unix | utf-8 | rust 61% 26:1
|
||||||
|
"/tmp/testfile.rs" 42L, 285C
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/tests/integration/compatibility.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
21 line3
|
||||||
|
20 line4
|
||||||
|
19 line5
|
||||||
|
18 line6
|
||||||
|
17 line7
|
||||||
|
16 line8
|
||||||
|
15 line9
|
||||||
|
14 line10
|
||||||
|
13 line11
|
||||||
|
12 line12
|
||||||
|
11 line13
|
||||||
|
10 line14
|
||||||
|
9 line15
|
||||||
|
8 line16
|
||||||
|
7 line17
|
||||||
|
6 line18
|
||||||
|
5 line19
|
||||||
|
4 line20
|
||||||
|
3 line21
|
||||||
|
2 line22
|
||||||
|
1 line23
|
||||||
|
24 line24
|
||||||
|
1 line25
|
||||||
|
2 line26
|
||||||
|
3 line27
|
||||||
|
NORMAL testfile.rs unix | utf-8 | rust 57% 24:1
|
||||||
|
"/tmp/testfile.rs" 42L, 285C
|
||||||
|
Bye from Mosaic!█
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
---
|
||||||
|
source: src/tests/integration/compatibility.rs
|
||||||
|
expression: snapshot
|
||||||
|
---
|
||||||
|
22 line2
|
||||||
|
21 line3
|
||||||
|
20 line4
|
||||||
|
19 line5
|
||||||
|
18 line6
|
||||||
|
17 line7
|
||||||
|
16 line8
|
||||||
|
15 line9
|
||||||
|
14 line10
|
||||||
|
13 line11
|
||||||
|
12 line12
|
||||||
|
11 line13
|
||||||
|
10 line14
|
||||||
|
9 line15
|
||||||
|
8 line16
|
||||||
|
7 line17
|
||||||
|
6 line18
|
||||||
|
5 line19
|
||||||
|
4 line20
|
||||||
|
3 line21
|
||||||
|
2 line22
|
||||||
|
1 line23
|
||||||
|
24 █ine24
|
||||||
|
1 line25
|
||||||
|
2 line26
|
||||||
|
3 line27
|
||||||
|
NORMAL testfile.rs unix | utf-8 | rust 57% 24:1
|
||||||
|
"/tmp/testfile.rs" 42L, 285C
|
||||||
Loading…
Add table
Reference in a new issue