JS Repl: Add live syntax highlighting

This patchset adds live syntax highlighting to the js repl.
It is turned off by default and can be enabled via the -s flag.
This commit is contained in:
AnotherTest 2020-04-05 18:33:12 +04:30 committed by Andreas Kling
parent 7b54274ac5
commit d077637fd6
Notes: sideshowbarker 2024-07-19 07:53:01 +09:00

View file

@ -350,6 +350,7 @@ int main(int argc, char** argv)
{
bool gc_on_every_allocation = false;
bool print_last_result = false;
bool syntax_highlight = false;
bool test_mode = false;
const char* script_path = nullptr;
@ -357,6 +358,7 @@ int main(int argc, char** argv)
args_parser.add_option(dump_ast, "Dump the AST", "dump-ast", 'A');
args_parser.add_option(print_last_result, "Print last result", "print-last-result", 'l');
args_parser.add_option(gc_on_every_allocation, "GC on every allocation", "gc-on-every-allocation", 'g');
args_parser.add_option(syntax_highlight, "Enable live syntax highlighting", "syntax-highlight", 's');
args_parser.add_option(test_mode, "Run the interpretter with added functionality for the test harness", "test-mode", 't');
args_parser.add_positional_argument(script_path, "Path to script file", "script", Core::ArgsParser::Required::No);
args_parser.parse(argc, argv);
@ -371,6 +373,126 @@ int main(int argc, char** argv)
editor = make<Line::Editor>();
editor->initialize();
if (syntax_highlight)
editor->on_display_refresh = [](Line::Editor& editor) {
editor.strip_styles();
StringBuilder builder;
builder.append({ editor.buffer().data(), editor.buffer().size() });
// FIXME: The lexer returns weird position information without this
builder.append(" ");
String str = builder.build();
JS::Lexer lexer(str, false);
for (JS::Token token = lexer.next(); token.type() != JS::TokenType::Eof; token = lexer.next()) {
auto length = token.value().length();
auto start = token.line_column() - 2;
auto end = start + length;
switch (token.type()) {
case JS::TokenType::Invalid:
case JS::TokenType::Eof:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Red), Line::Style::Underline });
break;
case JS::TokenType::NumericLiteral:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Magenta) });
break;
case JS::TokenType::StringLiteral:
case JS::TokenType::RegexLiteral:
case JS::TokenType::UnterminatedStringLiteral:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Red) });
break;
case JS::TokenType::BracketClose:
case JS::TokenType::BracketOpen:
case JS::TokenType::Caret:
case JS::TokenType::Comma:
case JS::TokenType::CurlyClose:
case JS::TokenType::CurlyOpen:
case JS::TokenType::ParenClose:
case JS::TokenType::ParenOpen:
case JS::TokenType::Semicolon:
case JS::TokenType::Period:
break;
case JS::TokenType::Ampersand:
case JS::TokenType::AmpersandEquals:
case JS::TokenType::Asterisk:
case JS::TokenType::AsteriskAsteriskEquals:
case JS::TokenType::AsteriskEquals:
case JS::TokenType::DoubleAmpersand:
case JS::TokenType::DoubleAsterisk:
case JS::TokenType::DoublePipe:
case JS::TokenType::DoubleQuestionMark:
case JS::TokenType::Equals:
case JS::TokenType::EqualsEquals:
case JS::TokenType::EqualsEqualsEquals:
case JS::TokenType::ExclamationMark:
case JS::TokenType::ExclamationMarkEquals:
case JS::TokenType::ExclamationMarkEqualsEquals:
case JS::TokenType::GreaterThan:
case JS::TokenType::GreaterThanEquals:
case JS::TokenType::LessThan:
case JS::TokenType::LessThanEquals:
case JS::TokenType::Minus:
case JS::TokenType::MinusEquals:
case JS::TokenType::MinusMinus:
case JS::TokenType::Percent:
case JS::TokenType::PercentEquals:
case JS::TokenType::Pipe:
case JS::TokenType::PipeEquals:
case JS::TokenType::Plus:
case JS::TokenType::PlusEquals:
case JS::TokenType::PlusPlus:
case JS::TokenType::QuestionMark:
case JS::TokenType::QuestionMarkPeriod:
case JS::TokenType::ShiftLeft:
case JS::TokenType::ShiftLeftEquals:
case JS::TokenType::ShiftRight:
case JS::TokenType::ShiftRightEquals:
case JS::TokenType::Slash:
case JS::TokenType::SlashEquals:
case JS::TokenType::Tilde:
case JS::TokenType::UnsignedShiftRight:
case JS::TokenType::UnsignedShiftRightEquals:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Magenta) });
break;
case JS::TokenType::NullLiteral:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Yellow), Line::Style::Bold });
break;
case JS::TokenType::BoolLiteral:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Green), Line::Style::Bold });
break;
case JS::TokenType::Class:
case JS::TokenType::Const:
case JS::TokenType::Delete:
case JS::TokenType::Function:
case JS::TokenType::In:
case JS::TokenType::Instanceof:
case JS::TokenType::Interface:
case JS::TokenType::Let:
case JS::TokenType::New:
case JS::TokenType::Typeof:
case JS::TokenType::Var:
case JS::TokenType::Void:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Blue), Line::Style::Bold });
break;
case JS::TokenType::Await:
case JS::TokenType::Catch:
case JS::TokenType::Do:
case JS::TokenType::Else:
case JS::TokenType::Finally:
case JS::TokenType::For:
case JS::TokenType::If:
case JS::TokenType::Return:
case JS::TokenType::Try:
case JS::TokenType::While:
case JS::TokenType::Yield:
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Cyan), Line::Style::Italic });
break;
case JS::TokenType::Identifier:
default:
break;
}
}
};
repl(*interpreter);
} else {
auto interpreter = JS::Interpreter::create<JS::GlobalObject>();