Final performance improvements, finish tutorial

This commit is contained in:
Timothy Warren 2021-03-16 14:29:04 -04:00
parent 76e1b24855
commit cd7ff3b6e5
3 changed files with 53 additions and 20 deletions

View File

@ -17,14 +17,11 @@ impl Document {
pub fn open(filename: &str) -> Result<Self, std::io::Error> { pub fn open(filename: &str) -> Result<Self, std::io::Error> {
let contents = fs::read_to_string(filename)?; let contents = fs::read_to_string(filename)?;
let file_type = FileType::from(filename); let file_type = FileType::from(filename);
let mut start_with_comment = false;
let mut rows = Vec::new(); let mut rows = Vec::new();
for value in contents.lines() { for value in contents.lines() {
let mut row = Row::from(value); rows.push(Row::from(value));
start_with_comment = row.highlight(&file_type.highlighting_options(), None, start_with_comment);
rows.push(row);
} }
Ok(Self { Ok(Self {
@ -71,7 +68,7 @@ impl Document {
row.insert(at.x, c); row.insert(at.x, c);
} }
self.highlight(None); self.unhighlight_rows(at.y);
} }
#[allow(clippy::integer_arithmetic, clippy::indexing_slicing)] #[allow(clippy::integer_arithmetic, clippy::indexing_slicing)]
@ -93,23 +90,17 @@ impl Document {
row.delete(at.x); row.delete(at.x);
} }
self.highlight(None); self.unhighlight_rows(at.y);
} }
pub fn save(&mut self) -> Result<(), Error> { pub fn save(&mut self) -> Result<(), Error> {
if let Some(file_name) = &self.file_name { if let Some(file_name) = &self.file_name {
let mut file = fs::File::create(file_name)?; let mut file = fs::File::create(file_name)?;
self.file_type = FileType::from(file_name); self.file_type = FileType::from(file_name);
let mut start_with_comment = false;
for row in &mut self.rows { for row in &mut self.rows {
file.write_all(row.as_bytes())?; file.write_all(row.as_bytes())?;
file.write_all(b"\n")?; file.write_all(b"\n")?;
start_with_comment = row.highlight(
&self.file_type.highlighting_options(),
None,
start_with_comment,
);
} }
// File has been cleaned! (Saved) // File has been cleaned! (Saved)
@ -119,10 +110,20 @@ impl Document {
Ok(()) Ok(())
} }
pub fn highlight(&mut self, word: Option<&str>) { pub fn highlight(&mut self, word: &Option<String>, until: Option<usize>) {
let mut start_with_comment = false; let mut start_with_comment = false;
let until = if let Some(until) = until {
if until.saturating_add(1) < self.rows.len() {
until.saturating_add(1)
} else {
self.rows.len()
}
} else {
self.rows.len()
};
for row in &mut self.rows { #[allow(clippy::indexing_slicing)]
for row in &mut self.rows[..until] {
start_with_comment = row.highlight( start_with_comment = row.highlight(
&self.file_type.highlighting_options(), &self.file_type.highlighting_options(),
word, word,
@ -187,4 +188,11 @@ impl Document {
#[allow(clippy::integer_arithmetic)] #[allow(clippy::integer_arithmetic)]
self.rows.insert(at.y + 1, new_row); self.rows.insert(at.y + 1, new_row);
} }
fn unhighlight_rows(&mut self, start: usize) {
let start = start.saturating_sub(1);
for row in self.rows.iter_mut().skip(start) {
row.is_highlighted = false;
}
}
} }

View File

@ -55,6 +55,7 @@ pub struct Editor {
document: Document, document: Document,
status_message: StatusMessage, status_message: StatusMessage,
quit_times: u8, quit_times: u8,
highlighted_word: Option<String>,
} }
impl Editor { impl Editor {
@ -96,16 +97,23 @@ impl Editor {
offset: Position::default(), offset: Position::default(),
status_message: StatusMessage::from(initial_status), status_message: StatusMessage::from(initial_status),
quit_times: QUIT_TIMES, quit_times: QUIT_TIMES,
highlighted_word: None,
} }
} }
fn refresh_screen(&self) -> Result<(), std::io::Error> { fn refresh_screen(&mut self) -> Result<(), std::io::Error> {
Terminal::cursor_hide(); Terminal::cursor_hide();
Terminal::cursor_position(&Position::default()); Terminal::cursor_position(&Position::default());
if self.should_quit { if self.should_quit {
Terminal::clear_screen(); Terminal::clear_screen();
println!("Goodbye.\r"); println!("Goodbye.\r");
} else { } else {
self.document.highlight(
&self.highlighted_word,
Some(
self.offset.y.saturating_add(self.terminal.size().height as usize),
)
);
self.draw_rows(); self.draw_rows();
self.draw_status_bar(); self.draw_status_bar();
self.draw_message_bar(); self.draw_message_bar();
@ -222,7 +230,7 @@ impl Editor {
editor.move_cursor(Key::Left); editor.move_cursor(Key::Left);
} }
editor.document.highlight(Some(query)); editor.highlighted_word = Some(query.to_string());
}, },
) )
.unwrap_or(None); .unwrap_or(None);
@ -232,7 +240,7 @@ impl Editor {
self.scroll(); self.scroll();
} }
self.document.highlight(None); self.highlighted_word = None;
} }
fn process_keypress(&mut self) -> Result<(), std::io::Error> { fn process_keypress(&mut self) -> Result<(), std::io::Error> {

View File

@ -9,6 +9,7 @@ use unicode_segmentation::UnicodeSegmentation;
pub struct Row { pub struct Row {
string: String, string: String,
highlighting: Vec<highlighting::Type>, highlighting: Vec<highlighting::Type>,
pub is_highlighted: bool,
len: usize, len: usize,
} }
@ -17,6 +18,7 @@ impl From<&str> for Row {
Self { Self {
string: String::from(slice), string: String::from(slice),
highlighting: Vec::new(), highlighting: Vec::new(),
is_highlighted: false,
len: slice.graphemes(true).count(), len: slice.graphemes(true).count(),
} }
} }
@ -143,10 +145,12 @@ impl Row {
self.string = row; self.string = row;
self.len = length; self.len = length;
self.is_highlighted = false;
Self { Self {
string: splitted_row, string: splitted_row,
len: splittend_length, len: splittend_length,
is_highlighted: false,
highlighting: Vec::new(), highlighting: Vec::new(),
} }
} }
@ -190,7 +194,7 @@ impl Row {
None None
} }
fn highlight_match(&mut self, word: Option<&str>) { fn highlight_match(&mut self, word: &Option<String>) {
if let Some(word) = word { if let Some(word) = word {
if word.is_empty() { if word.is_empty() {
return; return;
@ -454,11 +458,22 @@ impl Row {
pub fn highlight( pub fn highlight(
&mut self, &mut self,
opts: &HighlightingOptions, opts: &HighlightingOptions,
word: Option<&str>, word: &Option<String>,
start_with_comment: bool, start_with_comment: bool,
) -> bool { ) -> bool {
self.highlighting = Vec::new();
let chars: Vec<char> = self.string.chars().collect(); let chars: Vec<char> = self.string.chars().collect();
if self.is_highlighted && word.is_none() {
if let Some(hl_type) = self.highlighting.last() {
if *hl_type == highlighting::Type::MultilineComment && self.string.len() > 1 && self.string[self.string.len() - 2..] == *"*/" {
return true;
}
}
return false;
}
self.highlighting = Vec::new();
let mut index = 0; let mut index = 0;
let mut in_ml_comment = start_with_comment; let mut in_ml_comment = start_with_comment;
@ -507,6 +522,8 @@ impl Row {
return true; return true;
} }
self.is_highlighted = true;
false false
} }
} }