Code colors: Rust, JavaScript, Ruby, Haskell, Erlang presets; TOML and CMake comments follow code (Ely R2.12)
This commit is contained in:
2 files changed
+134
-157
No files matched your search
+106
-157
@@ -11,182 +11,134 @@ pub(crate) struct Syntax {
|
||||
pub constants: &'static [&'static str],
|
||||
}
|
||||
|
||||
/// C, Rust, JavaScript, Go, Java, Swift and kin.
|
||||
pub(crate) const C_LIKE: Syntax = Syntax {
|
||||
comment: "//",
|
||||
word_comment: false,
|
||||
keywords: &[
|
||||
"as",
|
||||
"async",
|
||||
"await",
|
||||
"break",
|
||||
"case",
|
||||
"catch",
|
||||
"class",
|
||||
"const",
|
||||
"continue",
|
||||
"do",
|
||||
"else",
|
||||
"enum",
|
||||
"export",
|
||||
"extends",
|
||||
"fn",
|
||||
"for",
|
||||
"from",
|
||||
"func",
|
||||
"function",
|
||||
"if",
|
||||
"impl",
|
||||
"import",
|
||||
"in",
|
||||
"interface",
|
||||
"let",
|
||||
"match",
|
||||
"mut",
|
||||
"new",
|
||||
"package",
|
||||
"pub",
|
||||
"return",
|
||||
"static",
|
||||
"struct",
|
||||
"switch",
|
||||
"throw",
|
||||
"trait",
|
||||
"try",
|
||||
"type",
|
||||
"use",
|
||||
"var",
|
||||
"where",
|
||||
"while",
|
||||
"yield",
|
||||
],
|
||||
constants: &[
|
||||
"false",
|
||||
"nil",
|
||||
"null",
|
||||
"self",
|
||||
"Self",
|
||||
"this",
|
||||
"true",
|
||||
"undefined",
|
||||
"None",
|
||||
"Some",
|
||||
],
|
||||
};
|
||||
impl Syntax {
|
||||
const fn new(
|
||||
comment: &'static str,
|
||||
keywords: &'static [&'static str],
|
||||
constants: &'static [&'static str],
|
||||
) -> Self {
|
||||
Self {
|
||||
comment,
|
||||
word_comment: false,
|
||||
keywords,
|
||||
constants,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PYTHON: Syntax = Syntax {
|
||||
comment: "#",
|
||||
word_comment: false,
|
||||
keywords: &[
|
||||
"and", "as", "assert", "async", "await", "break", "class", "continue", "def", "del",
|
||||
"elif", "else", "except", "finally", "for", "from", "global", "if", "import", "in", "is",
|
||||
"lambda", "nonlocal", "not", "or", "pass", "raise", "return", "try", "while", "with",
|
||||
"yield",
|
||||
],
|
||||
constants: &["True", "False", "None", "self"],
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
const RUST: Syntax = Syntax::new("//", &[
|
||||
"as", "async", "await", "break", "const", "continue", "crate", "dyn", "else", "enum", "extern",
|
||||
"fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref",
|
||||
"return", "static", "struct", "super", "trait", "type", "unsafe", "use", "where", "while",
|
||||
], &["true", "false", "self", "Self", "None", "Some", "Ok", "Err"]);
|
||||
|
||||
const SHELL: Syntax = Syntax {
|
||||
comment: "#",
|
||||
#[rustfmt::skip]
|
||||
const SCRIPT: Syntax = Syntax::new("//", &[
|
||||
"as", "async", "await", "break", "case", "catch", "class", "const", "continue", "default",
|
||||
"delete", "do", "else", "export", "extends", "finally", "for", "from", "function", "if",
|
||||
"import", "in", "instanceof", "interface", "let", "new", "of", "return", "static", "switch",
|
||||
"throw", "try", "type", "typeof", "var", "void", "while", "yield",
|
||||
], &["true", "false", "null", "undefined", "this", "NaN"]);
|
||||
|
||||
/// C, C++, Java, Go, Swift, Kotlin, C# and kin.
|
||||
#[rustfmt::skip]
|
||||
pub(crate) const C_LIKE: Syntax = Syntax::new("//", &[
|
||||
"break", "case", "catch", "class", "const", "continue", "default", "defer", "do", "else",
|
||||
"enum", "extends", "final", "for", "func", "fun", "go", "if", "implements", "import",
|
||||
"interface", "let", "namespace", "new", "package", "private", "protected", "public", "return",
|
||||
"static", "struct", "switch", "throw", "try", "typedef", "union", "using", "val", "var",
|
||||
"void", "while",
|
||||
], &["true", "false", "null", "nil", "nullptr", "this", "self"]);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const PYTHON: Syntax = Syntax::new("#", &[
|
||||
"and", "as", "assert", "async", "await", "break", "class", "continue", "def", "del", "elif",
|
||||
"else", "except", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda",
|
||||
"nonlocal", "not", "or", "pass", "raise", "return", "try", "while", "with", "yield",
|
||||
], &["True", "False", "None", "self"]);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const RUBY: Syntax = Syntax::new("#", &[
|
||||
"alias", "and", "begin", "break", "case", "class", "def", "do", "else", "elsif", "end",
|
||||
"ensure", "for", "if", "in", "module", "next", "not", "or", "redo", "rescue", "retry",
|
||||
"return", "then", "unless", "until", "when", "while", "yield",
|
||||
], &["true", "false", "nil", "self"]);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const SHELL: Syntax = Syntax { word_comment: true, ..Syntax::new("#", &[
|
||||
"case", "do", "done", "elif", "else", "esac", "export", "fi", "for", "function", "if", "in",
|
||||
"local", "return", "then", "until", "while",
|
||||
], &["true", "false"]) };
|
||||
|
||||
/// `#` languages, CMake and Make: no word list.
|
||||
const HASH: Syntax = Syntax::new("#", &[], &["true", "false"]);
|
||||
|
||||
/// YAML, whose `#` starts a comment only after a space.
|
||||
const YAML: Syntax = Syntax {
|
||||
word_comment: true,
|
||||
keywords: &[
|
||||
"case", "do", "done", "elif", "else", "esac", "export", "fi", "for", "function", "if",
|
||||
"in", "local", "return", "then", "until", "while",
|
||||
],
|
||||
constants: &["true", "false"],
|
||||
..Syntax::new("#", &[], &["true", "false", "null", "yes", "no"])
|
||||
};
|
||||
|
||||
/// TOML, YAML, INI and other settings: keys are not words.
|
||||
const SETTINGS: Syntax = Syntax {
|
||||
comment: "#",
|
||||
word_comment: true,
|
||||
keywords: &[],
|
||||
constants: &["true", "false", "null", "yes", "no", "on", "off"],
|
||||
};
|
||||
const INI: Syntax = Syntax::new(";", &[], &["true", "false", "yes", "no", "on", "off"]);
|
||||
|
||||
const INI: Syntax = Syntax {
|
||||
comment: ";",
|
||||
..SETTINGS
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
const SQL: Syntax = Syntax::new("--", &[
|
||||
"SELECT", "FROM", "WHERE", "JOIN", "LEFT", "RIGHT", "INNER", "OUTER", "ON", "AND", "OR",
|
||||
"NOT", "AS", "GROUP", "BY", "ORDER", "HAVING", "LIMIT", "OFFSET", "INSERT", "INTO", "VALUES",
|
||||
"UPDATE", "SET", "DELETE", "CREATE", "TABLE", "INDEX", "DROP", "ALTER", "DESC", "ASC",
|
||||
"DISTINCT", "UNION", "WITH", "CASE", "WHEN", "THEN", "ELSE", "END", "IS", "IN", "LIKE",
|
||||
"BETWEEN", "EXISTS",
|
||||
], &["NULL", "TRUE", "FALSE"]);
|
||||
|
||||
const SQL: Syntax = Syntax {
|
||||
comment: "--",
|
||||
word_comment: false,
|
||||
keywords: &[
|
||||
"SELECT", "FROM", "WHERE", "JOIN", "LEFT", "RIGHT", "INNER", "OUTER", "ON", "AND", "OR",
|
||||
"NOT", "AS", "GROUP", "BY", "ORDER", "HAVING", "LIMIT", "OFFSET", "INSERT", "INTO",
|
||||
"VALUES", "UPDATE", "SET", "DELETE", "CREATE", "TABLE", "INDEX", "DROP", "ALTER", "DESC",
|
||||
"ASC", "DISTINCT", "UNION", "WITH", "CASE", "WHEN", "THEN", "ELSE", "END", "IS", "IN",
|
||||
"LIKE", "BETWEEN", "EXISTS",
|
||||
],
|
||||
constants: &["NULL", "TRUE", "FALSE"],
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
const LUA: Syntax = Syntax::new("--", &[
|
||||
"and", "break", "do", "else", "elseif", "end", "for", "function", "goto", "if", "in", "local",
|
||||
"not", "or", "repeat", "return", "then", "until", "while",
|
||||
], &["true", "false", "nil"]);
|
||||
|
||||
const LUA: Syntax = Syntax {
|
||||
comment: "--",
|
||||
word_comment: false,
|
||||
keywords: &[
|
||||
"and", "break", "do", "else", "elseif", "end", "for", "function", "goto", "if", "in",
|
||||
"local", "not", "or", "repeat", "return", "then", "until", "while",
|
||||
],
|
||||
constants: &["true", "false", "nil"],
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
const HASKELL: Syntax = Syntax::new("--", &[
|
||||
"case", "class", "data", "deriving", "do", "else", "if", "import", "in", "instance", "let",
|
||||
"module", "newtype", "of", "then", "type", "where",
|
||||
], &["True", "False"]);
|
||||
|
||||
const LISP: Syntax = Syntax {
|
||||
comment: ";",
|
||||
word_comment: false,
|
||||
keywords: &[
|
||||
"defun", "defn", "define", "lambda", "let", "if", "cond", "quote",
|
||||
],
|
||||
constants: &["nil", "t", "true", "false"],
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
const LISP: Syntax = Syntax::new(";", &[
|
||||
"defun", "defn", "define", "lambda", "let", "if", "cond",
|
||||
], &["nil", "t"]);
|
||||
|
||||
/// Ruby, Perl, CMake and other `#` languages.
|
||||
const HASH: Syntax = Syntax {
|
||||
comment: "#",
|
||||
..C_LIKE
|
||||
};
|
||||
#[rustfmt::skip]
|
||||
const ERLANG: Syntax = Syntax::new("%", &[
|
||||
"after", "begin", "case", "catch", "end", "fun", "if", "of", "receive", "try", "when",
|
||||
], &["true", "false"]);
|
||||
|
||||
const TEX: Syntax = Syntax {
|
||||
comment: "%",
|
||||
word_comment: false,
|
||||
keywords: &[],
|
||||
constants: &[],
|
||||
};
|
||||
const TEX: Syntax = Syntax::new("%", &[], &[]);
|
||||
|
||||
/// Extensions of prose and plain text, which read plain.
|
||||
#[rustfmt::skip]
|
||||
const PROSE: &[&str] = &[
|
||||
"md", "markdown", "mdown", "mkd", "txt", "text", "rst", "adoc", "asciidoc", "org", "csv",
|
||||
"tsv", "log",
|
||||
"md", "markdown", "mdown", "mkd", "txt", "text", "rst", "adoc", "asciidoc", "org", "csv", "tsv",
|
||||
"log",
|
||||
];
|
||||
|
||||
/// Languages by extension; any other code reads C-like.
|
||||
#[rustfmt::skip]
|
||||
const BY_EXTENSION: &[(&Syntax, &[&str])] = &[
|
||||
(&RUST, &["rs"]),
|
||||
(&SCRIPT, &["js", "mjs", "cjs", "jsx", "ts", "tsx", "mts"]),
|
||||
(&PYTHON, &["py", "pyi", "pyw"]),
|
||||
(&RUBY, &["rb", "rake", "gemspec"]),
|
||||
(&SHELL, &["sh", "bash", "zsh", "fish", "ksh"]),
|
||||
(
|
||||
&HASH,
|
||||
&[
|
||||
"rb", "pl", "r", "cmake", "mk", "nix", "ex", "exs", "jl", "nim", "cr", "tcl", "ps1",
|
||||
],
|
||||
),
|
||||
(
|
||||
&SETTINGS,
|
||||
&[
|
||||
"toml",
|
||||
"yaml",
|
||||
"yml",
|
||||
"conf",
|
||||
"cfg",
|
||||
"gitignore",
|
||||
"env",
|
||||
"properties",
|
||||
],
|
||||
),
|
||||
(&HASH, &["pl", "r", "cmake", "mk", "nix", "ex", "exs", "jl", "nim", "cr", "tcl", "ps1",
|
||||
"toml", "conf", "cfg", "gitignore", "env", "properties"]),
|
||||
(&YAML, &["yaml", "yml"]),
|
||||
(&INI, &["ini"]),
|
||||
(&SQL, &["sql"]),
|
||||
(&LUA, &["lua"]),
|
||||
(&HASKELL, &["hs", "lhs", "elm"]),
|
||||
(&LISP, &["clj", "cljs", "lisp", "el", "scm"]),
|
||||
(&ERLANG, &["erl", "hrl"]),
|
||||
(&TEX, &["tex", "sty", "bib"]),
|
||||
];
|
||||
|
||||
@@ -195,13 +147,10 @@ pub(crate) fn syntax_of(path: &str) -> Option<&'static Syntax> {
|
||||
let name = path.rsplit_once('/').map_or(path, |(_, name)| name);
|
||||
// Named files first: CMakeLists.txt is not prose.
|
||||
match name {
|
||||
"Makefile" | "GNUmakefile" | "Dockerfile" | "CMakeLists.txt" => return Some(&SHELL),
|
||||
"Makefile" | "GNUmakefile" | "Dockerfile" | "CMakeLists.txt" => return Some(&HASH),
|
||||
_ => {}
|
||||
}
|
||||
let ext = match name.rsplit_once('.') {
|
||||
Some((_, ext)) => ext.to_ascii_lowercase(),
|
||||
None => return None,
|
||||
};
|
||||
let ext = name.rsplit_once('.')?.1.to_ascii_lowercase();
|
||||
if PROSE.contains(&ext.as_str()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -184,6 +184,34 @@ mod tests {
|
||||
Some(syntax.keyword),
|
||||
"a TOML key"
|
||||
);
|
||||
// Words belong to their own language.
|
||||
assert_ne!(
|
||||
color("let from = 42;", "main.rs", cx)[1].1,
|
||||
Some(syntax.keyword),
|
||||
"Rust's from"
|
||||
);
|
||||
assert_eq!(
|
||||
color("def hello", "a.rb", cx)[0].1,
|
||||
Some(syntax.keyword),
|
||||
"Ruby's def"
|
||||
);
|
||||
assert_eq!(
|
||||
color("-- return 42", "Main.hs", cx),
|
||||
[(0..12, Some(syntax.comment))]
|
||||
);
|
||||
assert_eq!(
|
||||
color("% return 42", "main.erl", cx),
|
||||
[(0..11, Some(syntax.comment))]
|
||||
);
|
||||
// A comment may follow code at once outside Shell.
|
||||
assert_eq!(
|
||||
color("answer = 42# return 99", "config.toml", cx).last(),
|
||||
Some(&(11..22, Some(syntax.comment)))
|
||||
);
|
||||
assert_eq!(
|
||||
color("set(x 1)# return 42", "CMakeLists.txt", cx).last(),
|
||||
Some(&(8..19, Some(syntax.comment)))
|
||||
);
|
||||
// Shell comments start words only.
|
||||
let shell = color("echo foo#bar 42", "run.sh", cx);
|
||||
assert!(
|
||||
|
||||
Reference in new issue
Block a user