From 0df8461f67419ccbc5e90306836070e3c91d20cd Mon Sep 17 00:00:00 2001 From: Willians Faria Date: Tue, 21 May 2024 17:08:47 -0300 Subject: [PATCH] feat: scope aware newlines --- config/src/default_config.rs | 2 +- reqtui/src/syntax/highlighter.rs | 18 +++++++++++ reqtui/src/text_object/text_object.rs | 17 ++++++++-- tui/src/components/api_explorer/req_editor.rs | 31 ++++++++++--------- 4 files changed, 49 insertions(+), 19 deletions(-) diff --git a/config/src/default_config.rs b/config/src/default_config.rs index 6fb32e5..aa9e0af 100644 --- a/config/src/default_config.rs +++ b/config/src/default_config.rs @@ -23,7 +23,7 @@ pub static DEFAULT_CONFIG: &str = r##" "C-u" = "PageUp" "S-D" = "DeleteUntilEOL" "x" = "DeleteCurrentChar" -"o" = "InsertLineBelow" +"o" = ["InsertLineBelow", "InsertAtEOL"] "S-O" = "InsertLineAbove" "p" = "PasteBelow" "a" = "InsertAhead" diff --git a/reqtui/src/syntax/highlighter.rs b/reqtui/src/syntax/highlighter.rs index ae4f403..21f8398 100644 --- a/reqtui/src/syntax/highlighter.rs +++ b/reqtui/src/syntax/highlighter.rs @@ -82,4 +82,22 @@ impl Highlighter { colors } + + pub fn find_indentation_level(tree: &Tree, cursor_byte_idx: usize) -> usize { + let root_node = tree.root_node(); + let current_node = root_node + .descendant_for_byte_range(cursor_byte_idx, cursor_byte_idx) + .unwrap(); + let mut indent_level: usize = 0; + let mut current_node = current_node; + while let Some(parent) = current_node.parent() { + if parent.kind().eq("pair") { + current_node = parent; + continue; + } + current_node = parent; + indent_level += 1; + } + indent_level.saturating_sub(1) + } } diff --git a/reqtui/src/text_object/text_object.rs b/reqtui/src/text_object/text_object.rs index 9afdebe..ef951d3 100644 --- a/reqtui/src/text_object/text_object.rs +++ b/reqtui/src/text_object/text_object.rs @@ -3,8 +3,9 @@ use std::{ ops::{Add, Sub}, }; -use crate::text_object::cursor::Cursor; +use crate::{syntax::highlighter::Highlighter, text_object::cursor::Cursor}; use ropey::Rope; +use tree_sitter::Tree; #[derive(Debug, PartialEq, Clone)] pub enum LineBreak { @@ -354,9 +355,19 @@ impl TextObject { end_idx.sub(start_idx) } - pub fn insert_line_below(&mut self, cursor: &Cursor) { + pub fn insert_line_below(&mut self, cursor: &Cursor, tree: Option<&Tree>) { + let indentation = if let Some(tree) = tree { + let line_byte_idx = self.content.line_to_byte(cursor.row()); + let cursor_byte_idx = line_byte_idx.add(cursor.col()); + let indentation_level = Highlighter::find_indentation_level(tree, cursor_byte_idx); + tracing::debug!("{indentation_level}"); + " ".repeat(indentation_level) + } else { + String::new() + }; let next_line = self.content.line_to_char(cursor.row().add(1)); - self.content.insert(next_line, &self.line_break.to_string()); + let line_with_indentation = format!("{}{}", indentation, &self.line_break.to_string()); + self.content.insert(next_line, &line_with_indentation); } pub fn insert_line_above(&mut self, cursor: &Cursor) { diff --git a/tui/src/components/api_explorer/req_editor.rs b/tui/src/components/api_explorer/req_editor.rs index 4bfbbee..79315a8 100644 --- a/tui/src/components/api_explorer/req_editor.rs +++ b/tui/src/components/api_explorer/req_editor.rs @@ -321,10 +321,10 @@ impl<'re> ReqEditor<'re> { Action::JumpToClosing => self.jump_to_opposing_token(), Action::JumpToEmptyLineBelow => self.jump_to_empty_line_below(), Action::JumpToEmptyLineAbove => self.jump_to_empty_line_above(), - Action::Undo => todo!(), - Action::FindNext => todo!(), - Action::FindPrevious => todo!(), - Action::PasteBelow => todo!(), + Action::Undo => {} + Action::FindNext => {} + Action::FindPrevious => {} + Action::PasteBelow => {} } } @@ -414,7 +414,8 @@ impl<'re> ReqEditor<'re> { } fn insert_line_below(&mut self) { - self.body.insert_line_below(&self.cursor); + self.body + .insert_line_below(&self.cursor, self.tree.as_ref()); self.cursor.move_down(1); self.maybe_scroll_view(); let line_len = self.body.line_len(self.cursor.row()); @@ -685,18 +686,18 @@ impl Eventful for ReqEditor<'_> { Some(key_action) => self.keymap_buffer = Some(key_action.clone()), None => {} }, - EditorMode::Insert => { - match self.config.editor_keys.insert.get(&key_str) { - Some(KeyAction::Simple(action)) => self.handle_action(action), - Some(KeyAction::Multiple(actions)) => { - actions.iter().for_each(|a| self.handle_action(a)) + EditorMode::Insert => match self.config.editor_keys.insert.get(&key_str) { + Some(KeyAction::Simple(action)) => self.handle_action(action), + Some(KeyAction::Multiple(actions)) => { + actions.iter().for_each(|a| self.handle_action(a)) + } + Some(key_action) => self.keymap_buffer = Some(key_action.clone()), + None => { + if let Some(char) = key_str.chars().last() { + self.handle_action(&Action::InsertChar(char)); } - Some(key_action) => self.keymap_buffer = Some(key_action.clone()), - None => self.handle_action(&Action::InsertChar(key_str.chars().nth(0).expect( - "failed to insert char into body. something is wrong with the index", - ))), } - } + }, } self.tree = HIGHLIGHTER.write().unwrap().parse(&self.body.to_string());