From f88abe6ad86da27695dac82ea8ad2e1c6fd4cc9e Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Mon, 23 Nov 2020 18:01:16 +0100 Subject: [PATCH] fix(compatibility): various htop issues (#66) * fix(compatibility): various htop issues * style(format): make rustfmt happy * fix(logging): do not delete log dir on startup * fix(tests): update htop with command toggle * chore(ci): reduce test concurrency to 1 --- .github/workflows/rust.yml | 2 +- src/main.rs | 3 - src/terminal_pane/scroll.rs | 108 ++++++++++++++++-- src/terminal_pane/terminal_pane.rs | 84 ++++++++++---- src/tests/fixtures/htop | Bin 0 -> 16234 bytes src/tests/integration/compatibility.rs | 23 ++++ ...s__integration__compatibility__htop-2.snap | 32 ++++++ ...sts__integration__compatibility__htop.snap | 32 ++++++ src/utils/logging.rs | 5 + 9 files changed, 257 insertions(+), 32 deletions(-) create mode 100644 src/tests/fixtures/htop create mode 100644 src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop-2.snap create mode 100644 src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop.snap diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 64441fc3..f31838a6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -19,7 +19,7 @@ jobs: - name: Build run: cargo build --verbose - name: Run tests - run: cargo test --verbose + run: cargo test -j 1 --verbose fmt: name: Rustfmt runs-on: ubuntu-latest diff --git a/src/main.rs b/src/main.rs index f8f2ca3b..0126069b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -97,9 +97,6 @@ pub fn start(mut os_input: Box, opts: Opt) { let command_is_executing = CommandIsExecuting::new(); - delete_log_dir().unwrap(); - delete_log_file().unwrap(); - let full_screen_ws = os_input.get_terminal_size_using_fd(0); os_input.into_raw_mode(0); let (send_screen_instructions, receive_screen_instructions): ( diff --git a/src/terminal_pane/scroll.rs b/src/terminal_pane/scroll.rs index 5884ea32..fd811fa9 100644 --- a/src/terminal_pane/scroll.rs +++ b/src/terminal_pane/scroll.rs @@ -1,7 +1,10 @@ use ::std::collections::VecDeque; use ::std::fmt::{self, Debug, Formatter}; -use crate::terminal_pane::terminal_character::{TerminalCharacter, EMPTY_TERMINAL_CHARACTER}; +use crate::terminal_pane::terminal_character::{ + CharacterStyles, TerminalCharacter, EMPTY_TERMINAL_CHARACTER, +}; +use crate::utils::logging::{debug_log_to_file, debug_log_to_file_pid_0}; /* * Scroll @@ -75,6 +78,64 @@ impl CanonicalLine { fragment_to_clear.clear_after_and_including(column_index); self.wrapped_fragments.truncate(fragment_index + 1); } + pub fn replace_with_empty_chars( + &mut self, + fragment_index: usize, + from_col: usize, + count: usize, + style_of_empty_space: CharacterStyles, + ) { + let mut characters_replaced = 0; + let mut column_position_in_fragment = from_col; + let mut current_fragment = fragment_index; + let mut empty_space_character = EMPTY_TERMINAL_CHARACTER; + empty_space_character.styles = style_of_empty_space; + loop { + if characters_replaced == count { + break; + } + match self.wrapped_fragments.get_mut(current_fragment) { + Some(fragment_to_clear) => { + let fragment_characters_count = fragment_to_clear.characters.len(); + if fragment_characters_count >= column_position_in_fragment { + fragment_to_clear + .add_character(empty_space_character, column_position_in_fragment); + column_position_in_fragment += 1; + characters_replaced += 1; + } else { + current_fragment += 1; + column_position_in_fragment = 0; + } + } + None => { + // end of line, nothing more to clear + break; + } + } + } + } + pub fn replace_with_empty_chars_after_cursor( + &mut self, + fragment_index: usize, + from_col: usize, + total_columns: usize, + style_of_empty_space: CharacterStyles, + ) { + let mut empty_char_character = EMPTY_TERMINAL_CHARACTER; + empty_char_character.styles = style_of_empty_space; + let current_fragment = self.wrapped_fragments.get_mut(fragment_index).unwrap(); + let fragment_characters_count = current_fragment.characters.len(); + + for i in from_col..fragment_characters_count { + current_fragment.add_character(empty_char_character, i); + } + + for i in fragment_characters_count..total_columns { + current_fragment.add_character(empty_char_character, i); + } + + self.wrapped_fragments.truncate(fragment_index + 1); + } } impl Debug for CanonicalLine { @@ -283,7 +344,7 @@ impl Scroll { // scroll region should be ignored if the cursor is hidden let scroll_region_top_index = scroll_region_top - 1; let scroll_region_bottom_index = scroll_region_bottom - 1; - if current_canonical_line_index == scroll_region_bottom_index { + if current_canonical_line_index == scroll_region_bottom_index + 1 { // end of scroll region // when we have a scroll region set and we're at its bottom // we need to delete its first line, thus shifting all lines in it upwards @@ -292,7 +353,7 @@ impl Scroll { // scroll buffer, but that's not something we control) self.canonical_lines.remove(scroll_region_top_index); self.canonical_lines - .insert(scroll_region_bottom_index, CanonicalLine::new()); + .insert(scroll_region_bottom_index + 1, CanonicalLine::new()); return; } } @@ -405,7 +466,7 @@ impl Scroll { self.lines_in_view = lines; self.total_columns = columns; } - pub fn clear_canonical_line_right_of_cursor(&mut self) { + pub fn clear_canonical_line_right_of_cursor(&mut self, style_of_empty_space: CharacterStyles) { let (current_canonical_line_index, current_line_wrap_position) = self.cursor_position.line_index; let current_cursor_column_position = self.cursor_position.column_index; @@ -413,8 +474,12 @@ impl Scroll { .canonical_lines .get_mut(current_canonical_line_index) .expect("cursor out of bounds"); - current_canonical_line - .clear_after(current_line_wrap_position, current_cursor_column_position); + current_canonical_line.replace_with_empty_chars_after_cursor( + current_line_wrap_position, + current_cursor_column_position, + self.total_columns, + style_of_empty_space, + ); } pub fn clear_all_after_cursor(&mut self) { let (current_canonical_line_index, current_line_wrap_position) = @@ -429,6 +494,25 @@ impl Scroll { self.canonical_lines .truncate(current_canonical_line_index + 1); } + pub fn replace_with_empty_chars( + &mut self, + count: usize, + style_of_empty_space: CharacterStyles, + ) { + let (current_canonical_line_index, current_line_wrap_position) = + self.cursor_position.line_index; + let current_cursor_column_position = self.cursor_position.column_index; + let current_canonical_line = self + .canonical_lines + .get_mut(current_canonical_line_index) + .expect("cursor out of bounds"); + current_canonical_line.replace_with_empty_chars( + current_line_wrap_position, + current_cursor_column_position, + count, + style_of_empty_space, + ); + } pub fn clear_all(&mut self) { self.canonical_lines.clear(); self.canonical_lines.push(CanonicalLine::new()); @@ -458,6 +542,14 @@ impl Scroll { } self.cursor_position.move_to_column(col); } + pub fn move_cursor_to_column(&mut self, col: usize) { + let current_canonical_line = self.cursor_position.line_index.0; + self.move_cursor_to(current_canonical_line, col); + } + pub fn move_cursor_to_line(&mut self, line: usize) { + let current_column = self.cursor_position.column_index; + self.move_cursor_to(line, current_column); + } pub fn set_scroll_region(&mut self, top_line: usize, bottom_line: usize) { self.scroll_region = Some((top_line, bottom_line)); // TODO: clear linewraps in scroll region? @@ -481,7 +573,7 @@ impl Scroll { for _ in 0..count { self.canonical_lines.remove(current_canonical_line_index); self.canonical_lines - .insert(scroll_region_bottom_index, CanonicalLine::new()); + .insert(scroll_region_bottom_index + 1, CanonicalLine::new()); } } } @@ -500,7 +592,7 @@ impl Scroll { // so we add an empty line where the cursor currently is, and delete the last line // of the scroll region for _ in 0..count { - self.canonical_lines.remove(scroll_region_bottom_index); + self.canonical_lines.remove(scroll_region_bottom_index + 1); self.canonical_lines .insert(current_canonical_line_index, CanonicalLine::new()); } diff --git a/src/terminal_pane/terminal_pane.rs b/src/terminal_pane/terminal_pane.rs index eb000550..dcd06744 100644 --- a/src/terminal_pane/terminal_pane.rs +++ b/src/terminal_pane/terminal_pane.rs @@ -335,8 +335,31 @@ impl vte::Perform for TerminalPane { 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 { @@ -655,7 +678,8 @@ impl vte::Perform for TerminalPane { } else if c == 'K' { // clear line (0 => right, 1 => left, 2 => all) if params[0] == 0 { - self.scroll.clear_canonical_line_right_of_cursor(); + self.scroll + .clear_canonical_line_right_of_cursor(self.pending_styles); } // TODO: implement 1 and 2 } else if c == 'J' { @@ -669,9 +693,11 @@ impl vte::Perform for TerminalPane { } else if c == 'H' { // goto row/col let (row, col) = if params.len() == 1 { - (params[0] as usize, 0) // TODO: is this always correct ? + (params[0] as usize, params[0] as usize) } else { - (params[0] as usize - 1, params[1] as usize - 1) // we subtract 1 here because this csi is 1 indexed and we index from 0 + // we subtract 1 from the column because after we get a cursor goto, the print + // character should be printed on top of the cursor + (params[0] as usize, params[1] as usize - 1) }; self.scroll.move_cursor_to(row, col); } else if c == 'A' { @@ -749,19 +775,39 @@ impl vte::Perform for TerminalPane { }; self.scroll .add_empty_lines_in_scroll_region(line_count_to_add); - } else if c == 'q' || c == 'd' || c == 'X' || c == 'G' { + } else if c == 'q' { // ignore for now to run on mac + } else if c == 'G' { + let column = if params[0] == 0 { + 0 + } else { + // params[0] as usize + params[0] as usize - 1 + }; + self.scroll.move_cursor_to_column(column); + } else if c == 'd' { + // goto line + let line = if params[0] == 0 { + 1 + } else { + params[0] as usize + }; + self.scroll.move_cursor_to_line(line); + } else if c == 'X' || c == 'P' { + // erase characters + let count = if params[0] == 0 { + 1 + } else { + params[0] as usize + }; + self.scroll + .replace_with_empty_chars(count, self.pending_styles); } else if c == 'T' { /* * 124 54 T SD * Scroll down, new lines inserted at top of screen * [4T = Scroll down 4, bring previous lines back into view */ - debug_log_to_file(format!( - "htop (only?) linux csi: {}->{:?} ({:?} - ignore: {})", - c, params, _intermediates, _ignore - )) - .unwrap(); let line_count: i64 = *params.get(0).expect("A number of lines was expected."); if line_count >= 0 { @@ -769,17 +815,15 @@ impl vte::Perform for TerminalPane { } else { self.rotate_scroll_region_down(line_count.abs() as usize); } - } else if c == 'P' { - /* - * 120 50 P * DCH - * Delete Character, from current position to end of field - * [4P = Delete 4 characters, VT102 series - */ - debug_log_to_file(format!( - "htop (only?) linux csi: {}->{:?} (intermediates: {:?}, ignore: {})", - c, params, _intermediates, _ignore - )) - .unwrap(); + } else if c == 'S' { + // move scroll up + let count = if params[0] == 0 { + 1 + } else { + params[0] as usize + }; + self.scroll.delete_lines_in_scroll_region(count); + self.scroll.add_empty_lines_in_scroll_region(count); } else { debug_log_to_file(format!("Unhandled csi: {}->{:?}", c, params)).unwrap(); panic!("unhandled csi: {}->{:?}", c, params); diff --git a/src/tests/fixtures/htop b/src/tests/fixtures/htop new file mode 100644 index 0000000000000000000000000000000000000000..37ee0777175ef96c63168734eb7e21e634750b8a GIT binary patch literal 16234 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 literal 0 HcmV?d00001 diff --git a/src/tests/integration/compatibility.rs b/src/tests/integration/compatibility.rs index a763d594..8034bfb4 100644 --- a/src/tests/integration/compatibility.rs +++ b/src/tests/integration/compatibility.rs @@ -192,3 +192,26 @@ pub fn vim_ctrl_u() { assert_snapshot!(snapshot); } } + +#[test] +pub fn htop() { + let fake_win_size = PositionAndSize { + columns: 116, + rows: 28, + x: 0, + y: 0, + }; + let fixture_name = "htop"; + let mut fake_input_output = get_fake_os_input(&fake_win_size, fixture_name); + fake_input_output.add_terminal_input(&[COMMAND_TOGGLE, COMMAND_TOGGLE, QUIT]); + start(Box::new(fake_input_output.clone()), Opt::default()); + 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); + } +} diff --git a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop-2.snap b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop-2.snap new file mode 100644 index 00000000..2fa4647b --- /dev/null +++ b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop-2.snap @@ -0,0 +1,32 @@ +--- +source: src/tests/integration/compatibility.rs +expression: snapshot +--- + 1 [||||| 10.1%] Tasks: 73, 413 thr; 1 running + 2 [||||||| 13.5%] Load average: 1.03 1.07 1.30 + 3 [|||||| 10.8%] Uptime: 22:41:15 + 4 [|||||| 10.6%] + Mem[|||||||||||||||||||||||||||||||||||||3.28G/15.3G] + Swp[ 0K/16.0G] + + PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command + 1352 aram 20 0 3776M 581M 238M S 8.7 3.7 2h01:10 /usr/lib/firefox/firefox + 98777 aram 20 0 537M 6184 4240 S 8.1 0.0 0:00.80 target/debug/mosaic --debug + 1669 aram 20 0 2944M 318M 130M S 8.1 2.0 1h01:33 /usr/lib/firefox/firefox -contentproc -childID 6 -i + 826 aram 9 -11 1581M 15092 11244 S 6.1 0.1 42:21.83 /usr/bin/pulseaudio --daemonize=no + 9419 aram 20 0 533M 7392 3344 S 4.7 0.0 22:01.92 /usr/local/bin/mosaic --max-panes 4 + 98913 aram 20 0 537M 6184 4240 S 3.4 0.0 0:00.31 target/debug/mosaic --debug + 1505 aram 20 0 3187M 329M 206M S 3.4 2.1 23:35.90 /usr/lib/firefox/firefox -contentproc -childID 2 -i + 98912 aram 20 0 537M 6184 4240 S 2.7 0.0 0:00.22 target/debug/mosaic --debug + 1164 aram -6 0 1581M 15092 11244 S 2.7 0.1 21:39.80 /usr/bin/pulseaudio --daemonize=no + 1247 aram 20 0 1184M 292M 84828 S 2.7 1.9 38:01.54 /usr/lib/Xorg -nolisten tcp :0 vt1 -keeptty -auth / + 1475 aram -11 0 3776M 581M 238M S 2.0 3.7 14:27.94 /usr/lib/firefox/firefox + 8574 aram 20 0 2944M 318M 130M S 2.0 2.0 14:36.50 /usr/lib/firefox/firefox -contentproc -childID 6 -i + 1364 aram 20 0 3776M 581M 238M S 2.0 3.7 18:01.89 /usr/lib/firefox/firefox + 1870 aram 20 0 3776M 581M 238M S 2.0 3.7 13:27.06 /usr/lib/firefox/firefox + 9427 aram 20 0 533M 7392 3344 S 2.0 0.0 6:53.47 /usr/local/bin/mosaic --max-panes 4 + 98905 aram 20 0 537M 6184 4240 S 2.0 0.0 0:00.17 target/debug/mosaic --debug + 99272 aram 20 0 8456 4348 3320 R 1.3 0.0 0:00.13 htop + 8611 aram 20 0 2944M 318M 130M S 1.3 2.0 8:17.90 /usr/lib/firefox/firefox -contentproc -childID 6 -i +F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit +Bye from Mosaic! diff --git a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop.snap b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop.snap new file mode 100644 index 00000000..98351875 --- /dev/null +++ b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop.snap @@ -0,0 +1,32 @@ +--- +source: src/tests/integration/compatibility.rs +expression: snapshot +--- + + 1 [||||| 10.1%] Tasks: 73, 413 thr; 1 running + 2 [||||||| 13.5%] Load average: 1.03 1.07 1.30 + 3 [|||||| 10.8%] Uptime: 22:41:15 + 4 [|||||| 10.6%] + Mem[|||||||||||||||||||||||||||||||||||||3.28G/15.3G] + Swp[ 0K/16.0G] + + PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command + 1352 aram 20 0 3776M 581M 238M S 8.7 3.7 2h01:10 /usr/lib/firefox/firefox + 98777 aram 20 0 537M 6184 4240 S 8.1 0.0 0:00.80 target/debug/mosaic --debug + 1669 aram 20 0 2944M 318M 130M S 8.1 2.0 1h01:33 /usr/lib/firefox/firefox -contentproc -childID 6 -i + 826 aram 9 -11 1581M 15092 11244 S 6.1 0.1 42:21.83 /usr/bin/pulseaudio --daemonize=no + 9419 aram 20 0 533M 7392 3344 S 4.7 0.0 22:01.92 /usr/local/bin/mosaic --max-panes 4 + 98913 aram 20 0 537M 6184 4240 S 3.4 0.0 0:00.31 target/debug/mosaic --debug + 1505 aram 20 0 3187M 329M 206M S 3.4 2.1 23:35.90 /usr/lib/firefox/firefox -contentproc -childID 2 -i + 98912 aram 20 0 537M 6184 4240 S 2.7 0.0 0:00.22 target/debug/mosaic --debug + 1164 aram -6 0 1581M 15092 11244 S 2.7 0.1 21:39.80 /usr/bin/pulseaudio --daemonize=no + 1247 aram 20 0 1184M 292M 84828 S 2.7 1.9 38:01.54 /usr/lib/Xorg -nolisten tcp :0 vt1 -keeptty -auth / + 1475 aram -11 0 3776M 581M 238M S 2.0 3.7 14:27.94 /usr/lib/firefox/firefox + 8574 aram 20 0 2944M 318M 130M S 2.0 2.0 14:36.50 /usr/lib/firefox/firefox -contentproc -childID 6 -i + 1364 aram 20 0 3776M 581M 238M S 2.0 3.7 18:01.89 /usr/lib/firefox/firefox + 1870 aram 20 0 3776M 581M 238M S 2.0 3.7 13:27.06 /usr/lib/firefox/firefox + 9427 aram 20 0 533M 7392 3344 S 2.0 0.0 6:53.47 /usr/local/bin/mosaic --max-panes 4 + 98905 aram 20 0 537M 6184 4240 S 2.0 0.0 0:00.17 target/debug/mosaic --debug + 99272 aram 20 0 8456 4348 3320 R 1.3 0.0 0:00.13 htop + 8611 aram 20 0 2944M 318M 130M S 1.3 2.0 8:17.90 /usr/lib/firefox/firefox -contentproc -childID 6 -i +F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit diff --git a/src/utils/logging.rs b/src/utils/logging.rs index 38ac57c4..031813ed 100644 --- a/src/utils/logging.rs +++ b/src/utils/logging.rs @@ -7,7 +7,12 @@ use std::{ use crate::utils::consts::{MOSAIC_TMP_LOG_DIR, MOSAIC_TMP_LOG_FILE}; +fn atomic_create_file(file_name: &str) { + let _ = fs::OpenOptions::new().create(true).open(file_name); +} + pub fn debug_log_to_file(message: String) -> io::Result<()> { + atomic_create_file(MOSAIC_TMP_LOG_FILE); let mut file = fs::OpenOptions::new() .append(true) .create(true)