From cf6e10e2a8bcf2a1215b2c7e525f8be5234c2fac Mon Sep 17 00:00:00 2001 From: Carol Date: Tue, 10 Jan 2023 14:04:27 +0200 Subject: [PATCH 01/12] Add functionality for CTRL + LeftArrow to move to previous word --- src/editor.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index e9cc605..58f5c00 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -187,10 +187,25 @@ impl Editor { fn rx(&self) -> usize { self.current_row().map_or(0, |r| r.cx2rx[self.cursor.x]) } /// Move the cursor following an arrow key (← → ↑ ↓). - fn move_cursor(&mut self, key: &AKey) { + /// ctrl bool marks if CTRL key is pressed or not + fn move_cursor(&mut self, key: &AKey, ctrl: bool) { match (key, self.current_row()) { - (AKey::Left, Some(row)) if self.cursor.x > 0 => - self.cursor.x -= row.get_char_size(row.cx2rx[self.cursor.x] - 1), + (AKey::Left, Some(row)) if self.cursor.x > 0 => { + let mut cursor_x = self.cursor.x; + if ctrl == false { + cursor_x -= row.get_char_size(row.cx2rx[cursor_x]) + } else { + // Skips whitespaces + while cursor_x > 0 && row.chars[cursor_x - 1] == 0x20 { + cursor_x -= row.get_char_size(row.cx2rx[cursor_x]); + } + // Previous word + while cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { + cursor_x -= row.get_char_size(row.cx2rx[cursor_x - 1]); + } + } + self.cursor.x = cursor_x; + } (AKey::Left, _) if self.cursor.y > 0 => { // ← at the beginning of the line: move to the end of the previous line. The x // position will be adjusted after this `match` to accommodate the current row @@ -393,7 +408,7 @@ impl Editor { } else if self.cursor.y == self.rows.len() { // If the cursor is located after the last row, pressing backspace is equivalent to // pressing the left arrow key. - self.move_cursor(&AKey::Left); + self.move_cursor(&AKey::Left, false); } } @@ -600,7 +615,8 @@ impl Editor { match key { // TODO: CtrlArrow should move to next word - Key::Arrow(arrow) | Key::CtrlArrow(arrow) => self.move_cursor(arrow), + Key::Arrow(arrow) => self.move_cursor(arrow, false), + Key::CtrlArrow(arrow) => self.move_cursor(arrow, true), Key::Page(PageKey::Up) => { self.cursor.y = self.cursor.roff.saturating_sub(self.screen_rows); self.update_cursor_x_position(); @@ -615,7 +631,7 @@ impl Editor { Key::Char(BACKSPACE | DELETE_BIS) => self.delete_char(), // Backspace or Ctrl + H Key::Char(REMOVE_LINE) => self.delete_current_row(), Key::Delete => { - self.move_cursor(&AKey::Right); + self.move_cursor(&AKey::Right, false); self.delete_char(); } Key::Escape | Key::Char(REFRESH_SCREEN) => (), @@ -910,8 +926,8 @@ mod tests { } editor.delete_char(); assert_eq!(editor.rows[0].chars, "Hello".as_bytes()); - editor.move_cursor(&AKey::Left); - editor.move_cursor(&AKey::Left); + editor.move_cursor(&AKey::Left, false); + editor.move_cursor(&AKey::Left, false); editor.delete_char(); assert_eq!(editor.rows[0].chars, "Helo".as_bytes()); } From aa6d81e92faa6c8315e94eed3d3d60239edbe006 Mon Sep 17 00:00:00 2001 From: Carol Date: Tue, 10 Jan 2023 14:05:42 +0200 Subject: [PATCH 02/12] Add functionality for CTRL + RightArrow to move to next word --- src/editor.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 58f5c00..3d2b36d 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -213,8 +213,22 @@ impl Editor { self.cursor.y -= 1; self.cursor.x = usize::MAX; } - (AKey::Right, Some(row)) if self.cursor.x < row.chars.len() => - self.cursor.x += row.get_char_size(row.cx2rx[self.cursor.x]), + (AKey::Right, Some(row)) if self.cursor.x < row.chars.len() => { + let mut cursor_x = self.cursor.x; + if ctrl == false { + cursor_x += row.get_char_size(row.cx2rx[cursor_x]) + } else { + // Skips current word + while cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { + cursor_x += row.get_char_size(row.cx2rx[cursor_x]); + } + // Skips whitespaces + while cursor_x < row.chars.len() && row.chars[cursor_x] == 0x20 { + cursor_x += row.get_char_size(row.cx2rx[cursor_x]); + } + } + self.cursor.x = cursor_x; + } (AKey::Right, Some(_)) => self.cursor.move_to_next_line(), // TODO: For Up and Down, move self.cursor.x to be consistent with tabs and UTF-8 // characters, i.e. according to rx From 877b6b908e6d0f17318505946901469099d60293 Mon Sep 17 00:00:00 2001 From: Carol Date: Tue, 10 Jan 2023 14:09:26 +0200 Subject: [PATCH 03/12] Modify README.md to reflect changes --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0e50640..396bd6a 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,8 @@ kibi --version # Print version information and exit | Ctrl-C | Copies the entire line | | Ctrl-X | Cuts the entire line | | Ctrl-V | Will paste the copied line | +| Ctrl-LeftArrow | Moves cursor to previous word | +| Ctrl-RightArrow | Moves cursor to next word | ### Configuration From a1070ff25ff3ffb565bafb33eb076a03c9f871fd Mon Sep 17 00:00:00 2001 From: Carol Date: Tue, 10 Jan 2023 18:40:33 +0200 Subject: [PATCH 04/12] Code refactoring to fit in 1024 lines --- src/editor.rs | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 3d2b36d..9971c11 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -187,47 +187,29 @@ impl Editor { fn rx(&self) -> usize { self.current_row().map_or(0, |r| r.cx2rx[self.cursor.x]) } /// Move the cursor following an arrow key (← → ↑ ↓). - /// ctrl bool marks if CTRL key is pressed or not fn move_cursor(&mut self, key: &AKey, ctrl: bool) { + let mut cursor_x = self.cursor.x; match (key, self.current_row()) { (AKey::Left, Some(row)) if self.cursor.x > 0 => { - let mut cursor_x = self.cursor.x; - if ctrl == false { - cursor_x -= row.get_char_size(row.cx2rx[cursor_x]) - } else { - // Skips whitespaces - while cursor_x > 0 && row.chars[cursor_x - 1] == 0x20 { - cursor_x -= row.get_char_size(row.cx2rx[cursor_x]); - } - // Previous word - while cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { - cursor_x -= row.get_char_size(row.cx2rx[cursor_x - 1]); - } + if !ctrl { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } + else { // ← moving to previous word + while cursor_x > 0 && row.chars[cursor_x - 1] == 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } + while cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } } - self.cursor.x = cursor_x; } (AKey::Left, _) if self.cursor.y > 0 => { // ← at the beginning of the line: move to the end of the previous line. The x // position will be adjusted after this `match` to accommodate the current row // length, so we can just set here to the maximum possible value here. self.cursor.y -= 1; - self.cursor.x = usize::MAX; + cursor_x = usize::MAX; } (AKey::Right, Some(row)) if self.cursor.x < row.chars.len() => { - let mut cursor_x = self.cursor.x; - if ctrl == false { - cursor_x += row.get_char_size(row.cx2rx[cursor_x]) - } else { - // Skips current word - while cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { - cursor_x += row.get_char_size(row.cx2rx[cursor_x]); - } - // Skips whitespaces - while cursor_x < row.chars.len() && row.chars[cursor_x] == 0x20 { - cursor_x += row.get_char_size(row.cx2rx[cursor_x]); - } + if !ctrl { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } + else { // → moving to next word + while cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } + while cursor_x < row.chars.len() && row.chars[cursor_x] == 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } } - self.cursor.x = cursor_x; } (AKey::Right, Some(_)) => self.cursor.move_to_next_line(), // TODO: For Up and Down, move self.cursor.x to be consistent with tabs and UTF-8 @@ -236,6 +218,7 @@ impl Editor { (AKey::Down, Some(_)) => self.cursor.y += 1, _ => (), } + self.cursor.x = cursor_x; self.update_cursor_x_position(); } From 9e8a8a6cc134f69b718ab96894141380c2db9154 Mon Sep 17 00:00:00 2001 From: Carol Date: Tue, 10 Jan 2023 18:54:14 +0200 Subject: [PATCH 05/12] More code refactoring to fit in 1024 lines --- src/editor.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 9971c11..ed1093e 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -191,11 +191,10 @@ impl Editor { let mut cursor_x = self.cursor.x; match (key, self.current_row()) { (AKey::Left, Some(row)) if self.cursor.x > 0 => { - if !ctrl { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } - else { // ← moving to previous word - while cursor_x > 0 && row.chars[cursor_x - 1] == 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } - while cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } - } + cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); + // ← moving to previous word + while ctrl && cursor_x > 0 && row.chars[cursor_x - 1] == 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } + while ctrl && cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } } (AKey::Left, _) if self.cursor.y > 0 => { // ← at the beginning of the line: move to the end of the previous line. The x @@ -205,11 +204,10 @@ impl Editor { cursor_x = usize::MAX; } (AKey::Right, Some(row)) if self.cursor.x < row.chars.len() => { - if !ctrl { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } - else { // → moving to next word - while cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } - while cursor_x < row.chars.len() && row.chars[cursor_x] == 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } - } + cursor_x += row.get_char_size(row.cx2rx[cursor_x]); + // → moving to next word + while ctrl && cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } + while ctrl && cursor_x < row.chars.len() && row.chars[cursor_x] == 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } } (AKey::Right, Some(_)) => self.cursor.move_to_next_line(), // TODO: For Up and Down, move self.cursor.x to be consistent with tabs and UTF-8 From e1aea96a84b18a51ce9051b59d9f7930937a1d79 Mon Sep 17 00:00:00 2001 From: Carol Date: Mon, 16 Jan 2023 21:23:58 +0200 Subject: [PATCH 06/12] Code refactoring --- src/editor.rs | 33 ++++++++++++++------------------- src/row.rs | 12 ++++-------- src/unix.rs | 7 +++---- 3 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index ed1093e..a93c362 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -193,21 +193,22 @@ impl Editor { (AKey::Left, Some(row)) if self.cursor.x > 0 => { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); // ← moving to previous word - while ctrl && cursor_x > 0 && row.chars[cursor_x - 1] == 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } - while ctrl && cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } + while ctrl && cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { + cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); + } } (AKey::Left, _) if self.cursor.y > 0 => { // ← at the beginning of the line: move to the end of the previous line. The x // position will be adjusted after this `match` to accommodate the current row // length, so we can just set here to the maximum possible value here. - self.cursor.y -= 1; - cursor_x = usize::MAX; + (self.cursor.y, cursor_x) = (self.cursor.y - 1, usize::MAX); } (AKey::Right, Some(row)) if self.cursor.x < row.chars.len() => { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); // → moving to next word - while ctrl && cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } - while ctrl && cursor_x < row.chars.len() && row.chars[cursor_x] == 0x20 { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } + while ctrl && cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { + cursor_x += row.get_char_size(row.cx2rx[cursor_x]); + } } (AKey::Right, Some(_)) => self.cursor.move_to_next_line(), // TODO: For Up and Down, move self.cursor.x to be consistent with tabs and UTF-8 @@ -355,8 +356,7 @@ impl Editor { self.update_screen_cols(); } self.update_row(self.cursor.y, false); - (self.cursor.x, self.n_bytes) = (self.cursor.x + 1, self.n_bytes + 1); - self.dirty = true; + (self.cursor.x, self.n_bytes, self.dirty) = (self.cursor.x + 1, self.n_bytes + 1, true); } /// Insert a new line at the current cursor position and move the cursor to the start of the new @@ -557,14 +557,12 @@ impl Editor { fn draw_status_bar(&self, buffer: &mut String) -> Result<(), Error> { // Left part of the status bar let modified = if self.dirty { " (modified)" } else { "" }; - let mut left = - format!("{:.30}{modified}", self.file_name.as_deref().unwrap_or("[No Name]")); + let mut left = format!("{:.30}{modified}", self.file_name.as_deref().unwrap_or("[No Name]")); left.truncate(self.window_width); // Right part of the status bar let size = format_size(self.n_bytes + self.rows.len().saturating_sub(1) as u64); - let right = - format!("{} | {size} | {}:{}", self.syntax.name, self.cursor.y + 1, self.rx() + 1); + let right = format!("{} | {size} | {}:{}", self.syntax.name, self.cursor.y + 1, self.rx() + 1); // Draw let rw = self.window_width.saturating_sub(left.len()); @@ -675,10 +673,9 @@ impl Editor { current = (current + if forward { 1 } else { num_rows - 1 }) % num_rows; let row = &mut self.rows[current]; if let Some(cx) = slice_find(&row.chars, query.as_bytes()) { - (self.cursor.x, self.cursor.y) = (cx, current); - // Try to reset the column offset; if the match is after the offset, this + // self.cursor.coff: Try to reset the column offset; if the match is after the offset, this // will be updated in self.cursor.scroll() so that the result is visible - self.cursor.coff = 0; + (self.cursor.x, self.cursor.y, self.cursor.coff) = (cx, current, 0); let rx = row.cx2rx[cx]; row.match_segment = Some(rx..rx + query.len()); return Some(current); @@ -774,8 +771,7 @@ impl PromptMode { match process_prompt_keypress(b, key) { PromptState::Active(query) => { let (last_match, forward) = match key { - Key::Arrow(AKey::Right | AKey::Down) | Key::Char(FIND) => - (last_match, true), + Key::Arrow(AKey::Right | AKey::Down) | Key::Char(FIND) => (last_match, true), Key::Arrow(AKey::Left | AKey::Up) => (last_match, false), _ => (None, true), }; @@ -792,8 +788,7 @@ impl PromptMode { PromptState::Active(b) => return Ok(Some(Self::GoTo(b))), PromptState::Cancelled => (), PromptState::Completed(b) => { - let mut split = b - .splitn(2, ':') + let mut split = b.splitn(2, ':') // saturating_sub: Lines and cols are 1-indexed .map(|u| u.trim().parse().map(|s: usize| s.saturating_sub(1))); match (split.next().transpose(), split.next().transpose()) { diff --git a/src/row.rs b/src/row.rs index f1decd0..aee58db 100644 --- a/src/row.rs +++ b/src/row.rs @@ -65,8 +65,7 @@ impl Row { self.render.push_str(&(if c == '\t' { " ".repeat(n_rend_chars) } else { c.into() })); self.cx2rx.extend(std::iter::repeat(rx).take(n_bytes)); self.rx2cx.extend(std::iter::repeat(cx).take(n_rend_chars)); - rx += n_rend_chars; - cx += n_bytes; + (rx, cx) = (rx + n_rend_chars, cx + n_bytes); } self.cx2rx.push(rx); self.rx2cx.push(cx); @@ -92,8 +91,7 @@ impl Row { 'syntax_loop: while self.hl.len() < line.len() { let i = self.hl.len(); - let find_str = - |s: &str| line.get(i..(i + s.len())).map_or(false, |r| r.eq(s.as_bytes())); + let find_str = |s: &str| line.get(i..(i + s.len())).map_or(false, |r| r.eq(s.as_bytes())); if hl_state == HlState::Normal && syntax.sl_comment_start.iter().any(|s| find_str(s)) { self.hl.extend(repeat(HlType::Comment).take(line.len() - i)); @@ -104,8 +102,7 @@ impl Row { // differences are: the start/end delimiters, the `HLState`, the `HLType`. for (delims, mstate, mtype) in &[ (ml_comment_delims, HlState::MultiLineComment, HlType::MlComment), - (ml_string_delims, HlState::MultiLineString, HlType::MlString), - ] { + (ml_string_delims, HlState::MultiLineString, HlType::MlString),] { if let Some((start, end)) = delims { if hl_state == *mstate { if find_str(end) { @@ -168,8 +165,7 @@ impl Row { } // String state doesn't propagate to the next row - self.hl_state = - if matches!(hl_state, HlState::String(_)) { HlState::Normal } else { hl_state }; + self.hl_state = if matches!(hl_state, HlState::String(_)) { HlState::Normal } else { hl_state }; self.hl_state } diff --git a/src/unix.rs b/src/unix.rs index 4dd89d8..8a239f5 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -70,10 +70,9 @@ pub fn enable_raw_mode() -> Result { let orig_term = unsafe { maybe_term.assume_init() }; let mut term = orig_term; unsafe { libc::cfmakeraw(&mut term) }; - // Set the minimum number of characters for non-canonical reads - term.c_cc[VMIN] = 0; - // Set the timeout in deciseconds for non-canonical reads - term.c_cc[VTIME] = 1; + // First sets the minimum number of characters for non-canonical reads + // Second sets the timeout in deciseconds for non-canonical reads + (term.c_cc[VMIN], term.c_cc[VTIME]) = (0, 1); set_term_mode(&term)?; Ok(orig_term) } From 9f558ac2cdb6f42b1ba5ec14af8fee3fb295a49e Mon Sep 17 00:00:00 2001 From: Carol Date: Tue, 17 Jan 2023 10:47:55 +0200 Subject: [PATCH 07/12] Ran formatting tool --- src/editor.rs | 20 +++++++++++--------- src/row.rs | 9 ++++++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index a93c362..20e0ea8 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -197,12 +197,11 @@ impl Editor { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } } - (AKey::Left, _) if self.cursor.y > 0 => { - // ← at the beginning of the line: move to the end of the previous line. The x - // position will be adjusted after this `match` to accommodate the current row - // length, so we can just set here to the maximum possible value here. - (self.cursor.y, cursor_x) = (self.cursor.y - 1, usize::MAX); - } + // ← at the beginning of the line: move to the end of the previous line. The x + // position will be adjusted after this `match` to accommodate the current row + // length, so we can just set here to the maximum possible value here. + (AKey::Left, _) if self.cursor.y > 0 => + (self.cursor.y, cursor_x) = (self.cursor.y - 1, usize::MAX), (AKey::Right, Some(row)) if self.cursor.x < row.chars.len() => { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); // → moving to next word @@ -557,12 +556,14 @@ impl Editor { fn draw_status_bar(&self, buffer: &mut String) -> Result<(), Error> { // Left part of the status bar let modified = if self.dirty { " (modified)" } else { "" }; - let mut left = format!("{:.30}{modified}", self.file_name.as_deref().unwrap_or("[No Name]")); + let mut left = + format!("{:.30}{modified}", self.file_name.as_deref().unwrap_or("[No Name]")); left.truncate(self.window_width); // Right part of the status bar let size = format_size(self.n_bytes + self.rows.len().saturating_sub(1) as u64); - let right = format!("{} | {size} | {}:{}", self.syntax.name, self.cursor.y + 1, self.rx() + 1); + let right = + format!("{} | {size} | {}:{}", self.syntax.name, self.cursor.y + 1, self.rx() + 1); // Draw let rw = self.window_width.saturating_sub(left.len()); @@ -771,7 +772,8 @@ impl PromptMode { match process_prompt_keypress(b, key) { PromptState::Active(query) => { let (last_match, forward) = match key { - Key::Arrow(AKey::Right | AKey::Down) | Key::Char(FIND) => (last_match, true), + Key::Arrow(AKey::Right | AKey::Down) | Key::Char(FIND) => + (last_match, true), Key::Arrow(AKey::Left | AKey::Up) => (last_match, false), _ => (None, true), }; diff --git a/src/row.rs b/src/row.rs index aee58db..53c11b7 100644 --- a/src/row.rs +++ b/src/row.rs @@ -91,7 +91,8 @@ impl Row { 'syntax_loop: while self.hl.len() < line.len() { let i = self.hl.len(); - let find_str = |s: &str| line.get(i..(i + s.len())).map_or(false, |r| r.eq(s.as_bytes())); + let find_str = + |s: &str| line.get(i..(i + s.len())).map_or(false, |r| r.eq(s.as_bytes())); if hl_state == HlState::Normal && syntax.sl_comment_start.iter().any(|s| find_str(s)) { self.hl.extend(repeat(HlType::Comment).take(line.len() - i)); @@ -102,7 +103,8 @@ impl Row { // differences are: the start/end delimiters, the `HLState`, the `HLType`. for (delims, mstate, mtype) in &[ (ml_comment_delims, HlState::MultiLineComment, HlType::MlComment), - (ml_string_delims, HlState::MultiLineString, HlType::MlString),] { + (ml_string_delims, HlState::MultiLineString, HlType::MlString), + ] { if let Some((start, end)) = delims { if hl_state == *mstate { if find_str(end) { @@ -165,7 +167,8 @@ impl Row { } // String state doesn't propagate to the next row - self.hl_state = if matches!(hl_state, HlState::String(_)) { HlState::Normal } else { hl_state }; + self.hl_state = + if matches!(hl_state, HlState::String(_)) { HlState::Normal } else { hl_state }; self.hl_state } From 44d25beff777fb0ffffee9c0a5d44563dba6cede Mon Sep 17 00:00:00 2001 From: Carol Date: Thu, 19 Jan 2023 10:17:02 +0200 Subject: [PATCH 08/12] Add unit test for CTRL+Arrow --- src/editor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 20e0ea8..648ca1e 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -193,7 +193,7 @@ impl Editor { (AKey::Left, Some(row)) if self.cursor.x > 0 => { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); // ← moving to previous word - while ctrl && cursor_x > 0 && row.chars[cursor_x - 1] != 0x20 { + while ctrl && cursor_x > 0 && row.chars[cursor_x - 1] != b' ' { cursor_x -= row.get_char_size(row.cx2rx[cursor_x] - 1); } } @@ -205,7 +205,7 @@ impl Editor { (AKey::Right, Some(row)) if self.cursor.x < row.chars.len() => { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); // → moving to next word - while ctrl && cursor_x < row.chars.len() && row.chars[cursor_x] != 0x20 { + while ctrl && cursor_x < row.chars.len() && row.chars[cursor_x] != b' ' { cursor_x += row.get_char_size(row.cx2rx[cursor_x]); } } From 896e3b44d6bba4eb8854382a40154f35125ed2a1 Mon Sep 17 00:00:00 2001 From: Carol Date: Thu, 19 Jan 2023 10:25:22 +0200 Subject: [PATCH 09/12] Add unit test for CTRL+Arrow --- src/editor.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/editor.rs b/src/editor.rs index 648ca1e..35dbd13 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -920,6 +920,7 @@ mod tests { assert_eq!(editor.rows[0].chars, "Hello".as_bytes()); editor.move_cursor(&AKey::Left, false); editor.move_cursor(&AKey::Left, false); + editor.move_cursor(&AKey::Left, true); editor.delete_char(); assert_eq!(editor.rows[0].chars, "Helo".as_bytes()); } From ca524b91b2bf8bbf38305215f132be43ebce2abd Mon Sep 17 00:00:00 2001 From: Carol Date: Thu, 19 Jan 2023 12:30:53 +0200 Subject: [PATCH 10/12] Fix unit test result --- src/editor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 35dbd13..c85156c 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -917,11 +917,11 @@ mod tests { editor.insert_byte(*b); } editor.delete_char(); - assert_eq!(editor.rows[0].chars, "Hello".as_bytes()); + assert_eq!(editor.rows[0].chars, "Hello world".as_bytes()); + editor.move_cursor(&AKey::Left, true); editor.move_cursor(&AKey::Left, false); editor.move_cursor(&AKey::Left, false); - editor.move_cursor(&AKey::Left, true); editor.delete_char(); - assert_eq!(editor.rows[0].chars, "Helo".as_bytes()); + assert_eq!(editor.rows[0].chars, "Helo world".as_bytes()); } } From cd6b7d8d8b2131f324b3ed25a17667227ee961c9 Mon Sep 17 00:00:00 2001 From: Carol Date: Thu, 19 Jan 2023 12:37:00 +0200 Subject: [PATCH 11/12] Fix unit test result --- src/editor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index c85156c..d195754 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -913,15 +913,15 @@ mod tests { #[test] fn editor_delete_char() { let mut editor = Editor::default(); - for b in "Hello!".as_bytes() { + for b in "Hello world!".as_bytes() { editor.insert_byte(*b); } editor.delete_char(); - assert_eq!(editor.rows[0].chars, "Hello world".as_bytes()); + assert_eq!(editor.rows[0].chars, "Hello world!".as_bytes()); editor.move_cursor(&AKey::Left, true); editor.move_cursor(&AKey::Left, false); editor.move_cursor(&AKey::Left, false); editor.delete_char(); - assert_eq!(editor.rows[0].chars, "Helo world".as_bytes()); + assert_eq!(editor.rows[0].chars, "Helo world!".as_bytes()); } } From 7b3e58f7f0fa820ead2ea5442861d7f1e9097ee4 Mon Sep 17 00:00:00 2001 From: Carol Date: Thu, 19 Jan 2023 12:42:03 +0200 Subject: [PATCH 12/12] Fix unit test result --- src/editor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index d195754..b8d4b47 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -917,11 +917,11 @@ mod tests { editor.insert_byte(*b); } editor.delete_char(); - assert_eq!(editor.rows[0].chars, "Hello world!".as_bytes()); + assert_eq!(editor.rows[0].chars, "Hello world".as_bytes()); editor.move_cursor(&AKey::Left, true); editor.move_cursor(&AKey::Left, false); editor.move_cursor(&AKey::Left, false); editor.delete_char(); - assert_eq!(editor.rows[0].chars, "Helo world!".as_bytes()); + assert_eq!(editor.rows[0].chars, "Helo world".as_bytes()); } }