1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Early support for line/statement moving

This commit is contained in:
Brian Fiete 2020-09-06 09:05:00 -07:00
parent a62a995472
commit a650c7ab9c
5 changed files with 291 additions and 115 deletions

View file

@ -212,6 +212,10 @@ namespace IDE
Add("Make Uppercase", new () => { gApp.[Friend]ChangeCase(true); });
Add("Match Brace Select", new => gApp.Cmd_MatchBrace);
Add("Match Brace", new => gApp.Cmd_MatchBrace);
Add("Move Line Down", new () => gApp.Cmd_MoveLine(.Down));
Add("Move Line Up", new () => gApp.Cmd_MoveLine(.Up));
Add("Move Statement Down", new () => gApp.Cmd_MoveStatement(.Down));
Add("Move Statement Up", new () => gApp.Cmd_MoveStatement(.Up));
Add("Navigate Backwards", new => gApp.[Friend]NavigateBackwards);
Add("Navigate Forwards", new => gApp.[Friend]NavigateForwards);
Add("New Debug Session", new => gApp.Cmd_NewDebugSession);

View file

@ -2065,6 +2065,17 @@ namespace IDE
mBfResolveSystem.AddProject(project);
#endif
mWorkspace.ClearProjectNameCache();
if (!mWorkspace.mLoading)
{
for (var checkProject in mWorkspace.mProjects)
{
int idx = checkProject.mDependencies.FindIndex(scope (dep) => dep.mProjectName == project.mProjectName);
if (idx != -1)
ProjectOptionsChanged(checkProject);
}
ProjectOptionsChanged(project, false);
}
}
public void AddNewProjectToWorkspace(Project project, VerSpecRecord verSpec = null)
@ -2102,14 +2113,6 @@ namespace IDE
dep.mVerSpec = new .();
dep.mVerSpec.SetSemVer("*");
project.mDependencies.Add(dep);
for (var checkProject in mWorkspace.mProjects)
{
int idx = checkProject.mDependencies.FindIndex(scope (dep) => dep.mProjectName == project.mProjectName);
if (idx != -1)
ProjectOptionsChanged(checkProject);
}
ProjectOptionsChanged(project, false);
}
public Project CreateProject(String projName, String projDir, Project.TargetType targetType)
@ -2348,7 +2351,7 @@ namespace IDE
return .Err;
}
void FlushDeferredLoadProjects()
void FlushDeferredLoadProjects(bool addToUI = false)
{
while (true)
{
@ -2369,6 +2372,8 @@ namespace IDE
}
AddProjectToWorkspace(project, false);
if (addToUI)
mProjectPanel.InitProject(project);
}
}
if (!hadLoad)
@ -2402,6 +2407,12 @@ namespace IDE
bool isNew = false;
bool wantSave = false;
mWorkspace.mLoading = true;
defer
{
mWorkspace.mLoading = false;
}
if (StructuredLoad(data, workspaceFileName) case .Err(let err))
{
mBeefConfig.Refresh();
@ -3668,6 +3679,22 @@ namespace IDE
sourceViewPanel.MatchBrace();
}
[IDECommand]
public void Cmd_MoveLine(VertDir dir)
{
var sewc = GetActiveSourceEditWidgetContent();
if (sewc != null)
sewc.MoveLine(dir);
}
[IDECommand]
public void Cmd_MoveStatement(VertDir dir)
{
var sewc = GetActiveSourceEditWidgetContent();
if (sewc != null)
sewc.MoveStatement(dir);
}
[IDECommand]
public void Cmd_GotoNextItem()
{
@ -5169,6 +5196,12 @@ namespace IDE
AddMenuItem(bookmarkMenu, "&Clear Bookmarks", "Bookmark Clear");
var advancedEditMenu = subMenu.AddMenuItem("Advanced");
AddMenuItem(advancedEditMenu, "Duplicate Line", "Duplicate Line");
AddMenuItem(advancedEditMenu, "Move Line Up", "Move Line Up");
AddMenuItem(advancedEditMenu, "Move Line Down", "Move Line Down");
AddMenuItem(advancedEditMenu, "Move Statement Up", "Move Statement Up");
AddMenuItem(advancedEditMenu, "Move Statement Down", "Move Statement Down");
advancedEditMenu.AddMenuItem(null);
AddMenuItem(advancedEditMenu, "Make Uppercase", "Make Uppercase");
AddMenuItem(advancedEditMenu, "Make Lowercase", "Make Lowercase");
mViewWhiteSpace.mMenu = AddMenuItem(advancedEditMenu, "View White Space", "View White Space", null, null, true, mViewWhiteSpace.Bool ? 1 : 0);
@ -8692,6 +8725,7 @@ namespace IDE
{
RemoveProjectItems(project);
project.mDeleted = true;
mWorkspace.SetChanged();
mWorkspace.mProjects.Remove(project);
#if IDE_C_SUPPORT

View file

@ -687,6 +687,10 @@ namespace IDE
Add("Make Uppercase", "Ctrl+Shift+U");
Add("Match Brace Select", "Ctrl+Shift+RBracket");
Add("Match Brace", "Ctrl+RBracket");
Add("Move Line Down", "Alt+Shift+Down");
Add("Move Line Up", "Alt+Shift+Up");
Add("Move Statement Down", "Ctrl+Shift+Down");
Add("Move Statement Up", "Ctrl+Shift+Up");
Add("Navigate Backwards", "Alt+Left");
Add("Navigate Forwards", "Alt+Right");
Add("Next Document Panel", "Ctrl+Comma");

9
IDE/src/VertDir.bf Normal file
View file

@ -0,0 +1,9 @@
namespace IDE
{
enum VertDir
{
Up = -1,
None = 0,
Down = 1
}
}

View file

@ -2139,21 +2139,51 @@ namespace IDE.ui
mData.mUndoManager.Add(undoBatchStart.mBatchEnd);
}
bool GetStatementRange(int checkIdx, out int startIdx, out int endIdx, out char8 endChar)
enum StatementRangeFlags
{
None,
IncludeBlock,
AllowInnerMethodSelect
}
enum StatementKind
{
None,
Normal,
Method
}
StatementKind GetStatementRange(int startCheckPos, StatementRangeFlags flags, out int startIdx, out int endIdx, out char8 endChar)
{
StatementKind statementKind = .Normal;
startIdx = -1;
endIdx = -1;
endChar = 0;
GetLineCharAtIdx(checkIdx, var line, var lineChar);
GetLineCharAtIdx(startCheckPos, var line, var lineChar);
GetBlockStart(line, var foundBlockStartIdx, var blockOpenSpaceCount);
if (foundBlockStartIdx < 0)
return .None;
bool expectingStatement = true;
int stmtCommentStart = -1;
int stmtStart = -1;
int prevLineEnd = -1;
int lastNonWS = -1;
int parenCount = 0;
int lastCrPos = -1;
int braceCount = 0;
int innerBraceCount = 0;
bool hadOuterMethodColoring = false;
int lastOpenBrace = -1;
int lastCloseBrace = -1;
int commentLineStart = -1;
int commentStart = -1;
bool lineIsComment = false;
bool lineHasNonComment = false;
for (int checkPos = foundBlockStartIdx; true; checkPos++)
{
@ -2162,19 +2192,62 @@ namespace IDE.ui
char8 checkC = mData.mText[checkPos].mChar;
if (checkC == '\n')
{
prevLineEnd = checkPos;
lastCrPos = checkPos;
if (!lineIsComment)
{
commentStart = -1;
commentLineStart = -1;
}
lineIsComment = false;
lineHasNonComment = false;
}
if (checkC.IsWhiteSpace)
continue;
let displayType = (SourceElementType)mData.mText[checkPos].mDisplayTypeId;
if (displayType == .Comment)
{
if (!lineHasNonComment)
{
if (commentStart == -1)
commentStart = checkPos;
if (commentLineStart == -1)
commentLineStart = prevLineEnd + 1;
lineIsComment = true;
}
continue;
}
lineHasNonComment = true;
lineIsComment = false;
if (innerBraceCount > 0)
{
if (checkC == '{')
{
innerBraceCount++;
braceCount++;
}
if (checkC == '}')
{
lastNonWS = checkPos;
innerBraceCount--;
braceCount--;
}
if (innerBraceCount > 0)
continue;
}
if (displayType == .Normal)
{
if (checkC == '(')
{
parenCount++;
}
else if (checkC == ')')
parenCount--;
}
@ -2182,40 +2255,116 @@ namespace IDE.ui
if (parenCount != 0)
continue;
if (displayType == .Method)
hadOuterMethodColoring = true;
if ((displayType == .Normal) &&
((checkC == '{') || (checkC == '}') || (checkC == ';')))
{
if ((checkPos >= checkIdx) && (!expectingStatement))
if (checkC == '{')
{
lastOpenBrace = checkPos;
braceCount++;
}
if (checkC == '}')
{
lastCloseBrace = checkPos;
braceCount--;
}
if ((checkPos >= startCheckPos) && (!expectingStatement))
{
if (checkC == '{')
{
if (hadOuterMethodColoring)
statementKind = .Method;
if ((flags.HasFlag(.IncludeBlock)) || (statementKind == .Method))
{
innerBraceCount++;
continue;
}
}
endChar = checkC;
if (lastNonWS < checkIdx)
return false;
if (lastNonWS < startCheckPos)
return .None;
startIdx = stmtStart;
if ((stmtCommentStart != -1) && (stmtCommentStart < startIdx))
startIdx = stmtCommentStart;
if (checkC == '{')
endIdx = lastNonWS + 1;
return true;
else
endIdx = checkPos + 1;
return statementKind;
}
expectingStatement = true;
hadOuterMethodColoring = false;
}
else if (expectingStatement)
{
if (lastCrPos >= checkIdx)
if (lastCrPos >= startCheckPos)
{
return false;
if ((commentLineStart == -1) || (commentLineStart > startCheckPos))
break;
}
expectingStatement = false;
stmtStart = checkPos;
stmtCommentStart = commentStart;
}
lastNonWS = checkPos;
commentStart = -1;
}
if (!flags.HasFlag(.AllowInnerMethodSelect))
return .None;
// If out starting pos is within a method then select the whole thing
if ((startCheckPos >= lastOpenBrace) && (startCheckPos <= lastCloseBrace) && (braceCount != 0))
{
let checkStmtKind = GetStatementRange(Math.Max(lastOpenBrace - 1, 0), .None, var checkStartIdx, var checkEndIdx, var checkEndChar);
//if ((checkStmtKind == .Method) && (startCheckPos >= checkStartIdx) && (startCheckPos <= checkEndIdx))
if (checkStmtKind == .Method)
{
startIdx = checkStartIdx;
endIdx = checkEndIdx;
endChar = checkEndChar;
return checkStmtKind;
}
}
return .None;
}
bool LineIsComment(int lineNum)
{
if (lineNum >= GetLineCount())
return false;
GetLinePosition(lineNum, var lineStart, var lineEnd);
bool lineIsComment = false;
for (int checkPos = lineStart; checkPos < lineEnd; checkPos++)
{
char8 checkC = mData.mText[checkPos].mChar;
if (checkC.IsWhiteSpace)
continue;
let displayType = (SourceElementType)mData.mText[checkPos].mDisplayTypeId;
if (displayType != .Comment)
return false;
lineIsComment = true;
}
void MoveSelection(int toLinePos)
return lineIsComment;
}
void MoveSelection(int toLinePos, bool isStatementAware)
{
/*if (GetStatementRange(CursorTextPos, var startIdx, var endIdx))
{
@ -2246,12 +2395,14 @@ namespace IDE.ui
String offsetText = scope .();
ExtractString(offsetLineStart, offsetLineEnd - offsetLineStart, offsetText);
if (isStatementAware)
{
if (movingDown)
{
GetLinePosition(Math.Max(offsetLinePos - 1, 0), var toLineStart, var toLineEnd);
String txt = scope .();
ExtractString(toLineStart, toLineEnd - toLineStart, txt);
if (GetStatementRange(toLineStart, var stmtStartIdx, var stmtEndIdx, var stmtEndChar))
if (GetStatementRange(toLineStart, .None, var stmtStartIdx, var stmtEndIdx, var stmtEndChar) != .None)
{
String stmt = scope .();
ExtractString(stmtStartIdx, stmtEndIdx - stmtStartIdx, stmt);
@ -2262,35 +2413,29 @@ namespace IDE.ui
if (stmtEndChar == '{')
offsetLinePos++;
}
else if (GetStatementRange(toLineStart, .AllowInnerMethodSelect, var stmtStartIdx, var stmtEndIdx, var stmtEndChar) == .Method)
{
if (stmtStartIdx <= toLineStart)
{
GetLineCharAtIdx(stmtEndIdx, var endLine, var endChar);
//if (offsetLinePos)
offsetLinePos = endLine + 1;
}
}
}
else
{
/*for (int checkPos = offsetLineStart; checkPos < offsetLineEnd; checkPos++)
{
if (mData.mText[checkPos].mDisplayTypeId != 0)
continue;
char8 checkC = mData.mText[checkPos].mChar;
if (checkC.IsWhiteSpace)
continue;
if (checkC == '{')
{
if (offsetLinePos > prevCursorLineAndColumn.mLine)
offsetLinePos--;
}
break;
}*/
GetLinePosition(Math.Max(offsetLinePos, 0), var toLineStart, var toLineEnd);
String txt = scope .();
ExtractString(toLineStart, toLineEnd - toLineStart, txt);
if (!GetStatementRange(toLineStart, var stmtStartIdx, var stmtEndIdx, var stmtEndChar))
if (GetStatementRange(toLineStart, .None, var stmtStartIdx, var stmtEndIdx, var stmtEndChar) == .None)
{
if (stmtEndChar == '{')
GetLinePosition(Math.Max(offsetLinePos - 1, 0), out toLineStart, out toLineEnd);
}
if (GetStatementRange(toLineStart, var stmtStartIdx, var stmtEndIdx, var stmtEndChar))
if (GetStatementRange(toLineStart, .AllowInnerMethodSelect, var stmtStartIdx, var stmtEndIdx, var stmtEndChar) != .None)
{
String stmt = scope .();
ExtractString(stmtStartIdx, stmtEndIdx - stmtStartIdx, stmt);
@ -2299,9 +2444,9 @@ namespace IDE.ui
GetLinePosition(Math.Max(offsetLinePos, 0), out offsetLineStart, out offsetLineEnd);
}
}
}
let wantCursorPos = LineAndColumn(Math.Max(offsetLinePos, 0), 0);
var wantCursorPos = LineAndColumn(Math.Max(offsetLinePos, 0), 0);
if (wantCursorPos.mLine >= GetLineCount())
{
CursorTextPos = mData.mTextLength;
@ -2309,6 +2454,19 @@ namespace IDE.ui
}
CursorLineAndColumn = wantCursorPos;
String txt = scope .();
ExtractLine(offsetLinePos, txt);
if ((isStatementAware) && (LineIsComment(offsetLinePos - 1)))
{
if (movingDown)
{
InsertAtCursor("\n");
wantCursorPos.mLine++;
}
}
PasteText(str, "line");
CursorLineAndColumn = LineAndColumn(wantCursorPos.mLine, prevCursorLineAndColumn.mColumn);
@ -2320,61 +2478,26 @@ namespace IDE.ui
int lineNum = CursorLineAndColumn.mLine;
GetLinePosition(lineNum, var lineStart, var lineEnd);
mSelection = .(lineStart, Math.Min(lineEnd + 1, mData.mTextLength));
MoveSelection(lineNum + (int)dir);
MoveSelection(lineNum + (int)dir, false);
}
public void MoveStatement(VertDir dir)
{
int lineNum = CursorLineAndColumn.mLine;
int origLineNum = lineNum;
GetLinePosition(lineNum, var lineStart, var lineEnd);
int selStart = -1;
int selEnd = -1;
int parenDepth = 0;
int checkPos = lineStart;
for ( ; checkPos < mData.mTextLength - 1; checkPos++)
{
char8 checkC = mData.mText[checkPos].mChar;
if (selStart == -1)
{
if (checkC == '\n')
break; // Don't support moving empty lines
if (!checkC.IsWhiteSpace)
{
selStart = checkPos;
}
}
if (mData.mText[checkPos].mDisplayTypeId != 0)
continue;
if ((checkC == ';') && (parenDepth == 0))
{
selEnd = checkPos + 1;
break;
}
if (checkC == '{')
{
parenDepth++;
}
if (checkC == '}')
{
parenDepth--;
if (parenDepth <= 0)
{
selEnd = checkPos + 1;
break;
}
}
}
if (selEnd == -1)
var stmtKind = GetStatementRange(lineStart, .IncludeBlock, var stmtStart, var stmtEnd, var endChar);
if (stmtKind == .None)
return;
GetLineCharAtIdx(stmtStart, var startLineNum, var startLineChar);
GetLinePosition(startLineNum, out lineStart, out lineEnd);
lineNum = startLineNum;
int checkPos = stmtEnd;
int selEnd = stmtEnd;
for ( ; checkPos < mData.mTextLength - 1; checkPos++)
{
char8 checkC = mData.mText[checkPos].mChar;
@ -2396,7 +2519,9 @@ namespace IDE.ui
GetLineCharAtIdx(selEnd, var line, var lineChar);
toLine = line;
}
MoveSelection(toLine);
MoveSelection(toLine, true);
CursorLineAndColumn = .(Math.Min(CursorLineAndColumn.mLine + (origLineNum - startLineNum), Math.Max(GetLineCount() - 1, 0)), CursorLineAndColumn.mColumn);
mData.mUndoManager.Add(undoBatchStart.mBatchEnd);
}