mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
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:
parent
7b54274ac5
commit
d077637fd6
Notes:
sideshowbarker
2024-07-19 07:53:01 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/d077637fd6a Pull-request: https://github.com/SerenityOS/serenity/pull/1631 Reviewed-by: https://github.com/awesomekling
1 changed files with 122 additions and 0 deletions
122
Userland/js.cpp
122
Userland/js.cpp
|
@ -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>();
|
||||
|
|
Loading…
Reference in a new issue