From 31a7f7022b6156b4594440a822b0cdc1ec84aca4 Mon Sep 17 00:00:00 2001 From: Razvan Rus Date: Sat, 20 Jan 2024 12:08:24 +0200 Subject: [PATCH 1/4] added partial solution --- src/editor.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index fe3c1e1..124e202 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -3,7 +3,7 @@ use std::fmt::{Display, Write as _}; use std::io::{self, BufRead, BufReader, ErrorKind, Read, Seek, Write}; use std::iter::{self, repeat, successors}; -use std::{fs::File, path::Path, process::Command, thread, time::Instant}; +use std::{cell::RefCell, fs::File, path::Path, process::Command, thread, time::Instant}; use crate::row::{HlState, Row}; use crate::{ansi_escape::*, syntax::Conf as SyntaxConf, sys, terminal, Config, Error}; @@ -593,7 +593,7 @@ impl Editor { (self.rx() - self.cursor.coff + 1 + self.ln_pad, self.cursor.y - self.cursor.roff + 1) } else { // If in prompt mode, position the cursor on the prompt line at the end of the line. - (self.status_msg.as_ref().map_or(0, |sm| sm.msg.len() + 1), self.screen_rows + 2) + (self.status_msg.as_ref().map_or(0, |s| s.msg.chars().count() + 1), self.screen_rows + 2) }; // Finally, print `buffer` and move the cursor print!("{buffer}\x1b[{cursor_y};{cursor_x}H{SHOW_CURSOR}"); @@ -678,7 +678,7 @@ impl Editor { // will be updated in self.cursor.scroll() so that the result is visible (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()); + row.match_segment = Some(rx..rx + query.chars().count()); return Some(current); } } @@ -837,15 +837,15 @@ enum PromptState { Cancelled, } +thread_local! (static CHARACTER: RefCell> = {let mut cache = Vec::new(); RefCell::new(cache)}); /// Process a prompt keypress event and return the new state for the prompt. fn process_prompt_keypress(mut buffer: String, key: &Key) -> PromptState { match key { Key::Char(b'\r') => return PromptState::Completed(buffer), Key::Escape | Key::Char(EXIT) => return PromptState::Cancelled, - Key::Char(BACKSPACE | DELETE_BIS) => { - buffer.pop(); - } + Key::Char(BACKSPACE | DELETE_BIS) => {buffer.pop();}, Key::Char(c @ 0..=126) if !c.is_ascii_control() => buffer.push(*c as char), + Key::Char(c @ 128..=255) => CHARACTER.with(|cache| {cache.borrow_mut().push(*c); if String::from_utf8(cache.borrow_mut().clone()).is_ok() {buffer.push_str(String::from_utf8(cache.borrow_mut().clone()).unwrap().as_str()); cache.borrow_mut().clear();}}), // No-op _ => (), } From f63bcdb581bd820cfc63ea5767baf063ff12e24a Mon Sep 17 00:00:00 2001 From: Razvan Rus Date: Sat, 20 Jan 2024 13:24:32 +0200 Subject: [PATCH 2/4] better highlight length getter (using unicode_width) --- src/editor.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 124e202..8645048 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -5,6 +5,7 @@ use std::io::{self, BufRead, BufReader, ErrorKind, Read, Seek, Write}; use std::iter::{self, repeat, successors}; use std::{cell::RefCell, fs::File, path::Path, process::Command, thread, time::Instant}; +use unicode_width::UnicodeWidthStr; use crate::row::{HlState, Row}; use crate::{ansi_escape::*, syntax::Conf as SyntaxConf, sys, terminal, Config, Error}; @@ -593,7 +594,7 @@ impl Editor { (self.rx() - self.cursor.coff + 1 + self.ln_pad, self.cursor.y - self.cursor.roff + 1) } else { // If in prompt mode, position the cursor on the prompt line at the end of the line. - (self.status_msg.as_ref().map_or(0, |s| s.msg.chars().count() + 1), self.screen_rows + 2) + (self.status_msg.as_ref().map_or(0, |s| UnicodeWidthStr::width(s.msg.as_str()) + 1), self.screen_rows + 2) }; // Finally, print `buffer` and move the cursor print!("{buffer}\x1b[{cursor_y};{cursor_x}H{SHOW_CURSOR}"); @@ -678,7 +679,7 @@ impl Editor { // will be updated in self.cursor.scroll() so that the result is visible (self.cursor.x, self.cursor.y, self.cursor.coff) = (cx, current, 0); let rx = row.cx2rx[cx]; - row.match_segment = Some(rx..rx + query.chars().count()); + row.match_segment = Some(rx..rx + UnicodeWidthStr::width(query)); return Some(current); } } @@ -843,7 +844,7 @@ fn process_prompt_keypress(mut buffer: String, key: &Key) -> PromptState { match key { Key::Char(b'\r') => return PromptState::Completed(buffer), Key::Escape | Key::Char(EXIT) => return PromptState::Cancelled, - Key::Char(BACKSPACE | DELETE_BIS) => {buffer.pop();}, + Key::Char(BACKSPACE | DELETE_BIS) => _ = buffer.pop(), Key::Char(c @ 0..=126) if !c.is_ascii_control() => buffer.push(*c as char), Key::Char(c @ 128..=255) => CHARACTER.with(|cache| {cache.borrow_mut().push(*c); if String::from_utf8(cache.borrow_mut().clone()).is_ok() {buffer.push_str(String::from_utf8(cache.borrow_mut().clone()).unwrap().as_str()); cache.borrow_mut().clear();}}), // No-op From 7df0d7a457ec0953f61ddcb868ac79597bc2066d Mon Sep 17 00:00:00 2001 From: Razvan Rus Date: Sat, 20 Jan 2024 15:48:29 +0200 Subject: [PATCH 3/4] finnished coding style --- src/editor.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 8645048..0104026 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -6,6 +6,7 @@ use std::iter::{self, repeat, successors}; use std::{cell::RefCell, fs::File, path::Path, process::Command, thread, time::Instant}; use unicode_width::UnicodeWidthStr; + use crate::row::{HlState, Row}; use crate::{ansi_escape::*, syntax::Conf as SyntaxConf, sys, terminal, Config, Error}; @@ -29,9 +30,9 @@ const HELP_MESSAGE: &str = /// `set_status!` sets a formatted status message for the editor. /// Example usage: `set_status!(editor, "{} written to {}", file_size, file_name)` -macro_rules! set_status { - ($editor:expr, $($arg:expr),*) => ($editor.status_msg = Some(StatusMessage::new(format!($($arg),*)))) -} +macro_rules! set_status { ($editor:expr, $($arg:expr),*) => ($editor.status_msg = Some(StatusMessage::new(format!($($arg),*)))) } +// `width!` returns the display width of a string, plus one for the cursor +fn dsp_width(msg: &String) -> usize { UnicodeWidthStr::width(msg.as_str()) + 1 } /// Enum of input keys enum Key { @@ -594,7 +595,7 @@ impl Editor { (self.rx() - self.cursor.coff + 1 + self.ln_pad, self.cursor.y - self.cursor.roff + 1) } else { // If in prompt mode, position the cursor on the prompt line at the end of the line. - (self.status_msg.as_ref().map_or(0, |s| UnicodeWidthStr::width(s.msg.as_str()) + 1), self.screen_rows + 2) + (self.status_msg.as_ref().map_or(0, |s| dsp_width(&s.msg)), self.screen_rows + 2) }; // Finally, print `buffer` and move the cursor print!("{buffer}\x1b[{cursor_y};{cursor_x}H{SHOW_CURSOR}"); @@ -838,7 +839,7 @@ enum PromptState { Cancelled, } -thread_local! (static CHARACTER: RefCell> = {let mut cache = Vec::new(); RefCell::new(cache)}); +thread_local! (static CHARACTER: RefCell> = {let cache = Vec::new(); RefCell::new(cache)}); /// Process a prompt keypress event and return the new state for the prompt. fn process_prompt_keypress(mut buffer: String, key: &Key) -> PromptState { match key { @@ -846,10 +847,14 @@ fn process_prompt_keypress(mut buffer: String, key: &Key) -> PromptState { Key::Escape | Key::Char(EXIT) => return PromptState::Cancelled, Key::Char(BACKSPACE | DELETE_BIS) => _ = buffer.pop(), Key::Char(c @ 0..=126) if !c.is_ascii_control() => buffer.push(*c as char), - Key::Char(c @ 128..=255) => CHARACTER.with(|cache| {cache.borrow_mut().push(*c); if String::from_utf8(cache.borrow_mut().clone()).is_ok() {buffer.push_str(String::from_utf8(cache.borrow_mut().clone()).unwrap().as_str()); cache.borrow_mut().clear();}}), + Key::Char(c @ 128..=255) => CHARACTER.with(|cache| cache.borrow_mut().push(*c)), // No-op _ => (), } + let character = CHARACTER.with(|cache| String::from_utf8(cache.borrow_mut().clone())); + character.clone().map_or((), |c| buffer.push_str(c.as_str())); + character.map_or((), |_| CHARACTER.with(|cache| cache.borrow_mut().clear())); + PromptState::Active(buffer) } From 755da5ae52bbec8cf2c5a798425bba08d0a370e6 Mon Sep 17 00:00:00 2001 From: Razvan Rus Date: Sun, 21 Jan 2024 15:33:32 +0200 Subject: [PATCH 4/4] fixed warnings --- src/editor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 0104026..2af3489 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -852,8 +852,8 @@ fn process_prompt_keypress(mut buffer: String, key: &Key) -> PromptState { _ => (), } let character = CHARACTER.with(|cache| String::from_utf8(cache.borrow_mut().clone())); - character.clone().map_or((), |c| buffer.push_str(c.as_str())); - character.map_or((), |_| CHARACTER.with(|cache| cache.borrow_mut().clear())); + let _ = character.clone().map_or((), |c| buffer.push_str(c.as_str())); + let _ = character.map_or((), |_| CHARACTER.with(|cache| cache.borrow_mut().clear())); PromptState::Active(buffer) }