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() {
let mut row = Row::from(value);
row.highlight(file_type.highlighting_options(), None);
row.highlight(&file_type.highlighting_options(), None);
rows.push(row);
}
@ -66,13 +66,13 @@ impl Document {
if at.y == self.rows.len() {
let mut row = Row::default();
row.insert(0, c);
row.highlight(self.file_type.highlighting_options(), None);
row.highlight(&self.file_type.highlighting_options(), None);
self.rows.push(row);
} else {
#[allow(clippy::indexing_slicing)]
let row = &mut self.rows[at.y];
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 row = &mut self.rows[at.y];
row.append(&next_row);
row.highlight(self.file_type.highlighting_options(), None);
row.highlight(&self.file_type.highlighting_options(), None);
} else {
let row = &mut self.rows[at.y];
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 {
file.write_all(row.as_bytes())?;
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)
@ -118,7 +118,7 @@ impl Document {
pub fn highlight(&mut self, word: Option<&str>) {
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 mut new_row = current_row.split(at.x);
current_row.highlight(self.file_type.highlighting_options(), None);
new_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);
#[allow(clippy::integer_arithmetic)]
self.rows.insert(at.y + 1, new_row);

View File

@ -3,12 +3,14 @@ pub struct FileType {
hl_opts: HighlightingOptions,
}
#[derive(Default, Copy, Clone)]
#[derive(Default)]
pub struct HighlightingOptions {
numbers: bool,
strings: bool,
characters: bool,
comments: bool,
primary_keywords: Vec<String>,
secondary_keywords: Vec<String>,
}
impl Default for FileType {
@ -25,8 +27,8 @@ impl FileType {
self.name.clone()
}
pub fn highlighting_options(&self) -> HighlightingOptions {
self.hl_opts
pub fn highlighting_options(&self) -> &HighlightingOptions {
&self.hl_opts
}
pub fn from(file_name: &str) -> Self {
@ -38,6 +40,77 @@ impl FileType {
strings: true,
characters: 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 {
pub fn numbers(self) -> bool {
pub fn numbers(&self) -> bool {
self.numbers
}
pub fn strings(self) -> bool {
pub fn strings(&self) -> bool {
self.strings
}
pub fn characters(self) -> bool {
pub fn characters(&self) -> bool {
self.characters
}
pub fn comments(self) -> bool {
pub fn comments(&self) -> bool {
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;
#[derive(PartialEq)]
#[derive(PartialEq, Clone, Copy)]
pub enum Type {
None,
Number,
@ -8,16 +8,20 @@ pub enum Type {
String,
Character,
Comment,
PrimaryKeywords,
SecondaryKeywords,
}
impl Type {
pub fn to_color(&self) -> impl color::Color {
pub fn to_color(self) -> impl color::Color {
match self {
Type::Number => color::Rgb(220, 163, 163),
Type::Match => color::Rgb(38, 139, 210),
Type::String => color::Rgb(211, 54, 130),
Type::Character => color::Rgb(108, 113, 196),
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),
}
}

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(
&mut self,
index: &mut usize,
opts: HighlightingOptions,
opts: &HighlightingOptions,
c: char,
chars: &[char],
) -> bool {
@ -247,7 +307,7 @@ impl Row {
fn highlight_comment(
&mut self,
index: &mut usize,
opts: HighlightingOptions,
opts: &HighlightingOptions,
c: char,
chars: &[char],
) -> bool {
@ -270,7 +330,7 @@ impl Row {
fn highlight_string(
&mut self,
index: &mut usize,
opts: HighlightingOptions,
opts: &HighlightingOptions,
c: char,
chars: &[char],
) -> bool {
@ -299,7 +359,7 @@ impl Row {
fn highlight_number(
&mut self,
index: &mut usize,
opts: HighlightingOptions,
opts: &HighlightingOptions,
c: char,
chars: &[char],
) -> bool {
@ -307,7 +367,7 @@ impl Row {
if *index > 0 {
#[allow(clippy::indexing_slicing, clippy::integer_arithmetic)]
let prev_char = chars[*index - 1];
if !prev_char.is_ascii_punctuation() && !prev_char.is_ascii_whitespace() {
if !is_separator(prev_char) {
return false;
}
}
@ -330,7 +390,7 @@ impl Row {
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();
let chars: Vec<char> = self.string.chars().collect();
let mut index = 0;
@ -338,6 +398,7 @@ impl Row {
while let Some(c) = chars.get(index) {
if self.highlight_char(&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_number(&mut index, opts, *c, &chars)
{
@ -351,3 +412,7 @@ impl Row {
self.highlight_match(word);
}
}
fn is_separator(c: char) -> bool {
c.is_ascii_punctuation() || c.is_ascii_whitespace()
}