1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 06:37:44 +00:00

JS repl: Fix indentation when a line starts with '})]'

This commit is contained in:
AnotherTest 2020-04-09 08:00:45 +04:30 committed by Andreas Kling
parent da9335dbec
commit 6545a74743

View file

@ -61,20 +61,27 @@ private:
bool dump_ast = false; bool dump_ast = false;
static OwnPtr<Line::Editor> editor; static OwnPtr<Line::Editor> editor;
static int repl_line_level = 0;
static String prompt_for_level(int level)
{
static StringBuilder prompt_builder;
prompt_builder.clear();
prompt_builder.append("> ");
for (auto i = 0; i < level; ++i)
prompt_builder.append(" ");
return prompt_builder.build();
}
String read_next_piece() String read_next_piece()
{ {
StringBuilder piece; StringBuilder piece;
int level = 0;
StringBuilder prompt_builder;
do { do {
prompt_builder.clear();
prompt_builder.append("> ");
for (auto i = 0; i < level; ++i)
prompt_builder.append(" ");
String line = editor->get_line(prompt_builder.build()); String line = editor->get_line(prompt_for_level(repl_line_level));
editor->add_to_history(line); editor->add_to_history(line);
piece.append(line); piece.append(line);
@ -85,18 +92,18 @@ String read_next_piece()
case JS::TokenType::BracketOpen: case JS::TokenType::BracketOpen:
case JS::TokenType::CurlyOpen: case JS::TokenType::CurlyOpen:
case JS::TokenType::ParenOpen: case JS::TokenType::ParenOpen:
level++; repl_line_level++;
break; break;
case JS::TokenType::BracketClose: case JS::TokenType::BracketClose:
case JS::TokenType::CurlyClose: case JS::TokenType::CurlyClose:
case JS::TokenType::ParenClose: case JS::TokenType::ParenClose:
level--; repl_line_level--;
break; break;
default: default:
break; break;
} }
} }
} while (level > 0); } while (repl_line_level > 0);
return piece.to_string(); return piece.to_string();
} }
@ -390,126 +397,141 @@ int main(int argc, char** argv)
editor = make<Line::Editor>(); editor = make<Line::Editor>();
editor->initialize(); editor->initialize();
if (syntax_highlight) editor->on_display_refresh = [syntax_highlight](Line::Editor& editor) {
editor->on_display_refresh = [](Line::Editor& editor) { auto stylize = [&](Line::Span span, Line::Style styles) {
editor.strip_styles(); if (syntax_highlight)
StringBuilder builder; editor.stylize(span, styles);
builder.append({ editor.buffer().data(), editor.buffer().size() }); };
// FIXME: The lexer returns weird position information without this editor.strip_styles();
builder.append(" "); StringBuilder builder;
String str = builder.build(); 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); size_t open_indents = repl_line_level;
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()) { JS::Lexer lexer(str, false);
case JS::TokenType::Invalid: bool indenters_starting_line = true;
case JS::TokenType::Eof: for (JS::Token token = lexer.next(); token.type() != JS::TokenType::Eof; token = lexer.next()) {
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Red), Line::Style::Underline }); auto length = token.value().length();
break; auto start = token.line_column() - 2;
case JS::TokenType::NumericLiteral: auto end = start + length;
editor.stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Magenta) }); if (indenters_starting_line) {
break; if (token.type() != JS::TokenType::ParenClose && token.type() != JS::TokenType::BracketClose && token.type() != JS::TokenType::CurlyClose) {
case JS::TokenType::StringLiteral: indenters_starting_line = false;
case JS::TokenType::RegexLiteral: } else {
case JS::TokenType::UnterminatedStringLiteral: --open_indents;
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;
} }
} }
};
switch (token.type()) {
case JS::TokenType::Invalid:
case JS::TokenType::Eof:
stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Red), Line::Style::Underline });
break;
case JS::TokenType::NumericLiteral:
stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Magenta) });
break;
case JS::TokenType::StringLiteral:
case JS::TokenType::RegexLiteral:
case JS::TokenType::UnterminatedStringLiteral:
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:
stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Magenta) });
break;
case JS::TokenType::NullLiteral:
stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Yellow), Line::Style::Bold });
break;
case JS::TokenType::BoolLiteral:
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:
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:
stylize({ start, end }, { Line::Style::Foreground(Line::Style::Color::Cyan), Line::Style::Italic });
break;
case JS::TokenType::Identifier:
default:
break;
}
}
editor.set_prompt(prompt_for_level(open_indents));
};
repl(*interpreter); repl(*interpreter);
} else { } else {
auto interpreter = JS::Interpreter::create<JS::GlobalObject>(); auto interpreter = JS::Interpreter::create<JS::GlobalObject>();