fix(compatibility): htop horizontal scrolling (#81)

* fix(compatibility): htop horizontal scrolling

* style(format): make rustfmt happy
This commit is contained in:
Aram Drevekenin 2020-12-04 10:02:51 +01:00 committed by GitHub
parent b7b3ff74cf
commit a56cb3c9ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 179 additions and 28 deletions

View file

@ -40,33 +40,9 @@ impl CanonicalLine {
self.wrapped_fragments.push(new_fragment);
}
pub fn change_width(&mut self, new_width: usize) {
let mut characters: Vec<TerminalCharacter> = self
.wrapped_fragments
.iter()
.fold(
Vec::with_capacity(self.wrapped_fragments.len()),
|mut characters, wrapped_fragment| {
characters.push(wrapped_fragment.characters.iter().copied());
characters
},
)
.into_iter()
.flatten()
.collect();
let mut wrapped_fragments = Vec::with_capacity(characters.len() / new_width);
while !characters.is_empty() {
if characters.len() > new_width {
wrapped_fragments.push(WrappedFragment::from_vec(
characters.drain(..new_width).collect(),
));
} else {
wrapped_fragments.push(WrappedFragment::from_vec(characters.drain(..).collect()));
}
}
if wrapped_fragments.is_empty() {
wrapped_fragments.push(WrappedFragment::new());
}
let characters = self.flattened_characters();
let wrapped_fragments =
CanonicalLine::fill_fragments_up_to_width(characters, new_width, None);
self.wrapped_fragments = wrapped_fragments;
}
pub fn clear_after(&mut self, fragment_index: usize, column_index: usize) {
@ -113,6 +89,28 @@ impl CanonicalLine {
}
}
}
pub fn erase_chars(
&mut self,
fragment_index: usize,
from_col: usize,
count: usize,
style_of_empty_space: CharacterStyles,
) {
let mut empty_character = EMPTY_TERMINAL_CHARACTER;
empty_character.styles = style_of_empty_space;
let current_width = self.wrapped_fragments.get(0).unwrap().characters.len();
let mut characters = self.flattened_characters();
let absolute_position_of_character = fragment_index * current_width + from_col;
for _ in 0..count {
characters.remove(absolute_position_of_character);
}
let wrapped_fragments = CanonicalLine::fill_fragments_up_to_width(
characters,
current_width,
Some(empty_character),
);
self.wrapped_fragments = wrapped_fragments;
}
pub fn replace_with_empty_chars_after_cursor(
&mut self,
fragment_index: usize,
@ -157,6 +155,49 @@ impl CanonicalLine {
current_fragment.add_character(empty_char_character, i);
}
}
fn flattened_characters(&self) -> Vec<TerminalCharacter> {
self.wrapped_fragments
.iter()
.fold(
Vec::with_capacity(self.wrapped_fragments.len()),
|mut characters, wrapped_fragment| {
characters.push(wrapped_fragment.characters.iter().copied());
characters
},
)
.into_iter()
.flatten()
.collect()
}
fn fill_fragments_up_to_width(
mut characters: Vec<TerminalCharacter>,
width: usize,
padding: Option<TerminalCharacter>,
) -> Vec<WrappedFragment> {
let mut wrapped_fragments = vec![];
while !characters.is_empty() {
if characters.len() > width {
wrapped_fragments.push(WrappedFragment::from_vec(
characters.drain(..width).collect(),
));
} else {
let mut last_fragment = WrappedFragment::from_vec(characters.drain(..).collect());
let last_fragment_len = last_fragment.characters.len();
if let Some(empty_char_character) = padding {
if last_fragment_len < width {
for _ in last_fragment_len..width {
last_fragment.characters.push(empty_char_character);
}
}
}
wrapped_fragments.push(last_fragment);
}
}
if wrapped_fragments.is_empty() {
wrapped_fragments.push(WrappedFragment::new());
}
wrapped_fragments
}
}
impl Debug for CanonicalLine {
@ -538,6 +579,21 @@ impl Scroll {
style_of_empty_space,
);
}
pub fn erase_characters(&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.erase_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());

View file

