diff --git a/src/core/ui.rs b/src/core/ui.rs index 8736e9c..e0716ee 100644 --- a/src/core/ui.rs +++ b/src/core/ui.rs @@ -399,6 +399,7 @@ fn to_syntax(language: &str) -> Syntax { match language { "py" => Syntax::python(), "rs" => Syntax::rust(), + "js" => Syntax::javascript(), _ => Syntax::shell(), } } diff --git a/src/editor/syntax/javascript.rs b/src/editor/syntax/javascript.rs index e69de29..7f47934 100644 --- a/src/editor/syntax/javascript.rs +++ b/src/editor/syntax/javascript.rs @@ -0,0 +1,24 @@ +use super::Syntax; +use std::collections::BTreeSet; + +impl Syntax { + pub fn javascript() -> Syntax { + Syntax { + language: "Javascript", + case_sensitive: true, + comment: "//", + comment_multiline: ["/*", "*/"], + keywords: BTreeSet::from([ + "&&", "||", "!", "let", "var", "abstract", "arguments", "await", "break", "case", "catch", "class", "const", "continue", + "debugger", "default", "delete", "do", "else", "enum", "eval", "export", "extends", "final", "finally", "for", "function", + "goto", "if", "implements", "import", "in", "instanceof", "interface", "let", "native", "new", "package", "private", "protected", + "public", "return", "static", "super", "switch", "synchronized", "this","throw", "throws", "transient", "try", "typeof", + "var", "volatile", "while", "with", "yield", + ]), + types: BTreeSet::from([ + "Boolean", "Number", "BigInt", "Undefined", "Null", "String", "Symbol", "byte", "char", "float", "int", "long", "short", "void", + ]), + special: BTreeSet::from(["false", "null", "true"]), + } + } +} diff --git a/src/editor/syntax/mod.rs b/src/editor/syntax/mod.rs index c67ef88..c100d2e 100644 --- a/src/editor/syntax/mod.rs +++ b/src/editor/syntax/mod.rs @@ -1,5 +1,6 @@ #![allow(dead_code)] pub mod asm; +pub mod javascript; pub mod lua; pub mod python; pub mod rust; @@ -18,179 +19,179 @@ type Float = bool; #[derive(Default, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum TokenType { - Comment(MultiLine), - Function, - Keyword, - Literal, - Numeric(Float), - Punctuation(char), - Special, - Str(char), - Type, - Whitespace(char), - #[default] - Unknown, + Comment(MultiLine), + Function, + Keyword, + Literal, + Numeric(Float), + Punctuation(char), + Special, + Str(char), + Type, + Whitespace(char), + #[default] + Unknown, } impl std::fmt::Debug for TokenType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut name = String::new(); - match &self { - TokenType::Comment(multiline) => { - name.push_str("Comment"); - { - if *multiline { - name.push_str(" MultiLine"); - } else { - name.push_str(" SingleLine"); - } - } - } - TokenType::Function => name.push_str("Function"), - TokenType::Keyword => name.push_str("Keyword"), - TokenType::Literal => name.push_str("Literal"), - TokenType::Numeric(float) => { - name.push_str("Numeric"); - if *float { - name.push_str(" Float"); - } else { - name.push_str(" Integer"); - } - } - TokenType::Punctuation(_) => name.push_str("Punctuation"), - TokenType::Special => name.push_str("Special"), - TokenType::Str(quote) => { - name.push_str("Str "); - name.push(*quote); - } - TokenType::Type => name.push_str("Type"), - TokenType::Whitespace(c) => { - name.push_str("Whitespace"); - match c { - ' ' => name.push_str(" Space"), - '\t' => name.push_str(" Tab"), - '\n' => name.push_str(" New Line"), - _ => (), - }; - } - TokenType::Unknown => name.push_str("Unknown"), - }; - write!(f, "{name}") - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut name = String::new(); + match &self { + TokenType::Comment(multiline) => { + name.push_str("Comment"); + { + if *multiline { + name.push_str(" MultiLine"); + } else { + name.push_str(" SingleLine"); + } + } + } + TokenType::Function => name.push_str("Function"), + TokenType::Keyword => name.push_str("Keyword"), + TokenType::Literal => name.push_str("Literal"), + TokenType::Numeric(float) => { + name.push_str("Numeric"); + if *float { + name.push_str(" Float"); + } else { + name.push_str(" Integer"); + } + } + TokenType::Punctuation(_) => name.push_str("Punctuation"), + TokenType::Special => name.push_str("Special"), + TokenType::Str(quote) => { + name.push_str("Str "); + name.push(*quote); + } + TokenType::Type => name.push_str("Type"), + TokenType::Whitespace(c) => { + name.push_str("Whitespace"); + match c { + ' ' => name.push_str(" Space"), + '\t' => name.push_str(" Tab"), + '\n' => name.push_str(" New Line"), + _ => (), + }; + } + TokenType::Unknown => name.push_str("Unknown"), + }; + write!(f, "{name}") + } } impl From for TokenType { - fn from(c: char) -> Self { - match c { - c if c.is_whitespace() => TokenType::Whitespace(c), - c if QUOTES.contains(&c) => TokenType::Str(c), - c if c.is_numeric() => TokenType::Numeric(false), - c if c.is_alphabetic() || SEPARATORS.contains(&c) => TokenType::Literal, - c if c.is_ascii_punctuation() => TokenType::Punctuation(c), - _ => TokenType::Unknown, - } - } + fn from(c: char) -> Self { + match c { + c if c.is_whitespace() => TokenType::Whitespace(c), + c if QUOTES.contains(&c) => TokenType::Str(c), + c if c.is_numeric() => TokenType::Numeric(false), + c if c.is_alphabetic() || SEPARATORS.contains(&c) => TokenType::Literal, + c if c.is_ascii_punctuation() => TokenType::Punctuation(c), + _ => TokenType::Unknown, + } + } } #[derive(Clone, Debug, PartialEq)] /// Rules for highlighting. pub struct Syntax { - pub language: &'static str, - pub case_sensitive: bool, - pub comment: &'static str, - pub comment_multiline: [&'static str; 2], - pub keywords: BTreeSet<&'static str>, - pub types: BTreeSet<&'static str>, - pub special: BTreeSet<&'static str>, + pub language: &'static str, + pub case_sensitive: bool, + pub comment: &'static str, + pub comment_multiline: [&'static str; 2], + pub keywords: BTreeSet<&'static str>, + pub types: BTreeSet<&'static str>, + pub special: BTreeSet<&'static str>, } impl Default for Syntax { - fn default() -> Self { - Syntax::rust() - } + fn default() -> Self { + Syntax::rust() + } } impl Hash for Syntax { - fn hash(&self, state: &mut H) { - self.language.hash(state); - } + fn hash(&self, state: &mut H) { + self.language.hash(state); + } } impl Syntax { - pub fn new(language: &'static str) -> Self { - Syntax { - language, - ..Default::default() - } - } - pub fn with_case_sensitive(self, case_sensitive: bool) -> Self { - Syntax { - case_sensitive, - ..self - } - } - pub fn with_comment(self, comment: &'static str) -> Self { - Syntax { comment, ..self } - } - pub fn with_comment_multiline(self, comment_multiline: [&'static str; 2]) -> Self { - Syntax { - comment_multiline, - ..self - } - } - pub fn with_keywords>>(self, keywords: T) -> Self { - Syntax { - keywords: keywords.into(), - ..self - } - } - pub fn with_types>>(self, types: T) -> Self { - Syntax { - types: types.into(), - ..self - } - } - pub fn with_special>>(self, special: T) -> Self { - Syntax { - special: special.into(), - ..self - } - } + pub fn new(language: &'static str) -> Self { + Syntax { + language, + ..Default::default() + } + } + pub fn with_case_sensitive(self, case_sensitive: bool) -> Self { + Syntax { + case_sensitive, + ..self + } + } + pub fn with_comment(self, comment: &'static str) -> Self { + Syntax { comment, ..self } + } + pub fn with_comment_multiline(self, comment_multiline: [&'static str; 2]) -> Self { + Syntax { + comment_multiline, + ..self + } + } + pub fn with_keywords>>(self, keywords: T) -> Self { + Syntax { + keywords: keywords.into(), + ..self + } + } + pub fn with_types>>(self, types: T) -> Self { + Syntax { + types: types.into(), + ..self + } + } + pub fn with_special>>(self, special: T) -> Self { + Syntax { + special: special.into(), + ..self + } + } - pub fn language(&self) -> &str { - self.language - } - pub fn comment(&self) -> &str { - self.comment - } - pub fn is_keyword(&self, word: &str) -> bool { - if self.case_sensitive { - self.keywords.contains(&word) - } else { - self.keywords.contains(word.to_ascii_uppercase().as_str()) - } - } - pub fn is_type(&self, word: &str) -> bool { - if self.case_sensitive { - self.types.contains(&word) - } else { - self.types.contains(word.to_ascii_uppercase().as_str()) - } - } - pub fn is_special(&self, word: &str) -> bool { - if self.case_sensitive { - self.special.contains(&word) - } else { - self.special.contains(word.to_ascii_uppercase().as_str()) - } - } + pub fn language(&self) -> &str { + self.language + } + pub fn comment(&self) -> &str { + self.comment + } + pub fn is_keyword(&self, word: &str) -> bool { + if self.case_sensitive { + self.keywords.contains(&word) + } else { + self.keywords.contains(word.to_ascii_uppercase().as_str()) + } + } + pub fn is_type(&self, word: &str) -> bool { + if self.case_sensitive { + self.types.contains(&word) + } else { + self.types.contains(word.to_ascii_uppercase().as_str()) + } + } + pub fn is_special(&self, word: &str) -> bool { + if self.case_sensitive { + self.special.contains(&word) + } else { + self.special.contains(word.to_ascii_uppercase().as_str()) + } + } } impl Syntax { - pub fn simple(comment: &'static str) -> Self { - Syntax { - language: "", - case_sensitive: false, - comment, - comment_multiline: [comment; 2], - keywords: BTreeSet::new(), - types: BTreeSet::new(), - special: BTreeSet::new(), - } - } + pub fn simple(comment: &'static str) -> Self { + Syntax { + language: "", + case_sensitive: false, + comment, + comment_multiline: [comment; 2], + keywords: BTreeSet::new(), + types: BTreeSet::new(), + special: BTreeSet::new(), + } + } } diff --git a/src/sub_windows/shortcuts.rs b/src/sub_windows/shortcuts.rs index 9b4869c..1151924 100644 --- a/src/sub_windows/shortcuts.rs +++ b/src/sub_windows/shortcuts.rs @@ -1,42 +1,44 @@ use eframe::egui; pub struct ShortcutsWindow { - pub visible: bool, + pub visible: bool, } impl ShortcutsWindow { - pub fn new() -> Self { - Self { visible: false } - } + pub fn new() -> Self { + Self { visible: false } + } - pub fn show(&mut self, ctx: &egui::Context) { - let mut visible = self.visible; - egui::Window::new("Shortcuts") - .open(&mut visible) - .vscroll(true) - .hscroll(true) - .show(ctx, |ui| self.ui(ui)); - self.visible = self.visible && visible; - } + pub fn show(&mut self, ctx: &egui::Context) { + let mut visible = self.visible; + egui::Window::new("Shortcuts") + .open(&mut visible) + .vscroll(true) + .hscroll(true) + .show(ctx, |ui| self.ui(ui)); + self.visible = self.visible && visible; + } - fn ui(&mut self, ui: &mut egui::Ui) { - ui.set_min_width(250.0); - ui.label("Ctrl+S : save file"); - ui.label("Ctrl+Shift+S : save file as"); - ui.label("Ctrl+R : reload file"); - ui.separator(); - ui.label("Ctrl+F : open search window"); - ui.separator(); - ui.label("Ctrl+Z : undo"); - ui.label("Ctrl+Y : redo"); - ui.label("Tab on selection : add indent of selection"); - ui.label("Shift+Tab on selection : remove indent of selection"); - ui.label("Ctrl+E : comment selection"); - ui.separator(); - ui.label("Alt+Arrows : move between tabs"); - ui.separator(); - ui.label("Enter (project_mode) : edit item"); - ui.label("Arrows (project_mode) : change selected item"); - ui.label("Shift+Arrows (project_mode) : move selected item"); - } + fn ui(&mut self, ui: &mut egui::Ui) { + ui.set_min_width(250.0); + ui.label("Ctrl+S : save file"); + ui.label("Ctrl+Shift+S : save file as"); + ui.label("Ctrl+R : reload file"); + ui.separator(); + ui.label("Ctrl+F : open search window"); + ui.separator(); + ui.label("Ctrl+T : reload tree"); + ui.separator(); + ui.label("Ctrl+Z : undo"); + ui.label("Ctrl+Y : redo"); + ui.label("Tab on selection : add indent of selection"); + ui.label("Shift+Tab on selection : remove indent of selection"); + ui.label("Ctrl+E : comment selection"); + ui.separator(); + ui.label("Alt+Arrows : move between tabs"); + ui.separator(); + ui.label("Enter (project_mode) : edit item"); + ui.label("Arrows (project_mode) : change selected item"); + ui.label("Shift+Arrows (project_mode) : move selected item"); + } }