Add configurable Tab Out support

Add an optional Tab Out behavior that moves a single cursor past configured trailing characters when pressing Tab. Expose the feature in Global Document Settings, keep it disabled by default, persist its configuration, and preserve existing selection and multi-cursor indentation behavior (SpartanJ/ecode#951).
This commit is contained in:
Martín Lucas Golini
2026-08-21 11:35:35 -03:00
parent 2895d771ab
commit 8eed5fcd58
13 changed files with 159 additions and 0 deletions
+4
View File
@@ -184,6 +184,8 @@ void AppConfig::load( const std::string& confPath, std::string& keybindingsPath,
doc.indentWidth = ini.getValueI( "document", "indent_width", 4 );
doc.indentSpaces = ini.getValueB( "document", "indent_spaces", false );
doc.tabStops = ini.getValueB( "document", "tab_stops", true );
doc.tabOutEnabled = ini.getValueB( "document", "tab_out_enabled", false );
doc.tabOutChars = ini.getValue( "document", "tab_out_chars", ")]}'\":;>," );
doc.lineEndings =
TextFormat::stringToLineEnding( ini.getValue( "document", "line_endings", "LF" ) );
editor.newTabPosition =
@@ -395,6 +397,8 @@ void AppConfig::save( const std::vector<std::string>& recentFiles,
ini.setValueB( "document", "write_bom", doc.writeUnicodeBOM );
ini.setValueI( "document", "indent_width", doc.indentWidth );
ini.setValueB( "document", "tab_stops", doc.tabStops );
ini.setValueB( "document", "tab_out_enabled", doc.tabOutEnabled );
ini.setValue( "document", "tab_out_chars", doc.tabOutChars );
ini.setValueB( "document", "indent_spaces", doc.indentSpaces );
ini.setValue( "document", "line_endings", TextFormat::lineEndingToString( doc.lineEndings ) );
ini.setValueI( "document", "tab_width", doc.tabWidth );
+2
View File
@@ -156,8 +156,10 @@ struct DocumentConfig {
bool writeUnicodeBOM{ false };
bool indentSpaces{ false };
bool tabStops{ true };
bool tabOutEnabled{ false };
TextFormat::LineEnding lineEndings{ TextFormat::LineEnding::LF };
TextDocument::AutoIndentConfig autoIndent{ TextDocument::AutoIndentConfig::Smart };
std::string tabOutChars{ ")]}'\":;>," };
int indentWidth{ 4 };
int tabWidth{ 4 };
int lineBreakingColumn{ 100 };
+2
View File
@@ -2985,6 +2985,8 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
doc.setAutoCloseBrackets( !mConfig.editor.autoCloseBrackets.empty() );
doc.setAutoCloseBracketsPairs( makeAutoClosePairs( mConfig.editor.autoCloseBrackets ) );
doc.setTabOutEnabled( mConfig.doc.tabOutEnabled );
doc.setTabOutChars( String::fromUtf8( mConfig.doc.tabOutChars ) );
doc.setLineEnding( docc.lineEndings );
doc.setTrimTrailingWhitespaces( docc.trimTrailingWhitespaces );
doc.setForceNewLineAtEndOfFile( docc.forceNewLineAtEndOfFile );
+19
View File
@@ -251,6 +251,25 @@ void SettingsActions::setIndentTabCharacter() {
mApp->setFocusEditorOnClose( msgBox );
}
void SettingsActions::setTabOutChars() {
UIMessageBox* msgBox = UIMessageBox::New(
UIMessageBox::INPUT,
i18n( "set_tab_out_characters_message",
"Set the characters the cursor can move past when pressing Tab." ) );
msgBox->setTitle( i18n( "set_tab_out_characters", "Set Tab Out Characters" ) );
msgBox->setCloseShortcut( { KEY_ESCAPE, 0 } );
msgBox->getTextInput()->setText( String::fromUtf8( mApp->getConfig().doc.tabOutChars ) );
msgBox->showWhenReady();
msgBox->on( Event::OnConfirm, [this, msgBox]( const Event* ) {
String chars = msgBox->getTextInput()->getText();
mApp->getConfig().doc.tabOutChars = chars.toUtf8();
mApp->getSplitter()->forEachEditor(
[&chars]( UICodeEditor* editor ) { editor->getDocument().setTabOutChars( chars ); } );
msgBox->closeWindow();
} );
mApp->setFocusEditorOnClose( msgBox );
}
void SettingsActions::setFoldRefreshFreq() {
UIMessageBox* msgBox = UIMessageBox::New(
UIMessageBox::INPUT,
+2
View File
@@ -25,6 +25,8 @@ class SettingsActions {
void setIndentTabCharacter();
void setTabOutChars();
void setFoldRefreshFreq();
void setUIScaleFactor();
+15
View File
@@ -824,6 +824,14 @@ UIMenu* SettingsMenu::createDocumentMenu() {
"like a fixed number of spaces regardless of their position." ) )
->setId( "tab_stops" );
mGlobalMenu->addCheckBox( i18n( "tab_out", "Tab Out" ), mApp->getConfig().doc.tabOutEnabled )
->setTooltipText( i18n(
"tab_out_desc", "Pressing Tab before a configured character moves the cursor past it. "
"Only applies to a single cursor without a selection." ) )
->setId( "tab_out" );
mGlobalMenu->add( i18n( "set_tab_out_characters", "Set Tab Out Characters" ) )
->setId( "set_tab_out_characters" );
mGlobalMenu
->addCheckBox( i18n( "force_new_line_at_end_of_file", "Force New Line at End of File" ),
mApp->getConfig().doc.forceNewLineAtEndOfFile )
@@ -948,6 +956,11 @@ UIMenu* SettingsMenu::createDocumentMenu() {
mSplitter->forEachEditor( [this]( UICodeEditor* editor ) {
editor->setTabStops( mApp->getConfig().doc.tabStops );
} );
} else if ( "tab_out" == id ) {
mApp->getConfig().doc.tabOutEnabled = item->isActive();
mSplitter->forEachEditor( [this]( UICodeEditor* editor ) {
editor->getDocument().setTabOutEnabled( mApp->getConfig().doc.tabOutEnabled );
} );
}
} else if ( "line_breaking_column" == id ) {
mApp->getSettingsActions()->setLineBreakingColumn();
@@ -957,6 +970,8 @@ UIMenu* SettingsMenu::createDocumentMenu() {
mApp->getSettingsActions()->setCursorBlinkingTime();
} else if ( "indent_tab_character" == id ) {
mApp->getSettingsActions()->setIndentTabCharacter();
} else if ( "set_tab_out_characters" == id ) {
mApp->getSettingsActions()->setTabOutChars();
}
} );