Rust编写的JavaScript引擎,该项目是一个试验性质的项目。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.8 KiB

use colored::{Color, Colorize};
use phf::{phf_set, Set};
use regex::{Captures, Regex, Replacer};
use rustyline::{
error::ReadlineError,
highlight::Highlighter,
validate::{MatchingBracketValidator, ValidationContext, ValidationResult, Validator},
Bump rustyline from 10.1.1 to 11.0.0 (#2612) Bumps [rustyline](https://github.com/kkawakam/rustyline) from 10.1.1 to 11.0.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/kkawakam/rustyline/releases">rustyline's releases</a>.</em></p> <blockquote> <h2>11.0.0</h2> <h2>What's Changed</h2> <ul> <li>Refactor listeners by <a href="https://github.com/gwenn"><code>@​gwenn</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/666">kkawakam/rustyline#666</a></li> <li>Introduce History trait by <a href="https://github.com/gwenn"><code>@​gwenn</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/604">kkawakam/rustyline#604</a></li> <li>Fix cargo test --no-default-features by <a href="https://github.com/gwenn"><code>@​gwenn</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/667">kkawakam/rustyline#667</a></li> <li>Don't set height for skim by <a href="https://github.com/figsoda"><code>@​figsoda</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/668">kkawakam/rustyline#668</a></li> <li>Turn off skim's default features by <a href="https://github.com/figsoda"><code>@​figsoda</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/669">kkawakam/rustyline#669</a></li> <li>Add derive feature that reexports rustyline-derive's API by <a href="https://github.com/figsoda"><code>@​figsoda</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/670">kkawakam/rustyline#670</a></li> <li>docs: update branch for wez/wezterm by <a href="https://github.com/LeoDog896"><code>@​LeoDog896</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/674">kkawakam/rustyline#674</a></li> <li>Upgrade to Rust edition 2021 by <a href="https://github.com/gwenn"><code>@​gwenn</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/675">kkawakam/rustyline#675</a></li> <li>Replace memchr::memchr by matches! by <a href="https://github.com/gwenn"><code>@​gwenn</code></a> in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/676">kkawakam/rustyline#676</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/figsoda"><code>@​figsoda</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/668">kkawakam/rustyline#668</a></li> <li><a href="https://github.com/LeoDog896"><code>@​LeoDog896</code></a> made their first contribution in <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/pull/674">kkawakam/rustyline#674</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/kkawakam/rustyline/compare/v10.1.0...v11.0.0">https://github.com/kkawakam/rustyline/compare/v10.1.0...v11.0.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/kkawakam/rustyline/commit/0384654d4274f152897e4fdd8bf8d23c75bf1b95"><code>0384654</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/issues/682">#682</a> from gwenn/11.0.0</li> <li><a href="https://github.com/kkawakam/rustyline/commit/a63a2494c5f60e235a625457d32d22c1cd8c6502"><code>a63a249</code></a> Prepare next release</li> <li><a href="https://github.com/kkawakam/rustyline/commit/36f273901142d7a32791822e7bdff4083095e2b9"><code>36f2739</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/issues/680">#680</a> from figsoda/unsorted</li> <li><a href="https://github.com/kkawakam/rustyline/commit/5486779fef20637127c9534438edd046242a37f2"><code>5486779</code></a> Add FilenameCompleter::complete_path_unsorted</li> <li><a href="https://github.com/kkawakam/rustyline/commit/b71975d9ea826ba8593381f2c95675eada6fc602"><code>b71975d</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/issues/679">#679</a> from figsoda/clone</li> <li><a href="https://github.com/kkawakam/rustyline/commit/792a828c94236db9a783823945e2ff7b09b5140c"><code>792a828</code></a> Implement Clone for Pair</li> <li><a href="https://github.com/kkawakam/rustyline/commit/1986b16a431d7e73f7e9c4b3ce9a2148fce2814a"><code>1986b16</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/issues/676">#676</a> from gwenn/memchr-to-matches</li> <li><a href="https://github.com/kkawakam/rustyline/commit/c75f56de4d70dd743142e8098dfdbea0588c2969"><code>c75f56d</code></a> Replace memchr::memchr by matches!</li> <li><a href="https://github.com/kkawakam/rustyline/commit/45b9e3d3c2dff76f265f720663532aafe0e009b9"><code>45b9e3d</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/kkawakam/rustyline/issues/675">#675</a> from gwenn/edition</li> <li><a href="https://github.com/kkawakam/rustyline/commit/6830d8ae48802e947690e7fa117db71aab02689c"><code>6830d8a</code></a> Fix clippy warning on windows</li> <li>Additional commits viewable in <a href="https://github.com/kkawakam/rustyline/compare/v10.1.1...v11.0.0">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rustyline&package-manager=cargo&previous-version=10.1.1&new-version=11.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Co-authored-by: jedel1043 <jedel0124@gmail.com>
2 years ago
Completer, Helper, Hinter,
};
use std::borrow::Cow::{self, Borrowed};
const STRING_COLOR: Color = Color::Green;
const KEYWORD_COLOR: Color = Color::Yellow;
const PROPERTY_COLOR: Color = Color::Magenta;
const OPERATOR_COLOR: Color = Color::TrueColor {
r: 214,
g: 95,
b: 26,
};
const UNDEFINED_COLOR: Color = Color::TrueColor {
r: 100,
g: 100,
b: 100,
};
const NUMBER_COLOR: Color = Color::TrueColor {
r: 26,
g: 214,
b: 175,
};
const IDENTIFIER_COLOR: Color = Color::TrueColor {
r: 26,
g: 160,
b: 214,
};
const READLINE_COLOR: Color = Color::Cyan;
#[allow(clippy::upper_case_acronyms, clippy::redundant_pub_crate)]
#[derive(Completer, Helper, Hinter)]
pub(crate) struct RLHelper {
highlighter: LineHighlighter,
validator: MatchingBracketValidator,
colored_prompt: String,
}
impl RLHelper {
pub(crate) fn new(prompt: &str) -> Self {
Self {
highlighter: LineHighlighter::new(),
validator: MatchingBracketValidator::new(),
colored_prompt: prompt.color(READLINE_COLOR).bold().to_string(),
}
}
}
impl Validator for RLHelper {
fn validate(
&self,
context: &mut ValidationContext<'_>,
) -> Result<ValidationResult, ReadlineError> {
self.validator.validate(context)
}
fn validate_while_typing(&self) -> bool {
self.validator.validate_while_typing()
}
}
impl Highlighter for RLHelper {
fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
self.highlighter.highlight(line, pos)
}
// Must match signature of Highlighter::highlight_prompt, can't elide lifetimes.
#[allow(single_use_lifetimes)]
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
&'s self,
prompt: &'p str,
default: bool,
) -> Cow<'b, str> {
if default {
Borrowed(&self.colored_prompt)
} else {
Borrowed(prompt)
}
}
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
hint.into()
}
fn highlight_candidate<'c>(
&self,
candidate: &'c str,
_completion: rustyline::CompletionType,
) -> Cow<'c, str> {
self.highlighter.highlight(candidate, 0)
}
fn highlight_char(&self, line: &str, _: usize) -> bool {
!line.is_empty()
}
}
static KEYWORDS: Set<&'static str> = phf_set! {
"break",
"case",
"catch",
"class",
"const",
"continue",
"default",
"delete",
"do",
"else",
"export",
"extends",
"finally",
"for",
"function",
"if",
"import",
"instanceof",
"new",
"return",
"super",
"switch",
"this",
"throw",
"try",
"typeof",
"var",
"void",
"while",
"with",
"yield",
"await",
"enum",
"let",
};
struct LineHighlighter {
regex: Regex,
}
impl LineHighlighter {
fn new() -> Self {
// Precompiles the regex to avoid creating it again after every highlight
let regex = Regex::new(
r#"(?x)
(?P<identifier>\b[$_\p{ID_Start}][$_\p{ID_Continue}\u{200C}\u{200D}]*\b) |
(?P<string_double_quote>"([^"\\]|\\.)*") |
(?P<string_single_quote>'([^'\\]|\\.)*') |
(?P<template_literal>`([^`\\]|\\.)*`) |
(?P<op>[+\-/*%~^!&|=<>;:]) |
(?P<number>0[bB][01](_?[01])*n?|0[oO][0-7](_?[0-7])*n?|0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?|(([0-9](_?[0-9])*\.([0-9](_?[0-9])*)?)|(([0-9](_?[0-9])*)?\.[0-9](_?[0-9])*)|([0-9](_?[0-9])*))([eE][+-]?[0-9](_?[0-9])*)?n?)"#,
).expect("could not compile regular expression");
Self { regex }
}
}
impl Highlighter for LineHighlighter {
fn highlight<'l>(&self, line: &'l str, _: usize) -> Cow<'l, str> {
use std::fmt::Write;
struct Colorizer;
impl Replacer for Colorizer {
// Changing to map_or_else moves the handling of "identifier" after all other kinds,
// which reads worse than this version.
#[allow(clippy::option_if_let_else)]
fn replace_append(&mut self, caps: &Captures<'_>, dst: &mut String) {
let colored = if let Some(cap) = caps.name("identifier") {
let cap = cap.as_str();
let colored = match cap {
"true" | "false" | "null" | "Infinity" | "globalThis" => {
cap.color(PROPERTY_COLOR)
}
"undefined" => cap.color(UNDEFINED_COLOR),
identifier if KEYWORDS.contains(identifier) => {
cap.color(KEYWORD_COLOR).bold()
}
_ => cap.color(IDENTIFIER_COLOR),
};
Some(colored)
} else if let Some(cap) = caps
.name("string_double_quote")
.or_else(|| caps.name("string_single_quote"))
.or_else(|| caps.name("template_literal"))
{
Some(cap.as_str().color(STRING_COLOR))
} else if let Some(cap) = caps.name("op") {
Some(cap.as_str().color(OPERATOR_COLOR))
} else {
caps.name("number")
.map(|cap| cap.as_str().color(NUMBER_COLOR))
};
if let Some(colored) = colored {
write!(dst, "{colored}").expect("could not append data to dst");
} else {
dst.push_str(&caps[0]);
}
}
}
self.regex.replace_all(line, Colorizer)
}
}