fix(scroll): support show/hide cursor and fix vim scrolling behaviour (#27)
This commit is contained in:
parent
cc347ab24a
commit
13af16b336
8 changed files with 92 additions and 38 deletions
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
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;
|
||||
(x, y)
|
||||
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();
|
||||
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![];
|
||||
|
|
|
|||
|
|
@ -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,10 +245,17 @@ 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
|
||||
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
|
||||
|
|
@ -260,6 +269,7 @@ impl Scroll {
|
|||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if current_canonical_line_index == self.canonical_lines.len() - 1 {
|
||||
let new_canonical_line = CanonicalLine::new();
|
||||
self.canonical_lines.push(new_canonical_line);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -29,4 +29,4 @@ expression: snapshot
|
|||
│ │
|
||||
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
||||
Press <SPACE> to pause. Use <TAB> to rearrange tables. (DNS queries hidden).
|
||||
Bye from Mosaic!█
|
||||
Bye from Mosaic!
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ expression: snapshot
|
|||
┌Utilization by process name───────────────────────────────────────────────────────────────────────────────────────┐
|
||||
│Process Connections Up / Down │
|
||||
│ │
|
||||
│firefox 3 46Bps / 5█Bps │
|
||||
│firefox 3 46Bps / 57Bps │
|
||||
│ │
|
||||
│ │
|
||||
│ │
|
||||
|
|
|
|||
|
|
@ -14,16 +14,18 @@ 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 let Some((cursor_x, cursor_y)) = cursor_coordinates {
|
||||
if line_index == cursor_y && character_index == cursor_x {
|
||||
snapshot.push('█');
|
||||
} else {
|
||||
snapshot.push(terminal_character.character);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
snapshot.push(terminal_character.character);
|
||||
}
|
||||
if line_index != output_lines.len() - 1 {
|
||||
snapshot.push('\n');
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue