mirror of
https://github.com/zellij-org/zellij.git
synced 2024-12-24 17:53:36 +03:00
fix(compatibility): bandwhich + various fixes for fish
This commit is contained in:
parent
cf1080bc3f
commit
909b9eec0e
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user