diff --git a/BeefLibs/Beefy2D/src/widgets/EditWidget.bf b/BeefLibs/Beefy2D/src/widgets/EditWidget.bf index bd28a686..53a153a8 100644 --- a/BeefLibs/Beefy2D/src/widgets/EditWidget.bf +++ b/BeefLibs/Beefy2D/src/widgets/EditWidget.bf @@ -540,6 +540,7 @@ namespace Beefy.widgets public EditWidget mEditWidget; public float mTabSize; + public bool mWantsTabsAsSpaces; public float mCharWidth = -1; public int32 mTabLength = 4; public uint8 mExtendDisplayFlags; @@ -1267,7 +1268,9 @@ namespace Beefy.widgets { int prevTabCount = (int)((textX + 0.5f) / mTabSize); int wantTabCount = (int)((cursorX + 0.5f) / mTabSize); - int wantAddTabs = wantTabCount - prevTabCount; + int wantAddTabs = 0; + if (!mWantsTabsAsSpaces) + wantAddTabs = wantTabCount - prevTabCount; if (wantAddTabs > 0) textX = wantTabCount * mTabSize + mTextInsets.mLeft; @@ -3209,6 +3212,14 @@ namespace Beefy.widgets mEditWidget.UpdateScrollbars(); } + protected void GetTabString(String str, int tabCount = 1) + { + if (mWantsTabsAsSpaces) + str.Append(' ', mTabLength * tabCount); + else + str.Append('\t', tabCount); + } + public void BlockIndentSelection(bool unIndent = false) { if (CheckReadOnly()) @@ -3270,15 +3281,30 @@ namespace Beefy.widgets } else { - startAdjust++; + if (mWantsTabsAsSpaces) + startAdjust += mTabLength; + else + startAdjust++; + for (int lineIdx = minLineIdx; lineIdx <= maxLineIdx; lineIdx++) { int lineStart; int lineEnd; GetLinePosition(lineIdx, out lineStart, out lineEnd); lineStart += endAdjust; - indentTextAction.mInsertCharList.Add(((int32)lineStart, '\t')); - endAdjust++; + if (mWantsTabsAsSpaces) + { + for (int i < mTabLength) + { + indentTextAction.mInsertCharList.Add(((int32)lineStart, ' ')); + endAdjust++; + } + } + else + { + indentTextAction.mInsertCharList.Add(((int32)lineStart, '\t')); + endAdjust++; + } } indentTextAction.Redo(); @@ -3413,17 +3439,16 @@ namespace Beefy.widgets let prevSelection = mSelection.Value; mSelection = null; for (int32 i = 0; i < indentCount; i++) - InsertAtCursor("\t"); + InsertAtCursor(GetTabString(.. scope .())); GetLinePosition(minLineIdx, out lineStart, out lineEnd); mSelection = EditSelection(prevSelection.mStartPos + indentCount, prevSelection.mEndPos + indentCount); } else - InsertAtCursor("\t"); + InsertAtCursor(GetTabString(.. scope .())); } else { - for (int32 i = 0; i < indentCount; i++) - InsertAtCursor("\t"); + InsertAtCursor(GetTabString(.. scope .(), indentCount)); } } } diff --git a/IDE/src/Compiler/BfParser.bf b/IDE/src/Compiler/BfParser.bf index 8ffe3846..cd728b2e 100644 --- a/IDE/src/Compiler/BfParser.bf +++ b/IDE/src/Compiler/BfParser.bf @@ -145,7 +145,8 @@ namespace IDE.Compiler static extern bool BfParser_Reduce(void* bfParser, void* bfPassInstance); [CallingConvention(.Stdcall), CLink] - static extern char8* BfParser_Format(void* bfParser, int32 formatEnd, int32 formatStart, out int32* outCharMapping, int32 maxCol); + static extern char8* BfParser_Format(void* bfParser, int32 formatEnd, int32 formatStart, out int32* outCharMapping, int32 maxCol, int32 tabSize, bool wantsTabsAsSpaces, + bool indentCaseLabels); [CallingConvention(.Stdcall), CLink] static extern char8* BfParser_GetDebugExpressionAt(void* bfParser, int32 cursorIdx); @@ -244,7 +245,8 @@ namespace IDE.Compiler { int32* charMappingPtr; var maxCol = gApp.mSettings.mEditorSettings.mWrapCommentsAt; - var stringPtr = BfParser_Format(mNativeBfParser, (int32)formatStart, (int32)formatEnd, out charMappingPtr, maxCol); + var stringPtr = BfParser_Format(mNativeBfParser, (int32)formatStart, (int32)formatEnd, out charMappingPtr, maxCol, + gApp.mSettings.mEditorSettings.mTabSize, gApp.mSettings.mEditorSettings.mTabsOrSpaces == .Spaces, gApp.mSettings.mEditorSettings.mIndentCaseLabels); str.Append(stringPtr); charMapping = new int32[str.Length]; diff --git a/IDE/src/Settings.bf b/IDE/src/Settings.bf index 3a4e0a0b..a3994b58 100644 --- a/IDE/src/Settings.bf +++ b/IDE/src/Settings.bf @@ -622,6 +622,12 @@ namespace IDE BackupOnly } + public enum TabsOrSpaces + { + Tabs, + Spaces + } + public List mFonts = new .() ~ DeleteContainerAndItems!(_); public float mFontSize = 12; public AutoCompleteShowKind mAutoCompleteShowKind = .PanelIfVisible; @@ -641,9 +647,13 @@ namespace IDE public bool mShowLineNumbers = true; public bool mFreeCursorMovement; public FileRecoveryKind mEnableFileRecovery = .Yes; - public bool mFormatOnSave = false; public bool mSyncWithWorkspacePanel = false; public int32 mWrapCommentsAt = 0; + public bool mFormatOnSave = false; + public bool mIndentCaseLabels = false; + public bool mLeftAlignPreprocessor = true; + public TabsOrSpaces mTabsOrSpaces = .Tabs; + public int32 mTabSize = 4; public void Serialize(StructuredData sd) { @@ -669,9 +679,13 @@ namespace IDE sd.Add("ShowLineNumbers", mShowLineNumbers); sd.Add("FreeCursorMovement", mFreeCursorMovement); sd.Add("EnableFileRecovery", mEnableFileRecovery); - sd.Add("FormatOnSave", mFormatOnSave); sd.Add("SyncWithWorkspacePanel", mSyncWithWorkspacePanel); sd.Add("WrapCommentsAt", mWrapCommentsAt); + sd.Add("FormatOnSave", mFormatOnSave); + sd.Add("TabsOrSpaces", mTabsOrSpaces); + sd.Add("TabSize", mTabSize); + sd.Add("IndentCaseLabels", mIndentCaseLabels); + sd.Add("LeftAlignPreprocessor", mLeftAlignPreprocessor); } public void Deserialize(StructuredData sd) @@ -701,9 +715,13 @@ namespace IDE sd.Get("ShowLineNumbers", ref mShowLineNumbers); sd.Get("FreeCursorMovement", ref mFreeCursorMovement); sd.GetEnum("EnableFileRecovery", ref mEnableFileRecovery); - sd.Get("FormatOnSave", ref mFormatOnSave); sd.Get("SyncWithWorkspacePanel", ref mSyncWithWorkspacePanel); sd.Get("WrapCommentsAt", ref mWrapCommentsAt); + sd.Get("FormatOnSave", ref mFormatOnSave); + sd.Get("TabsOrSpaces", ref mTabsOrSpaces); + sd.Get("TabSize", ref mTabSize); + sd.Get("IndentCaseLabels", ref mIndentCaseLabels); + sd.Get("LeftAlignPreprocessor", ref mLeftAlignPreprocessor); } public void SetDefaults() @@ -717,6 +735,8 @@ namespace IDE public void Apply() { + mTabSize = Math.Clamp(mTabSize, 1, 16); + if (mSpellCheckEnabled) { if (gApp.mSpellChecker == null) @@ -1197,6 +1217,7 @@ namespace IDE gApp.mSettings.mEditorSettings.mFontSize = Math.Clamp(gApp.mSettings.mEditorSettings.mFontSize, 6.0f, 72.0f); mUISettings.Apply(); + mEditorSettings.Apply(); Font.ClearFontNameCache(); gApp.PhysSetScale(gApp.mSettings.mUISettings.mScale / 100.0f, true); @@ -1205,7 +1226,7 @@ namespace IDE mKeySettings.Apply(); mDebuggerSettings.Apply(); - mEditorSettings.Apply(); + for (var window in gApp.mWindows) { diff --git a/IDE/src/ui/SettingsDialog.bf b/IDE/src/ui/SettingsDialog.bf index 842cdcda..8c4e9c93 100644 --- a/IDE/src/ui/SettingsDialog.bf +++ b/IDE/src/ui/SettingsDialog.bf @@ -128,10 +128,18 @@ namespace IDE.ui AddPropertiesItem(category, "Show Line Numbers", "mShowLineNumbers"); AddPropertiesItem(category, "Free Cursor Movement", "mFreeCursorMovement"); AddPropertiesItem(category, "Enable File Recovery", "mEnableFileRecovery"); - AddPropertiesItem(category, "Format on Save", "mFormatOnSave"); AddPropertiesItem(category, "Sync with Workspace Panel", "mSyncWithWorkspacePanel"); - AddPropertiesItem(category, "Wrap Comments at Column", "mWrapCommentsAt"); + category.Open(true, true); + (category, propEntry) = AddPropertiesItem(root, "Formatting"); + category.mIsBold = true; + category.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, cHeaderColor); + AddPropertiesItem(category, "Format on Save", "mFormatOnSave"); + AddPropertiesItem(category, "Tabs or Spaces", "mTabsOrSpaces"); + AddPropertiesItem(category, "Tab Size", "mTabSize"); + AddPropertiesItem(category, "Wrap Comments at Column", "mWrapCommentsAt"); + AddPropertiesItem(category, "Indent Case Labels", "mIndentCaseLabels"); + AddPropertiesItem(category, "Left Align Preprocessor", "mLeftAlignPreprocessor"); category.Open(true, true); } diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index d7a6467a..99d0c6d4 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -779,7 +779,9 @@ namespace IDE.ui SetFont(IDEApp.sApp.mCodeFont, true, true); //SetFont(DarkTheme.sDarkTheme.mSmallFont, false, false); - mTabSize = mFont.GetWidth(" "); + mWantsTabsAsSpaces = gApp.mSettings.mEditorSettings.mTabsOrSpaces == .Spaces; + mTabLength = gApp.mSettings.mEditorSettings.mTabSize; + mTabSize = mFont.GetWidth(scope String(' ', gApp.mSettings.mEditorSettings.mTabSize)); mTextColors = sTextColors; mExtendDisplayFlags = (uint8)(SourceElementFlags.SpellingError | SourceElementFlags.SymbolReference); mShowLineBottomPadding = 2; @@ -793,7 +795,9 @@ namespace IDE.ui public override void RehupScale(float oldScale, float newScale) { base.RehupScale(oldScale, newScale); - mTabSize = mFont.GetWidth(" "); + mWantsTabsAsSpaces = gApp.mSettings.mEditorSettings.mTabsOrSpaces == .Spaces; + mTabLength = gApp.mSettings.mEditorSettings.mTabSize; + mTabSize = mFont.GetWidth(scope String(' ', gApp.mSettings.mEditorSettings.mTabSize)); } protected override EditWidgetContent.Data CreateEditData() @@ -1244,7 +1248,7 @@ namespace IDE.ui else if (c == ' ') blockOpenSpaceCount++; else if (c == '\t') - blockOpenSpaceCount += 4; // SpacesInTab + blockOpenSpaceCount += gApp.mSettings.mEditorSettings.mTabSize; // SpacesInTab else { blockOpenSpaceCount = 0; @@ -1332,7 +1336,7 @@ namespace IDE.ui return spaceCount; } - public int GetLineEndColumn(int line, bool openingBlock, bool force, bool ignoreLineText = false, bool insertingElseStmt = false, float* outWidth = null) + public int GetLineEndColumn(int line, bool openingBlock, bool force, bool ignoreLineText = false, bool insertingElseStmt = false, bool ignoreCaseExpr = false, float* outWidth = null) { String curLineStr = scope String(); GetLineText(line, curLineStr); @@ -1404,6 +1408,8 @@ namespace IDE.ui List ifCtlDepthStack = scope List(); bool keepBlockIndented = false; + bool inSwitchCaseBlock = false; + bool mayBeDefaultCase = false; for (int checkIdx = foundBlockStartIdx + 1; checkIdx < endingPos; checkIdx++) { char8 c = mData.mText[checkIdx].mChar; @@ -1427,6 +1433,14 @@ namespace IDE.ui skippingLine = true; } + if (mayBeDefaultCase) + { + if (c == ':') + inSwitchCaseBlock = true; + else if (!isWhitespace) + mayBeDefaultCase = false; + } + if ((inCaseExpr) && (c == ':') && (elementType == .Normal) && (parenDepth == 0)) { inCaseExpr = false; @@ -1499,9 +1513,12 @@ namespace IDE.ui case "case": if (parenDepth == 0) { - caseStartPos = checkIdx - 4; + caseStartPos = checkIdx - gApp.mSettings.mEditorSettings.mTabSize; inCaseExpr = true; + inSwitchCaseBlock = true; } + case "default": + mayBeDefaultCase = true; case "switch": ifDepth = 0; } @@ -1725,9 +1742,12 @@ namespace IDE.ui if ((openingBlock) && (!keepBlockIndented) && (parenDepth == 0)) extraTab = Math.Max(1, extraTab - 1); + if ((inSwitchCaseBlock) && (!ignoreCaseExpr) && (gApp.mSettings.mEditorSettings.mIndentCaseLabels)) + extraTab++; + int wantSpaceCount = blockOpenSpaceCount; //if (!openingBlock) - wantSpaceCount += extraTab * 4; + wantSpaceCount += extraTab * gApp.mSettings.mEditorSettings.mTabSize; if (inCaseExprNextLine) wantSpaceCount++; @@ -1890,7 +1910,7 @@ namespace IDE.ui int alignColumn = GetLineEndColumn(lineAndColumn.mLine, isBlock, true, true); - String linePrefix = scope String('\t', alignColumn / tabSpaceCount); + String linePrefix = GetTabString(.. scope String(), alignColumn / tabSpaceCount); CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, alignColumn); bool isFullSwitch = false; @@ -2080,7 +2100,7 @@ namespace IDE.ui float x; float y; float wantWidth = 0; - int column = GetLineEndColumn(line, false, false, false, false, &wantWidth); + int column = GetLineEndColumn(line, false, false, false, false, false, &wantWidth); GetTextCoordAtLineAndColumn(line, column, out x, out y); if (wantWidth != 0) x = wantWidth + mTextInsets.mLeft; @@ -2285,7 +2305,7 @@ namespace IDE.ui } } - int indentCount = GetLineEndColumn(minLineIdx, true, true, true) / 4; + int indentCount = GetLineEndColumn(minLineIdx, true, true, true) / gApp.mSettings.mEditorSettings.mTabSize; bool wantsContentTab = indentCount == selectedIndentCount; /*if (mAllowVirtualCursor) @@ -2339,25 +2359,39 @@ namespace IDE.ui lineStart += endAdjust; lineEnd += endAdjust; } + + String tabStr = scope .(); + GetTabString(tabStr); + int32 i = 0; + + void AddTab() + { + InsertText(lineStart + i, tabStr); + for (var c in tabStr.RawChars) + { + indentTextAction.mInsertCharList.Add(((int32)(lineStart + i), c)); + endAdjust++; + i++; + } + } + if (lineIdx == minLineIdx) { - int32 i; - for (i = 0; i < indentCount; i++) + for (int indentIdx < indentCount) { - InsertText(lineStart + i, "\t"); - indentTextAction.mInsertCharList.Add(((int32)(lineStart + i), '\t')); - endAdjust++; + AddTab(); } newSel.mStartPos = (int32)(lineStart + i); if (wantsContentTab) { - InsertText(lineStart + i, "{\n\t"); + InsertText(lineStart + i, "{\n"); indentTextAction.mInsertCharList.Add(((int32)(lineStart + i), '{')); indentTextAction.mInsertCharList.Add(((int32)(lineStart + i + 1), '\n')); - indentTextAction.mInsertCharList.Add(((int32)(lineStart + i + 2), '\t')); - endAdjust += 3; + i += 2; + endAdjust += 2; + AddTab(); } else { @@ -2381,12 +2415,10 @@ namespace IDE.ui lineStart++; } - int32 i; - for (i = 0; i < indentCount; i++) - { - InsertText(lineStart + i, "\t"); - indentTextAction.mInsertCharList.Add(((int32)(lineStart + i), '\t')); - } + for (int indentIdx < indentCount) + { + AddTab(); + } if (isEmbeddedEnd) { @@ -2409,9 +2441,7 @@ namespace IDE.ui char8 c = mData.mText[lineStart].mChar; if (c != '#') { - InsertText(lineStart, "\t"); - indentTextAction.mInsertCharList.Add(((int32)(lineStart), '\t')); - endAdjust++; + AddTab(); } } } @@ -2465,7 +2495,7 @@ namespace IDE.ui int column = GetLineEndColumn(lineIdx, true, false, true); // If we're aligned with the previous line then do the 'block indent' logic, otherwise are are already indented - if (indentCount == column / 4) + if (indentCount == column / gApp.mSettings.mEditorSettings.mTabSize) { bool isExpr = false; bool mayBeExpr = false; @@ -2542,12 +2572,12 @@ namespace IDE.ui if (isExpr) { // Lambda opening or initializer expression - column += 4; + column += gApp.mSettings.mEditorSettings.mTabSize; } } CursorLineAndColumn = LineAndColumn(lineIdx, column); - indentCount = column / 4; + indentCount = column / gApp.mSettings.mEditorSettings.mTabSize; } if (lineIdx < GetLineCount() - 1) @@ -2559,13 +2589,13 @@ namespace IDE.ui for (int32 i = 0; i < nextLineText.Length; i++) { if (nextLineText[i] == '\t') - spaceCount += 4; + spaceCount += gApp.mSettings.mEditorSettings.mTabSize; else if (nextLineText[i] == ' ') spaceCount++; else break; } - if (spaceCount > indentCount * 4) + if (spaceCount > indentCount * gApp.mSettings.mEditorSettings.mTabSize) { // Next line is indented? Just simple open InsertAtCursor("{"); @@ -2581,15 +2611,14 @@ namespace IDE.ui if ((lineText.Length > 0) && (String.IsNullOrWhiteSpace(lineText))) { ClearLine(); - CursorLineAndColumn = LineAndColumn(lineIdx, indentCount * 4); + CursorLineAndColumn = LineAndColumn(lineIdx, indentCount * gApp.mSettings.mEditorSettings.mTabSize); } // This will already insert at correct position InsertAtCursor("{"); sb.Append("\n"); sb.Append("\n"); - for (int32 i = 0; i < indentCount; i++) - sb.Append("\t"); + GetTabString(sb, indentCount); sb.Append("}"); InsertAtCursor(sb); } @@ -2607,11 +2636,9 @@ namespace IDE.ui for (int i = lineText.Length; i < indentCount; i++) sb.Append("\t"); sb.Append("{\n"); - for (int i = 0; i < indentCount; i++) - sb.Append("\t"); + GetTabString(sb, indentCount); sb.Append("\t\n"); - for (int i = 0; i < indentCount; i++) - sb.Append("\t"); + GetTabString(sb, indentCount); sb.Append("}"); InsertAtCursor(sb); } @@ -2771,7 +2798,7 @@ namespace IDE.ui InsertAtCursor("*/"); if (doComment != null) - mSelection = EditSelection(firstCharPos, lastCharPos + 4); + mSelection = EditSelection(firstCharPos, lastCharPos + gApp.mSettings.mEditorSettings.mTabSize); } if (undoBatchStart != null) @@ -2877,7 +2904,7 @@ namespace IDE.ui continue; } if (c == '\t') - lineStartCol += 4; + lineStartCol += gApp.mSettings.mEditorSettings.mTabSize; else if (c == ' ') lineStartCol++; else @@ -2911,7 +2938,7 @@ namespace IDE.ui commentNow = true; if (c == '\t') - lineStartCol += 4; + lineStartCol += gApp.mSettings.mEditorSettings.mTabSize; else if (c == ' ') lineStartCol++; else @@ -2921,9 +2948,9 @@ namespace IDE.ui { CursorTextPos = i; String str = scope .(); - while (lineStartCol + 4 <= wantLineCol) + while (lineStartCol + gApp.mSettings.mEditorSettings.mTabSize <= wantLineCol) { - lineStartCol += 4; + lineStartCol += gApp.mSettings.mEditorSettings.mTabSize; str.Append("\t"); } str.Append("//"); @@ -3927,13 +3954,13 @@ namespace IDE.ui int column = GetLineEndColumn(line, isBlockOpen, true, true); if (lineTextAtCursor.StartsWith("}")) { - column -= 4; // SpacesInTab + column -= gApp.mSettings.mEditorSettings.mTabSize; // SpacesInTab } if (column > 0) { String tabStr = scope String(); - tabStr.Append('\t', column / 4); - tabStr.Append(' ', column % 4); + tabStr.Append('\t', column / gApp.mSettings.mEditorSettings.mTabSize); + tabStr.Append(' ', column % gApp.mSettings.mEditorSettings.mTabSize); InsertAtCursor(tabStr); } @@ -4076,7 +4103,7 @@ namespace IDE.ui int closeLineChar; GetLineCharAtIdx(checkPos, out closeLine, out closeLineChar); - int expectedColumn = GetLineEndColumn(closeLine, true, true, true) - 4; + int expectedColumn = GetLineEndColumn(closeLine, true, true, true) - gApp.mSettings.mEditorSettings.mTabSize; int actualColumn = GetActualLineStartColumn(closeLine); if (expectedColumn == actualColumn) @@ -4145,7 +4172,7 @@ namespace IDE.ui String lineText = scope String(); GetLineText(line, lineText); lineText.Trim(); - if ((lineText.Length == 0) && (mAllowVirtualCursor)) + if ((lineText.Length == 0) && (mAllowVirtualCursor) && (gApp.mSettings.mEditorSettings.mLeftAlignPreprocessor)) CursorLineAndColumn = LineAndColumn(line, 0); doChar = true; } @@ -4162,7 +4189,7 @@ namespace IDE.ui if (lineText.Length == 0) { ClearLine(); - CursorLineAndColumn = LineAndColumn(line, Math.Max(0, GetLineEndColumn(line, false, false) - 4)); + CursorLineAndColumn = LineAndColumn(line, Math.Max(0, GetLineEndColumn(line, false, false) - gApp.mSettings.mEditorSettings.mTabSize)); CursorMoved(); } base.KeyChar(keyChar); @@ -4282,7 +4309,11 @@ namespace IDE.ui if ((isLabel) && (trimmedLineText != "default:")) wantLineColumn = GetLineEndColumn(line, true, true, true); else - wantLineColumn = GetLineEndColumn(line, false, true, true) - 4; + { + wantLineColumn = GetLineEndColumn(line, false, true, true, false, true); + if (!gApp.mSettings.mEditorSettings.mIndentCaseLabels) + wantLineColumn -= gApp.mSettings.mEditorSettings.mTabSize; + } } // Move "case" back to be inline with switch statement @@ -4291,7 +4322,7 @@ namespace IDE.ui String tabStartStr = scope String(); tabStartStr.Append(lineText, 0, lineChar - trimmedLineText.Length); int32 columnPos = (int32)(GetTabbedWidth(tabStartStr, 0) / mCharWidth + 0.001f); - if (columnPos >= wantLineColumn + 4) + if (columnPos >= wantLineColumn + gApp.mSettings.mEditorSettings.mTabSize) { mSelection = EditSelection(); mSelection.ValueRef.mEndPos = (int32)(cursorTextIdx - trimmedLineText.Length); @@ -5193,7 +5224,7 @@ namespace IDE.ui GetCursorLineChar(out line, out lineChar); float wantWidth = 0; - int virtualEnd = GetLineEndColumn(line, false, false, false, false, &wantWidth); + int virtualEnd = GetLineEndColumn(line, false, false, false, false, false, &wantWidth); String curLineStr = scope String(); GetLineText(line, curLineStr); diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index 93353fc1..720601ee 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -6873,7 +6873,8 @@ namespace IDE.ui { int idx = embedEWC.GetTextIdx(mQueuedEmitShowData.mLine, mQueuedEmitShowData.mColumn); emitEmbed.mView.mSourceViewPanel.FocusEdit(); - emitEmbed.mView.mSourceViewPanel.ShowFileLocation(idx, .Always); + if (idx >= 0) + emitEmbed.mView.mSourceViewPanel.ShowFileLocation(idx, .Always); DeleteAndNullify!(mQueuedEmitShowData); } } diff --git a/IDEHelper/Compiler/BfParser.cpp b/IDEHelper/Compiler/BfParser.cpp index a56a3c64..d4c61f8d 100644 --- a/IDEHelper/Compiler/BfParser.cpp +++ b/IDEHelper/Compiler/BfParser.cpp @@ -3940,7 +3940,8 @@ BF_EXPORT bool BF_CALLTYPE BfParser_Reduce(BfParser* bfParser, BfPassInstance* b } static Array gCharMapping; -BF_EXPORT const char* BF_CALLTYPE BfParser_Format(BfParser* bfParser, int formatStart, int formatEnd, int** outCharMapping, int maxCol) +BF_EXPORT const char* BF_CALLTYPE BfParser_Format(BfParser* bfParser, int formatStart, int formatEnd, int** outCharMapping, int maxCol, int tabSize, bool wantsTabsAsSpaces, + bool indentCaseLabels) { BP_ZONE("BfParser_Reduce"); String& outString = *gTLStrReturn.Get(); @@ -3948,6 +3949,9 @@ BF_EXPORT const char* BF_CALLTYPE BfParser_Format(BfParser* bfParser, int format gCharMapping.Clear(); BfPrinter bfPrinter(bfParser->mRootNode, bfParser->mSidechannelRootNode, bfParser->mErrorRootNode); bfPrinter.mMaxCol = maxCol; + bfPrinter.mTabSize = tabSize; + bfPrinter.mWantsTabsAsSpaces = wantsTabsAsSpaces; + bfPrinter.mIndentCaseLabels = indentCaseLabels; bfPrinter.mFormatStart = formatStart; bfPrinter.mFormatEnd = formatEnd; bfPrinter.mCharMapping = &gCharMapping; diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index c90d0952..2d94e39a 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -45,6 +45,9 @@ BfPrinter::BfPrinter(BfRootNode *rootNode, BfRootNode *sidechannelRootNode, BfRo mCurTypeDecl = NULL; mCurCol = 0; mMaxCol = 120; + mTabSize = 4; + mWantsTabsAsSpaces = false; + mIndentCaseLabels = false; } void BfPrinter::Write(const StringView& str) @@ -59,7 +62,7 @@ void BfPrinter::Write(const StringView& str) { char c = str[i]; if (c == '\t') - mCurCol = ((mCurCol + 1) & ~3) + 4; + mCurCol = ((mCurCol / mTabSize) + 1) * mTabSize; else mCurCol++; } @@ -114,10 +117,10 @@ void BfPrinter::Write(const StringView& str) void BfPrinter::FlushIndent() { - while (mQueuedSpaceCount >= 4) + while ((mQueuedSpaceCount >= mTabSize) && (!mWantsTabsAsSpaces)) { Write("\t"); - mQueuedSpaceCount -= 4; + mQueuedSpaceCount -= mTabSize; } while (mQueuedSpaceCount > 0) @@ -141,15 +144,10 @@ void BfPrinter::Write(BfAstNode* node, int start, int len) { char c = parserData->mSrc[start + i]; if (c == '\t') - mCurCol = ((mCurCol + 1) & ~3) + 4; + mCurCol = ((mCurCol / mTabSize) + 1) * mTabSize; else mCurCol++; - } - - if ((mCurCol > mMaxCol) && (startCol != 0)) - { - NOP; - } + } } mOutString.Append(node->GetSourceData()->mSrc + start, len); @@ -287,7 +285,7 @@ int BfPrinter::CalcOrigLineSpacing(BfAstNode* bfAstNode, int* lineStartIdx) if (c == '\n') break; if (c == '\t') - origLineSpacing += 4; + origLineSpacing += mTabSize; else if (c == ' ') origLineSpacing += 1; else @@ -539,7 +537,7 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node) } else if (c == '\t') { - mQueuedSpaceCount += 4; + mQueuedSpaceCount += mTabSize; emitChar = false; } else @@ -548,7 +546,7 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node) if ((c != '#') || (mQueuedSpaceCount > 0)) mQueuedSpaceCount = std::max(0, mQueuedSpaceCount + mLastSpaceOffset); else - mQueuedSpaceCount = mCurIndentLevel * 4; // Do default indent + mQueuedSpaceCount = mCurIndentLevel * mTabSize; // Do default indent isNewLine = false; } } @@ -581,7 +579,7 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node) if ((mCurCol + len > mMaxCol) && (lineEmittedChars >= 8)) { Write("\n"); - mQueuedSpaceCount = mCurIndentLevel * 4; + mQueuedSpaceCount = mCurIndentLevel * mTabSize; FlushIndent(); if (isStarredBlockComment) @@ -674,7 +672,7 @@ void BfPrinter::CheckRawNode(BfAstNode* node) { ExpectSpace(); if (inLineStart) - spaceCount += 4; + spaceCount += mTabSize; } else if (c == ' ') { @@ -690,7 +688,7 @@ void BfPrinter::CheckRawNode(BfAstNode* node) if ((spaceCount > 0) && (mCurBlockState != NULL)) { - int indentCount = spaceCount / 4; + int indentCount = spaceCount / mTabSize; mNextStateModify.mWantVirtualIndent = BF_MAX(indentCount, mCurBlockState->mIndentStart + 1); } } @@ -765,11 +763,11 @@ void BfPrinter::Visit(BfAstNode* bfAstNode) if (c == ' ') prevSpaceCount++; else if (c == '\t') - prevSpaceCount += 4; + prevSpaceCount += mTabSize; else if (c == '\n') { // Found previous line - mCurIndentLevel = prevSpaceCount / 4; + mCurIndentLevel = prevSpaceCount / mTabSize; break; } else @@ -819,11 +817,11 @@ void BfPrinter::Visit(BfAstNode* bfAstNode) if (c == ' ') spaceCount++; else if (c == '\t') - spaceCount += 4; + spaceCount += mTabSize; if (((c == '\n') || (i == bfAstNode->GetSrcStart() - 1)) && (hadPrevLineSpacing) && (prevSpaceCount > 0)) { - mQueuedSpaceCount += std::max(0, spaceCount - prevSpaceCount) - std::max(0, indentOffset * 4); + mQueuedSpaceCount += std::max(0, spaceCount - prevSpaceCount) - std::max(0, indentOffset * mTabSize); prevSpaceCount = -1; hadPrevLineSpacing = false; @@ -840,18 +838,18 @@ void BfPrinter::Visit(BfAstNode* bfAstNode) if (c == ' ') prevSpaceCount++; else if (c == '\t') - prevSpaceCount += 4; + prevSpaceCount += mTabSize; if ((c == '\n') || (backIdx == 0)) { // Found previous line usedTrivia = true; Write("\n"); - mQueuedSpaceCount = mCurIndentLevel * 4; + mQueuedSpaceCount = mCurIndentLevel * mTabSize; // Indents extra if we have a statement split over multiple lines if (!mExpectingNewLine) - mQueuedSpaceCount += 4; + mQueuedSpaceCount += mTabSize; break; } @@ -885,7 +883,7 @@ void BfPrinter::Visit(BfAstNode* bfAstNode) if (!isspace((uint8)c)) { Write("\n"); - mQueuedSpaceCount = mCurIndentLevel * 4; + mQueuedSpaceCount = mCurIndentLevel * mTabSize; if (!mNextStateModify.mDoingBlockClose) { int origLineSpacing = CalcOrigLineSpacing(bfAstNode, NULL); @@ -1958,6 +1956,9 @@ void BfPrinter::Visit(BfCaseExpression* caseExpr) void BfPrinter::Visit(BfSwitchCase* switchCase) { + if (mIndentCaseLabels) + ExpectIndent(); + VisitChild(switchCase->mCaseToken); for (int caseIdx = 0; caseIdx < (int) switchCase->mCaseExpressions.size(); caseIdx++) { @@ -1979,6 +1980,9 @@ void BfPrinter::Visit(BfSwitchCase* switchCase) VisitChild(switchCase->mEndingSemicolonToken); ExpectNewLine(); } + + if (mIndentCaseLabels) + ExpectUnindent(); } void BfPrinter::Visit(BfWhenExpression* whenExpr) diff --git a/IDEHelper/Compiler/BfPrinter.h b/IDEHelper/Compiler/BfPrinter.h index 5c48ce67..76b68b62 100644 --- a/IDEHelper/Compiler/BfPrinter.h +++ b/IDEHelper/Compiler/BfPrinter.h @@ -79,6 +79,9 @@ public: bool mExpectingNewLine; int mCurCol; int mMaxCol; + int mTabSize; + bool mWantsTabsAsSpaces; + bool mIndentCaseLabels; bool mIsFirstStatementInBlock; bool mForceUseTrivia;