mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-18 06:55:48 +03:00
Added XML tags auto-close.
This commit is contained in:
@@ -13,7 +13,7 @@ SyntaxDefinition::SyntaxDefinition( const std::string& languageName,
|
||||
const std::string& comment,
|
||||
const std::vector<std::string> headers ) :
|
||||
mLanguageName( languageName ),
|
||||
mLanguageId( String::hash( languageName ) ),
|
||||
mLanguageId( String::hash( String::toLower( languageName ) ) ),
|
||||
mFiles( files ),
|
||||
mPatterns( patterns ),
|
||||
mSymbols( symbols ),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
#include <eepp/ui/doc/syntaxdefinitionmanager.hpp>
|
||||
#include <eepp/ui/doc/syntaxhighlighter.hpp>
|
||||
#include <eepp/ui/doc/syntaxtokenizer.hpp>
|
||||
|
||||
@@ -90,4 +91,20 @@ bool SyntaxHighlighter::updateDirty( int visibleLinesCount ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const SyntaxDefinition&
|
||||
SyntaxHighlighter::getSyntaxDefinitionFromTextPosition( const TextPosition& position ) {
|
||||
auto found = mLines.find( position.line() );
|
||||
if ( found == mLines.end() )
|
||||
return SyntaxDefinitionManager::instance()->getPlainStyle();
|
||||
|
||||
TokenizedLine& line = found->second;
|
||||
SyntaxState state =
|
||||
SyntaxTokenizer::retrieveSyntaxState( mDoc->getSyntaxDefinition(), line.state );
|
||||
|
||||
if ( nullptr == state.currentSyntax )
|
||||
return SyntaxDefinitionManager::instance()->getPlainStyle();
|
||||
|
||||
return *state.currentSyntax;
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Doc
|
||||
|
||||
@@ -61,14 +61,8 @@ std::pair<int, int> findNonEscaped( const std::string& text, const std::string&
|
||||
}
|
||||
}
|
||||
|
||||
struct SyntaxState {
|
||||
const SyntaxDefinition* currentSyntax{ nullptr };
|
||||
const SyntaxPattern* subsyntaxInfo{ nullptr };
|
||||
Uint32 currentPatternIdx{ 0 };
|
||||
Uint32 currentLevel{ 0 };
|
||||
};
|
||||
|
||||
SyntaxState retrieveSyntaxState( const SyntaxDefinition& syntax, const Uint32& state ) {
|
||||
SyntaxState SyntaxTokenizer::retrieveSyntaxState( const SyntaxDefinition& syntax,
|
||||
const Uint32& state ) {
|
||||
SyntaxState syntaxState{ &syntax, nullptr, state, 0 };
|
||||
if ( state > 0 &&
|
||||
( state > 255 ||
|
||||
|
||||
@@ -766,6 +766,8 @@ Uint32 UICodeEditor::onTextInput( const TextInputEvent& event ) {
|
||||
|
||||
mDoc->textInput( event.getText() );
|
||||
|
||||
checkAutoCloseXMLTag( event.getText() );
|
||||
|
||||
for ( auto& module : mModules )
|
||||
if ( module->onTextInput( this, event ) )
|
||||
return 1;
|
||||
@@ -2569,7 +2571,8 @@ Rectf UICodeEditor::getMinimapRect( const Vector2f& start ) const {
|
||||
|
||||
void UICodeEditor::drawMinimap( const Vector2f& start, const std::pair<int, int>& lineRange ) {
|
||||
Float charHeight = PixelDensity::getPixelDensity() * mMinimapConfig.scale;
|
||||
Float charSpacing = eemax( 1.f, eefloor( 0.8 * PixelDensity::getPixelDensity() * mMinimapConfig.scale ) );
|
||||
Float charSpacing =
|
||||
eemax( 1.f, eefloor( 0.8 * PixelDensity::getPixelDensity() * mMinimapConfig.scale ) );
|
||||
Float lineSpacing = getMinimapLineSpacing();
|
||||
Rectf rect( getMinimapRect( start ) );
|
||||
int visibleLinesCount = ( lineRange.second - lineRange.first );
|
||||
@@ -2756,4 +2759,45 @@ bool UICodeEditor::isMinimapFileTooLarge() const {
|
||||
eefloor( getMinimapRect( getScreenStart() ).getHeight() / getMinimapLineSpacing() );
|
||||
}
|
||||
|
||||
bool UICodeEditor::getAutoCloseXMLTags() const {
|
||||
return mAutoCloseXMLTags;
|
||||
}
|
||||
|
||||
void UICodeEditor::setAutoCloseXMLTags( bool autoCloseXMLTags ) {
|
||||
mAutoCloseXMLTags = autoCloseXMLTags;
|
||||
}
|
||||
|
||||
bool UICodeEditor::checkAutoCloseXMLTag( const String& text ) {
|
||||
if ( !mAutoCloseXMLTags || text.empty() || text.size() > 1 || text[0] != '>' ||
|
||||
mDoc->getSelection().hasSelection() )
|
||||
return false;
|
||||
TextPosition start( mDoc->getSelection().start() );
|
||||
if ( start.line() >= (Int64)mDoc->linesCount() )
|
||||
return false;
|
||||
const auto& line = mDoc->line( start.line() ).getText();
|
||||
if ( start.column() >= (Int64)line.size() )
|
||||
return false;
|
||||
if ( line[start.column() - 1] != '>' || ( line.size() > 2 && line[start.column() - 2] == '/' ) )
|
||||
return false;
|
||||
// Only close tags if the current line syntax is XML or HTML
|
||||
const SyntaxDefinition& definition = mHighlighter.getSyntaxDefinitionFromTextPosition( start );
|
||||
const String::HashType xmlType = String::hash( "xml" );
|
||||
const String::HashType htmlType = String::hash( "html" );
|
||||
if ( definition.getLanguageId() != xmlType && definition.getLanguageId() != htmlType )
|
||||
return false;
|
||||
size_t foundOpenPos = line.find_last_of( "<", start.column() - 1 );
|
||||
if ( foundOpenPos == String::InvalidPos || start.column() - foundOpenPos < 1 )
|
||||
return false;
|
||||
std::string tag( line.substr( foundOpenPos, start.column() - foundOpenPos ).toUtf8() );
|
||||
LuaPattern pattern( "<([%w_%-]+).*>" );
|
||||
auto match = pattern.gmatch( tag );
|
||||
if ( match.matches() ) {
|
||||
std::string tagName( match.group( 1 ) );
|
||||
mDoc->textInput( String( "</" + tagName + ">" ) );
|
||||
mDoc->setSelection( start );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -98,6 +98,7 @@ void AppConfig::load( std::string& confPath, std::string& keybindingsPath,
|
||||
ini.getValueB( "editor", "single_click_tree_navigation", false );
|
||||
editor.syncProjectTreeWithEditor =
|
||||
ini.getValueB( "editor", "sync_project_tree_with_editor", false );
|
||||
editor.autoCloseXMLTags = ini.getValueB( "editor", "auto_close_xml_tags", true );
|
||||
iniInfo = FileInfo( ini.path() );
|
||||
}
|
||||
|
||||
@@ -164,6 +165,7 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
|
||||
ini.setValueB( "editor", "hide_tab_bar_on_single_tab", editor.hideTabBarOnSingleTab );
|
||||
ini.setValueB( "editor", "single_click_tree_navigation", editor.singleClickTreeNavigation );
|
||||
ini.setValueB( "editor", "sync_project_tree_with_editor", editor.syncProjectTreeWithEditor );
|
||||
ini.setValueB( "editor", "auto_close_xml_tags", editor.autoCloseXMLTags );
|
||||
ini.writeFile();
|
||||
iniState.writeFile();
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ struct CodeEditorConfig {
|
||||
bool hideTabBarOnSingleTab{ true };
|
||||
bool singleClickTreeNavigation{ false };
|
||||
bool syncProjectTreeWithEditor{ true };
|
||||
bool autoCloseXMLTags{ true };
|
||||
std::string autoCloseBrackets{ "" };
|
||||
int indentWidth{ 4 };
|
||||
int tabWidth{ 4 };
|
||||
|
||||
@@ -916,7 +916,7 @@ UIMenu* App::createDocumentMenu() {
|
||||
} );
|
||||
|
||||
UIPopUpMenu* bracketsMenu = UIPopUpMenu::New();
|
||||
mDocMenu->addSubMenu( "Auto-Close Brackets", nullptr, bracketsMenu );
|
||||
mDocMenu->addSubMenu( "Auto-Close Brackets & Tags", nullptr, bracketsMenu );
|
||||
auto& closeBrackets = mConfig.editor.autoCloseBrackets;
|
||||
auto shouldCloseCb = []( UIMenuItem* ) -> bool { return false; };
|
||||
bracketsMenu->addCheckBox( "Brackets ()", closeBrackets.find( '(' ) != std::string::npos )
|
||||
@@ -939,10 +939,20 @@ UIMenu* App::createDocumentMenu() {
|
||||
bracketsMenu->addCheckBox( "Back Quotes ``", closeBrackets.find( '`' ) != std::string::npos )
|
||||
->setOnShouldCloseCb( shouldCloseCb )
|
||||
->setId( "``" );
|
||||
bracketsMenu->addCheckBox( "Auto Close XML Tags", mConfig.editor.autoCloseXMLTags )
|
||||
->setOnShouldCloseCb( shouldCloseCb )
|
||||
->setId( "XML" );
|
||||
bracketsMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) {
|
||||
std::string id = event->getNode()->getId();
|
||||
if ( event->getNode()->isType( UI_TYPE_MENUCHECKBOX ) ) {
|
||||
UIMenuCheckBox* item = event->getNode()->asType<UIMenuCheckBox>();
|
||||
if ( item->getId() == "XML" ) {
|
||||
mConfig.editor.autoCloseXMLTags = item->isActive();
|
||||
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
|
||||
editor->setAutoCloseXMLTags( mConfig.editor.autoCloseXMLTags );
|
||||
} );
|
||||
return;
|
||||
}
|
||||
auto curPairs = String::split( mConfig.editor.autoCloseBrackets, ',' );
|
||||
auto found = std::find( curPairs.begin(), curPairs.end(), id );
|
||||
if ( item->isActive() ) {
|
||||
@@ -1372,6 +1382,7 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
|
||||
editor->setColorPreview( config.colorPreview );
|
||||
editor->setFont( mFontMono );
|
||||
editor->setMenuIconSize( mMenuIconSize );
|
||||
editor->setAutoCloseXMLTags( config.autoCloseXMLTags );
|
||||
doc.setAutoCloseBrackets( !mConfig.editor.autoCloseBrackets.empty() );
|
||||
doc.setAutoCloseBracketsPairs( makeAutoClosePairs( mConfig.editor.autoCloseBrackets ) );
|
||||
doc.setAutoDetectIndentType( config.autoDetectIndentType );
|
||||
|
||||
Reference in New Issue
Block a user