diff --git a/Cargo.lock b/Cargo.lock index 82b0e03..a2ef1d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,7 +43,6 @@ version = "0.1.0" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index 00f9896..05b992c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,5 @@ edition = "2018" [dependencies] bitflags = "1.1.0" lazy_static = "1.4.0" -libc = "0.2" # Rust wrappers for C/POSIX headers nix = "0.15.0" diff --git a/src/editor.rs b/src/editor.rs index deeb303..ce3ec8a 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -435,9 +435,11 @@ impl Editor { None }; let row = &mut rows[index]; + let render_len = row.render.len(); + // Reset the highlighting of the row - row.highlight = vec![Highlight::Normal; row.render.len()]; + row.highlight = vec![Highlight::Normal; render_len]; if self.syntax.is_none() { return; @@ -462,7 +464,7 @@ impl Editor { let mut i = 0; let bytes = row.render.clone().into_bytes(); - 'outer: while i < row.render.len() { + while i < render_len { let c = bytes[i] as char; let prev_highlight = if i > 0 { row.highlight[i - 1] @@ -472,12 +474,12 @@ impl Editor { // Single line comments if scs.len() > 0 && !in_string && !in_comment { - let range = get_slice_range(i as usize, scs.len(), row.render.len()); + let range = get_slice_range(i, scs.len(), render_len); if &row.render[range] == scs { // Pretty simple, highlight from the match to the end of the line highlight_range( &mut row.highlight, - i as usize..row.render.len(), + i..render_len, Highlight::LineComment, ); break; @@ -486,16 +488,16 @@ impl Editor { // Multi-line comments if mcs.len() > 0 && mce.len() > 0 && !in_string { - let mce_slice_range = get_slice_range(i as usize, mce.len(), row.render.len()); - let mcs_slice_range = get_slice_range(i as usize, mcs.len(), row.render.len()); + let mce_range = get_slice_range(i, mce.len(), render_len); + let mcs_range = get_slice_range(i, mcs.len(), render_len); if in_comment { - row.highlight[i as usize] = Highlight::MultiLineComment; + row.highlight[i] = Highlight::MultiLineComment; // End of a comment - if &row.render[mce_slice_range.clone()] == mce { + if &row.render[mce_range.clone()] == mce { highlight_range( &mut row.highlight, - mce_slice_range, + mce_range, Highlight::MultiLineComment, ); @@ -507,11 +509,11 @@ impl Editor { i += 1; continue; } - } else if &row.render[mcs_slice_range.clone()] == mcs { + } else if &row.render[mcs_range.clone()] == mcs { // Start of a multi-line comment highlight_range( &mut row.highlight, - mcs_slice_range, + mcs_range, Highlight::MultiLineComment, ); @@ -527,10 +529,10 @@ impl Editor { .contains(SyntaxFlags::HIGHLIGHT_STRINGS) { if in_string { - row.highlight[i as usize] = Highlight::String; + row.highlight[i] = Highlight::String; // Don't end highlighting for a string on an escaped quote - if c == '\\' && i + 1 < row.render.len() { - row.highlight[i as usize + 1] = Highlight::String; + if c == '\\' && i + 1 < render_len { + row.highlight[i + 1] = Highlight::String; i += 2; continue; } @@ -547,7 +549,7 @@ impl Editor { if (c == '"' || c == '\'') && prev_separator { in_string = true; str_start = c; - row.highlight[i as usize] = Highlight::String; + row.highlight[i] = Highlight::String; i += 1; continue; } @@ -562,7 +564,7 @@ impl Editor { if (c.is_ascii_digit() && (prev_separator || prev_highlight == Highlight::Number)) || (c == '.' && prev_highlight == Highlight::Number) { - row.highlight[i as usize] = Highlight::Number; + row.highlight[i] = Highlight::Number; i += 1; prev_separator = false; continue; @@ -572,10 +574,14 @@ impl Editor { // Keywords if prev_separator { for &keyword in keywords1 { - let search_range = get_slice_range(i as usize, keyword.len(), row.render.len()); + if i + keyword.len() >= render_len { + continue; + } - let next_char_offset = i as usize + keyword.len() + 1; - let is_end_of_line = next_char_offset >= row.render.len(); + let search_range = get_slice_range(i, keyword.len(), render_len); + + let next_char_offset = i + keyword.len() + 1; + let is_end_of_line = next_char_offset >= render_len; let next_char = if is_end_of_line { '\0' } else { @@ -589,10 +595,14 @@ impl Editor { } for &keyword in keywords2 { - let search_range = get_slice_range(i as usize, keyword.len(), row.render.len()); + if i + keyword.len() >= render_len { + continue; + } - let next_char_offset = i as usize + keyword.len() + 1; - let is_end_of_line = next_char_offset >= row.render.len(); + let search_range = get_slice_range(i, keyword.len(), render_len); + + let next_char_offset = i + keyword.len() + 1; + let is_end_of_line = next_char_offset >= render_len; let next_char = if is_end_of_line { '\0' } else { @@ -1579,8 +1589,9 @@ where match res { Ok(value) => value, Err(e) => { + print!("\x1b[2J"); + print!("\x1b[H"); disable_raw_mode(); - println!("\r\n"); panic!("{:?}", e); } } @@ -1603,7 +1614,19 @@ mod tests { #[test] fn is_separator_works() { - assert_eq!(is_separator(' '), true); - assert_eq!(is_separator('_'), false); + // Check each explicit character + for ch in ",.()+-/*=~%<>[];".chars() { + assert_eq!(is_separator(ch), true); + } + + // Check each whitespace character + for ch in " \t\n\x0c".chars() { + assert_eq!(is_separator(ch), true, "Character {:#} should be a separator", ch as u8); + } + + // Letters are not separators! + for ch in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".chars() { + assert_eq!(is_separator(ch), false); + } } } diff --git a/src/main.rs b/src/main.rs index 2fe4c9d..1a0746e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ mod terminal_helpers; use crate::editor::Editor; use crate::terminal_helpers::*; -use libc::STDIN_FILENO; +use nix::libc::STDIN_FILENO; use nix::sys::termios::Termios; use std::env; use std::io::Error; diff --git a/src/terminal_helpers.rs b/src/terminal_helpers.rs index 7495fde..da3f3c8 100644 --- a/src/terminal_helpers.rs +++ b/src/terminal_helpers.rs @@ -1,8 +1,8 @@ //! # Helpers //! //! Various functions calling C wrappers to get/set terminal functionality -use libc::ioctl; -use libc::{c_ushort, STDIN_FILENO, STDOUT_FILENO, TIOCGWINSZ}; +use nix::libc::ioctl; +use nix::libc::{c_ushort, STDIN_FILENO, STDOUT_FILENO, TIOCGWINSZ}; use nix::sys::termios; use nix::sys::termios::{ ControlFlags, InputFlags, LocalFlags, OutputFlags, SpecialCharacterIndices, Termios,