fix(compatibility): bandwhich + various fixes for fish

This commit is contained in:
Aram Drevekenin 2020-09-29 11:43:22 +02:00
parent cf1080bc3f
commit 909b9eec0e
3 changed files with 122 additions and 87 deletions

View File

@ -162,7 +162,8 @@ pub fn start(mut os_input: Box<dyn OsApi>) {
}
// cleanup();
let reset_style = "\u{1b}[m";
let goodbye_message = format!("\n\r{}Bye from Mosaic!", reset_style);
let goto_start_of_last_line = format!("\u{1b}[{};{}H", full_screen_ws.ws_row, 1);
let goodbye_message = format!("{}\n{}Bye from Mosaic!", goto_start_of_last_line, reset_style);
os_input.get_stdout_writer().write(goodbye_message.as_bytes()).unwrap();
os_input.get_stdout_writer().flush().unwrap();

View File

@ -183,9 +183,11 @@ impl Screen {
}
fn get_active_terminal_cursor_position(&self) -> (usize, usize) { // (x, y)
let active_terminal = &self.get_active_terminal().unwrap();
let x = active_terminal.x_coords as usize + active_terminal.cursor_position_in_last_line();
let y = active_terminal.y_coords + active_terminal.display_rows - 1;
(x, y as usize)
let (x_in_terminal, y_in_terminal) = active_terminal.cursor_coordinates();
let x = active_terminal.x_coords as usize + x_in_terminal;
let y = active_terminal.y_coords as usize + y_in_terminal;
(x, y)
}
pub fn render (&mut self) {
let mut stdout = self.os_api.get_stdout_writer();

View File

@ -242,6 +242,7 @@ impl TerminalOutput {
x = 0;
next_newline_index = newline_indices.next();
} else if x == self.display_cols as u64 && i <= self.cursor_position {
// TODO: maybe remove <= self.cursor_position? why not reflow lines after cursor?
self.linebreak_indices.push(i);
x = 0;
}
@ -354,83 +355,65 @@ impl TerminalOutput {
Vec::from(output)
}
pub fn cursor_position_in_last_line (&self) -> usize {
if self.cursor_position <= self.characters.len() {
let start_of_last_line = self.index_of_beginning_of_last_line();
if self.cursor_position < start_of_last_line {
// TODO: why does this happen?
return self.display_cols as usize
};
let difference_from_last_newline = self.cursor_position - start_of_last_line;
difference_from_last_newline
} else {
self.display_cols as usize
}
}
pub fn cursor_coordinates (&self) -> (usize, usize) { // (x, y)
let mut lines_from_end = 0;
let mut newline_indices = self.newline_indices.iter().rev();
let mut linebreak_indices = self.linebreak_indices.iter().rev();
let mut next_newline_index = newline_indices.next().unwrap_or(&0);
let mut next_linebreak_index = linebreak_indices.next().unwrap_or(&0);
let mut next_newline_index = newline_indices.next().copied();
let mut next_linebreak_index = linebreak_indices.next().copied();
let next_line_start = loop {
let next_line_start = ::std::cmp::max(*next_newline_index, *next_linebreak_index);
if self.cursor_position >= next_line_start {
break next_line_start;
let next_line_index = ::std::cmp::max(next_newline_index, next_linebreak_index);
if let Some(next_line_index) = next_line_index {
if self.cursor_position > next_line_index {
break next_line_index;
}
} else {
break next_line_index.unwrap_or(0);
}
if next_line_start == *next_newline_index {
next_newline_index = newline_indices.next().unwrap_or(&0);
if next_line_index == next_newline_index {
next_newline_index = newline_indices.next().copied();
lines_from_end += 1;
}
if next_line_start == *next_linebreak_index {
next_linebreak_index = linebreak_indices.next().unwrap_or(&0);
if next_line_index == next_linebreak_index {
next_linebreak_index = linebreak_indices.next().copied();
lines_from_end += 1;
}
};
let y = self.display_rows - lines_from_end; // TODO: this might overflow, fix when introducing scrolling
let y = if self.display_rows < lines_from_end { 1 } else { self.display_rows - 1 - lines_from_end };
// TODO: why 1?
let x = self.cursor_position - next_line_start;
(x, y as usize)
}
fn index_of_beginning_of_last_line (&self) -> usize {
let last_newline_index = if self.newline_indices.is_empty() {
None
} else {
// return last
Some(*self.newline_indices.last().unwrap())
};
let last_linebreak_index = if self.linebreak_indices.is_empty() {
None
} else {
// return last
Some(*self.linebreak_indices.last().unwrap())
};
match (last_newline_index, last_linebreak_index) {
(Some(last_newline_index), Some(last_linebreak_index)) => {
max(last_newline_index, last_linebreak_index)
},
(None, Some(last_linebreak_index)) => last_linebreak_index,
(Some(last_newline_index), None) => last_newline_index,
(None, None) => 0
}
}
fn index_of_beginning_of_last_canonical_line (&self) -> usize {
if self.newline_indices.is_empty() {
0
} else {
// return last
*self.newline_indices.last().unwrap()
}
}
fn index_of_end_of_canonical_line(&self, index_in_line: usize) -> usize {
let newlines = self.newline_indices.iter().rev();
let mut index_of_end_of_canonical_line = self.characters.len();
for line_index in newlines {
if *line_index <= index_in_line {
break
}
if index_of_end_of_canonical_line > *line_index {
index_of_end_of_canonical_line = *line_index;
}
}
index_of_end_of_canonical_line
}
fn index_of_beginning_of_line (&self, index_in_line: usize) -> usize {
let last_newline_index = if self.newline_indices.is_empty() {
None
} else {
// return last less than index_in_line
let last_newline_index = *self.newline_indices.last().unwrap();
if last_newline_index <= index_in_line {
if last_newline_index < index_in_line {
Some(last_newline_index)
} else {
let mut last_newline_index = 0;
@ -449,7 +432,7 @@ impl TerminalOutput {
} else {
// return last less than index_in_line
let last_linebreak_index = *self.linebreak_indices.last().unwrap();
if last_linebreak_index <= index_in_line {
if last_linebreak_index < index_in_line {
Some(last_linebreak_index)
} else {
let mut last_linebreak_index = 0;
@ -473,8 +456,13 @@ impl TerminalOutput {
}
}
fn add_newline (&mut self) {
self.newline_indices.push(self.characters.len());
self.cursor_position = self.characters.len();
let nearest_line_end = self.index_of_end_of_canonical_line(self.cursor_position);
if nearest_line_end == self.characters.len() {
self.newline_indices.push(nearest_line_end);
self.cursor_position = nearest_line_end; // + 1 ?
} else {
self.cursor_position = nearest_line_end; // + 1 ?
}
self.should_render = true;
self.pending_foreground_ansi_codes.clear();
self.pending_background_ansi_codes.clear();
@ -489,7 +477,6 @@ impl TerminalOutput {
impl vte::Perform for TerminalOutput {
fn print(&mut self, c: char) {
// print!("\n\r{}", c);
if DEBUGGING {
println!("\r[print] {:?}", c);
} else {
@ -534,9 +521,15 @@ impl vte::Perform for TerminalOutput {
} else if self.characters.len() > self.cursor_position {
self.characters.remove(self.cursor_position);
self.characters.insert(self.cursor_position, terminal_character);
if self.newline_indices.contains(&(self.cursor_position + 1)) {
// TODO: ???
return;
}
} else {
for _ in self.characters.len()..self.cursor_position {
self.characters.push(EMPTY_TERMINAL_CHARACTER.clone());
for i in self.characters.len()..self.cursor_position {
if !self.newline_indices.contains(&i) {
self.characters.push(EMPTY_TERMINAL_CHARACTER.clone());
}
};
self.characters.push(terminal_character);
@ -551,25 +544,12 @@ impl vte::Perform for TerminalOutput {
}
fn execute(&mut self, byte: u8) {
if DEBUGGING {
if byte == 13 { // 0d, carriage return
println!("\rEXECUTE CARRIAGE RETURN");
} else if byte == 10 { // 0a, newline
println!("\rEXECUTE NEW LINE");
} else if byte == 08 { // backspace
println!("\rEXECUTE BACKSPACE");
} else {
println!("\r[execute] {:02x}", byte);
}
} else {
if byte == 13 { // 0d, carriage return
self.move_to_beginning_of_line();
} else if byte == 08 { // backspace
self.cursor_position -= 1;
self.characters.truncate(self.cursor_position);
} else if byte == 10 { // 0a, newline
self.add_newline();
}
if byte == 13 { // 0d, carriage return
self.move_to_beginning_of_line();
} else if byte == 08 { // backspace
self.cursor_position -= 1;
} else if byte == 10 { // 0a, newline
self.add_newline();
}
}
@ -602,10 +582,6 @@ impl vte::Perform for TerminalOutput {
}
fn csi_dispatch(&mut self, params: &[i64], intermediates: &[u8], ignore: bool, c: char) {
// println!(
// "\n\r[csi_dispatch] params={:?}, intermediates={:?}, ignore={:?}, char={:?}",
// params, intermediates, ignore, c
// );
if DEBUGGING {
println!(
"\r[csi_dispatch] params={:?}, intermediates={:?}, ignore={:?}, char={:?}",
@ -642,16 +618,47 @@ impl vte::Perform for TerminalOutput {
self.reset_misc_ansi_code = false;
}
} else if c == 'C' { // move cursor forward
self.cursor_position += params[0] as usize; // TODO: negative value?
let move_by = params[0] as usize;
let closest_newline = self.newline_indices.iter().find(|x| x > &&self.cursor_position).copied();
let closest_linebreak = self.linebreak_indices.iter().find(|x| x > &&self.cursor_position).copied();
let max_move_position = match (closest_newline, closest_linebreak) {
(Some(closest_newline), Some(closest_linebreak)) => {
::std::cmp::min(
closest_newline,
closest_linebreak
)
},
(Some(closest_newline), None) => {
closest_newline
},
(None, Some(closest_linebreak)) => {
closest_linebreak
},
(None, None) => {
// TODO: NO!!
self.cursor_position + move_by
}
};
if self.cursor_position + move_by < max_move_position {
self.cursor_position += move_by;
} else {
self.cursor_position = max_move_position;
}
} else if c == 'K' { // clear line (0 => right, 1 => left, 2 => all)
if params[0] == 0 {
if let Some(position_of_first_newline_index_to_delete) = self.newline_indices.iter().position(|&ni| ni > self.cursor_position) {
self.newline_indices.truncate(position_of_first_newline_index_to_delete);
let newlines = self.newline_indices.iter().rev();
let mut delete_until = self.characters.len();
for newline_index in newlines {
if newline_index < &self.cursor_position {
break;
}
delete_until = *newline_index;
}
if let Some(position_of_first_linebreak_index_to_delete) = self.linebreak_indices.iter().position(|&li| li > self.cursor_position) {
self.newline_indices.truncate(position_of_first_linebreak_index_to_delete);
// TODO: better
for i in self.cursor_position..delete_until {
self.characters[i] = EMPTY_TERMINAL_CHARACTER.clone();
}
self.characters.truncate(self.cursor_position + 1);
}
// TODO: implement 1 and 2
} else if c == 'J' { // clear all (0 => below, 1 => above, 2 => all, 3 => saved)
@ -689,9 +696,34 @@ impl vte::Perform for TerminalOutput {
let index_of_start_of_row = self.newline_indices.get(row - 1).unwrap();
self.cursor_position = index_of_start_of_row + col;
}
} else if c == 'A' { // move cursor up until edge of screen
let move_up_count = if params[0] == 0 { 1 } else { params[0] };
let newlines = self.newline_indices.iter().rev();
let mut position_in_line = None;
let mut lines_traversed = 0;
for newline_index in newlines {
if position_in_line.is_some() {
lines_traversed += 1;
}
if newline_index < &self.cursor_position && position_in_line.is_none() {
// this is the current cursor line
position_in_line = Some(self.cursor_position - newline_index);
}
if lines_traversed == move_up_count {
self.cursor_position = newline_index + position_in_line.unwrap();
break;
}
}
// TODO: stop at upper edge of screen
} else if c == 'D' {
// move cursor backwards, stop at left edge of screen
self.cursor_position -= params[0] as usize;
let reduce_by = if params[0] == 0 { 1 } else { params[0] as usize };
if reduce_by > self.cursor_position {
// TODO: no, this is incorrect
self.cursor_position = 0;
} else {
self.cursor_position -= reduce_by;
}
// TODO: stop at left edge of screen
} else if c == 'l' {
// TBD