public GetVirtualIndentationColumn ( Mono.TextEditor.DocumentLocation loc ) : int | ||
loc | Mono.TextEditor.DocumentLocation | |
return | int |
public static void Right(TextEditorData data) { if (Platform.IsMac && data.IsSomethingSelected && !data.Caret.PreserveSelection) { data.Caret.Offset = System.Math.Max(data.SelectionAnchor, data.Caret.Offset); data.ClearSelection(); return; } DocumentLine line = data.Document.GetLine(data.Caret.Line); IEnumerable <FoldSegment> foldings = data.Document.GetStartFoldings(line); FoldSegment segment = null; foreach (FoldSegment folding in foldings) { if (folding.IsFolded && folding.Column == data.Caret.Column) { segment = folding; break; } } if (segment != null) { data.Caret.Offset = segment.EndOffset; return; } if (data.Caret.Column >= line.Length + 1) { int nextColumn; if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual && data.Caret.Column == DocumentLocation.MinColumn) { nextColumn = data.GetVirtualIndentationColumn(data.Caret.Location); } else if (data.Caret.AllowCaretBehindLineEnd) { nextColumn = data.Caret.Column + 1; } else { nextColumn = line.Length + 1; } if (data.Caret.Column < nextColumn) { data.Caret.Column = nextColumn; } else { if (data.Caret.Line < data.LineCount) { data.Caret.Location = new DocumentLocation(data.Caret.Line + 1, DocumentLocation.MinColumn); } } } else { data.Caret.Column++; } }
void CheckColumn() { var curLine = TextEditorData.Document.GetLine(Line); if (TextEditorData.HasIndentationTracker && TextEditorData.Options.IndentStyle == IndentStyle.Virtual && curLine.Length == 0) { if (column > DocumentLocation.MinColumn) { var indentColumn = TextEditorData.GetVirtualIndentationColumn(Location); if (column < indentColumn) { column = indentColumn; UpdateCaretOffset(); return; } if (column == indentColumn) { return; } } } if (!AllowCaretBehindLineEnd) { var max = curLine.Length + 1; if (column > max) { column = max; UpdateCaretOffset(); } } }
static void SmartBackspace(TextEditorData data, DocumentLine line) { var prevLine = line.PreviousLine; var prevLineIsEmpty = prevLine != null && prevLine.Length == 0; var startOffset = prevLine != null ? prevLine.EndOffset : 0; var count = data.Caret.Offset - startOffset; if (count < 0 || startOffset >= data.Length) { return; } data.Remove(startOffset, count); if (prevLine != null) { if (prevLineIsEmpty) { if (line.Length - data.Caret.Column - 1 > 0 && data.HasIndentationTracker) { data.InsertAtCaret(data.IndentationTracker.GetIndentationString(data.Caret.Line)); } else { data.Caret.Column = data.GetVirtualIndentationColumn(prevLine.Offset); } } data.FixVirtualIndentation(); } }
public static void Left (TextEditorData data) { if (Platform.IsMac && data.IsSomethingSelected && !data.Caret.PreserveSelection) { data.Caret.Offset = System.Math.Min (data.SelectionAnchor, data.Caret.Offset); data.ClearSelection (); return; } if (data.Caret.Column > DocumentLocation.MinColumn) { DocumentLine line = data.Document.GetLine (data.Caret.Line); if (data.Caret.Column > line.Length + 1) { if (data.Caret.AllowCaretBehindLineEnd) { data.Caret.Column--; } else { data.Caret.Column = line.Length + 1; } } else { int offset = data.Caret.Offset - 1; foreach (var folding in data.Document.GetFoldingsFromOffset (offset).Where (f => f.IsFolded && f.Offset < offset)) { offset = System.Math.Min (offset, folding.Offset); } data.Caret.Offset = offset; } } else if (data.Caret.Line > DocumentLocation.MinLine) { DocumentLine prevLine = data.Document.GetLine (data.Caret.Line - 1); var nextLocation = new DocumentLocation (data.Caret.Line - 1, prevLine.Length + 1); if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual && nextLocation.Column == DocumentLocation.MinColumn) nextLocation = new DocumentLocation (data.Caret.Line - 1, data.GetVirtualIndentationColumn (nextLocation)); data.Caret.Location = nextLocation; } }
public static void InsertNewLine(TextEditorData data) { if (!data.CanEditSelection) { return; } using (var undo = data.OpenUndoGroup()) { if (data.IsSomethingSelected) { data.DeleteSelectedText(); } switch (data.Options.IndentStyle) { case IndentStyle.None: data.InsertAtCaret(data.EolMarker); break; case IndentStyle.Auto: data.EnsureCaretIsNotVirtual(); var sb = new StringBuilder(data.EolMarker); sb.Append(data.Document.GetLineIndent(data.Caret.Line)); data.InsertAtCaret(sb.ToString()); break; case IndentStyle.Smart: if (!data.HasIndentationTracker) { goto case IndentStyle.Auto; } NewLineSmartIndent(data); break; case IndentStyle.Virtual: if (!data.HasIndentationTracker) { goto case IndentStyle.Auto; } var oldLine = data.Caret.Line; var curLine = data.GetLine(oldLine); var indentCol = data.GetVirtualIndentationColumn(data.Caret.Location); if (curLine.Length >= data.Caret.Column) { NewLineSmartIndent(data); data.FixVirtualIndentation(); data.FixVirtualIndentation(oldLine); break; } data.Insert(data.Caret.Offset, data.EolMarker); data.FixVirtualIndentation(oldLine); data.Caret.Column = indentCol; break; default: throw new ArgumentOutOfRangeException(); } } }
internal void UpdateCaretPosition(DocumentChangeEventArgs e) { if (e.AnchorMovementType == AnchorMovementType.BeforeInsertion && caretOffset == e.Offset) { return; } var curVersion = TextEditorData.Version; if (offsetVersion == null) { offsetVersion = curVersion; return; } var newOffset = offsetVersion.MoveOffsetTo(curVersion, caretOffset); offsetVersion = curVersion; if (newOffset == caretOffset || !AutoUpdatePosition) { return; } DocumentLocation old = Location; var newLocation = TextEditorData.OffsetToLocation(newOffset); int newColumn = newLocation.Column; var curLine = TextEditorData.GetLine(newLocation.Line); if (TextEditorData.HasIndentationTracker && TextEditorData.Options.IndentStyle == IndentStyle.Virtual && curLine.Length == 0) { var indentColumn = TextEditorData.GetVirtualIndentationColumn(Location); if (column == indentColumn) { newColumn = indentColumn; } } if (AllowCaretBehindLineEnd) { if (curLine != null && column > curLine.Length) { newColumn = column; } } line = newLocation.Line; column = newColumn; SetDesiredColumn(); UpdateCaretOffset(); OnPositionChanged(new DocumentLocationEventArgs(old)); }
public static void Left(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { if (Platform.IsMac && data.IsSomethingSelected && !data.Caret.PreserveSelection) { data.Caret.Offset = System.Math.Min(data.SelectionAnchor, data.Caret.Offset); data.ClearSelection(); return; } if (data.Caret.Column > DocumentLocation.MinColumn) { DocumentLine line = data.Document.GetLine(data.Caret.Line); if (data.Caret.Column > line.Length + 1) { if (data.Caret.AllowCaretBehindLineEnd) { data.Caret.Column--; } else { data.Caret.Column = line.Length + 1; } } else { int offset = data.Caret.Offset - 1; foreach (var folding in data.Document.GetFoldingsFromOffset(offset).Where(f => f.IsFolded && f.Offset < offset)) { offset = System.Math.Min(offset, folding.Offset); } data.Caret.Offset = offset; } } else if (data.Caret.Line > DocumentLocation.MinLine) { DocumentLine prevLine = data.Document.GetLine(data.Caret.Line - 1); var nextLocation = new DocumentLocation(data.Caret.Line - 1, prevLine.Length + 1); if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual && nextLocation.Column == DocumentLocation.MinColumn) { nextLocation = new DocumentLocation(data.Caret.Line - 1, data.GetVirtualIndentationColumn(nextLocation)); } data.Caret.Location = nextLocation; } } }
internal void UpdateCaretPosition(TextChangeEventArgs e) { //if (e.AnchorMovementType == AnchorMovementType.BeforeInsertion && caretOffset == e.Offset) { // offsetVersion = TextEditorData.Version; // return; //} var curVersion = TextEditorData.Version; var newOffset = e.GetNewOffset(caretOffset); if (!AutoUpdatePosition) { return; } DocumentLocation old = Location; var newLocation = TextEditorData.OffsetToLocation(newOffset); int newColumn = newLocation.Column; var curLine = TextEditorData.GetLine(newLocation.Line); if (TextEditorData.HasIndentationTracker && TextEditorData.Options.IndentStyle == IndentStyle.Virtual && curLine.Length == 0) { var indentColumn = TextEditorData.GetVirtualIndentationColumn(newLocation); if (column == indentColumn) { newColumn = indentColumn; } } if (AllowCaretBehindLineEnd) { if (curLine != null && column > curLine.Length) { newColumn = column; } } line = newLocation.Line; column = newColumn; SetDesiredColumn(); UpdateCaretOffset(); OnPositionChanged(new CaretLocationEventArgs(old, currentBuffer ?? TextEditorData.Document.TextBuffer.CurrentSnapshot, CaretChangeReason.BufferChange)); }
public static void LineEnd(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { if (!data.Caret.PreserveSelection) { data.ClearSelection(); } var line = data.Document.GetLine(data.Caret.Line); var newLocation = new DocumentLocation(data.Caret.Line, line.Length + 1); // handle folding IEnumerable <FoldSegment> foldings = data.Document.GetStartFoldings(line); FoldSegment segment = null; foreach (FoldSegment folding in foldings) { if (folding.IsFolded && folding.Contains(data.Document.LocationToOffset(newLocation))) { segment = folding; break; } } if (segment != null) { newLocation = data.Document.OffsetToLocation(segment.EndLine.Offset + segment.EndColumn - 1); } if (newLocation != data.Caret.Location) { data.Caret.Location = newLocation; } if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual) { int virtualIndentColumn = data.GetVirtualIndentationColumn(data.Caret.Location); if (virtualIndentColumn > data.Caret.Column) { data.Caret.Column = virtualIndentColumn; } } } }
void SetColumn() { var curLine = TextEditorData.Document.GetLine(Line); if (curLine == null) { return; } column = System.Math.Max(DocumentLocation.MinColumn, Column); column = curLine.GetLogicalColumn(TextEditorData, DesiredColumn); if (TextEditorData.HasIndentationTracker && TextEditorData.Options.IndentStyle == IndentStyle.Virtual && curLine.GetVisualColumn(TextEditorData, column) < DesiredColumn) { column = TextEditorData.GetVirtualIndentationColumn(Line, column); } else { if (!AllowCaretBehindLineEnd && Column > curLine.Length + 1) { column = System.Math.Min(curLine.Length + 1, column); } } }
public void SetToOffsetWithDesiredColumn(int desiredOffset) { DocumentLocation old = Location; int desiredLineNumber = TextEditorData.Document.OffsetToLineNumber(desiredOffset); var desiredLine = TextEditorData.Document.GetLine(desiredLineNumber); int newColumn = desiredOffset - desiredLine.Offset + 1; if (desiredLine.Length + 1 < Column && newColumn == 1) { if (TextEditorData.HasIndentationTracker && TextEditorData.Options.IndentStyle == IndentStyle.Virtual) { newColumn = TextEditorData.GetVirtualIndentationColumn(desiredLineNumber, 1); } } line = desiredLineNumber; column = newColumn; var logicalDesiredColumn = desiredLine.GetLogicalColumn(TextEditorData, DesiredColumn); if (logicalDesiredColumn <= desiredLine.Length + 1) { int possibleOffset = TextEditorData.LocationToOffset(desiredLineNumber, logicalDesiredColumn); if (!TextEditorData.Document.GetFoldingsFromOffset(possibleOffset).Any(f => f.IsCollapsed)) { column = logicalDesiredColumn; } } else { column = System.Math.Max(newColumn, desiredLine.Length + 1); } UpdateCaretOffset(); OnPositionChanged(new CaretLocationEventArgs(old, currentBuffer ?? TextEditorData.Document.TextBuffer.CurrentSnapshot, CaretChangeReason.Movement)); }
public static void InsertNewLine (TextEditorData data) { if (!data.CanEditSelection) return; using (var undo = data.OpenUndoGroup ()) { if (data.IsSomethingSelected) data.DeleteSelectedText (); switch (data.Options.IndentStyle) { case IndentStyle.None: data.InsertAtCaret (data.EolMarker); break; case IndentStyle.Auto: data.EnsureCaretIsNotVirtual (); var sb = new StringBuilder (data.EolMarker); sb.Append (data.Document.GetLineIndent (data.Caret.Line)); data.InsertAtCaret (sb.ToString ()); break; case IndentStyle.Smart: if (!data.HasIndentationTracker) goto case IndentStyle.Auto; NewLineSmartIndent (data); break; case IndentStyle.Virtual: if (!data.HasIndentationTracker) goto case IndentStyle.Auto; var oldLine = data.Caret.Line; var curLine = data.GetLine (oldLine); var indentCol = data.GetVirtualIndentationColumn (data.Caret.Location); if (curLine.Length >= data.Caret.Column) { NewLineSmartIndent (data); data.FixVirtualIndentation (); data.FixVirtualIndentation (oldLine); break; } data.Insert (data.Caret.Offset, data.EolMarker); data.FixVirtualIndentation (oldLine); data.Caret.Column = indentCol; break; default: throw new ArgumentOutOfRangeException (); } } }
public static void Left(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { if (Platform.IsMac && data.IsSomethingSelected && !data.Caret.PreserveSelection) { data.Caret.Offset = System.Math.Min(data.SelectionAnchor, data.Caret.Offset); data.ClearSelection(); return; } if (data.Caret.Column > DocumentLocation.MinColumn) { DocumentLine line = data.Document.GetLine(data.Caret.Line); if (data.Caret.Column > line.Length + 1) { if (data.Caret.AllowCaretBehindLineEnd) { data.Caret.Column--; } else { data.Caret.Column = line.Length + 1; } } else { int offset = data.Caret.Offset - 1; bool foundFolding = false; foreach (var folding in data.Document.GetFoldingsFromOffset(offset).Where(f => f.IsCollapsed && f.Offset < offset)) { offset = System.Math.Min(offset, folding.Offset); foundFolding = true; } if (!foundFolding) { var layout = data.Parent?.TextViewMargin?.GetLayout(line); if (layout != null && data.Caret.Column < line.Length) { uint curIndex = 0, byteIndex = 0; int utf8ByteIndex = (int)layout.TranslateToUTF8Index((uint)(offset - line.Offset), ref curIndex, ref byteIndex); layout.Layout.GetCursorPos(utf8ByteIndex, out var strong_pos, out var weak_pos); if (strong_pos.X != weak_pos.X) { offset--; } } } data.Caret.Offset = offset; } } else if (data.Caret.Line > DocumentLocation.MinLine) { DocumentLine prevLine = data.Document.GetLine(data.Caret.Line - 1); var nextLocation = new DocumentLocation(data.Caret.Line - 1, prevLine.Length + 1); if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual && nextLocation.Column == DocumentLocation.MinColumn) { nextLocation = new DocumentLocation(data.Caret.Line - 1, data.GetVirtualIndentationColumn(nextLocation)); } data.Caret.Location = nextLocation; } var curOffset = data.Caret.Offset; if (curOffset > 0 && curOffset < data.Length && IsLowSurrogateMarkerSet(data.GetCharAt(curOffset))) { data.Caret.Offset--; } } }
public static void Right(TextEditorData data) { using (var undo = data.OpenUndoGroup()) { if (Platform.IsMac && data.IsSomethingSelected && !data.Caret.PreserveSelection) { data.Caret.Offset = System.Math.Max(data.SelectionAnchor, data.Caret.Offset); data.ClearSelection(); return; } DocumentLine line = data.Document.GetLine(data.Caret.Line); IEnumerable <FoldSegment> foldings = data.Document.GetStartFoldings(line); FoldSegment segment = null; foreach (FoldSegment folding in foldings) { if (folding.IsCollapsed && folding.Offset == data.Caret.Offset) { segment = folding; break; } } if (segment != null) { data.Caret.Offset = segment.EndOffset; return; } if (data.Caret.Column >= line.Length + 1) { int nextColumn; if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual && data.Caret.Column == DocumentLocation.MinColumn) { nextColumn = data.GetVirtualIndentationColumn(data.Caret.Location); } else if (data.Caret.AllowCaretBehindLineEnd) { nextColumn = data.Caret.Column + 1; } else { nextColumn = line.Length + 1; } if (data.Caret.Column < nextColumn) { data.Caret.Column = nextColumn; } else { if (data.Caret.Line < data.LineCount) { data.Caret.Location = new DocumentLocation(data.Caret.Line + 1, DocumentLocation.MinColumn); } } } else { data.Caret.Column++; var layout = data.Parent?.TextViewMargin?.GetLayout(line); if (layout != null && data.Caret.Column < line.Length) { uint curIndex = 0, byteIndex = 0; int utf8ByteIndex = (int)layout.TranslateToUTF8Index((uint)data.Caret.Column - 1, ref curIndex, ref byteIndex); layout.Layout.GetCursorPos(utf8ByteIndex, out var strong_pos, out var weak_pos); if (strong_pos.X != weak_pos.X) { data.Caret.Column++; } } } var curOffset = data.Caret.Offset; if (curOffset > 0 && curOffset < data.Length && IsLowSurrogateMarkerSet(data.GetCharAt(curOffset))) { data.Caret.Offset++; } } }
public static void InsertNewLine(TextEditorData data) { if (!data.CanEditSelection) { return; } using (var undo = data.OpenUndoGroup()) { if (data.IsSomethingSelected) { var end = data.MainSelection.End; data.DeleteSelectedText(); if (end.Column == 1) { CaretMoveActions.InternalCaretMoveHome(data, true, false); return; } } switch (data.Options.IndentStyle) { case IndentStyle.None: data.InsertAtCaret(data.EolMarker); break; case IndentStyle.Auto: data.EnsureCaretIsNotVirtual(); var indent = data.Document.GetLineIndent(data.Caret.Line); data.InsertAtCaret(data.EolMarker); data.EnsureCaretIsNotVirtual(); if (data.GetLine(data.Caret.Line).Length == 0) { data.InsertAtCaret(indent); } break; case IndentStyle.Smart: if (!data.HasIndentationTracker) { goto case IndentStyle.Auto; } NewLineSmartIndent(data); break; case IndentStyle.Virtual: if (!data.HasIndentationTracker) { goto case IndentStyle.Auto; } var oldLine = data.Caret.Line; var curLine = data.GetLine(oldLine); var indentCol = data.GetVirtualIndentationColumn(data.Caret.Location); if (curLine.Length >= data.Caret.Column) { NewLineSmartIndent(data); data.FixVirtualIndentation(); data.FixVirtualIndentation(oldLine); break; } data.Insert(data.Caret.Offset, data.EolMarker); data.FixVirtualIndentation(oldLine); data.Caret.Column = indentCol; break; default: throw new ArgumentOutOfRangeException(); } } }
public static void Backspace (TextEditorData data, Action<TextEditorData> removeCharBeforeCaret) { if (!data.CanEditSelection) return; using (var undo = data.OpenUndoGroup ()) { if (data.IsSomethingSelected) { var visualAnchorLocation = data.LogicalToVisualLocation (data.MainSelection.Anchor); var visualLeadLocation = data.LogicalToVisualLocation (data.MainSelection.Lead); // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && visualAnchorLocation.Column == visualLeadLocation.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection (); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { var lineSegment = data.Document.GetLine (lineNumber); int insertOffset = lineSegment.GetLogicalColumn (data, visualAnchorLocation.Column - 1) - 1; data.Remove (lineSegment.Offset + insertOffset, 1); } var visualColumn = data.GetLine (data.Caret.Location.Line).GetVisualColumn (data, col - 1); data.MainSelection = new Selection ( new DocumentLocation (data.MainSelection.Anchor.Line, data.GetLine (data.MainSelection.Anchor.Line).GetLogicalColumn (data, visualColumn)), new DocumentLocation (data.MainSelection.Lead.Line, data.GetLine (data.MainSelection.Lead.Line).GetLogicalColumn (data, visualColumn)), SelectionMode.Block ); data.Caret.PreserveSelection = preserve; data.Document.CommitMultipleLineUpdate (data.MainSelection.MinLine, data.MainSelection.MaxLine); return; } data.DeleteSelectedText (data.MainSelection.SelectionMode != SelectionMode.Block); return; } if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn) return; // Virtual indentation needs to be fixed before to have the same behavior // if it's there or not (otherwise user has to press multiple backspaces in some cases) data.EnsureCaretIsNotVirtual (); var line = data.Document.GetLine (data.Caret.Line); // smart backspace (delete indentation) if (data.HasIndentationTracker && (data.IndentationTracker.SupportedFeatures & IndentatitonTrackerFeatures.SmartBackspace) != 0 && (data.Options.IndentStyle == IndentStyle.Smart || data.Options.IndentStyle == IndentStyle.Virtual)) { if (data.Caret.Column == data.GetVirtualIndentationColumn (data.Caret.Location)) { bool isAllIndent = line.GetIndentation (data.Document).Length == data.Caret.Column - 1; if (isAllIndent) { var prevLine = line.PreviousLine; var prevLineIsEmpty = prevLine != null && prevLine.Length == 0; var startOffset = prevLine != null ? prevLine.EndOffset : 0; data.Remove (startOffset, data.Caret.Offset - startOffset); if (prevLine != null) { if (prevLineIsEmpty) { if (line.Length - data.Caret.Column - 1 > 0 && data.HasIndentationTracker) { data.InsertAtCaret (data.IndentationTracker.GetIndentationString (data.Caret.Offset)); } else { data.Caret.Column = data.GetVirtualIndentationColumn (prevLine.Offset); } } data.FixVirtualIndentation (); } return; } } } // normal backspace. if (data.Caret.Column > line.Length + 1) { data.Caret.Column = line.Length + 1; } else if (data.Caret.Offset == line.Offset) { DocumentLine lineAbove = data.Document.GetLine (data.Caret.Line - 1); if (lineAbove.Length == 0 && data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual) { data.Caret.Location = new DocumentLocation (data.Caret.Line - 1, data.IndentationTracker.GetVirtualIndentationColumn (data.Caret.Line - 1, 1)); data.Replace (lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength, data.IndentationTracker.GetIndentationString (data.Caret.Line - 1, 1)); } else { data.Remove (lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength); } } else { removeCharBeforeCaret (data); } // Needs to be fixed after, the line may just contain the indentation data.FixVirtualIndentation (); } }
public static void Backspace(TextEditorData data, Action <TextEditorData> removeCharBeforeCaret) { if (!data.CanEditSelection) { return; } DocumentLine line; bool smartBackspace = false; using (var undo = data.OpenUndoGroup()) { if (data.IsSomethingSelected) { var visualAnchorLocation = data.LogicalToVisualLocation(data.MainSelection.Anchor); var visualLeadLocation = data.LogicalToVisualLocation(data.MainSelection.Lead); // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && visualAnchorLocation.Column == visualLeadLocation.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection(); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; var changes = new List <Microsoft.CodeAnalysis.Text.TextChange> (); for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { var lineSegment = data.Document.GetLine(lineNumber); int insertOffset = lineSegment.GetLogicalColumn(data, visualAnchorLocation.Column - 1) - 1; changes.Add(new Microsoft.CodeAnalysis.Text.TextChange(new Microsoft.CodeAnalysis.Text.TextSpan(lineSegment.Offset + insertOffset, 1), "")); } data.Document.ApplyTextChanges(changes); var visualColumn = data.GetLine(data.Caret.Location.Line).GetVisualColumn(data, col - 1); data.MainSelection = new MonoDevelop.Ide.Editor.Selection( new DocumentLocation(data.MainSelection.Anchor.Line, data.GetLine(data.MainSelection.Anchor.Line).GetLogicalColumn(data, visualColumn)), new DocumentLocation(data.MainSelection.Lead.Line, data.GetLine(data.MainSelection.Lead.Line).GetLogicalColumn(data, visualColumn)), SelectionMode.Block ); data.Caret.PreserveSelection = preserve; data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine); return; } data.DeleteSelectedText(data.MainSelection.SelectionMode != SelectionMode.Block); return; } if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn) { return; } // Virtual indentation needs to be fixed before to have the same behavior // if it's there or not (otherwise user has to press multiple backspaces in some cases) data.EnsureCaretIsNotVirtual(); line = data.Document.GetLine(data.Caret.Line); // smart backspace (delete indentation) if (data.HasIndentationTracker && (data.IndentationTracker.SupportedFeatures & IndentationTrackerFeatures.SmartBackspace) != 0 && (data.Options.IndentStyle == IndentStyle.Smart || data.Options.IndentStyle == IndentStyle.Virtual) && data.Options.SmartBackspace) { if (data.Caret.Column == data.GetVirtualIndentationColumn(data.Caret.Location)) { bool isAllIndent = line.GetIndentation(data.Document).Length == data.Caret.Column - 1; if (isAllIndent) { if (!data.Options.GenerateFormattingUndoStep) { SmartBackspace(data, line); return; } smartBackspace = true; } } } // normal backspace. if (data.Caret.Column > line.Length + 1) { data.Caret.Column = line.Length + 1; } else if (data.Caret.Offset == line.Offset) { DocumentLine lineAbove = data.Document.GetLine(data.Caret.Line - 1); if (lineAbove.Length == 0 && data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual) { data.Caret.Location = new DocumentLocation(data.Caret.Line - 1, data.GetVirtualIndentationColumn(data.Caret.Line - 1, 1)); data.Replace(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength, data.GetIndentationString(data.Caret.Line - 1, 1)); } else { data.Remove(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength); } } else { removeCharBeforeCaret(data); } // Needs to be fixed after, the line may just contain the indentation data.FixVirtualIndentation(); } if (data.Options.GenerateFormattingUndoStep && smartBackspace) { using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); SmartBackspace(data, line); } } }
public static void InsertNewLine (TextEditorData data) { if (!data.CanEditSelection) return; using (var undo = data.OpenUndoGroup ()) { if (data.IsSomethingSelected) { var end = data.MainSelection.End; data.DeleteSelectedText (); if (end.Column == 1) { CaretMoveActions.InternalCaretMoveHome (data, true, false); return; } } switch (data.Options.IndentStyle) { case IndentStyle.None: data.InsertAtCaret (data.EolMarker); break; case IndentStyle.Auto: data.EnsureCaretIsNotVirtual (); var indent = data.Document.GetLineIndent (data.Caret.Line); data.InsertAtCaret (data.EolMarker); data.EnsureCaretIsNotVirtual (); if (data.GetLine (data.Caret.Line).Length == 0) data.InsertAtCaret (indent); break; case IndentStyle.Smart: if (!data.HasIndentationTracker) goto case IndentStyle.Auto; NewLineSmartIndent (data); break; case IndentStyle.Virtual: if (!data.HasIndentationTracker) goto case IndentStyle.Auto; var oldLine = data.Caret.Line; var curLine = data.GetLine (oldLine); var indentCol = data.GetVirtualIndentationColumn (data.Caret.Location); if (curLine.Length >= data.Caret.Column) { NewLineSmartIndent (data); data.FixVirtualIndentation (); data.FixVirtualIndentation (oldLine); break; } data.Insert (data.Caret.Offset, data.EolMarker); data.FixVirtualIndentation (oldLine); data.Caret.Column = indentCol; break; default: throw new ArgumentOutOfRangeException (); } } }
static void SmartBackspace (TextEditorData data, DocumentLine line) { var prevLine = line.PreviousLine; var prevLineIsEmpty = prevLine != null && prevLine.Length == 0; var startOffset = prevLine != null ? prevLine.EndOffset : 0; var count = data.Caret.Offset - startOffset; if (count < 0) return; data.Remove (startOffset, count); if (prevLine != null) { if (prevLineIsEmpty) { if (line.Length - data.Caret.Column - 1 > 0 && data.HasIndentationTracker) { data.InsertAtCaret (data.IndentationTracker.GetIndentationString (data.Caret.Offset)); } else { data.Caret.Column = data.GetVirtualIndentationColumn (prevLine.Offset); } } data.FixVirtualIndentation (); } }
public static void Backspace(TextEditorData data, Action <TextEditorData> removeCharBeforeCaret) { if (!data.CanEditSelection) { return; } using (var undo = data.OpenUndoGroup()) { if (data.IsSomethingSelected) { var visualAnchorLocation = data.LogicalToVisualLocation(data.MainSelection.Anchor); var visualLeadLocation = data.LogicalToVisualLocation(data.MainSelection.Lead); // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && visualAnchorLocation.Column == visualLeadLocation.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection(); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { var lineSegment = data.Document.GetLine(lineNumber); int insertOffset = lineSegment.GetLogicalColumn(data, visualAnchorLocation.Column - 1) - 1; data.Remove(lineSegment.Offset + insertOffset, 1); } var visualColumn = data.GetLine(data.Caret.Location.Line).GetVisualColumn(data, col - 1); data.MainSelection = new Selection( new DocumentLocation(data.MainSelection.Anchor.Line, data.GetLine(data.MainSelection.Anchor.Line).GetLogicalColumn(data, visualColumn)), new DocumentLocation(data.MainSelection.Lead.Line, data.GetLine(data.MainSelection.Lead.Line).GetLogicalColumn(data, visualColumn)), SelectionMode.Block ); data.Caret.PreserveSelection = preserve; data.Document.CommitMultipleLineUpdate(data.MainSelection.MinLine, data.MainSelection.MaxLine); return; } data.DeleteSelectedText(data.MainSelection.SelectionMode != SelectionMode.Block); return; } if (data.Caret.Line == DocumentLocation.MinLine && data.Caret.Column == DocumentLocation.MinColumn) { return; } // Virtual indentation needs to be fixed before to have the same behavior // if it's there or not (otherwise user has to press multiple backspaces in some cases) data.EnsureCaretIsNotVirtual(); var line = data.Document.GetLine(data.Caret.Line); // smart backspace (delete indentation) if (data.HasIndentationTracker && (data.IndentationTracker.SupportedFeatures & IndentatitonTrackerFeatures.SmartBackspace) != 0 && (data.Options.IndentStyle == IndentStyle.Smart || data.Options.IndentStyle == IndentStyle.Virtual)) { if (data.Caret.Column == data.GetVirtualIndentationColumn(data.Caret.Location)) { bool isAllIndent = line.GetIndentation(data.Document).Length == data.Caret.Column - 1; if (isAllIndent) { var prevLine = line.PreviousLine; var prevLineIsEmpty = prevLine != null && prevLine.Length == 0; var startOffset = prevLine != null ? prevLine.EndOffset : 0; data.Remove(startOffset, data.Caret.Offset - startOffset); if (prevLine != null) { if (prevLineIsEmpty) { if (line.Length - data.Caret.Column - 1 > 0 && data.HasIndentationTracker) { data.InsertAtCaret(data.IndentationTracker.GetIndentationString(data.Caret.Offset)); } else { data.Caret.Column = data.GetVirtualIndentationColumn(prevLine.Offset); } } data.FixVirtualIndentation(); } return; } } } // normal backspace. if (data.Caret.Column > line.Length + 1) { data.Caret.Column = line.Length + 1; } else if (data.Caret.Offset == line.Offset) { DocumentLine lineAbove = data.Document.GetLine(data.Caret.Line - 1); if (lineAbove.Length == 0 && data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual) { data.Caret.Location = new DocumentLocation(data.Caret.Line - 1, data.IndentationTracker.GetVirtualIndentationColumn(data.Caret.Line - 1, 1)); data.Replace(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength, data.IndentationTracker.GetIndentationString(data.Caret.Line - 1, 1)); } else { data.Remove(lineAbove.EndOffsetIncludingDelimiter - lineAbove.DelimiterLength, lineAbove.DelimiterLength); } } else { removeCharBeforeCaret(data); } // Needs to be fixed after, the line may just contain the indentation data.FixVirtualIndentation(); } }
public static void LineEnd (TextEditorData data) { if (!data.Caret.PreserveSelection) data.ClearSelection (); var line = data.Document.GetLine (data.Caret.Line); var newLocation = new DocumentLocation (data.Caret.Line, line.Length + 1); // handle folding IEnumerable<FoldSegment> foldings = data.Document.GetStartFoldings (line); FoldSegment segment = null; foreach (FoldSegment folding in foldings) { if (folding.IsFolded && folding.Contains (data.Document.LocationToOffset (newLocation))) { segment = folding; break; } } if (segment != null) newLocation = data.Document.OffsetToLocation (segment.EndLine.Offset + segment.EndColumn - 1); if (newLocation != data.Caret.Location) data.Caret.Location = newLocation; if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual) { int virtualIndentColumn = data.GetVirtualIndentationColumn (data.Caret.Location); if (virtualIndentColumn > data.Caret.Column) data.Caret.Column = virtualIndentColumn; } }
public static void Right (TextEditorData data) { if (Platform.IsMac && data.IsSomethingSelected && !data.Caret.PreserveSelection) { data.Caret.Offset = System.Math.Max (data.SelectionAnchor, data.Caret.Offset); data.ClearSelection (); return; } DocumentLine line = data.Document.GetLine (data.Caret.Line); IEnumerable<FoldSegment > foldings = data.Document.GetStartFoldings (line); FoldSegment segment = null; foreach (FoldSegment folding in foldings) { if (folding.IsFolded && folding.Column == data.Caret.Column) { segment = folding; break; } } if (segment != null) { data.Caret.Offset = segment.EndOffset; return; } if (data.Caret.Column >= line.Length + 1) { int nextColumn; if (data.HasIndentationTracker && data.Options.IndentStyle == IndentStyle.Virtual && data.Caret.Column == DocumentLocation.MinColumn) { nextColumn = data.GetVirtualIndentationColumn (data.Caret.Location); } else if (data.Caret.AllowCaretBehindLineEnd) { nextColumn = data.Caret.Column + 1; } else { nextColumn = line.Length + 1; } if (data.Caret.Column < nextColumn) { data.Caret.Column = nextColumn; } else { if (data.Caret.Line < data.LineCount) data.Caret.Location = new DocumentLocation (data.Caret.Line + 1, DocumentLocation.MinColumn); } } else { data.Caret.Column++; } }