From 743a8da08bd01f7ef50eca8a10a724eaf9be2b78 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 17 Oct 2020 12:59:10 -0700 Subject: [PATCH] Reworked IDE paren pair support --- BeefLibs/Beefy2D/src/widgets/EditWidget.bf | 30 +++++++------ IDE/src/ui/SourceEditWidgetContent.bf | 50 ++++++++++++++++++---- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/BeefLibs/Beefy2D/src/widgets/EditWidget.bf b/BeefLibs/Beefy2D/src/widgets/EditWidget.bf index 1f8ea403..ae10afee 100644 --- a/BeefLibs/Beefy2D/src/widgets/EditWidget.bf +++ b/BeefLibs/Beefy2D/src/widgets/EditWidget.bf @@ -1116,7 +1116,7 @@ namespace Beefy.widgets if (moveCursor) { textPos += insertStr.Length; - MoveCursorToIdx((int32)textPos); + MoveCursorToIdx((int32)textPos, false, .FromTyping); if (mEnsureCursorVisibleOnModify) EnsureCursorVisible(); } @@ -1519,7 +1519,7 @@ namespace Beefy.widgets ContentChanged(); if (offset != 0) { - MoveCursorToIdx(textPos); + MoveCursorToIdx(textPos, false, .FromTyping); EnsureCursorVisible(); } } @@ -1675,12 +1675,12 @@ namespace Beefy.widgets return true; } - public void InsertCharPair(String char8Pair) + public void InsertCharPair(String charPair) { if (CheckReadOnly()) return; - InsertAtCursor(char8Pair); - MoveCursorToIdx(CursorTextPos - 1); + InsertAtCursor(charPair); + MoveCursorToIdx(CursorTextPos - 1, false, .FromTyping); mJustInsertedCharPair = true; } @@ -2865,9 +2865,15 @@ namespace Beefy.widgets y = 0; } + public enum CursorMoveKind + { + FromTyping, + Unknown + } + // We used to have a split between PhysCursorMoved and CursorMoved. CursorMoved has a "ResetWantX" and was non-virtual... uh- // so what was that for? - public virtual void PhysCursorMoved() + public virtual void PhysCursorMoved(CursorMoveKind moveKind) { mJustInsertedCharPair = false; mShowCursorAtLineEnd = false; @@ -2880,7 +2886,7 @@ namespace Beefy.widgets public void CursorMoved() { - PhysCursorMoved(); + PhysCursorMoved(.Unknown); /*mJustInsertedCharPair = false; mShowCursorAtLineEnd = false; @@ -3350,7 +3356,7 @@ namespace Beefy.widgets //public void MoveCursorTo - public void MoveCursorTo(int line, int char8Idx, bool centerCursor = false, int movingDir = 0) + public void MoveCursorTo(int line, int char8Idx, bool centerCursor = false, int movingDir = 0, CursorMoveKind cursorMoveKind = .Unknown) { int useCharIdx = char8Idx; @@ -3391,7 +3397,7 @@ namespace Beefy.widgets mCursorBlinkTicks = 0; if (mEnsureCursorVisibleOnModify) EnsureCursorVisible(true, centerCursor); - PhysCursorMoved(); + PhysCursorMoved(cursorMoveKind); } public void ResetWantX() @@ -3400,12 +3406,12 @@ namespace Beefy.widgets mCursorWantX = x; } - public void MoveCursorToIdx(int index, bool centerCursor = false) + public void MoveCursorToIdx(int index, bool centerCursor = false, CursorMoveKind cursorMoveKind = .Unknown) { int aLine; int aCharIdx; GetLineCharAtIdx(index, out aLine, out aCharIdx); - MoveCursorTo(aLine, aCharIdx, centerCursor); + MoveCursorTo(aLine, aCharIdx, centerCursor, 0, cursorMoveKind); } public void MoveCursorToCoord(float x, float y) @@ -3423,7 +3429,7 @@ namespace Beefy.widgets GetLineAndColumnAtCoord(x, y, out line, out column); CursorLineAndColumn = LineAndColumn(line, column); mCursorBlinkTicks = 0; - PhysCursorMoved(); + PhysCursorMoved(.Unknown); mShowCursorAtLineEnd = false; } else diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index 2e5f2931..f75da8a1 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -218,7 +218,7 @@ namespace IDE.ui ) ~ delete _; bool mHasCustomColors; FastCursorState mFastCursorState ~ delete _; - + public HashSet mCurParenPairIdSet = new .() ~ delete _; public List PersistentTextPositions { @@ -1439,7 +1439,7 @@ namespace IDE.ui InsertAtCursor(useString); // If we paste in "if (a)\n\tDoThing();", we want "DoThing();" to be indented, so we need to fix this. - // This isn't a problem if we had "if (a)\n\tDoThing()\nDoOtherThing();" because minColumn would match + // This isn't a problem if we had "if (a)\n\tDoThing()\nDoOtherThing(1);" because minColumn would match // DoOtherThing so DoThing would indent properly (for example) if ((didFormattedPaste) && (lineAndColumn.mLine < GetLineCount() - 1)) { @@ -2674,6 +2674,28 @@ namespace IDE.ui mAutoComplete.CloseListWindow();*/ } + bool IsCurrentPairClosing(int cursorIdx) + { + int32 closeId = mData.mTextIdData.GetIdAtIndex(cursorIdx); + if (closeId != -1) + { + int32 openId = closeId - 1; + if (mCurParenPairIdSet.Contains(openId)) + { + int openCursorIdx = mData.mTextIdData.GetIndexFromId(openId); + if (openCursorIdx != -1) + return true; + } + } + return false; + } + + void InsertCharPair(String charPair) + { + mCurParenPairIdSet.Add(mData.mNextCharId); + base.InsertCharPair(charPair); + } + public override void KeyChar(char32 keyChar) { scope AutoBeefPerf("SEWC.KeyChar"); @@ -3037,7 +3059,11 @@ namespace IDE.ui if (cursorTextPos < mData.mTextLength) { char8UnderCursor = (char8)mData.mText[cursorTextPos].mChar; - cursorInOpenSpace = ((char8UnderCursor == ')') || (char8UnderCursor == ']') || (char8UnderCursor == (char8)0) || (char8UnderCursor.IsWhiteSpace)); + cursorInOpenSpace = ((char8UnderCursor == ')') || (char8UnderCursor == ']') || (char8UnderCursor == ';') || (char8UnderCursor == (char8)0) || (char8UnderCursor.IsWhiteSpace)); + + if (((keyChar == '(') && (char8UnderCursor == ')')) || + ((keyChar == '[') && (char8UnderCursor == ']'))) + cursorInOpenSpace = IsCurrentPairClosing(cursorTextPos); if ((char8UnderCursor == keyChar) && (!HasSelection())) { @@ -3059,7 +3085,8 @@ namespace IDE.ui if (!ignore) { if ((mData.mText[checkPos].mDisplayTypeId == (int32)wantElementType) && - ((keyChar == '"') || (keyChar == '\'') || (keyChar == ')') || (keyChar == ']') || (keyChar == '>') || (keyChar == '}'))) + ((keyChar == '"') || (keyChar == '\'') || (keyChar == ')') || (keyChar == ']') || (keyChar == '>') || (keyChar == '}')) && + (IsCurrentPairClosing(checkPos))) { mJustInsertedCharPair = false; CursorTextPos++; @@ -3176,7 +3203,9 @@ namespace IDE.ui base.KeyChar(keyChar); } else if ((keyChar == '(') && (cursorInOpenSpace)) - InsertCharPair("()"); + { + InsertCharPair("()"); + } else if ((keyChar == '{') && (cursorInOpenSpace)) { /*int lineStart; @@ -4104,11 +4133,16 @@ namespace IDE.ui mVirtualCursorPos.ValueRef.mColumn = (.)Math.Min(mVirtualCursorPos.Value.mColumn, Math.Max(virtualEnd, lineEnd)); } - public override void PhysCursorMoved() + public override void PhysCursorMoved(CursorMoveKind moveKind) { - //Debug.WriteLine("Cursor moved {0} {1}", CursorLineAndColumn.mLine, CursorLineAndColumn.mColumn); + //Debug.WriteLine("Cursor moved {0} {1} {2}", CursorLineAndColumn.mLine, CursorLineAndColumn.mColumn, moveKind); - base.PhysCursorMoved(); + if (moveKind != .FromTyping) + { + mCurParenPairIdSet.Clear(); + } + + base.PhysCursorMoved(moveKind); mCursorStillTicks = 0; if ((mSourceViewPanel != null) && (mSourceViewPanel.mHoverWatch != null))