Highlight primary keywords

This commit is contained in:
Timothy Warren 2021-03-16 12:18:37 -04:00
parent d5b880dd9e
commit 6a43727240
4 changed files with 174 additions and 24 deletions

View File

@ -22,7 +22,7 @@ impl Document {
for value in contents.lines() { for value in contents.lines() {
let mut row = Row::from(value); let mut row = Row::from(value);
row.highlight(file_type.highlighting_options(), None); row.highlight(&file_type.highlighting_options(), None);
rows.push(row); rows.push(row);
} }
@ -66,13 +66,13 @@ impl Document {
if at.y == self.rows.len() { if at.y == self.rows.len() {
let mut row = Row::default(); let mut row = Row::default();
row.insert(0, c); row.insert(0, c);
row.highlight(self.file_type.highlighting_options(), None); row.highlight(&self.file_type.highlighting_options(), None);
self.rows.push(row); self.rows.push(row);
} else { } else {
#[allow(clippy::indexing_slicing)] #[allow(clippy::indexing_slicing)]
let row = &mut self.rows[at.y]; let row = &mut self.rows[at.y];
row.insert(at.x, c); row.insert(at.x, c);
row.highlight(self.file_type.highlighting_options(), None); row.highlight(&self.file_type.highlighting_options(), None);
} }
} }
@ -90,11 +90,11 @@ impl Document {
let next_row = self.rows.remove(at.y + 1); let next_row = self.rows.remove(at.y + 1);
let row = &mut self.rows[at.y]; let row = &mut self.rows[at.y];
row.append(&next_row); row.append(&next_row);
row.highlight(self.file_type.highlighting_options(), None); row.highlight(&self.file_type.highlighting_options(), None);
} else { } else {
let row = &mut self.rows[at.y]; let row = &mut self.rows[at.y];
row.delete(at.x); row.delete(at.x);
row.highlight(self.file_type.highlighting_options(), None); row.highlight(&self.file_type.highlighting_options(), None);
} }
} }
@ -106,7 +106,7 @@ impl Document {
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")?;
row.highlight(self.file_type.highlighting_options(), None) row.highlight(&self.file_type.highlighting_options(), None)
} }
// File has been cleaned! (Saved) // File has been cleaned! (Saved)
@ -118,7 +118,7 @@ impl Document {
pub fn highlight(&mut self, word: Option<&str>) { pub fn highlight(&mut self, word: Option<&str>) {
for row in &mut self.rows { for row in &mut self.rows {
row.highlight(self.file_type.highlighting_options(), word); row.highlight(&self.file_type.highlighting_options(), word);
} }
} }
@ -175,8 +175,8 @@ impl Document {
let current_row = &mut self.rows[at.y]; let current_row = &mut self.rows[at.y];
let mut new_row = current_row.split(at.x); let mut new_row = current_row.split(at.x);
current_row.highlight(self.file_type.highlighting_options(), None); current_row.highlight(&self.file_type.highlighting_options(), None);
new_row.highlight(self.file_type.highlighting_options(), None); new_row.highlight(&self.file_type.highlighting_options(), None);
#[allow(clippy::integer_arithmetic)] #[allow(clippy::integer_arithmetic)]
self.rows.insert(at.y + 1, new_row); self.rows.insert(at.y + 1, new_row);

View File

@ -3,12 +3,14 @@ pub struct FileType {
hl_opts: HighlightingOptions, hl_opts: HighlightingOptions,
} }
#[derive(Default, Copy, Clone)] #[derive(Default)]
pub struct HighlightingOptions { pub struct HighlightingOptions {
numbers: bool, numbers: bool,
strings: bool, strings: bool,
characters: bool, characters: bool,
comments: bool, comments: bool,
primary_keywords: Vec<String>,
secondary_keywords: Vec<String>,
} }
impl Default for FileType { impl Default for FileType {
@ -25,8 +27,8 @@ impl FileType {
self.name.clone() self.name.clone()
} }
pub fn highlighting_options(&self) -> HighlightingOptions { pub fn highlighting_options(&self) -> &HighlightingOptions {
self.hl_opts &self.hl_opts
} }
pub fn from(file_name: &str) -> Self { pub fn from(file_name: &str) -> Self {
@ -38,6 +40,77 @@ impl FileType {
strings: true, strings: true,
characters: true, characters: true,
comments: true, comments: true,
primary_keywords: vec![
"as".to_string(),
"break".to_string(),
"const".to_string(),
"continue".to_string(),
"crate".to_string(),
"else".to_string(),
"enum".to_string(),
"extern".to_string(),
"false".to_string(),
"fn".to_string(),
"For".to_string(),
"if".to_string(),
"impl".to_string(),
"in".to_string(),
"let".to_string(),
"loop".to_string(),
"match".to_string(),
"mod".to_string(),
"move".to_string(),
"mut".to_string(),
"pub".to_string(),
"ref".to_string(),
"return".to_string(),
"self".to_string(),
"Self".to_string(),
"static".to_string(),
"struct".to_string(),
"super".to_string(),
"trait".to_string(),
"true".to_string(),
"type".to_string(),
"unsafe".to_string(),
"use".to_string(),
"where".to_string(),
"while".to_string(),
"dyn".to_string(),
"abstract".to_string(),
"become".to_string(),
"box".to_string(),
"do".to_string(),
"final".to_string(),
"macro".to_string(),
"overrid".to_string(),
"priv".to_string(),
"typeof".to_string(),
"unsized".to_string(),
"virtual".to_string(),
"yield".to_string(),
"async".to_string(),
"await".to_string(),
"try".to_string(),
],
secondary_keywords: vec![
"bool".to_string(),
"char".to_string(),
"i8".to_string(),
"i16".to_string(),
"i32".to_string(),
"i64".to_string(),
"i128".to_string(),
"isize".to_string(),
"u8".to_string(),
"u16".to_string(),
"u32".to_string(),
"u64".to_string(),
"u128".to_string(),
"usize".to_string(),
"f32".to_string(),
"f64".to_string(),
],
}, },
}; };
} }
@ -47,19 +120,27 @@ impl FileType {
} }
impl HighlightingOptions { impl HighlightingOptions {
pub fn numbers(self) -> bool { pub fn numbers(&self) -> bool {
self.numbers self.numbers
} }
pub fn strings(self) -> bool { pub fn strings(&self) -> bool {
self.strings self.strings
} }
pub fn characters(self) -> bool { pub fn characters(&self) -> bool {
self.characters self.characters
} }
pub fn comments(self) -> bool { pub fn comments(&self) -> bool {
self.comments self.comments
} }
pub fn primary_keywords(&self) -> &Vec<String> {
&self.primary_keywords
}
pub fn secondary_keywords(&self) -> &Vec<String> {
&self.secondary_keywords
}
} }

