diff --git a/include/eepp/ui/doc/textdocument.hpp b/include/eepp/ui/doc/textdocument.hpp index 3ca519735..b74c51f49 100644 --- a/include/eepp/ui/doc/textdocument.hpp +++ b/include/eepp/ui/doc/textdocument.hpp @@ -48,6 +48,8 @@ class EE_API TextDocument { enum class IndentType { IndentSpaces, IndentTabs }; + enum class AutoIndentConfig { None, Preserve, Smart }; + enum class FindReplaceType { Normal, LuaPattern, RegEx }; enum class LoadStatus { Loaded, Interrupted, Failed }; @@ -477,6 +479,10 @@ class EE_API TextDocument { void setIndentType( const IndentType& indentType ); + const AutoIndentConfig& getAutoIndent() const; + + void setAutoIndent( const AutoIndentConfig& autoIndent ); + const SyntaxDefinition& getSyntaxDefinition() const; void setSyntaxDefinition( std::shared_ptr definition ); @@ -783,6 +789,7 @@ class EE_API TextDocument { std::vector> mAutoCloseBracketsPairs; Uint32 mIndentWidth{ 4 }; IndentType mIndentType{ IndentType::IndentTabs }; + AutoIndentConfig mAutoIndent{ AutoIndentConfig::Smart }; Clock mTimer; std::shared_ptr mSyntaxDefinition; std::string mDefaultFileName; @@ -876,7 +883,6 @@ class EE_API TextDocument { TextPosition findPreviousEmptyLines( size_t selIdx ); TextPosition findNextEmptyLines( size_t selIdx ); - }; struct TextSearchParams { diff --git a/src/eepp/ui/doc/textdocument.cpp b/src/eepp/ui/doc/textdocument.cpp index 02c82477d..db3cbb6bd 100644 --- a/src/eepp/ui/doc/textdocument.cpp +++ b/src/eepp/ui/doc/textdocument.cpp @@ -2724,16 +2724,19 @@ void TextDocument::newLine() { for ( int i = (int)mSelection.size() - 1; i >= 0; --i ) { TextPosition start = getSelectionIndex( i ).start(); - TextPosition indentPos = startOfContent( start ); String indentStr; - if ( indentPos.column() != 0 ) - indentStr = line( start.line() ).getText().substr( 0, indentPos.column() ); + if ( mAutoIndent != AutoIndentConfig::None ) { + TextPosition indentPos = startOfContent( start ); + if ( indentPos.column() != 0 ) + indentStr = line( start.line() ).getText().substr( 0, indentPos.column() ); + } String input( "\n" ); input.append( indentStr ); bool isPair = false; - if ( mAutoCloseBrackets && start > startOfDoc() && start < endOfDoc() ) { + if ( mAutoIndent == AutoIndentConfig::Smart && start > startOfDoc() && + start < endOfDoc() ) { String::StringBaseType curChar = getChar( start ); String::StringBaseType prevChar = getPrevChar( start ); for ( const auto& pair : mAutoCloseBracketsPairs ) { @@ -2767,9 +2770,11 @@ void TextDocument::newLineAbove() { for ( size_t i = 0; i < mSelection.size(); ++i ) { String input( "\n" ); TextPosition start = getSelectionIndex( i ).start(); - TextPosition indent = startOfContent( getSelectionIndex( i ).start() ); - if ( indent.column() != 0 ) - input.insert( 0, line( start.line() ).getText().substr( 0, indent.column() ) ); + if ( mAutoIndent != AutoIndentConfig::None ) { + TextPosition indent = startOfContent( getSelectionIndex( i ).start() ); + if ( indent.column() != 0 ) + input.insert( 0, line( start.line() ).getText().substr( 0, indent.column() ) ); + } insert( i, { start.line(), 0 }, input ); setSelection( i, { start.line(), (Int64)input.size() } ); } @@ -3009,6 +3014,14 @@ void TextDocument::setIndentType( const IndentType& indentType ) { mIndentType = indentType; } +const TextDocument::AutoIndentConfig& TextDocument::getAutoIndent() const { + return mAutoIndent; +} + +void TextDocument::setAutoIndent( const AutoIndentConfig& autoIndent ) { + mAutoIndent = autoIndent; +} + void TextDocument::undo() { setRunningTransaction( true ); bool stackWasFull = mUndoStack.getMaxStackSize() == mUndoStack.getUndoStackContainer().size(); diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 195ea417b..e2740c942 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -44,6 +44,23 @@ CharacterAlignment characterAlignmentFromString( const std::string_view& str ) { return CharacterAlignment::Left; } +static EE::UI::Doc::TextDocument::AutoIndentConfig autoIndentFromString( const std::string& str ) { + if ( str == "none" ) + return EE::UI::Doc::TextDocument::AutoIndentConfig::None; + if ( str == "preserve" ) + return EE::UI::Doc::TextDocument::AutoIndentConfig::Preserve; + return EE::UI::Doc::TextDocument::AutoIndentConfig::Smart; +} + +static std::string +autoIndentToString( const EE::UI::Doc::TextDocument::AutoIndentConfig& autoIndent ) { + if ( autoIndent == EE::UI::Doc::TextDocument::AutoIndentConfig::None ) + return "none"; + if ( autoIndent == EE::UI::Doc::TextDocument::AutoIndentConfig::Preserve ) + return "preserve"; + return "smart"; +} + static PanelPosition panelPositionFromString( const std::string& str ) { if ( String::toLower( str ) == "right" ) return PanelPosition::Right; @@ -151,6 +168,7 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, doc.forceNewLineAtEndOfFile = ini.getValueB( "document", "force_new_line_at_end_of_file", false ); doc.autoDetectIndentType = ini.getValueB( "document", "auto_detect_indent_type", true ); + doc.autoIndent = autoIndentFromString( ini.getValue( "document", "auto_indent", "smart" ) ); doc.writeUnicodeBOM = ini.getValueB( "document", "write_bom", false ); doc.indentWidth = ini.getValueI( "document", "indent_width", 4 ); doc.indentSpaces = ini.getValueB( "document", "indent_spaces", false ); @@ -226,8 +244,8 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath, term.colorScheme = ini.getValue( "terminal", "colorscheme", "eterm" ); term.newTerminalOrientation = NewTerminalOrientation::fromString( ini.getValue( "terminal", "new_terminal_orientation", "vertical" ) ); - term.workingDir = TerminalWorkingDir::fromString( - ini.getValue( "terminal", "working_dir", "project" ) ); + term.workingDir = + TerminalWorkingDir::fromString( ini.getValue( "terminal", "working_dir", "project" ) ); term.workingDirOther = ini.getValue( "terminal", "working_dir_other", "" ); term.scrollback = ini.getValueI( "terminal", "scrollback", 10000 ); term.unsupportedOSWarnDisabled = @@ -350,6 +368,7 @@ void AppConfig::save( const std::vector& recentFiles, ini.setValueB( "document", "trim_trailing_whitespaces", doc.trimTrailingWhitespaces ); ini.setValueB( "document", "force_new_line_at_end_of_file", doc.forceNewLineAtEndOfFile ); ini.setValueB( "document", "auto_detect_indent_type", doc.autoDetectIndentType ); + ini.setValue( "document", "auto_indent", autoIndentToString( doc.autoIndent ) ); ini.setValueB( "document", "write_bom", doc.writeUnicodeBOM ); ini.setValueI( "document", "indent_width", doc.indentWidth ); ini.setValueB( "document", "tab_stops", doc.tabStops ); @@ -569,6 +588,7 @@ void AppConfig::saveProject( std::string projectFolder, UICodeEditorSplitter* ed cfg.setValueB( "document", "force_new_line_at_end_of_file", docConfig.doc.forceNewLineAtEndOfFile ); cfg.setValueB( "document", "auto_detect_indent_type", docConfig.doc.autoDetectIndentType ); + cfg.setValue( "document", "auto_indent", autoIndentToString( docConfig.doc.autoIndent ) ); cfg.setValueB( "document", "write_bom", docConfig.doc.writeUnicodeBOM ); cfg.setValueI( "document", "indent_width", docConfig.doc.indentWidth ); cfg.setValueB( "document", "indent_spaces", docConfig.doc.indentSpaces ); @@ -859,6 +879,8 @@ void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* ed cfg.getValueB( "document", "force_new_line_at_end_of_file", false ); docConfig.doc.autoDetectIndentType = cfg.getValueB( "document", "auto_detect_indent_type", true ); + docConfig.doc.autoIndent = + autoIndentFromString( cfg.getValue( "document", "auto_indent", "smart" ) ); docConfig.doc.writeUnicodeBOM = cfg.getValueB( "document", "write_bom", false ); docConfig.doc.indentWidth = cfg.getValueI( "document", "indent_width", 4 ); docConfig.doc.indentSpaces = cfg.getValueB( "document", "indent_spaces", false ); diff --git a/src/tools/ecode/appconfig.hpp b/src/tools/ecode/appconfig.hpp index 6fd9fb20e..0b6176810 100644 --- a/src/tools/ecode/appconfig.hpp +++ b/src/tools/ecode/appconfig.hpp @@ -116,6 +116,7 @@ struct DocumentConfig { bool indentSpaces{ false }; bool tabStops{ true }; TextFormat::LineEnding lineEndings{ TextFormat::LineEnding::LF }; + TextDocument::AutoIndentConfig autoIndent{ TextDocument::AutoIndentConfig::Smart }; int indentWidth{ 4 }; int tabWidth{ 4 }; int lineBreakingColumn{ 100 }; diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 4c9ac8ecc..78d9809cd 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -2956,6 +2956,7 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) { : TextDocument::IndentType::IndentTabs ); doc.setIndentWidth( docc.indentWidth ); doc.setAutoDetectIndentType( docc.autoDetectIndentType ); + doc.setAutoIndent( docc.autoIndent ); doc.setBOM( docc.writeUnicodeBOM ); doc.getFoldRangeService().setEnabled( config.codeFoldingEnabled ); diff --git a/src/tools/ecode/settingsmenu.cpp b/src/tools/ecode/settingsmenu.cpp index e3db403e8..4e55057b4 100644 --- a/src/tools/ecode/settingsmenu.cpp +++ b/src/tools/ecode/settingsmenu.cpp @@ -343,6 +343,53 @@ UITerminal* SettingsMenu::getCurrentTerminal() const { UIMenu* SettingsMenu::createDocumentMenu() { auto shouldCloseCb = []( UIMenuItem* ) -> bool { return false; }; + auto setupAutoIndentMenu = [this]( + UIPopUpMenu* parentMenu, const std::string& menuId, + std::function getConfig, + std::function onClick ) { + UIPopUpMenu* autoIndentMenu = UIPopUpMenu::New(); + auto subMenu = + parentMenu->addSubMenu( i18n( "auto_indent", "Auto-Indent" ), nullptr, autoIndentMenu ); + subMenu + ->setTooltipText( + i18n( "auto_indent_tooltip", + "Configures the automatic indentation behavior when pressing Enter.\n" + "None: No automatic indentation.\n" + "Preserve: Preserves the indentation level of the previous line.\n" + "Smart: Preserves indentation and automatically indents between auto-closed " + "brackets." ) ) + ->setId( menuId ); + subMenu->on( Event::OnMenuShow, [this, autoIndentMenu, getConfig, onClick]( const Event* ) { + if ( autoIndentMenu->getCount() == 0 ) { + autoIndentMenu->addRadioButton( i18n( "auto_indent_none", "None" ) ) + ->setId( "auto_indent_none" ); + autoIndentMenu->addRadioButton( i18n( "auto_indent_preserve", "Preserve" ) ) + ->setId( "auto_indent_preserve" ); + autoIndentMenu->addRadioButton( i18n( "auto_indent_smart", "Smart" ) ) + ->setId( "auto_indent_smart" ); + autoIndentMenu->on( Event::OnItemClicked, [onClick]( const Event* event ) { + const String& text = event->getNode()->asType()->getId(); + TextDocument::AutoIndentConfig autoIndent = + text == "auto_indent_none" ? TextDocument::AutoIndentConfig::None + : text == "auto_indent_preserve" ? TextDocument::AutoIndentConfig::Preserve + : TextDocument::AutoIndentConfig::Smart; + onClick( autoIndent ); + } ); + } + TextDocument::AutoIndentConfig currentConfig = getConfig(); + autoIndentMenu->getItemId( "auto_indent_none" ) + ->asType() + ->setActive( currentConfig == TextDocument::AutoIndentConfig::None ); + autoIndentMenu->getItemId( "auto_indent_preserve" ) + ->asType() + ->setActive( currentConfig == TextDocument::AutoIndentConfig::Preserve ); + autoIndentMenu->getItemId( "auto_indent_smart" ) + ->asType() + ->setActive( currentConfig == TextDocument::AutoIndentConfig::Smart ); + } ); + return subMenu; + }; + mDocMenu = UIPopUpMenu::New(); // **** CURRENT DOCUMENT **** @@ -355,6 +402,18 @@ UIMenu* SettingsMenu::createDocumentMenu() { mApp->getConfig().doc.autoDetectIndentType ) ->setId( "auto_indent_cur" ); + setupAutoIndentMenu( + mDocMenu, "auto_indent_menu_cur", + [this]() { + return mSplitter->curEditorExistsAndFocused() + ? mSplitter->getCurEditor()->getDocument().getAutoIndent() + : TextDocument::AutoIndentConfig::Smart; + }, + [this]( TextDocument::AutoIndentConfig autoIndent ) { + if ( mSplitter->curEditorExistsAndFocused() ) + mSplitter->getCurEditor()->getDocument().setAutoIndent( autoIndent ); + } ); + UIMenuSubMenu* fileTypeMenu = mDocMenu->addSubMenu( i18n( "file_type", "File Type" ), findIcon( "file-code" ), createFileTypeMenu( true ) ); @@ -543,6 +602,15 @@ UIMenu* SettingsMenu::createDocumentMenu() { mApp->getConfig().doc.autoDetectIndentType ) ->setId( "auto_indent" ); + setupAutoIndentMenu( + mGlobalMenu, "auto_indent_menu", [this]() { return mApp->getConfig().doc.autoIndent; }, + [this]( TextDocument::AutoIndentConfig autoIndent ) { + mApp->getConfig().doc.autoIndent = autoIndent; + mSplitter->forEachEditor( [autoIndent]( UICodeEditor* editor ) { + editor->getDocument().setAutoIndent( autoIndent ); + } ); + } ); + UIPopUpMenu* tabTypeMenuGlobal = UIPopUpMenu::New(); tabTypeMenuGlobal->addRadioButton( i18n( "tabs", "Tabs" ) ) ->setActive( !mApp->getConfig().doc.indentSpaces ) @@ -803,6 +871,14 @@ UIMenu* SettingsMenu::createDocumentMenu() { ->setId( "auto_indent" ) ->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); + auto autoIndentProjectSubMenu = setupAutoIndentMenu( + mProjectDocMenu, "auto_indent_menu_project", + [this]() { return mApp->getProjectConfig().doc.autoIndent; }, + [this]( TextDocument::AutoIndentConfig autoIndent ) { + mApp->getProjectConfig().doc.autoIndent = autoIndent; + } ); + autoIndentProjectSubMenu->setEnabled( !mApp->getProjectConfig().useGlobalSettings ); + UIPopUpMenu* tabTypeMenuProject = UIPopUpMenu::New(); tabTypeMenuProject->addRadioButton( i18n( "tabs", "Tabs" ) ) ->setActive( !mApp->getProjectConfig().doc.indentSpaces ) @@ -1174,7 +1250,8 @@ UIMenu* SettingsMenu::createTerminalMenu() { ->setId( "configure-terminal-scrollback" ); mTerminalMenu - ->add( i18n( "configure_terminal_working_dir", "Configure Terminal Default Working Directory" ), + ->add( i18n( "configure_terminal_working_dir", + "Configure Terminal Default Working Directory" ), findIcon( "terminal" ), getKeybind( "configure-terminal-working-dir" ) ) ->setId( "configure-terminal-working-dir" );