public static int RemoveTabInLine (TextEditorData data, DocumentLine line) { if (line.LengthIncludingDelimiter == 0) return 0; char ch = data.Document.GetCharAt (line.Offset); if (ch == '\t') { data.Remove (line.Offset, 1); data.Document.CommitLineUpdate (line); return 1; } else if (ch == ' ') { int removeCount = 0; for (int i = 0; i < data.Options.IndentationSize;) { ch = data.Document.GetCharAt (line.Offset + i); if (ch == ' ') { removeCount ++; i++; } else if (ch == '\t') { removeCount ++; i += data.Options.TabSize; } else { break; } } data.Remove (line.Offset, removeCount); data.Document.CommitLineUpdate (line); return removeCount; } return 0; }
static void RemoveCharBeforCaret (TextEditorData data) { if (((ISourceEditorOptions)data.Options).AutoInsertMatchingBracket) { if (data.Caret.Offset > 0) { var line = data.GetLine (data.Caret.Line); var stack = line.StartSpan.Clone(); if (stack.Any (s => s.Color == "string.other")) { DeleteActions.Backspace (data); return; } stack = line.StartSpan.Clone(); if (stack.Any (s => s.Color == "string.other")) { DeleteActions.Backspace (data); return; } char ch = data.Document.GetCharAt (data.Caret.Offset - 1); int idx = open.IndexOf (ch); if (idx >= 0) { int nextCharOffset = GetNextNonWsCharOffset (data, data.Caret.Offset); if (nextCharOffset >= 0 && closing[idx] == data.Document.GetCharAt (nextCharOffset)) { bool updateToEnd = data.Document.OffsetToLineNumber (nextCharOffset) != data.Caret.Line; data.Remove (data.Caret.Offset, nextCharOffset - data.Caret.Offset + 1); } } } } DeleteActions.Backspace (data); }
static void NextWord (TextEditorData data, bool subword) { int oldLine = data.Caret.Line; int offset = subword? data.FindNextSubwordOffset (data.Caret.Offset) : data.FindNextWordOffset (data.Caret.Offset); if (data.Caret.Offset != offset && data.CanEdit (oldLine) && data.CanEdit (data.Caret.Line)) { data.Remove (data.Caret.Offset, offset - data.Caret.Offset); data.Document.CommitLineToEndUpdate (data.Caret.Line); } }
static void NextWord (TextEditorData data, bool subword) { int oldLine = data.Caret.Line; int caretOffset = data.Caret.Offset; int offset = subword? data.FindNextSubwordOffset (caretOffset) : data.FindNextWordOffset (caretOffset); if (caretOffset != offset && data.CanEdit (oldLine) && data.CanEdit (data.Caret.Line)) { data.Remove (caretOffset, offset - caretOffset); } }
static void PreviousWord (TextEditorData data, bool subword) { int oldLine = data.Caret.Line; int offset = subword? data.FindPrevSubwordOffset (data.Caret.Offset) : data.FindPrevWordOffset (data.Caret.Offset); if (data.Caret.Offset != offset && data.CanEdit (oldLine) && data.CanEdit (data.Caret.Line)) { data.Remove (offset, data.Caret.Offset - offset); data.Caret.Offset = offset; if (oldLine != data.Caret.Line) data.Document.CommitLineToEndUpdate (data.Caret.Line); } }
/// <summary> /// Don't use this unless you're implementing ICodeTemplateWidget. Use Insert instead. /// </summary> public TemplateResult InsertTemplateContents (MonoDevelop.Ide.Gui.Document document) { ProjectDom dom = document.Dom; ParsedDocument doc = document.ParsedDocument ?? MonoDevelop.Projects.Dom.Parser.ProjectDomService.GetParsedDocument (dom, document.FileName); MonoDevelop.Ide.Gui.TextEditor editor = document.TextEditor; Mono.TextEditor.TextEditorData data = document.TextEditorData; int offset = editor.CursorPosition; int line, col; editor.GetLineColumnFromPosition (offset, out line, out col); // string leadingWhiteSpace = GetLeadingWhiteSpace (editor, editor.CursorLine); TemplateContext context = new TemplateContext { Template = this, Document = document, ProjectDom = dom, ParsedDocument = doc, InsertPosition = new DomLocation (line, col), LineIndent = GetIndent (editor, line, 0), TemplateCode = IndentCode (Code, document.TextEditorData.EolMarker, GetIndent (editor, line, 0)) }; if (data.IsSomethingSelected) { int start = data.SelectionRange.Offset; while (Char.IsWhiteSpace (data.Document.GetCharAt (start))) { start++; } int end = data.SelectionRange.EndOffset; while (Char.IsWhiteSpace (data.Document.GetCharAt (end - 1))) { end--; } context.LineIndent = GetIndent (editor, data.Document.OffsetToLineNumber (start) + 1, 0); context.SelectedText = RemoveIndent (data.Document.GetTextBetween (start, end), context.LineIndent); data.Remove (start, end - start); offset = start; } else { string word = GetWordBeforeCaret (editor).Trim (); if (word.Length > 0) offset = DeleteWordBeforeCaret (editor); } TemplateResult template = FillVariables (context); template.InsertPosition = offset; document.TextEditorData.Insert (offset, template.Code); if (template.CaretEndOffset >= 0) { document.TextEditorData.Caret.Offset = offset + template.CaretEndOffset; } else { document.TextEditorData.Caret.Offset= offset + template.Code.Length; } return template; }
static void PreviousWord (TextEditorData data, bool subword) { using (var undo = data.OpenUndoGroup ()) { int oldLine = data.Caret.Line; int caretOffset = data.Caret.Offset; int offset = subword ? data.FindPrevSubwordOffset (caretOffset) : data.FindPrevWordOffset (caretOffset); if (caretOffset != offset && data.CanEdit (oldLine) && data.CanEdit (data.Caret.Line)) { data.Remove (offset, caretOffset - offset); } } }
public static void removeTrailingWhitespace( TextEditorData data, DocumentLine line ) { if( line != null ) { int num = 0; for( int i = line.Length - 1; i >= 0; i-- ) { if( !char.IsWhiteSpace( data.Document.GetCharAt( line.Offset + i ) ) ) break; num++; } if( num > 0 ) { int offset = line.Offset + line.Length - num; data.Remove( offset, num ); } } }
static void RemoveCharBeforCaret (TextEditorData data) { if (((ISourceEditorOptions)data.Options).AutoInsertMatchingBracket) { if (data.Caret.Offset > 0) { char ch = data.Document.GetCharAt (data.Caret.Offset - 1); int idx = open.IndexOf (ch); if (idx >= 0) { int nextCharOffset = GetNextNonWsCharOffset (data, data.Caret.Offset); if (nextCharOffset >= 0 && closing[idx] == data.Document.GetCharAt (nextCharOffset)) { bool updateToEnd = data.Document.OffsetToLineNumber (nextCharOffset) != data.Caret.Line; data.Remove (data.Caret.Offset, nextCharOffset - data.Caret.Offset + 1); if (updateToEnd) data.Document.CommitLineToEndUpdate (data.Caret.Line); } } } } DeleteActions.Backspace (data); }
static void RemoveCharBeforeCaret (TextEditorData data) { int offset = data.Caret.Offset; if (offset <= 0) return; var version = data.Version; data.Remove (offset - 1, 1); data.Caret.Location = data.OffsetToLocation (version.MoveOffsetTo (data.Version, offset)); }
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 (); DocumentLine line = data.Document.GetLine (data.Caret.Line); 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 // NOTE: Only in smart backspace mode otherwise the indentation tracker may not handle virtual indent correctly. if (data.HasIndentationTracker && (data.IndentationTracker.SupportedFeatures & IndentationTrackerFeatures.SmartBackspace) != 0) { data.FixVirtualIndentation(); } } if (data.Options.GenerateFormattingUndoStep && smartBackspace) { using (var undo = data.OpenUndoGroup()) { data.EnsureCaretIsNotVirtual(); SmartBackspace(data, line); } } }
public static void MoveBlockUp (TextEditorData data) { int lineStart = data.Caret.Line; int lineEnd = data.Caret.Line; bool setSelection = lineStart != lineEnd; if (data.IsSomethingSelected) { setSelection = true; lineStart = data.MainSelection.MinLine; lineEnd = data.MainSelection.MaxLine; } if (lineStart <= 0) return; Mono.TextEditor.LineSegment startLine = data.Document.GetLine (lineStart); Mono.TextEditor.LineSegment endLine = data.Document.GetLine (lineEnd); Mono.TextEditor.LineSegment prevLine = data.Document.GetLine (lineStart - 1); int relCaretOffset = data.Caret.Offset - startLine.Offset; data.Document.BeginAtomicUndo (); string text = data.Document.GetTextBetween (startLine.Offset, endLine.EndOffset); int delta = endLine.EndOffset - startLine.Offset; int newStartOffset = prevLine.Offset; bool hasEmptyDelimiter = endLine.DelimiterLength == 0; data.Remove (startLine.Offset, delta); // handle the last line case if (hasEmptyDelimiter) { text = text + data.EolMarker; data.Remove (prevLine.Offset + prevLine.EditableLength, prevLine.DelimiterLength); } // move markers List<TextMarker> markers = new List<TextMarker> (prevLine.Markers); prevLine.ClearMarker (); for (int i = lineStart; i <= lineEnd; i++) { foreach (TextMarker marker in data.Document.GetLine (i).Markers) { data.Document.GetLine (i - 1).AddMarker (marker); } data.Document.GetLine (i).ClearMarker (); } markers.ForEach (m => endLine.AddMarker (m)); data.Insert (newStartOffset, text); data.Caret.Offset = newStartOffset + relCaretOffset; if (setSelection) data.SetSelection (newStartOffset, newStartOffset + delta - endLine.DelimiterLength); data.Document.EndAtomicUndo (); }
public static void Delete (TextEditorData data) { if (!data.CanEditSelection) return; if (data.IsSomethingSelected) { data.DeleteSelectedText (); return; } if (data.Caret.Offset >= data.Document.Length) return; LineSegment line = data.Document.GetLine (data.Caret.Line); if (data.Caret.Column == line.EditableLength) { if (data.Caret.Line < data.Document.LineCount) { data.Remove (line.EndOffset - line.DelimiterLength, line.DelimiterLength); if (line.EndOffset == data.Document.Length) line.DelimiterLength = 0; } } else { data.Remove (data.Caret.Offset, 1); data.Document.CommitLineUpdate (data.Caret.Line); } }
public static void Backspace (TextEditorData data, Action<TextEditorData> removeCharBeforeCaret) { if (!data.CanEditSelection) return; if (data.IsSomethingSelected) { if (!data.MainSelection.IsDirty) { data.DeleteSelectedText (data.MainSelection.SelectionMode != SelectionMode.Block); } else { bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { data.Remove (data.Document.GetLine (lineNumber).Offset + data.Caret.Column - 1, 1); } data.Caret.Column--; data.MainSelection.Lead = new DocumentLocation (data.MainSelection.Lead.Line, data.Caret.Column); data.MainSelection.IsDirty = true; data.Caret.PreserveSelection = preserve; data.Document.CommitMultipleLineUpdate (data.MainSelection.MinLine, data.MainSelection.MaxLine); } return; } if (data.Caret.Offset == 0) return; LineSegment line = data.Document.GetLine (data.Caret.Line); if (data.Caret.Offset == line.Offset) { LineSegment lineAbove = data.Document.GetLine (data.Caret.Line - 1); data.Caret.Location = new DocumentLocation (data.Caret.Line - 1, lineAbove.EditableLength); data.Remove (lineAbove.EndOffset - lineAbove.DelimiterLength, lineAbove.DelimiterLength); } else { removeCharBeforeCaret (data); } }
public static void RemoveTrailingWhitespaces (TextEditorData data, LineSegment line) { if (line == null) return; int whitespaces = 0; for (int i = line.EditableLength - 1; i >= 0; i--) { if (Char.IsWhiteSpace (data.Document.GetCharAt (line.Offset + i))) { whitespaces++; } else { break; } } if (whitespaces > 0) { data.Remove (line.Offset + line.EditableLength - whitespaces, whitespaces); data.Caret.CheckCaretPosition (); } }
static void RemoveCharBeforeCaret (TextEditorData data) { int offset = data.Caret.Offset; if (offset <= 0) return; int column = data.Caret.Column; data.Remove (offset - 1, 1); data.Caret.Column = column - 1; }
public static void Backspace (TextEditorData data, Action<TextEditorData> removeCharBeforeCaret) { if (!data.CanEditSelection) return; if (data.IsSomethingSelected) { // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection (); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; col--; for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { data.Remove (data.Document.GetLine (lineNumber).Offset + col - 1, 1); } data.MainSelection.Lead = new DocumentLocation (data.MainSelection.Lead.Line, col); data.MainSelection.Anchor = new DocumentLocation (data.MainSelection.Anchor.Line, col); 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 (); DocumentLine line = data.Document.GetLine (data.Caret.Line); 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); 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 CaretLine (TextEditorData data) { if (data.Document.LineCount <= 1 || !data.CanEdit (data.Caret.Line)) return; var start = GetStartOfLineOffset (data, data.Caret.Location); var end = GetEndOfLineOffset (data, data.Caret.Location); data.Remove (start, end - start); data.Caret.Column = DocumentLocation.MinColumn; }
public static void CaretLineToStart (TextEditorData data) { if (!data.CanEdit (data.Caret.Line)) return; var line = data.Document.GetLine (data.Caret.Line); using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); int physColumn = data.Caret.Column - 1; var startLine = GetStartOfLineOffset (data, data.Caret.Location); data.Remove (startLine, (line.Offset + physColumn) - startLine); } data.Document.CommitLineUpdate (data.Caret.Line); }
/// <summary> /// Transpose characters (Emacs C-t) /// </summary> public static void TransposeCharacters(TextEditorData data) { if (data.Caret.Offset == 0) { return; } DocumentLine line = data.Document.GetLine(data.Caret.Line); if (line == null) { return; } int transposeOffset = data.Caret.Offset - 1; char ch; if (data.Caret.Column == 0) { DocumentLine lineAbove = data.Document.GetLine(data.Caret.Line - 1); if (lineAbove.Length == 0 && line.Length == 0) { return; } if (line.Length != 0) { ch = data.Document.GetCharAt(data.Caret.Offset); data.Remove(data.Caret.Offset, 1); data.Insert(lineAbove.Offset + lineAbove.Length, ch.ToString()); data.Document.CommitLineUpdate(data.Caret.Line - 1); return; } int lastCharOffset = lineAbove.Offset + lineAbove.Length - 1; ch = data.Document.GetCharAt(lastCharOffset); data.Remove(lastCharOffset, 1); data.InsertAtCaret(ch.ToString()); return; } int offset = data.Caret.Offset; if (data.Caret.Column >= line.Length + 1) { offset = line.Offset + line.Length - 1; transposeOffset = offset - 1; // case one char in line: if (transposeOffset < line.Offset) { DocumentLine lineAbove = data.Document.GetLine(data.Caret.Line - 1); transposeOffset = lineAbove.Offset + lineAbove.Length; ch = data.Document.GetCharAt(offset); data.Remove(offset, 1); data.Insert(transposeOffset, ch.ToString()); data.Caret.Offset = line.Offset; data.Document.CommitLineUpdate(data.Caret.Line - 1); return; } } ch = data.Document.GetCharAt(offset); data.Replace(offset, 1, data.Document.GetCharAt(transposeOffset).ToString()); data.Replace(transposeOffset, 1, ch.ToString()); if (data.Caret.Column < line.Length + 1) { data.Caret.Offset = offset + 1; } }
/// <summary> /// Don't use this unless you're implementing ICodeTemplateWidget. Use Insert instead. /// </summary> public TemplateResult InsertTemplateContents(MonoDevelop.Ide.Gui.Document document) { Mono.TextEditor.TextEditorData data = document.Editor; int offset = data.Caret.Offset; // string leadingWhiteSpace = GetLeadingWhiteSpace (editor, editor.CursorLine); var context = new TemplateContext { Template = this, Document = document, ParsedDocument = document.ParsedDocument != null ? document.ParsedDocument.ParsedFile : null, InsertPosition = data.Caret.Location, LineIndent = data.Document.GetLineIndent(data.Caret.Line), TemplateCode = Code }; if (data.IsSomethingSelected) { int start = data.SelectionRange.Offset; while (Char.IsWhiteSpace(data.Document.GetCharAt(start))) { start++; } int end = data.SelectionRange.EndOffset; while (Char.IsWhiteSpace(data.Document.GetCharAt(end - 1))) { end--; } context.LineIndent = data.Document.GetLineIndent(data.Document.OffsetToLineNumber(start)); context.SelectedText = RemoveIndent(data.Document.GetTextBetween(start, end), context.LineIndent); data.Remove(start, end - start); offset = start; } else { string word = GetWordBeforeCaret(data).Trim(); if (word.Length > 0) { offset = DeleteWordBeforeCaret(data); } } TemplateResult template = FillVariables(context); template.InsertPosition = offset; document.Editor.Insert(offset, template.Code); int newoffset; if (template.CaretEndOffset >= 0) { newoffset = offset + template.CaretEndOffset; } else { newoffset = offset + template.Code.Length; } document.Editor.Caret.Location = document.Editor.OffsetToLocation(newoffset); var prettyPrinter = CodeFormatterService.GetFormatter(data.MimeType); if (prettyPrinter != null && prettyPrinter.SupportsOnTheFlyFormatting) { int endOffset = template.InsertPosition + template.Code.Length; var oldVersion = data.Version; prettyPrinter.OnTheFlyFormat(document, template.InsertPosition, endOffset); foreach (var textLink in template.TextLinks) { for (int i = 0; i < textLink.Links.Count; i++) { var segment = textLink.Links [i]; var translatedOffset = oldVersion.MoveOffsetTo(data.Version, template.InsertPosition + segment.Offset) - template.InsertPosition; textLink.Links [i] = new TextSegment(translatedOffset, segment.Length); } } } return(template); }
public static void Delete (TextEditorData data) { if (!data.CanEditSelection) return; using (var undoGroup = data.OpenUndoGroup ()) { if (data.IsSomethingSelected) { // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection (); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; col--; for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { DocumentLine lineSegment = data.Document.GetLine (lineNumber); if (col < lineSegment.Length) data.Remove (lineSegment.Offset + col, 1); } 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.Offset >= data.Document.TextLength) return; data.EnsureCaretIsNotVirtual (); DocumentLine line = data.Document.GetLine (data.Caret.Line); if (data.Caret.Column == line.Length + 1) { if (data.Caret.Line < data.Document.LineCount) { data.Remove (line.EndOffsetIncludingDelimiter - line.DelimiterLength, line.DelimiterLength); if (line.EndOffsetIncludingDelimiter == data.Document.TextLength) line.UnicodeNewline = UnicodeNewline.Unknown; } } else { data.Remove (data.Caret.Offset, 1); data.Document.CommitLineUpdate (data.Caret.Line); } data.FixVirtualIndentation (); } }
public static void Delete(TextEditorData data) { if (!data.CanEditSelection) { return; } using (var undoGroup = data.OpenUndoGroup()) { if (data.IsSomethingSelected) { // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection(); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; col--; for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { DocumentLine lineSegment = data.Document.GetLine(lineNumber); if (col < lineSegment.Length) { data.Remove(lineSegment.Offset + col, 1); } } 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.Offset >= data.Document.TextLength) { return; } data.EnsureCaretIsNotVirtual(); DocumentLine line = data.Document.GetLine(data.Caret.Line); if (data.Caret.Column == line.Length + 1) { if (data.Caret.Line < data.Document.LineCount) { data.Remove(line.EndOffsetIncludingDelimiter - line.DelimiterLength, line.DelimiterLength); if (line.EndOffsetIncludingDelimiter == data.Document.TextLength) { line.DelimiterLength = 0; } } } else { data.Remove(data.Caret.Offset, 1); data.Document.CommitLineUpdate(data.Caret.Line); } data.FixVirtualIndentation(); } }
static int DeleteWordBeforeCaret (TextEditorData editor) { int offset = editor.Caret.Offset; int start = FindPrevWordStart (editor, offset); editor.Remove (start, offset - start); return start; }
public static void CaretLineToEnd (TextEditorData data) { if (!data.CanEdit (data.Caret.Line)) return; LineSegment line = data.Document.GetLine (data.Caret.Line); if (data.Caret.Column == line.EditableLength) { // Nothing after the cursor, delete the end-of-line sequence data.Remove (line.Offset + data.Caret.Column, line.Length - data.Caret.Column); } else { // Delete from cursor position to the end of the line data.Remove (line.Offset + data.Caret.Column, line.EditableLength - data.Caret.Column); } data.Document.CommitLineUpdate (data.Caret.Line); }
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 RemoveCharBeforeCaret (TextEditorData data) { data.Remove (data.Caret.Offset - 1, 1); data.Caret.Column--; }
public static void Backspace(TextEditorData data, Action <TextEditorData> removeCharBeforeCaret) { if (!data.CanEditSelection) { return; } if (data.IsSomethingSelected) { // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection(); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; col--; for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { data.Remove(data.Document.GetLine(lineNumber).Offset + col - 1, 1); } data.MainSelection.Lead = new DocumentLocation(data.MainSelection.Lead.Line, col); data.MainSelection.Anchor = new DocumentLocation(data.MainSelection.Anchor.Line, col); 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(); DocumentLine line = data.Document.GetLine(data.Caret.Line); 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); 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 MoveBlockDown (TextEditorData data) { int lineStart = data.Caret.Line; int lineEnd = data.Caret.Line; bool setSelection = lineStart != lineEnd; if (data.IsSomethingSelected) { setSelection = true; lineStart = data.MainSelection.MinLine; lineEnd = data.MainSelection.MaxLine; } if (lineEnd + 1 >= data.Document.LineCount) return; Mono.TextEditor.LineSegment startLine = data.Document.GetLine (lineStart); Mono.TextEditor.LineSegment endLine = data.Document.GetLine (lineEnd); Mono.TextEditor.LineSegment nextLine = data.Document.GetLine (lineEnd + 1); int relCaretOffset = data.Caret.Offset - startLine.Offset; data.Document.BeginAtomicUndo (); string text = data.Document.GetTextBetween (startLine.Offset, endLine.EndOffset); int nextLineOffset = nextLine.EndOffset; int delta = endLine.EndOffset - startLine.Offset; int newStartOffset = nextLineOffset - delta; // handle the last line case if (nextLine.DelimiterLength == 0) { text = data.EolMarker + text.Substring (0, text.Length - endLine.DelimiterLength); newStartOffset += data.EolMarker.Length; } data.Insert (nextLineOffset, text); data.Remove (startLine.Offset, delta); // move markers List<TextMarker> markers = new List<TextMarker> (nextLine.Markers); nextLine.ClearMarker (); for (int i = lineEnd; i <= lineStart; i++) { foreach (TextMarker marker in data.Document.GetLine (i).Markers) { data.Document.GetLine (i + 1).AddMarker (marker); } data.Document.GetLine (i).ClearMarker (); } markers.ForEach (m => startLine.AddMarker (m)); data.Caret.Offset = newStartOffset + relCaretOffset; if (setSelection) data.SetSelection (newStartOffset, newStartOffset + text.Length - endLine.DelimiterLength); data.Document.EndAtomicUndo (); }
public static void CaretLineToEnd (TextEditorData data) { if (!data.CanEdit (data.Caret.Line)) return; var line = data.Document.GetLine (data.Caret.Line); using (var undo = data.OpenUndoGroup ()) { data.EnsureCaretIsNotVirtual (); int physColumn = data.Caret.Column - 1; if (physColumn == line.Length) { // Nothing after the cursor, delete the end-of-line sequence data.Remove (line.Offset + physColumn, line.LengthIncludingDelimiter - physColumn); } else { // Delete from cursor position to the end of the line var end = GetEndOfLineOffset (data, data.Caret.Location, false); data.Remove (line.Offset + physColumn, end - (line.Offset + physColumn)); } } data.Document.CommitLineUpdate (data.Caret.Line); }
public static void CaretLine (TextEditorData data) { if (data.Document.LineCount <= 1 || !data.CanEdit (data.Caret.Line)) return; LineSegment line = data.Document.GetLine (data.Caret.Line); data.Remove (line.Offset, line.Length); data.Document.CommitLineToEndUpdate (data.Caret.Line); data.Caret.CheckCaretPosition (); }
public static void Delete(TextEditorData data) { if (!data.CanEditSelection) { return; } using (var undoGroup = data.OpenUndoGroup()) { if (data.IsSomethingSelected) { // case: zero width block selection if (data.MainSelection.SelectionMode == SelectionMode.Block && data.MainSelection.Anchor.Column == data.MainSelection.Lead.Column) { var col = data.MainSelection.Lead.Column; if (col <= DocumentLocation.MinColumn) { data.ClearSelection(); return; } bool preserve = data.Caret.PreserveSelection; data.Caret.PreserveSelection = true; col--; var changes = new List <Microsoft.CodeAnalysis.Text.TextChange> (); for (int lineNumber = data.MainSelection.MinLine; lineNumber <= data.MainSelection.MaxLine; lineNumber++) { DocumentLine lineSegment = data.Document.GetLine(lineNumber); if (col < lineSegment.Length) { changes.Add(new Microsoft.CodeAnalysis.Text.TextChange(new Microsoft.CodeAnalysis.Text.TextSpan(lineSegment.Offset + col, 1), "")); } } data.Document.ApplyTextChanges(changes); 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.Offset >= data.Document.Length) { return; } data.EnsureCaretIsNotVirtual(); DocumentLine line = data.Document.GetLine(data.Caret.Line); if (data.Caret.Column == line.Length + 1) { if (data.Caret.Line < data.Document.LineCount) { var deletionLength = line.DelimiterLength; // smart backspace (delete indentation) if (data.Options.IndentStyle == IndentStyle.Smart || data.Options.IndentStyle == IndentStyle.Virtual) { var next = line.NextLine; if (next != null) { if (data.HasIndentationTracker) { var lineIndentation = next.GetIndentation(data.Document); if (lineIndentation.StartsWith(data.IndentationTracker.GetIndentationString(next.LineNumber))) { deletionLength += lineIndentation.Length; } } } } data.Remove(line.EndOffsetIncludingDelimiter - line.DelimiterLength, deletionLength); if (line.EndOffsetIncludingDelimiter == data.Document.Length) { line.UnicodeNewline = UnicodeNewline.Unknown; } } } else { data.Remove(data.Caret.Offset, 1); data.Document.CommitLineUpdate(data.Caret.Line); } data.FixVirtualIndentation(); } }
/// <summary> /// Transpose characters (Emacs C-t) /// </summary> public static void TransposeCharacters (TextEditorData data) { if (data.Caret.Offset == 0) return; DocumentLine line = data.Document.GetLine (data.Caret.Line); if (line == null) return; int transposeOffset = data.Caret.Offset - 1; char ch; if (data.Caret.Column == 0) { DocumentLine lineAbove = data.Document.GetLine (data.Caret.Line - 1); if (lineAbove.Length == 0 && line.Length == 0) return; if (line.Length != 0) { ch = data.Document.GetCharAt (data.Caret.Offset); data.Remove (data.Caret.Offset, 1); data.Insert (lineAbove.Offset + lineAbove.Length, ch.ToString ()); data.Document.CommitLineUpdate (data.Caret.Line - 1); return; } int lastCharOffset = lineAbove.Offset + lineAbove.Length - 1; ch = data.Document.GetCharAt (lastCharOffset); data.Remove (lastCharOffset, 1); data.InsertAtCaret (ch.ToString ()); return; } int offset = data.Caret.Offset; if (data.Caret.Column >= line.Length + 1) { offset = line.Offset + line.Length - 1; transposeOffset = offset - 1; // case one char in line: if (transposeOffset < line.Offset) { DocumentLine lineAbove = data.Document.GetLine (data.Caret.Line - 1); transposeOffset = lineAbove.Offset + lineAbove.Length; ch = data.Document.GetCharAt (offset); data.Remove (offset, 1); data.Insert (transposeOffset, ch.ToString ()); data.Caret.Offset = line.Offset; data.Document.CommitLineUpdate (data.Caret.Line - 1); return; } } ch = data.Document.GetCharAt (offset); data.Replace (offset, 1, data.Document.GetCharAt (transposeOffset).ToString ()); data.Replace (transposeOffset, 1, ch.ToString ()); if (data.Caret.Column < line.Length + 1) data.Caret.Offset = offset + 1; }
static void TestStatementFormatting (CSharpFormattingPolicy policy, string input, string expectedOutput) { TextEditorData data = new TextEditorData (); data.Document.FileName = "a.cs"; data.Document.Text = @"class Test { MyType TestMethod () { " + input + @" } }"; var compilationUnit = new CSharpParser ().Parse (data); AstSpacingVisitor domSpacingVisitor = new AstSpacingVisitor (policy, data); domSpacingVisitor.AutoAcceptChanges = false; compilationUnit.AcceptVisitor (domSpacingVisitor, null); AstIndentationVisitor domIndentationVisitor = new AstIndentationVisitor (policy, data); domIndentationVisitor.AutoAcceptChanges = false; compilationUnit.AcceptVisitor (domIndentationVisitor, null); List<Change> changes = new List<Change> (); changes.AddRange (domSpacingVisitor.Changes); changes.AddRange (domIndentationVisitor.Changes); RefactoringService.AcceptChanges (null, null, changes); for (int i = 1; i <= data.Document.LineCount; i++) { LineSegment line = data.Document.GetLine (i); if (line.EditableLength < 2) continue; data.Remove (line.Offset, 2); } string text = data.Document.GetTextBetween (data.Document.GetLine (5).Offset, data.Document.GetLine (data.Document.LineCount - 1).Offset).Trim (); Console.WriteLine (text); Assert.AreEqual (expectedOutput, text); }
public static void RemoveTrailingWhitespaces (TextEditorData data, DocumentLine line) { if (line == null) return; int whitespaces = 0; for (int i = line.Length - 1; i >= 0; i--) { if (Char.IsWhiteSpace (data.Document.GetCharAt (line.Offset + i))) { whitespaces++; } else { break; } } if (whitespaces > 0) { var removeOffset = line.Offset + line.Length - whitespaces; data.Remove (removeOffset, whitespaces); } }
/// <summary> /// Don't use this unless you're implementing ICodeTemplateWidget. Use Insert instead. /// </summary> public TemplateResult InsertTemplateContents(MonoDevelop.Ide.Gui.Document document) { Mono.TextEditor.TextEditorData data = document.Editor; int offset = data.Caret.Offset; // string leadingWhiteSpace = GetLeadingWhiteSpace (editor, editor.CursorLine); var context = new TemplateContext { Template = this, Document = document, ParsedDocument = document.ParsedDocument != null ? document.ParsedDocument.ParsedFile : null, InsertPosition = data.Caret.Location, LineIndent = data.Document.GetLineIndent(data.Caret.Line), TemplateCode = Code }; if (data.IsSomethingSelected) { int start = data.SelectionRange.Offset; while (Char.IsWhiteSpace(data.Document.GetCharAt(start))) { start++; } int end = data.SelectionRange.EndOffset; while (Char.IsWhiteSpace(data.Document.GetCharAt(end - 1))) { end--; } context.LineIndent = data.Document.GetLineIndent(data.Document.OffsetToLineNumber(start)); context.SelectedText = RemoveIndent(data.Document.GetTextBetween(start, end), context.LineIndent); data.Remove(start, end - start); offset = start; } else { string word = GetWordBeforeCaret(data).Trim(); if (word.Length > 0) { offset = DeleteWordBeforeCaret(data); } } TemplateResult template = FillVariables(context); template.InsertPosition = offset; document.Editor.Insert(offset, template.Code); int newoffset; if (template.CaretEndOffset >= 0) { newoffset = offset + template.CaretEndOffset; } else { newoffset = offset + template.Code.Length; } document.Editor.Caret.Location = document.Editor.OffsetToLocation(newoffset); /* if (PropertyService.Get ("OnTheFlyFormatting", false)) { * string mt = DesktopService.GetMimeTypeForUri (document.FileName); * var formatter = MonoDevelop.Ide.CodeFormatting.CodeFormatterService.GetFormatter (mt); * if (formatter != null && formatter.SupportsOnTheFlyFormatting) { * document.Editor.Document.BeginAtomicUndo (); * formatter.OnTheFlyFormat (document.Project != null ? document.Project.Policies : null, * document.Editor, offset, offset + length); * document.Editor.Document.EndAtomicUndo (); * } * }*/ return(template); }
static void InsertFormattedText (TextEditorData data, int offset, string formattedText) { data.Document.BeginAtomicUndo (); // DocumentLocation caretLocation = data.Caret.Location; int selAnchor = data.IsSomethingSelected ? data.Document.LocationToOffset (data.MainSelection.Anchor) : -1; int selLead = data.IsSomethingSelected ? data.Document.LocationToOffset (data.MainSelection.Lead) : -1; int textOffset = 0; int caretOffset = data.Caret.Offset; // Console.WriteLine ("formattedText3:" + formattedText.Replace ("\t", "->").Replace (" ", "°").Replace ("\n", "\\n").Replace ("\r", "\\r")); while (textOffset < formattedText.Length /*&& offset < caretOffset*/) { if (offset < 0) { offset++; textOffset++; continue; } char ch1 = data.Document.GetCharAt (offset); char ch2 = formattedText[textOffset]; bool isCh1Eol = ch1 == '\n'|| ch1 == '\r'; if (ch1 == '\r' && offset + 1 < data.Document.Length && data.Document.GetCharAt (offset + 1) == '\n') { offset++; ch1 = '\n'; } if (ch1 == ch2 || (ch2 == '\n' && isCh1Eol)) { textOffset++; offset++; continue; } else if (isCh1Eol) { // int firstWhitespace = 0; // skip all white spaces in formatted text - we had a line break int firstWhitespace = -1; while (textOffset < formattedText.Length && IsPlainWhitespace (formattedText[textOffset])) { if (firstWhitespace < 0) firstWhitespace = textOffset; textOffset++; } if (firstWhitespace >= 0 && firstWhitespace != textOffset && formattedText[textOffset] == '\n') { int length = textOffset - firstWhitespace - 1; data.Insert (offset, formattedText.Substring (firstWhitespace, length) + data.EolMarker); data.Document.CommitLineUpdate (data.Document.OffsetToLineNumber (offset)); length += data.EolMarker.Length; if (offset < caretOffset) caretOffset += length; if (offset < selAnchor) selAnchor += length; if (offset < selLead) selLead += length; offset += length - 1; textOffset++; } offset++; while (offset < data.Caret.Offset && IsPlainWhitespace (data.Document.GetCharAt (offset))) { offset++; } continue; } bool ch1Ws = Char.IsWhiteSpace (ch1); bool ch2Ws = Char.IsWhiteSpace (ch2); if (ch2Ws && !ch1Ws) { if (ch2 == '\n') { data.Insert (offset, data.EolMarker); data.Document.CommitLineUpdate (data.Document.OffsetToLineNumber (offset)); if (offset < caretOffset) caretOffset += data.EolMarker.Length; if (offset < selAnchor) selAnchor += data.EolMarker.Length; if (offset < selLead) selLead += data.EolMarker.Length; textOffset++; offset += data.EolMarker.Length; } else { data.Insert (offset, ch2.ToString ()); data.Document.CommitLineUpdate (data.Document.OffsetToLineNumber (offset)); if (offset < caretOffset) caretOffset++; if (offset < selAnchor) selAnchor++; if (offset < selLead) selLead++; textOffset++; offset++; } continue; } if ((!ch2Ws || ch2 == '\n') && ch1Ws) { if (offset < caretOffset) caretOffset--; if (offset < selAnchor) selAnchor--; if (offset < selLead) selLead--; data.Remove (offset, 1); data.Document.CommitLineUpdate (data.Document.OffsetToLineNumber (offset)); continue; } if (ch1Ws && ch2Ws) { data.Replace (offset, 1, ch2.ToString ()); data.Document.CommitLineUpdate (data.Document.OffsetToLineNumber (offset)); textOffset++; offset++; continue; } Console.WriteLine ("BAIL OUT"); break; } data.Caret.Offset = caretOffset; if (selAnchor >= 0) data.MainSelection = new Selection (data.Document.OffsetToLocation (selAnchor), data.Document.OffsetToLocation (selLead)); data.Document.EndAtomicUndo (); }
public static void CaretLine (TextEditorData data) { if (data.Document.LineCount <= 1 || !data.CanEdit (data.Caret.Line)) return; using (var undo = data.OpenUndoGroup ()) { if (data.IsSomethingSelected) { var startLine = data.GetLine (data.MainSelection.Start.Line); var endLine = data.GetLine (data.MainSelection.End.Line); data.Remove (startLine.Offset, endLine.EndOffsetIncludingDelimiter - startLine.Offset); return; } var start = GetStartOfLineOffset (data, data.Caret.Location); var end = GetEndOfLineOffset (data, data.Caret.Location); data.Remove (start, end - start); data.Caret.Column = DocumentLocation.MinColumn; } }