From 21641d11df33fb3ad8facdb3ab8ec68a5c261d28 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Fri, 29 Nov 2024 11:39:57 +0100 Subject: [PATCH] Update clipboard behavior in editor (#706) * Update clipboard behavior in editor * Split run method * Move cursor to pasted line * Refactor cut_line --- src/usr/edit.rs | 178 +++++++++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 79 deletions(-) diff --git a/src/usr/edit.rs b/src/usr/edit.rs index be65b119..7b7f9380 100644 --- a/src/usr/edit.rs +++ b/src/usr/edit.rs @@ -28,7 +28,7 @@ struct Coords { pub struct Editor { pathname: String, - clipboard: Vec, + clipboard: Option, lines: Vec, cursor: Coords, offset: Coords, @@ -45,7 +45,7 @@ impl Editor { let cursor = Coords { x: 0, y: 0 }; let offset = Coords { x: 0, y: 0 }; let highlighted = Vec::new(); - let clipboard = Vec::new(); + let clipboard = None; let mut lines = Vec::new(); let config = EditorConfig { tab_size: 4 }; @@ -338,64 +338,19 @@ impl Editor { return res; } '\n' => { // Newline - let y = self.offset.y + self.cursor.y; - let old_line = self.lines[y].clone(); - let mut row: Vec = old_line.chars().collect(); - let new_line = row. - split_off(self.offset.x + self.cursor.x). - into_iter().collect(); - self.lines[y] = row.into_iter().collect(); - self.lines.insert(y + 1, new_line); - if self.cursor.y == rows() - 1 { - self.offset.y += 1; - } else { - self.cursor.y += 1; - } - self.cursor.x = 0; - self.offset.x = 0; - self.print_screen(); + self.handle_newline(); } '~' if csi && csi_params == "5" => { // Page Up - let scroll = rows() - 1; // Keep one line on screen - self.offset.y -= cmp::min(scroll, self.offset.y); - self.align_cursor(); - self.print_screen(); + self.handle_page_up(); } '~' if csi && csi_params == "6" => { // Page Down - let scroll = rows() - 1; // Keep one line on screen - let n = cmp::max(self.lines.len(), 1); - let remaining = n - self.offset.y - 1; - self.offset.y += cmp::min(scroll, remaining); - if self.cursor.y + scroll > remaining { - self.cursor.y = 0; - } - self.align_cursor(); - self.print_screen(); + self.handle_page_down(); } 'A' if csi => { // Arrow Up - if self.cursor.y > 0 { - self.cursor.y -= 1 - } else if self.offset.y > 0 { - self.offset.y -= 1; - } - self.align_cursor(); - self.print_screen(); + self.handle_arrow_up(); } 'B' if csi => { // Arrow Down - let n = self.lines.len() - 1; - let is_eof = n == (self.offset.y + self.cursor.y); - let is_bottom = self.cursor.y == rows() - 1; - if self.cursor.y < cmp::min(rows(), n) { - if is_bottom || is_eof { - if !is_eof { - self.offset.y += 1; - } - } else { - self.cursor.y += 1; - } - self.align_cursor(); - self.print_screen(); - } + self.handle_arrow_down(); } 'C' if csi => { // Arrow Right let line = &self.lines[self.offset.y + self.cursor.y]; @@ -460,37 +415,13 @@ impl Editor { self.print_screen(); } '\x04' => { // Ctrl D -> Delete (cut) line - let i = self.offset.y + self.cursor.y; - self.clipboard.push(self.lines.remove(i)); - if self.lines.is_empty() { - self.lines.push(String::new()); - } - - // Move cursor up to the previous line - if i >= self.lines.len() { - if self.cursor.y > 0 { - self.cursor.y -= 1; - } else if self.offset.y > 0 { - self.offset.y -= 1; - } - } - self.cursor.x = 0; - self.offset.x = 0; - - self.print_screen(); + self.cut_line(); } '\x19' => { // Ctrl Y -> Yank (copy) line - let i = self.offset.y + self.cursor.y; - self.clipboard.push(self.lines[i].clone()); + self.copy_line(); } '\x10' => { // Ctrl P -> Put (paste) line - let i = self.offset.y + self.cursor.y; - if let Some(line) = self.clipboard.pop() { - self.lines.insert(i + 1, line); - } - self.cursor.x = 0; - self.offset.x = 0; - self.print_screen(); + self.paste_line(); } '\x06' => { // Ctrl F -> Find self.find(); @@ -611,6 +542,95 @@ impl Editor { Ok(()) } + fn handle_newline(&mut self) { + let x = self.offset.x + self.cursor.x; + let y = self.offset.y + self.cursor.y; + + let old_line = self.lines[y].clone(); + let mut row: Vec = old_line.chars().collect(); + let new_line = row.split_off(x).into_iter().collect(); + self.lines[y] = row.into_iter().collect(); + self.lines.insert(y + 1, new_line); + if self.cursor.y == rows() - 1 { + self.offset.y += 1; + } else { + self.cursor.y += 1; + } + self.cursor.x = 0; + self.offset.x = 0; + self.print_screen(); + } + + fn handle_page_up(&mut self) { + let scroll = rows() - 1; // Keep one line on screen + self.offset.y -= cmp::min(scroll, self.offset.y); + self.align_cursor(); + self.print_screen(); + } + + fn handle_page_down(&mut self) { + let scroll = rows() - 1; // Keep one line on screen + let n = cmp::max(self.lines.len(), 1); + let remaining = n - self.offset.y - 1; + self.offset.y += cmp::min(scroll, remaining); + if self.cursor.y + scroll > remaining { + self.cursor.y = 0; + } + self.align_cursor(); + self.print_screen(); + } + + fn handle_arrow_up(&mut self) { + if self.cursor.y > 0 { + self.cursor.y -= 1 + } else if self.offset.y > 0 { + self.offset.y -= 1; + } + self.align_cursor(); + self.print_screen(); + } + + fn handle_arrow_down(&mut self) { + let n = self.lines.len() - 1; + let is_eof = n == (self.offset.y + self.cursor.y); + let is_bottom = self.cursor.y == rows() - 1; + if self.cursor.y < cmp::min(rows(), n) { + if is_bottom || is_eof { + if !is_eof { + self.offset.y += 1; + } + } else { + self.cursor.y += 1; + } + self.align_cursor(); + self.print_screen(); + } + } + + fn cut_line(&mut self) { + let i = self.offset.y + self.cursor.y; + self.clipboard = Some(self.lines.remove(i)); + if self.lines.is_empty() { + self.lines.push(String::new()); + } + self.handle_arrow_up(); // Move cursor to previous line + } + + fn copy_line(&mut self) { + let i = self.offset.y + self.cursor.y; + self.clipboard = Some(self.lines[i].clone()); + } + + fn paste_line(&mut self) { + let i = self.offset.y + self.cursor.y; + if let Some(line) = self.clipboard.clone() { + self.lines.insert(i + 1, line); + self.cursor.x = 0; + self.offset.x = 0; + self.handle_arrow_down(); // Move cursor to pasted line + } + } + fn exec(&mut self) -> Option { if let Some(cmd) = prompt(&mut self.command_prompt, ":") { // The cursor is disabled at the beginning of the loop in the `run`