Fixed an old bug in syntax highlighting that sometimes the first line of the file was not correctly highlighted.

Added Svelte syntax highlighting support.
Improved CSS syntax highlighting.
Added "Open All Files in Folder" option when right click a folder in the folder tree view.
This commit is contained in:
Martín Lucas Golini
2025-03-09 13:37:33 -03:00
parent b84080f7ec
commit ea8a44e7a9
11 changed files with 251 additions and 7 deletions

View File

@@ -713,6 +713,7 @@ class EE_API TextDocument {
Client* mActiveClient{ nullptr };
mutable Mutex mLoadingMutex;
mutable Mutex mLoadingFilePathMutex;
mutable Mutex mSyntaxDefinitionMutex;
size_t mLastSelection{ 0 };
std::unique_ptr<SyntaxHighlighter> mHighlighter;
Mutex mStopFlagsMutex;

View File

@@ -264,6 +264,118 @@ void addCSS() {
{ "magenta", "literal" },
{ "textinputpassword", "keyword" },
{ "important", "literal" },
{ "a", "keyword" },
{ "abbr", "keyword" },
{ "address", "keyword" },
{ "area", "keyword" },
{ "article", "keyword" },
{ "aside", "keyword" },
{ "audio", "keyword" },
{ "b", "keyword" },
{ "base", "keyword" },
{ "bdi", "keyword" },
{ "bdo", "keyword" },
{ "blockquote", "keyword" },
{ "body", "keyword" },
{ "br", "keyword" },
{ "button", "keyword" },
{ "canvas", "keyword" },
{ "caption", "keyword" },
{ "cite", "keyword" },
{ "code", "keyword" },
{ "col", "keyword" },
{ "colgroup", "keyword" },
{ "data", "keyword" },
{ "datalist", "keyword" },
{ "dd", "keyword" },
{ "del", "keyword" },
{ "details", "keyword" },
{ "dfn", "keyword" },
{ "dialog", "keyword" },
{ "div", "keyword" },
{ "dl", "keyword" },
{ "dt", "keyword" },
{ "em", "keyword" },
{ "embed", "keyword" },
{ "fieldset", "keyword" },
{ "figcaption", "keyword" },
{ "figure", "keyword" },
{ "footer", "keyword" },
{ "form", "keyword" },
{ "h1", "keyword" },
{ "h2", "keyword" },
{ "h3", "keyword" },
{ "h4", "keyword" },
{ "h5", "keyword" },
{ "h6", "keyword" },
{ "head", "keyword" },
{ "header", "keyword" },
{ "hr", "keyword" },
{ "html", "keyword" },
{ "i", "keyword" },
{ "iframe", "keyword" },
{ "img", "keyword" },
{ "input", "keyword" },
{ "ins", "keyword" },
{ "kbd", "keyword" },
{ "label", "keyword" },
{ "legend", "keyword" },
{ "li", "keyword" },
{ "link", "keyword" },
{ "main", "keyword" },
{ "map", "keyword" },
{ "mark", "keyword" },
{ "menu", "keyword" },
{ "meta", "keyword" },
{ "meter", "keyword" },
{ "nav", "keyword" },
{ "noscript", "keyword" },
{ "object", "keyword" },
{ "ol", "keyword" },
{ "optgroup", "keyword" },
{ "option", "keyword" },
{ "output", "keyword" },
{ "p", "keyword" },
{ "param", "keyword" },
{ "picture", "keyword" },
{ "pre", "keyword" },
{ "progress", "keyword" },
{ "q", "keyword" },
{ "rp", "keyword" },
{ "rt", "keyword" },
{ "ruby", "keyword" },
{ "s", "keyword" },
{ "samp", "keyword" },
{ "script", "keyword" },
{ "section", "keyword" },
{ "select", "keyword" },
{ "slot", "keyword" },
{ "small", "keyword" },
{ "source", "keyword" },
{ "span", "keyword" },
{ "strong", "keyword" },
{ "style", "keyword" },
{ "sub", "keyword" },
{ "summary", "keyword" },
{ "sup", "keyword" },
{ "table", "keyword" },
{ "tbody", "keyword" },
{ "td", "keyword" },
{ "template", "keyword" },
{ "textarea", "keyword" },
{ "tfoot", "keyword" },
{ "th", "keyword" },
{ "thead", "keyword" },
{ "time", "keyword" },
{ "title", "keyword" },
{ "tr", "keyword" },
{ "track", "keyword" },
{ "u", "keyword" },
{ "ul", "keyword" },
{ "var", "keyword" },
{ "video", "keyword" },
{ "wbr", "keyword" },
{ "Widget", "keyword" },
{ "LinearLayout", "keyword" },
{ "RelativeLayout", "keyword" },

View File

@@ -199,8 +199,8 @@ Int64 SyntaxHighlighter::getMaxWantedLine() const {
}
bool SyntaxHighlighter::updateDirty( int visibleLinesCount ) {
if ( visibleLinesCount <= 0 )
return 0;
if ( visibleLinesCount <= 0 || mTokenizeAsync )
return false;
if ( mFirstInvalidLine > mMaxWantedLine ) {
mMaxWantedLine = 0;
} else {

View File

@@ -100,7 +100,10 @@ void TextDocument::reset() {
mLastSelection = 0;
mLines.clear();
mLines.emplace_back( String( "\n" ) );
mSyntaxDefinition = SyntaxDefinitionManager::instance()->getPlainDefinition();
{
Lock l( mSyntaxDefinitionMutex );
mSyntaxDefinition = SyntaxDefinitionManager::instance()->getPlainDefinition();
}
mUndoStack.clear();
cleanChangeId();
notifySyntaxDefinitionChange();
@@ -403,6 +406,7 @@ void TextDocument::mergeSelection() {
}
bool TextDocument::hasSyntaxDefinition() const {
Lock l( mSyntaxDefinitionMutex );
return !mSyntaxDefinition.getPatterns().empty();
}
@@ -414,7 +418,10 @@ const SyntaxDefinition& TextDocument::guessSyntax() const {
void TextDocument::resetSyntax() {
String header( getText( { { 0, 0 }, positionOffset( { 0, 0 }, 128 ) } ) );
std::string oldDef = mSyntaxDefinition.getLSPName();
mSyntaxDefinition = SyntaxDefinitionManager::instance()->find( mFilePath, header, mHAsCpp );
{
Lock l( mSyntaxDefinitionMutex );
mSyntaxDefinition = SyntaxDefinitionManager::instance()->find( mFilePath, header, mHAsCpp );
}
if ( mSyntaxDefinition.getLSPName() != oldDef )
notifySyntaxDefinitionChange();
}
@@ -2421,12 +2428,16 @@ void TextDocument::redo() {
}
const SyntaxDefinition& TextDocument::getSyntaxDefinition() const {
Lock l( mSyntaxDefinitionMutex );
return mSyntaxDefinition;
}
void TextDocument::setSyntaxDefinition( const SyntaxDefinition& definition ) {
if ( mSyntaxDefinition.getLSPName() != definition.getLSPName() ) {
mSyntaxDefinition = definition;
{
Lock l( mSyntaxDefinitionMutex );
mSyntaxDefinition = definition;
}
notifySyntaxDefinitionChange();
}
}

View File

@@ -448,7 +448,8 @@ void UICodeEditor::scheduledUpdate( const Time& ) {
if ( !mVisible )
return;
if ( mDoc && !mDoc->isLoading() &&
if ( mDoc && !mDoc->isLoading() && !mDoc->isEmpty() &&
!mDoc->getSyntaxDefinition().getPatterns().empty() &&
mDoc->getHighlighter()->updateDirty( getVisibleLinesCount() ) ) {
invalidateDraw();
}

View File

@@ -0,0 +1,72 @@
#include <eepp/ui/doc/languages/svelte.hpp>
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
namespace EE { namespace UI { namespace Doc { namespace Language {
void addSvelte() {
SyntaxDefinitionManager::instance()
->add(
{ "Svelte",
{ "%.svelte$" },
{
{ { "<%s*[sS][cC][rR][iI][pP][tT]%s+[tT][yY][pP][eE]%s*=%s*['\"]%a+/"
"[jJ][aA][vV][aA][sS][cC][rR][iI][pP][tT]['\"]%s*>",
"<%s*/[sS][cC][rR][iI][pP][tT]>" },
"function",
"JavaScript" },
{ { "<%s*[sS][cC][rR][iI][pP][tT]%s+([lL][aA][nN][gG])%s*(=)%s*(['\"][tT][sS]['"
"\"])%s*>",
"<%s*/[sS][cC][rR][iI][pP][tT]>" },
{ "function", "keyword", "operator", "string" },
"TypeScript" },
{ { "<%s*[sS][cC][rR][iI][pP][tT]%s*>", "<%s*/%s*[sS][cC][rR][iI][pP][tT]>" },
"function",
"JavaScript" },
{ { "<%s*[sS][tT][yY][lL][eE][^>]*>", "<%s*/%s*[sS][tT][yY][lL][eE]%s*>" },
"function",
"CSS" },
{ { "<!%-%-", "%-%->" }, "comment" },
{ { "\"", "\"", "\\" }, "string" },
{ { "'", "'", "\\" }, "string" },
{ { "{@html[^}]*}" }, "keyword", "", true },
{ { "{@debug[^}]*}" }, "keyword", "", true },
{ { "{(:else|:then|:catch)}" },
std::vector<std::string>{ "keyword", "keyword2" },
"",
true },
{ { "{(/if|/each|/await|/key)}" },
std::vector<std::string>{ "keyword", "keyword2" },
"",
true },
{ { "{(#if|#each|#await|#key)", "}", "\\" },
{ "keyword", "keyword2", "normal" },
"JavaScript",
true },
{ { "{", "}", "\\" }, "keyword", "JavaScript" },
{ { "([%a_][%w_-]*)(:)([%a_][%w_-]*)(=)" },
{ "keyword", "keyword2", "normal", "keyword", "operator" } },
{ { "([%a_][%w_-]*)(=)" }, { "keyword", "keyword", "operator" } },
{ { "0x[%da-fA-F]+" }, "number" },
{ { "-?%d+[%d%.]*f?" }, "number" },
{ { "-?%.?%d+f?" }, "number" },
{ { "%f[^<][%a_][%w%_%-]*(:)([%w_-]+)" }, { "function", "normal", "keyword" } },
{ { "%f[^<]/[%a_][%w%_%-]*(:)([%w_-]+)" }, { "function", "normal", "keyword" } },
{ { "%f[^<]![%a_][%w%_%-]*" }, "keyword2" },
{ { "%f[^<][%a_][%w%_%-]*" }, "function" },
{ { "%f[^<]/[%a_][%w%_%-]*" }, "function" },
{ { "[/<>=]" }, "operator" },
},
{
},
"",
{}
} )
.setAutoCloseXMLTags( true );
}
}}}} // namespace EE::UI::Doc::Language

View File

@@ -0,0 +1,10 @@
#ifndef EE_UI_DOC_Svelte
#define EE_UI_DOC_Svelte
namespace EE { namespace UI { namespace Doc { namespace Language {
extern void addSvelte();
}}}} // namespace EE::UI::Doc::Language
#endif

View File

@@ -69,6 +69,7 @@
#include <eepp/ui/doc/languages/smallbasic.hpp>
#include <eepp/ui/doc/languages/solidity.hpp>
#include <eepp/ui/doc/languages/sql.hpp>
#include <eepp/ui/doc/languages/svelte.hpp>
#include <eepp/ui/doc/languages/swift.hpp>
#include <eepp/ui/doc/languages/tcl.hpp>
#include <eepp/ui/doc/languages/teal.hpp>
@@ -163,6 +164,7 @@ void LanguagesSyntaxHighlighting::load() {
addSmallBASIC();
addSolidity();
addSQL();
addSvelte();
addSwift();
addTeal();
addToml();

View File

@@ -2767,6 +2767,33 @@ void App::renameFile( const FileInfo& file ) {
} );
}
void App::openAllFilesInFolder( const FileInfo& folder ) {
auto files =
FileSystem::filesInfoGetInPath( folder.getDirectoryPath(), true, false, true,
getFileSystemModel()->getDisplayConfig().ignoreHidden );
std::vector<std::string> supportedExts(
SyntaxDefinitionManager::instance()->getExtensionsPatternsSupported() );
std::vector<LuaPatternStorage> acceptedPatterns;
acceptedPatterns.reserve( supportedExts.size() );
for ( const auto& strPattern : supportedExts )
acceptedPatterns.emplace_back( std::string{ strPattern } );
for ( const auto& file : files ) {
if ( file.isRegularFile() ) {
bool foundPattern = acceptedPatterns.empty();
for ( auto& pattern : acceptedPatterns ) {
if ( pattern.matches( file.getFilepath() ) ) {
foundPattern = true;
break;
}
}
if ( foundPattern )
loadFileFromPath( file.getFilepath() );
}
}
}
void App::toggleHiddenFiles() {
mFileSystemModel = FileSystemModel::New( mFileSystemModel->getRootPath(),
FileSystemModel::Mode::FilesAndDirectories,
@@ -3497,7 +3524,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
mThreadPool->run( [this] {
// Load language definitions
Clock defClock;
SyntaxDefinitionManager::createSingleton( 107 );
SyntaxDefinitionManager::createSingleton( 108 );
Language::LanguagesSyntaxHighlighting::load();
SyntaxDefinitionManager::instance()->setLanguageExtensionsPriority(
mConfig.languagesExtensions.priorities );

View File

@@ -390,6 +390,8 @@ class App : public UICodeEditorSplitter::Client, public PluginContextProvider {
void renameFile( const FileInfo& file );
void openAllFilesInFolder( const FileInfo& folder );
UIMessageBox* newInputMsgBox( const String& title, const String& msg );
std::string getNewFilePath( const FileInfo& file, UIMessageBox* msgBox, bool keepDir = true );

View File

@@ -2153,6 +2153,10 @@ void SettingsMenu::createProjectTreeMenu( const FileInfo& file ) {
mProjectTreeMenu
->add( i18n( "open_folder_ellipsis", "Open Folder..." ), findIcon( "folder-open" ) )
->setId( "open_folder" );
mProjectTreeMenu
->add( i18n( "open_all_files_in_folder", "Open All Files in Folder" ),
findIcon( "folder-open" ) )
->setId( "open_all_files_in_folder" );
} else {
if ( file.isRegularFile() ) {
auto curDir( mApp->getCurrentWorkingDir() );
@@ -2260,6 +2264,8 @@ void SettingsMenu::createProjectTreeMenu( const FileInfo& file ) {
Engine::instance()->openURI( file.getDirectoryPath() );
} else if ( "open_folder" == id ) {
Engine::instance()->openURI( file.getFilepath() );
} else if ( "open_all_files_in_folder" == id ) {
mApp->openAllFilesInFolder( file );
} else if ( "show-hidden-files" == id ) {
mApp->toggleHiddenFiles();
} else if ( "execute_in_terminal" == id ) {