diff --git a/reqtui/src/text_object/text_object.rs b/reqtui/src/text_object/text_object.rs index 2e10231..8400744 100644 --- a/reqtui/src/text_object/text_object.rs +++ b/reqtui/src/text_object/text_object.rs @@ -9,6 +9,24 @@ pub enum LineBreak { Crlf, } +impl From for usize { + fn from(value: LineBreak) -> usize { + match value { + LineBreak::Lf => 1, + LineBreak::Crlf => 2, + } + } +} + +impl std::fmt::Display for LineBreak { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Lf => f.write_str("\n"), + Self::Crlf => f.write_str("\r\n"), + } + } +} + #[derive(Debug, Clone, PartialEq)] pub struct Readonly; #[derive(Debug, Clone, PartialEq)] @@ -66,10 +84,8 @@ impl TextObject { pub fn insert_newline(&mut self, cursor: &Cursor) { let line = self.content.line_to_char(cursor.row()); let col_offset = line + cursor.col(); - match self.line_break { - LineBreak::Lf => self.content.insert_char(col_offset, '\n'), - LineBreak::Crlf => self.content.insert(col_offset, "\r\n"), - } + self.content + .insert(col_offset, &self.line_break.to_string()); } pub fn erase_backwards_up_to_line_start(&mut self, cursor: &Cursor) { @@ -101,15 +117,20 @@ impl TextObject { self.content.line(cursor.row()).as_str() } + pub fn line_len_with_linebreak(&self, line: usize) -> usize { + self.content + .line(line) + .as_str() + .map(|line| line.len()) + .unwrap_or_default() + } + pub fn line_len(&self, line: usize) -> usize { - let mut line_len = 0; - if let Some(line) = self.content.line(line).as_str() { - match self.line_break { - LineBreak::Lf => line_len = line.len().saturating_sub(1), - LineBreak::Crlf => line_len = line.len().saturating_sub(2), - } - } - line_len + self.content + .line(line) + .as_str() + .map(|line| line.len().saturating_sub(self.line_break.clone().into())) + .unwrap_or_default() } pub fn erase_until_eol(&mut self, cursor: &Cursor) { @@ -194,6 +215,12 @@ impl TextObject { pub fn len_lines(&self) -> usize { self.content.len_lines() } + + pub fn delete_line(&mut self, cursor: &Cursor) { + let start = self.content.line_to_char(cursor.row()); + let end = self.content.line_to_char(cursor.row().add(1)); + self.content.try_remove(start..end).ok(); + } } impl std::fmt::Display for TextObject { diff --git a/tui/src/components/api_explorer/req_editor.rs b/tui/src/components/api_explorer/req_editor.rs index 05667e5..95851fb 100644 --- a/tui/src/components/api_explorer/req_editor.rs +++ b/tui/src/components/api_explorer/req_editor.rs @@ -305,15 +305,15 @@ impl<'re> ReqEditor<'re> { Action::MoveAfterWhitespaceReverse => self.move_after_whitespace_reverse(), Action::MoveAfterWhitespace => self.move_after_whitespace(), Action::DeletePreviousNonWrapping => self.erase_backwards_up_to_line_start(), + Action::MoveToTop => self.move_to_top(), + Action::DeleteLine => self.delete_current_line(), Action::Undo => todo!(), Action::FindNext => todo!(), Action::FindPrevious => todo!(), Action::PreviousWord => todo!(), - Action::MoveToTop => self.move_to_top(), Action::PageDown => todo!(), Action::PageUp => todo!(), Action::DeleteWord => todo!(), - Action::DeleteLine => todo!(), Action::DeleteBack => todo!(), Action::InsertLineBelow => todo!(), Action::InsertLineAbove => todo!(), @@ -355,6 +355,16 @@ impl<'re> ReqEditor<'re> { self.cursor.move_right(1); } + fn delete_current_line(&mut self) { + self.body.delete_line(&self.cursor); + let len_lines = self.body.len_lines(); + if self.cursor.row().ge(&len_lines.saturating_sub(1)) { + self.cursor.move_to_row(len_lines.saturating_sub(1)); + } + let line_len = self.body.line_len(self.cursor.row()); + self.cursor.move_to_line_end(line_len); + } + fn erase_until_eol(&mut self) { self.body.erase_until_eol(&self.cursor); } @@ -534,6 +544,9 @@ impl Eventful for ReqEditor<'_> { _ => self.keymap_buffer = None, } + self.tree = HIGHLIGHTER.write().unwrap().parse(&self.body.to_string()); + self.styled_display = + build_styled_content(&self.body.to_string(), self.tree.as_ref(), self.colors); return Ok(None); }