From 0511059d604d7544a4af4e8ebd990c755fd1cff2 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Thu, 23 Feb 2023 15:35:57 +0000 Subject: [PATCH] LibJS: Assign folding regions for JS files Each {} block is now treated as a folding region, so that they can be collapsed and expanded in TextEditor, HackStudio, and anywhere else that uses the syntax highlighter. :^) --- .../Libraries/LibJS/SyntaxHighlighter.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Userland/Libraries/LibJS/SyntaxHighlighter.cpp b/Userland/Libraries/LibJS/SyntaxHighlighter.cpp index 0cd788fb8a..2973773967 100644 --- a/Userland/Libraries/LibJS/SyntaxHighlighter.cpp +++ b/Userland/Libraries/LibJS/SyntaxHighlighter.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, the SerenityOS developers. + * Copyright (c) 2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -54,6 +55,7 @@ void SyntaxHighlighter::rehighlight(Palette const& palette) Lexer lexer(text); Vector spans; + Vector folding_regions; GUI::TextPosition position { 0, 0 }; GUI::TextPosition start { 0, 0 }; @@ -92,16 +94,39 @@ void SyntaxHighlighter::rehighlight(Palette const& palette) span.range.end().line(), span.range.end().column()); }; + struct TokenData { + Token token; + GUI::TextRange range; + }; + Vector folding_region_start_tokens; + bool was_eof = false; for (auto token = lexer.next(); !was_eof; token = lexer.next()) { append_token(token.trivia(), token, true); + + auto token_start_position = position; append_token(token.value(), token, false); if (token.type() == TokenType::Eof) was_eof = true; + + // Create folding regions for {} blocks + if (token.type() == TokenType::CurlyOpen) { + folding_region_start_tokens.append({ .token = token, + .range = { token_start_position, position } }); + } else if (token.type() == TokenType::CurlyClose) { + if (!folding_region_start_tokens.is_empty()) { + auto curly_open = folding_region_start_tokens.take_last(); + GUI::TextDocumentFoldingRegion region; + region.range.set_start(curly_open.range.end()); + region.range.set_end(token_start_position); + folding_regions.append(region); + } + } } m_client->do_set_spans(move(spans)); + m_client->do_set_folding_regions(move(folding_regions)); m_has_brace_buddies = false; highlight_matching_token_pair();