View File

@ -1,6 +1,6 @@
use termion::color; use termion::color;
#[derive(PartialEq)] #[derive(PartialEq, Clone, Copy)]
pub enum Type { pub enum Type {
None, None,
Number, Number,
@ -8,16 +8,20 @@ pub enum Type {
String, String,
Character, Character,
Comment, Comment,
PrimaryKeywords,
SecondaryKeywords,
} }
impl Type { impl Type {
pub fn to_color(&self) -> impl color::Color { pub fn to_color(self) -> impl color::Color {
match self { match self {
Type::Number => color::Rgb(220, 163, 163), Type::Number => color::Rgb(220, 163, 163),
Type::Match => color::Rgb(38, 139, 210), Type::Match => color::Rgb(38, 139, 210),
Type::String => color::Rgb(211, 54, 130), Type::String => color::Rgb(211, 54, 130),
Type::Character => color::Rgb(108, 113, 196), Type::Character => color::Rgb(108, 113, 196),
Type::Comment => color::Rgb(133, 153, 0), Type::Comment => color::Rgb(133, 153, 0),
Type::PrimaryKeywords => color::Rgb(181, 137, 0),
Type::SecondaryKeywords => color::Rgb(42, 161, 152),
_ => color::Rgb(255, 255, 255), _ => color::Rgb(255, 255, 255),
} }
} }

View File

@ -213,10 +213,70 @@ impl Row {
} }
} }
fn highlight_str(
&mut self,
index: &mut usize,
substring: &str,
chars: &[char],
hl_type: highlighting::Type,
) -> bool {
if substring.is_empty() {
return false;
}
for (substring_index, c) in substring.chars().enumerate() {
if let Some(next_char) = chars.get(index.saturating_add(substring_index)) {
if *next_char != c {
return false;
}
} else {
return false;
}
}
for _ in 0..substring.len() {
self.highlighting.push(hl_type);
*index += 1;
}
true
}
fn highlight_primary_keywords(
&mut self,
index: &mut usize,
opts: &HighlightingOptions,
chars: &[char],
) -> bool {
if *index > 0 {
#[allow(clippy::indexing_slicing, clippy::integer_arithmetic)]
let prev_char = chars[*index - 1];
if !is_separator(prev_char) {
return false;
}
}
for word in opts.primary_keywords() {
if *index < chars.len().saturating_sub(word.len()) {
#[allow(clippy::indexing_slicing, clippy::integer_arithmetic)]
let next_char = chars[*index + word.len()];
if !is_separator(next_char) {
continue;
}
}
if self.highlight_str(index, word, chars, highlighting::Type::PrimaryKeywords) {
return true;
}
}
false
}
fn highlight_char( fn highlight_char(
&mut self, &mut self,
index: &mut usize, index: &mut usize,
opts: HighlightingOptions, opts: &HighlightingOptions,
c: char, c: char,
chars: &[char], chars: &[char],
) -> bool { ) -> bool {
@ -247,7 +307,7 @@ impl Row {
fn highlight_comment( fn highlight_comment(
&mut self, &mut self,
index: &mut usize, index: &mut usize,
opts: HighlightingOptions, opts: &HighlightingOptions,
c: char, c: char,
chars: &[char], chars: &[char],
) -> bool { ) -> bool {
@ -270,7 +330,7 @@ impl Row {
fn highlight_string( fn highlight_string(
&mut self, &mut self,
index: &mut usize, index: &mut usize,
opts: HighlightingOptions, opts: &HighlightingOptions,
c: char, c: char,
chars: &[char], chars: &[char],
) -> bool { ) -> bool {
@ -299,7 +359,7 @@ impl Row {
fn highlight_number( fn highlight_number(
&mut self, &mut self,
index: &mut usize, index: &mut usize,
opts: HighlightingOptions, opts: &HighlightingOptions,
c: char, c: char,
chars: &[char], chars: &[char],
) -> bool { ) -> bool {
@ -307,7 +367,7 @@ impl Row {
if *index > 0 { if *index > 0 {
#[allow(clippy::indexing_slicing, clippy::integer_arithmetic)] #[allow(clippy::indexing_slicing, clippy::integer_arithmetic)]
let prev_char = chars[*index - 1]; let prev_char = chars[*index - 1];
if !prev_char.is_ascii_punctuation() && !prev_char.is_ascii_whitespace() { if !is_separator(prev_char) {
return false; return false;
} }
} }
@ -330,7 +390,7 @@ impl Row {
false false
} }
pub fn highlight(&mut self, opts: HighlightingOptions, word: Option<&str>) { pub fn highlight(&mut self, opts: &HighlightingOptions, word: Option<&str>) {
self.highlighting = Vec::new(); self.highlighting = Vec::new();
let chars: Vec<char> = self.string.chars().collect(); let chars: Vec<char> = self.string.chars().collect();
let mut index = 0; let mut index = 0;
@ -338,6 +398,7 @@ impl Row {
while let Some(c) = chars.get(index) { while let Some(c) = chars.get(index) {
if self.highlight_char(&mut index, opts, *c, &chars) if self.highlight_char(&mut index, opts, *c, &chars)
|| self.highlight_comment(&mut index, opts, *c, &chars) || self.highlight_comment(&mut index, opts, *c, &chars)
|| self.highlight_primary_keywords(&mut index, &opts, &chars)
|| self.highlight_string(&mut index, opts, *c, &chars) || self.highlight_string(&mut index, opts, *c, &chars)
|| self.highlight_number(&mut index, opts, *c, &chars) || self.highlight_number(&mut index, opts, *c, &chars)
{ {
@ -351,3 +412,7 @@ impl Row {
self.highlight_match(word); self.highlight_match(word);
} }
} }
fn is_separator(c: char) -> bool {
c.is_ascii_punctuation() || c.is_ascii_whitespace()
}