aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2020-11-06 18:12:03 +0100
committerGitHub <noreply@github.com>2020-11-06 18:12:03 +0100
commit13af16b3360dddc8aede1e7c429696b115fadd6d (patch)
treef1102cfde94ee9f2d8dc10eb93c79884790b8eaf /src
parentdocs(architecture): fix title (diff)
downloadsl0ppij-13af16b3360dddc8aede1e7c429696b115fadd6d.tar.gz
sl0ppij-13af16b3360dddc8aede1e7c429696b115fadd6d.tar.xz
sl0ppij-13af16b3360dddc8aede1e7c429696b115fadd6d.zip
fix(scroll): support show/hide cursor and fix vim scrolling behaviour (#27)
Diffstat (limited to 'src')
-rw-r--r--src/main.rs2
-rw-r--r--src/screen.rs30
-rw-r--r--src/terminal_pane/scroll.rs43
-rw-r--r--src/terminal_pane/terminal_pane.rs37
-rw-r--r--src/tests/integration/basic.rs2
-rw-r--r--src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell-2.snap2
-rw-r--r--src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell.snap2
-rw-r--r--src/tests/utils.rs12
8 files changed, 92 insertions, 38 deletions
diff --git a/src/main.rs b/src/main.rs
index c4bf547d..87250ec2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -269,7 +269,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: Opt) {
send_screen_instructions.send(ScreenInstruction::ScrollDown).unwrap();
} else if buffer[0] == 24 { // ctrl-x
send_screen_instructions.send(ScreenInstruction::CloseFocusedPane).unwrap();
- } else if buffer[0] == 6 { // ctrl-f
+ } else if buffer[0] == 5 { // ctrl-e
send_screen_instructions.send(ScreenInstruction::ToggleActiveTerminalFullscreen).unwrap();
} else {
// println!("\r buffer {:?} ", buffer[0]);
diff --git a/src/screen.rs b/src/screen.rs
index 5acec8d8..e02f8e8f 100644
--- a/src/screen.rs
+++ b/src/screen.rs
@@ -264,13 +264,13 @@ impl Screen {
self.os_api.tcdrain(*active_terminal_id).expect("failed to drain terminal");
}
}
- fn get_active_terminal_cursor_position(&self) -> (usize, usize) { // (x, y)
+ fn get_active_terminal_cursor_position(&self) -> Option<(usize, usize)> { // (x, y)
let active_terminal = &self.get_active_terminal().unwrap();
- let (x_in_terminal, y_in_terminal) = active_terminal.cursor_coordinates();
-
- let x = active_terminal.get_x() + x_in_terminal;
- let y = active_terminal.get_y() + y_in_terminal;
- (x, y)
+ active_terminal.cursor_coordinates().and_then(|(x_in_terminal, y_in_terminal)| {
+ let x = active_terminal.get_x() + x_in_terminal;
+ let y = active_terminal.get_y() + y_in_terminal;
+ Some((x, y))
+ })
}
pub fn toggle_active_terminal_fullscreen(&mut self) {
if let Some(active_terminal_id) = self.get_active_terminal_id() {
@@ -312,10 +312,20 @@ impl Screen {
let vte_output = boundaries.vte_output();
stdout.write_all(&vte_output.as_bytes()).expect("cannot write to stdout");
- let (cursor_position_x, cursor_position_y) = self.get_active_terminal_cursor_position();
- let goto_cursor_position = format!("\u{1b}[{};{}H\u{1b}[m", cursor_position_y + 1, cursor_position_x + 1); // goto row/col
- stdout.write_all(&goto_cursor_position.as_bytes()).expect("cannot write to stdout");
- stdout.flush().expect("could not flush");
+ match self.get_active_terminal_cursor_position() {
+ Some((cursor_position_x, cursor_position_y)) => {
+ let show_cursor = "\u{1b}[?25h";
+ let goto_cursor_position = format!("\u{1b}[{};{}H\u{1b}[m", cursor_position_y + 1, cursor_position_x + 1); // goto row/col
+ stdout.write_all(&show_cursor.as_bytes()).expect("cannot write to stdout");
+ stdout.write_all(&goto_cursor_position.as_bytes()).expect("cannot write to stdout");
+ stdout.flush().expect("could not flush");
+ },
+ None => {
+ let hide_cursor = "\u{1b}[?25l";
+ stdout.write_all(&hide_cursor.as_bytes()).expect("cannot write to stdout");
+ stdout.flush().expect("could not flush");
+ }
+ }
}
fn terminal_ids_directly_left_of(&self, id: &RawFd) -> Option<Vec<RawFd>> {
let mut ids = vec![];
diff --git a/src/terminal_pane/scroll.rs b/src/terminal_pane/scroll.rs
index 13bdaf37..2867f122 100644
--- a/src/terminal_pane/scroll.rs
+++ b/src/terminal_pane/scroll.rs
@@ -172,7 +172,8 @@ pub struct Scroll {
total_columns: usize,
lines_in_view: usize,
viewport_bottom_offset: Option<usize>,
- scroll_region: Option<(usize, usize)> // start line, end line (if set, this is the area the will scroll)
+ scroll_region: Option<(usize, usize)>, // start line, end line (if set, this is the area the will scroll)
+ show_cursor: bool,
}
impl Scroll {
@@ -187,6 +188,7 @@ impl Scroll {
cursor_position,
viewport_bottom_offset: None,
scroll_region: None,
+ show_cursor: true,
}
}
pub fn as_character_lines(&self) -> Vec<Vec<TerminalCharacter>> {
@@ -243,21 +245,29 @@ impl Scroll {
self.cursor_position.move_to_beginning_of_linewrap();
}
}
+ pub fn show_cursor (&mut self) {
+ self.show_cursor = true;
+ }
+ pub fn hide_cursor (&mut self) {
+ self.show_cursor = false;
+ }
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
- 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 { // 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.insert(scroll_region_bottom_index, CanonicalLine::new());
- return;
+ 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 { // 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.insert(scroll_region_bottom_index, CanonicalLine::new());
+ return;
+ }
}
}
if current_canonical_line_index == self.canonical_lines.len() - 1 {
@@ -272,7 +282,10 @@ impl Scroll {
panic!("cursor out of bounds, cannot add_canonical_line");
}
}
- pub fn cursor_coordinates_on_screen(&self) -> (usize, usize) { // (x, y)
+ pub fn cursor_coordinates_on_screen(&self) -> Option<(usize, usize)> { // (x, y)
+ if !self.show_cursor {
+ return None
+ }
let (canonical_line_cursor_position, line_wrap_cursor_position) = self.cursor_position.line_index;
let x = self.cursor_position.column_index;
let mut y = 0;
@@ -294,10 +307,12 @@ impl Scroll {
let total_lines = self.canonical_lines.iter().fold(0, |total_lines, current_line| total_lines + current_line.wrapped_fragments.len()); // TODO: is this performant enough? should it be cached or kept track of?
let y = if total_lines < self.lines_in_view {
total_lines - y
+ } else if y > self.lines_in_view {
+ self.lines_in_view
} else {
self.lines_in_view - y
};
- (x, y)
+ Some((x, y))
}
pub fn move_cursor_forward(&mut self, count: usize) {
let (current_canonical_line_index, current_line_wrap_position) = self.cursor_position.line_index;
diff --git a/src/terminal_pane/terminal_pane.rs b/src/terminal_pane/terminal_pane.rs
index ce5198b1..6107f403 100644
--- a/src/terminal_pane/terminal_pane.rs
+++ b/src/terminal_pane/terminal_pane.rs
@@ -223,7 +223,7 @@ impl TerminalPane {
pub fn read_buffer_as_lines (&self) -> Vec<Vec<TerminalCharacter>> {
self.scroll.as_character_lines()
}
- pub fn cursor_coordinates (&self) -> (usize, usize) { // (x, y)
+ pub fn cursor_coordinates (&self) -> Option<(usize, usize)> { // (x, y)
self.scroll.cursor_coordinates_on_screen()
}
pub fn scroll_up(&mut self, count: usize) {
@@ -255,8 +255,8 @@ impl TerminalPane {
self.should_render = true;
}
fn add_newline (&mut self) {
- self.scroll.add_canonical_line(); // TODO: handle scroll region
- self.reset_all_ansi_codes();
+ self.scroll.add_canonical_line();
+ // self.reset_all_ansi_codes(); // TODO: find out if we should be resetting here or not
self.should_render = true;
}
fn move_to_beginning_of_line (&mut self) {
@@ -557,14 +557,41 @@ impl vte::Perform for TerminalPane {
let move_back_count = if params[0] == 0 { 1 } else { params[0] as usize };
self.scroll.move_cursor_back(move_back_count);
} else if c == 'l' {
- // TBD
+ let first_intermediate_is_questionmark = match _intermediates.get(0) {
+ Some(b'?') => true,
+ None => false,
+ _ => false
+ };
+ if first_intermediate_is_questionmark {
+ match params.get(0) {
+ Some(25) => {
+ self.scroll.hide_cursor();
+ self.should_render = true;
+ },
+ _ => {}
+ };
+ }
} else if c == 'h' {
- // TBD
+ let first_intermediate_is_questionmark = match _intermediates.get(0) {
+ Some(b'?') => true,
+ None => false,
+ _ => false
+ };
+ if first_intermediate_is_questionmark {
+ match params.get(0) {
+ Some(25) => {
+ self.scroll.show_cursor();
+ self.should_render = true;
+ },
+ _ => {}
+ };
+ }
} else if c == 'r' {
if params.len() > 1 {
let top_line_index = params[0] as usize;
let bottom_line_index = params[1] as usize;
self.scroll.set_scroll_region(top_line_index, bottom_line_index);
+ self.scroll.show_cursor();
} else {
self.scroll.clear_scroll_region();
}
diff --git a/src/tests/integration/basic.rs b/src/tests/integration/basic.rs
index 7067c8f6..eb542f95 100644
--- a/src/tests/integration/basic.rs
+++ b/src/tests/integration/basic.rs
@@ -170,7 +170,7 @@ pub fn toggle_focused_pane_fullscreen () {
// split-largest_terminal * 3, toggle-fullscreen * 2, ctrl-p, toggle-fullscreen * 2, ctrl-p, toggle-fullscreen * 2, ctrl-p, toggle-fullscreen * 2 and quit
// (ctrl-z + ctrl-z + ctrl-z + ctrl-z + ctrl-f, ctrl-f, ctrl-p, ctrl-f, ctrl-f, ctrl-p, ctrl-f,
// ctrl-f, ctrl-p, ctrl-f, ctrl-f, ctrl-q)
- fake_input_output.add_terminal_input(&[26, 26, 26, 6, 6, 16, 6, 6, 16, 6, 6, 16, 6, 6, 17]);
+ fake_input_output.add_terminal_input(&[26, 26, 26, 5, 5, 16, 5, 5, 16, 5, 5, 16, 5, 5, 17]);
let mut opts = Opt::default();
opts.max_panes = Some(4);
start(Box::new(fake_input_output.clone()), opts);
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 9c90df81..8ca0fe37 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/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell.snap b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell.snap
index f8f4a539..5d056ac2 100644
--- a/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell.snap
+++ b/src/tests/integration/snapshots/mosaic__tests__integration__compatibility__run_bandwhich_from_fish_shell.snap
@@ -6,7 +6,7 @@ expression: snapshot
┌Utilization by process name───────────────────────────────────────────────────────────────────────────────────────┐
│Process Connections Up / Down │
│ │
-│firefox 3 46Bps / 5█Bps │
+│firefox 3 46Bps / 57Bps │
│ │
│ │
│ │
diff --git a/src/tests/utils.rs b/src/tests/utils.rs
index 1e76b31f..779c72a4 100644
--- a/src/tests/utils.rs
+++ b/src/tests/utils.rs
@@ -14,15 +14,17 @@ pub fn get_output_frame_snapshots(output_frames: &[Vec<u8>], win_size: &Winsize)
vte_parser.advance(&mut terminal_output, *byte);
}
let output_lines = terminal_output.read_buffer_as_lines();
- let (cursor_x, cursor_y) = terminal_output.cursor_coordinates();
+ let cursor_coordinates = terminal_output.cursor_coordinates();
let mut snapshot = String::new();
for (line_index, line) in output_lines.iter().enumerate() {
for (character_index, terminal_character) in line.iter().enumerate() {
- if line_index == cursor_y && character_index == cursor_x {
- snapshot.push('█');
- } else {
- snapshot.push(terminal_character.character);
+ if let Some((cursor_x, cursor_y)) = cursor_coordinates {
+ if line_index == cursor_y && character_index == cursor_x {
+ snapshot.push('█');
+ continue;
+ }
}
+ snapshot.push(terminal_character.character);
}
if line_index != output_lines.len() - 1 {
snapshot.push('\n');