aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2020-11-30 09:40:24 +0100
committerGitHub <noreply@github.com>2020-11-30 09:40:24 +0100
commitc47fed927e8fad0395266fb30c58a094e430bee0 (patch)
tree8e934b835157fe4adcb4ccb7ed4169e6d366582b /src
parentfix(input): read stdin with lock (#72) (diff)
downloadsl0ppij-c47fed927e8fad0395266fb30c58a094e430bee0.tar.gz
sl0ppij-c47fed927e8fad0395266fb30c58a094e430bee0.tar.xz
sl0ppij-c47fed927e8fad0395266fb30c58a094e430bee0.zip
fic(compatibility): htop scrolling issues (#77)
* fix(compatibility): scrolling inside scroll region with 'M' esc dispatch * style(format): make rustfmt happy * fix(tests): send proper data * fix(logs): do not crash if log file doesn't exist
Diffstat (limited to 'src')
-rw-r--r--src/main.rs5
-rw-r--r--src/pty_bus.rs2
-rw-r--r--src/terminal_pane/scroll.rs64
-rw-r--r--src/terminal_pane/terminal_pane.rs22
-rw-r--r--src/tests/fixtures/htop_scrollingbin0 -> 18484 bytes
-rw-r--r--src/tests/integration/compatibility.rs23
-rw-r--r--src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop-2.snap2
-rw-r--r--src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling-2.snap32
-rw-r--r--src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling.snap32
-rw-r--r--src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell-2.snap2
-rw-r--r--src/utils/logging.rs11
11 files changed, 179 insertions, 16 deletions
diff --git a/src/main.rs b/src/main.rs
index 96b50cb2..0f5fcf06 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -450,10 +450,11 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
}
// cleanup();
let reset_style = "\u{1b}[m";
+ let show_cursor = "\u{1b}[?25h";
let goto_start_of_last_line = format!("\u{1b}[{};{}H", full_screen_ws.rows, 1);
let goodbye_message = format!(
- "{}\n{}Bye from Mosaic!",
- goto_start_of_last_line, reset_style
+ "{}\n{}{}Bye from Mosaic!",
+ goto_start_of_last_line, reset_style, show_cursor
);
os_input.unset_raw_mode(0);
diff --git a/src/pty_bus.rs b/src/pty_bus.rs
index 078e3271..3c8abcff 100644
--- a/src/pty_bus.rs
+++ b/src/pty_bus.rs
@@ -11,7 +11,7 @@ use std::path::PathBuf;
use crate::layout::Layout;
use crate::os_input_output::OsApi;
-use crate::utils::logging::debug_to_file;
+use crate::utils::logging::{debug_log_to_file, debug_to_file};
use crate::ScreenInstruction;
pub struct ReadFromPid {
diff --git a/src/terminal_pane/scroll.rs b/src/terminal_pane/scroll.rs
index 336c17bf..bfd6bd31 100644
--- a/src/terminal_pane/scroll.rs
+++ b/src/terminal_pane/scroll.rs
@@ -135,6 +135,28 @@ impl CanonicalLine {
self.wrapped_fragments.truncate(fragment_index + 1);
}
+ pub fn replace_with_empty_chars_before_cursor(
+ &mut self,
+ fragment_index: usize,
+ until_col: usize,
+ style_of_empty_space: CharacterStyles,
+ ) {
+ let mut empty_char_character = EMPTY_TERMINAL_CHARACTER;
+ empty_char_character.styles = style_of_empty_space;
+
+ if fragment_index > 0 {
+ for i in 0..(fragment_index - 1) {
+ let fragment = self.wrapped_fragments.get_mut(i).unwrap();
+ for i in 0..fragment.characters.len() {
+ fragment.add_character(empty_char_character, i);
+ }
+ }
+ }
+ let current_fragment = self.wrapped_fragments.get_mut(fragment_index).unwrap();
+ for i in 0..until_col {
+ current_fragment.add_character(empty_char_character, i);
+ }
+ }
}
impl Debug for CanonicalLine {
@@ -331,21 +353,18 @@ impl Scroll {
pub fn add_canonical_line(&mut self) {
let current_canonical_line_index = self.cursor_position.line_index.0;
if let Some((scroll_region_top, scroll_region_bottom)) = self.scroll_region {
- // the scroll region indices start at 1, so we need to adjust them
if self.show_cursor {
// 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 + 1 {
+ if current_canonical_line_index == scroll_region_bottom {
// 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
// then we add an empty line at its end which will be filled by the application
// controlling the scroll region (presumably filled by whatever comes next in the
// scroll buffer, but that's not something we control)
- self.canonical_lines.remove(scroll_region_top_index);
+ self.canonical_lines.remove(scroll_region_top);
self.canonical_lines
- .insert(scroll_region_bottom_index + 1, CanonicalLine::new());
+ .insert(scroll_region_bottom, CanonicalLine::new());
return;
}
}
@@ -473,6 +492,20 @@ impl Scroll {
style_of_empty_space,
);
}
+ pub fn clear_canonical_line_left_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;
+ 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_before_cursor(
+ current_line_wrap_position,
+ current_cursor_column_position,
+ style_of_empty_space,
+ );
+ }
pub fn clear_all_after_cursor(&mut self) {
let (current_canonical_line_index, current_line_wrap_position) =
self.cursor_position.line_index;
@@ -592,6 +625,25 @@ impl Scroll {
}
}
}
+ pub fn move_cursor_up_in_scroll_region(&mut self, count: usize) {
+ if let Some((scroll_region_top, scroll_region_bottom)) = self.scroll_region {
+ // the scroll region indices start at 1, so we need to adjust them
+ for _ in 0..count {
+ let current_canonical_line_index = self.cursor_position.line_index.0;
+ if current_canonical_line_index == scroll_region_top {
+ // if we're at the top line, we create a new line and remove the last line that
+ // would otherwise overflow
+ self.canonical_lines.remove(scroll_region_bottom);
+ self.canonical_lines
+ .insert(current_canonical_line_index, CanonicalLine::new());
+ } else if current_canonical_line_index > scroll_region_top
+ && current_canonical_line_index <= scroll_region_bottom
+ {
+ self.move_cursor_up(count);
+ }
+ }
+ }
+ }
/// [scroll_up](https://github.com/alacritty/alacritty/blob/ec42b42ce601808070462111c0c28edb0e89babb/alacritty_terminal/src/grid/mod.rs#L261)
/// This function takes the first line of the scroll region and moves it to the bottom (count times)
pub fn rotate_scroll_region_up(&mut self, count: usize) {
diff --git a/src/terminal_pane/terminal_pane.rs b/src/terminal_pane/terminal_pane.rs
index 42062e24..73635b1f 100644
--- a/src/terminal_pane/terminal_pane.rs
+++ b/src/terminal_pane/terminal_pane.rs
@@ -687,8 +687,11 @@ impl vte::Perform for TerminalPane {
if params[0] == 0 {
self.scroll
.clear_canonical_line_right_of_cursor(self.pending_styles);
+ } else if params[0] == 1 {
+ self.scroll
+ .clear_canonical_line_left_of_cursor(self.pending_styles);
}
- // TODO: implement 1 and 2
+ // TODO: implement 2
} else if c == 'J' {
// clear all (0 => below, 1 => above, 2 => all, 3 => saved)
if params[0] == 0 {
@@ -826,12 +829,21 @@ impl vte::Perform for TerminalPane {
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);
+ let _ = debug_log_to_file(format!("Unhandled csi: {}->{:?}", c, params));
}
}
- fn esc_dispatch(&mut self, _intermediates: &[u8], _ignore: bool, _byte: u8) {
- // TBD
+ fn esc_dispatch(&mut self, intermediates: &[u8], _ignore: bool, byte: u8) {
+ match (byte, intermediates.get(0)) {
+ (b'M', None) => {
+ self.scroll.move_cursor_up_in_scroll_region(1);
+ }
+ _ => {
+ let _ = debug_log_to_file(format!(
+ "Unhandled esc_dispatch: {}->{:?}",
+ byte, intermediates
+ ));
+ }
+ }
}
}
diff --git a/src/tests/fixtures/htop_scrolling b/src/tests/fixtures/htop_scrolling
new file mode 100644
index 00000000..4e0df629
--- /dev/null
+++ b/src/tests/fixtures/htop_scrolling
Binary files differ
diff --git a/src/tests/integration/compatibility.rs b/src/tests/integration/compatibility.rs
index c244f5bf..cb378ef5 100644
--- a/src/tests/integration/compatibility.rs
+++ b/src/tests/integration/compatibility.rs
@@ -214,3 +214,26 @@ pub fn htop() {
assert_snapshot!(snapshot);
}
}
+
+#[test]
+pub fn htop_scrolling() {
+ let fake_win_size = PositionAndSize {
+ columns: 116,
+ rows: 28,
+ x: 0,
+ y: 0,
+ };
+ let fixture_name = "htop_scrolling";
+ 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
index 2fa4647b..3754cdd4 100644
--- a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop-2.snap
+++ b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop-2.snap
@@ -29,4 +29,4 @@ expression: snapshot
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!
+Bye from Mosaic!█
diff --git a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling-2.snap b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling-2.snap
new file mode 100644
index 00000000..c4f6568c
--- /dev/null
+++ b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling-2.snap
@@ -0,0 +1,32 @@
+---
+source: src/tests/integration/compatibility.rs
+expression: snapshot
+---
+ 1 [||||||||||||||||||||||||||||||||||||||||||100.0%] Tasks: 79, 382 thr; 1 running
+ 2 [ 0.0%] Load average: 1.40 1.43 1.38
+ 3 [ 0.0%] Uptime: 2 days, 07:33:50
+ 4 [ 0.0%]
+ Mem[|||||||||||||||||||||||||||||||||||||3.64G/15.3G]
+ Swp[ 0K/16.0G]
+
+ PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
+ 123934 aram 20 0 8444 4384 3364 R 66.7 0.0 0:00.05 htop --delay=100000000000
+ 1 root 20 0 171M 11616 8608 S 0.0 0.1 0:56.91 /sbin/init
+ 268 root 20 0 93324 34340 33072 S 0.0 0.2 0:01.05 /usr/lib/systemd/systemd-journald
+ 276 root 20 0 32648 10192 7240 S 0.0 0.1 0:01.13 /usr/lib/systemd/systemd-udevd
+ 286 root 20 0 78060 1132 996 S 0.0 0.0 0:00.00 /usr/bin/lvmetad -f
+ 343 dbus 20 0 6952 4384 3520 S 0.0 0.0 0:13.85 /usr/bin/dbus-daemon --system --address=systemd: --
+ 344 root 20 0 14588 7512 6176 S 0.0 0.0 0:03.21 /usr/bin/connmand -n --nodnsproxy
+ 345 root 20 0 17696 8372 7128 S 0.0 0.1 0:00.67 /usr/lib/systemd/systemd-logind
+ 395 root 20 0 1635M 83324 44976 S 0.0 0.5 0:32.43 /usr/bin/dockerd -H fd://
+ 396 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.01 /usr/bin/dockerd -H fd://
+ 397 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.01 /usr/bin/dockerd -H fd://
+ 398 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd://
+ 399 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd://
+ 412 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd://
+ 441 root 20 0 1635M 83324 44976 S 0.0 0.5 0:41.35 /usr/bin/dockerd -H fd://
+ 442 root 20 0 1635M 83324 44976 S 0.0 0.5 0:33.61 /usr/bin/dockerd -H fd://
+ 444 root 20 0 1635M 83324 44976 S 0.0 0.5 0:33.13 /usr/bin/dockerd -H fd://
+ 449 root 20 0 1635M 83324 44976 S 0.0 0.5 0:41.39 /usr/bin/dockerd -H fd://
+F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit
+Bye from Mosaic!█
diff --git a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling.snap b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling.snap
new file mode 100644
index 00000000..fdf6cf89
--- /dev/null
+++ b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__htop_scrolling.snap
@@ -0,0 +1,32 @@
+---
+source: src/tests/integration/compatibility.rs
+expression: snapshot
+---
+ 1 [||||||||||||||||||||||||||||||||||||||||||100.0%] Tasks: 79, 382 thr; 1 running
+ 2 [ 0.0%] Load average: 1.40 1.43 1.38
+ 3 [ 0.0%] Uptime: 2 days, 07:33:50
+ 4 [ 0.0%]
+ Mem[|||||||||||||||||||||||||||||||||||||3.64G/15.3G]
+ Swp[ 0K/16.0G]
+
+ PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
+ 123934 aram 20 0 8444 4384 3364 R 66.7 0.0 0:00.05 htop --delay=100000000000
+ 1 root 20 0 171M 11616 8608 S 0.0 0.1 0:56.91 /sbin/init
+ 268 root 20 0 93324 34340 33072 S 0.0 0.2 0:01.05 /usr/lib/systemd/systemd-journald
+ 276 root 20 0 32648 10192 7240 S 0.0 0.1 0:01.13 /usr/lib/systemd/systemd-udevd
+ 286 root 20 0 78060 1132 996 S 0.0 0.0 0:00.00 /usr/bin/lvmetad -f
+ 343 dbus 20 0 6952 4384 3520 S 0.0 0.0 0:13.85 /usr/bin/dbus-daemon --system --address=systemd: --
+ 344 root 20 0 14588 7512 6176 S 0.0 0.0 0:03.21 /usr/bin/connmand -n --nodnsproxy
+ 345 root 20 0 17696 8372 7128 S 0.0 0.1 0:00.67 /usr/lib/systemd/systemd-logind
+ 395 root 20 0 1635M 83324 44976 S 0.0 0.5 0:32.43 /usr/bin/dockerd -H fd://
+ 396 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.01 /usr/bin/dockerd -H fd://
+ 397 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.01 /usr/bin/dockerd -H fd://
+ 398 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd://
+ 399 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd://
+ 412 root 20 0 1635M 83324 44976 S 0.0 0.5 0:00.00 /usr/bin/dockerd -H fd://
+ 441 root 20 0 1635M 83324 44976 S 0.0 0.5 0:41.35 /usr/bin/dockerd -H fd://
+ 442 root 20 0 1635M 83324 44976 S 0.0 0.5 0:33.61 /usr/bin/dockerd -H fd://
+ 444 root 20 0 1635M 83324 44976 S 0.0 0.5 0:33.13 /usr/bin/dockerd -H fd://
+ 449 root 20 0 1635M 83324 44976 S 0.0 0.5 0:41.39 /usr/bin/dockerd -H fd://
+F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit
+█
diff --git a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell-2.snap b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell-2.snap
index 8ca0fe37..9c90df81 100644
--- a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell-2.snap
+++ b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell-2.snap
@@ -29,4 +29,4 @@ expression: snapshot
│ │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Press <SPACE> to pause. Use <TAB> to rearrange tables. (DNS queries hidden).
-Bye from Mosaic!
+Bye from Mosaic!█
diff --git a/src/utils/logging.rs b/src/utils/logging.rs
index 1af1cb06..e175050e 100644
--- a/src/utils/logging.rs
+++ b/src/utils/logging.rs
@@ -33,6 +33,17 @@ pub fn debug_log_to_file(message: String) -> io::Result<()> {
file.write_all(b"\n")
}
+pub fn debug_log_to_file_without_newline(message: String) -> io::Result<()> {
+ atomic_create_file(MOSAIC_TMP_LOG_FILE);
+ let mut file = fs::OpenOptions::new()
+ .append(true)
+ .create(true)
+ .open(MOSAIC_TMP_LOG_FILE)?;
+ file.write_all(message.as_bytes())?;
+
+ Ok(())
+}
+
pub fn debug_log_to_file_pid_0(message: String, pid: RawFd) -> io::Result<()> {
if pid == 0 {
debug_log_to_file(message)