@ -868,13 +868,21 @@ impl vte::Perform for TerminalPane {
params[0] as usize
};
self.scroll.move_cursor_to_line(line);
} else if c == 'X' || c == 'P' {
} else if c == 'P' {
// erase characters
let count = if params[0] == 0 {
1
} else {
params[0] as usize
};
self.scroll.erase_characters(count, self.pending_styles);
} else if c == 'X' {
// erase characters and replace with empty characters of current style
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' {

BIN
src/tests/fixtures/htop_right_scrolling vendored Normal file

Binary file not shown.

View file

@ -237,3 +237,26 @@ pub fn htop_scrolling() {
assert_snapshot!(snapshot);
}
}
#[test]
pub fn htop_right_scrolling() {
let fake_win_size = PositionAndSize {
columns: 116,
rows: 28,
x: 0,
y: 0,
};
let fixture_name = "htop_right_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);
}
}

View file

@ -0,0 +1,32 @@
---
source: src/tests/integration/compatibility.rs
expression: snapshot
---
1 [|||||||||| 16.9%] Tasks: 110, 512 thr; 1 running
2 [|||||||||| 17.1%] Load average: 1.04 1.30 1.29
3 [||||||| 13.9%] Uptime: 6 days, 07:01:39
4 [||||||||| 14.9%]
Mem[|||||||||||||||||||||||||||||||||||||8.80G/15.3G]
Swp[| 2.82M/16.0G]
PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
20 0 8576 4508 3356 R 1.3 0.0 0:00.11 htop
20 0 171M 10868 7804 S 0.0 0.1 2:08.38 /sbin/init
20 0 107M 29364 28092 S 0.0 0.2 0:03.42 /usr/lib/systemd/systemd-journald
20 0 32648 9568 6616 S 0.0 0.1 0:01.87 /usr/lib/systemd/systemd-udevd
20 0 78060 992 856 S 0.0 0.0 0:00.00 /usr/bin/lvmetad -f
20 0 6952 4356 3492 S 0.0 0.0 0:57.67 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidf
20 0 14824 7552 5984 S 0.0 0.0 0:12.93 /usr/bin/connmand -n --nodnsproxy
20 0 17696 7940 6696 S 0.0 0.0 0:01.25 /usr/lib/systemd/systemd-logind
20 0 1635M 56148 20460 S 0.0 0.3 1:27.24 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:38.37 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.01 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:47.55 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:26.19 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:40.77 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:47.26 /usr/bin/dockerd -H fd://
F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit
Bye from Mosaic!█

View file

@ -0,0 +1,32 @@
---
source: src/tests/integration/compatibility.rs
expression: snapshot
---
1 [|||||||||| 16.9%] Tasks: 110, 512 thr; 1 running
2 [|||||||||| 17.1%] Load average: 1.04 1.30 1.29
3 [||||||| 13.9%] Uptime: 6 days, 07:01:39
4 [||||||||| 14.9%]
Mem[|||||||||||||||||||||||||||||||||||||8.80G/15.3G]
Swp[| 2.82M/16.0G]
PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
20 0 8576 4508 3356 R 1.3 0.0 0:00.11 htop
20 0 171M 10868 7804 S 0.0 0.1 2:08.38 /sbin/init
20 0 107M 29364 28092 S 0.0 0.2 0:03.42 /usr/lib/systemd/systemd-journald
20 0 32648 9568 6616 S 0.0 0.1 0:01.87 /usr/lib/systemd/systemd-udevd
20 0 78060 992 856 S 0.0 0.0 0:00.00 /usr/bin/lvmetad -f
20 0 6952 4356 3492 S 0.0 0.0 0:57.67 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidf
20 0 14824 7552 5984 S 0.0 0.0 0:12.93 /usr/bin/connmand -n --nodnsproxy
20 0 17696 7940 6696 S 0.0 0.0 0:01.25 /usr/lib/systemd/systemd-logind
20 0 1635M 56148 20460 S 0.0 0.3 1:27.24 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:38.37 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.01 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 0:00.00 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:47.55 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:26.19 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:40.77 /usr/bin/dockerd -H fd://
20 0 1635M 56148 20460 S 0.0 0.3 1:47.26 /usr/bin/dockerd -H fd://
F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit