public void PreOverType(out bool handledCommand) { handledCommand = false; if (ClosingPoint == null) { return; } // Brace completion is not cancellable. var cancellationToken = CancellationToken.None; var snapshot = this.SubjectBuffer.CurrentSnapshot; var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); SnapshotPoint closingSnapshotPoint = ClosingPoint.GetPoint(snapshot); if (!HasForwardTyping && _session.AllowOverType(this, cancellationToken)) { SnapshotPoint?caretPos = this.GetCaretPosition(); Debug.Assert(caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position); // ensure that we are within the session before clearing if (caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position && closingSnapshotPoint.Position > 0) { using (ITextUndoTransaction undo = CreateUndoTransaction()) { _editorOperations.AddBeforeTextBufferChangePrimitive(); SnapshotSpan span = new SnapshotSpan(caretPos.Value, closingSnapshotPoint.Subtract(1)); using (ITextEdit edit = SubjectBuffer.CreateEdit()) { edit.Delete(span); if (edit.HasFailedChanges) { Debug.Fail("Unable to clear closing brace"); edit.Cancel(); undo.Cancel(); } else { handledCommand = true; edit.Apply(); MoveCaretToClosingPoint(); _editorOperations.AddAfterTextBufferChangePrimitive(); undo.Complete(); } } } } } }
public void PreOverType(out bool handledCommand) { handledCommand = false; // AllowOverType may make changes to the buffer such as for completing intellisense if (!HasForwardTyping && (_context == null || _context.AllowOverType(this))) { SnapshotPoint?caretPos = CaretPosition; SnapshotPoint closingSnapshotPoint = _closingPoint.GetPoint(SubjectBuffer.CurrentSnapshot); Debug.Assert(caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position); // ensure that we are within the session before clearing if (caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position && closingSnapshotPoint.Position > 0) { using (ITextUndoTransaction undo = CreateUndoTransaction()) { _editorOperations.AddBeforeTextBufferChangePrimitive(); SnapshotSpan span = new SnapshotSpan(caretPos.Value, closingSnapshotPoint.Subtract(1)); using (ITextEdit edit = _subjectBuffer.CreateEdit()) { edit.Delete(span); if (edit.HasFailedChanges) { Debug.Fail("Unable to clear closing brace"); edit.Cancel(); undo.Cancel(); } else { handledCommand = true; edit.Apply(); MoveCaretToClosingPoint(); _editorOperations.AddAfterTextBufferChangePrimitive(); undo.Complete(); } } } } } }
void PerformActionInUndo(Func <bool> action) { ITrackingPoint anchor = _textView.TextSnapshot.CreateTrackingPoint(_textView.Selection.AnchorPoint.Position, PointTrackingMode.Positive); ITrackingPoint active = _textView.TextSnapshot.CreateTrackingPoint(_textView.Selection.ActivePoint.Position, PointTrackingMode.Positive); bool empty = _textView.Selection.IsEmpty; TextSelectionMode mode = _textView.Selection.Mode; using (var undo = _undoHistory.CreateTransaction("Untabify")) { _operations.AddBeforeTextBufferChangePrimitive(); if (!action()) { undo.Cancel(); return; } ITextSnapshot after = _textView.TextSnapshot; _operations.SelectAndMoveCaret(new VirtualSnapshotPoint(anchor.GetPoint(after)), new VirtualSnapshotPoint(active.GetPoint(after)), mode, EnsureSpanVisibleOptions.ShowStart); _operations.AddAfterTextBufferChangePrimitive(); undo.Complete(); } }
private void DeleteSpan(NormalizedSnapshotSpanCollection applicabilitySpans) { using (ITextUndoTransaction undoTransaction = _undoHistory.CreateTransaction("HTML Cut")) { _editorOperations.AddBeforeTextBufferChangePrimitive(); bool successfulEdit = true; using (ITextEdit edit = _textView.TextBuffer.CreateEdit()) { foreach (SnapshotSpan span in applicabilitySpans) { successfulEdit &= edit.Delete(span); } if (successfulEdit) { edit.Apply(); } } _editorOperations.AddAfterTextBufferChangePrimitive(); if (successfulEdit) { undoTransaction.Complete(); } } }
public CaretPreservingEditTransaction(string description, ITextUndoHistory?undoHistory, IEditorOperations editorOperations) { _editorOperations = editorOperations; _undoHistory = undoHistory; _active = true; if (_undoHistory != null) { _transaction = new HACK_TextUndoTransactionThatRollsBackProperly(_undoHistory.CreateTransaction(description)); _editorOperations.AddBeforeTextBufferChangePrimitive(); } }
public CaretPreservingEditTransaction( string description, ITextView textView, ITextUndoHistoryRegistry undoHistoryRegistry, IEditorOperationsFactoryService editorOperationsFactoryService) { _editorOperations = editorOperationsFactoryService.GetEditorOperations(textView); _undoHistory = undoHistoryRegistry.GetHistory(textView.TextBuffer); _active = true; if (_undoHistory != null) { _transaction = new HACK_TextUndoTransactionThatRollsBackProperly(_undoHistory.CreateTransaction(description)); _editorOperations.AddBeforeTextBufferChangePrimitive(); } }
public TextUndoTransaction( string description, ITextView textView, ITextUndoHistoryRegistry undoHistoryRegistry, IEditorOperationsFactoryService editorOperationsFactoryService) { _inTransaction = true; _editorOperations = editorOperationsFactoryService.GetEditorOperations(textView); var undoHistory = undoHistoryRegistry.GetHistory(textView.TextBuffer); if (undoHistory != null) { _transaction = undoHistory.CreateTransaction(description); _editorOperations.AddBeforeTextBufferChangePrimitive(); } }
public void Open(string name) { Debug.Assert(_undoTransaction == null); if (_undoTransaction == null && _undoManager != null && _editorOperations != null) { _undoTransaction = _undoManager.TextBufferUndoHistory.CreateTransaction(name); if (_addRollbackOnCancel) { // Some hosts (*cough* VS *cough*) don't properly implement ITextUndoTransaction such // that their Cancel operation doesn't rollback the already performed actions. // In those scenarios, we'll use our own rollback mechanism (unabashedly copied // from Roslyn) _undoTransaction = new TextUndoTransactionThatRollsBackProperly(_undoTransaction); } _editorOperations.AddBeforeTextBufferChangePrimitive(); } }
/// <summary> /// Called by the editor when return is pressed while both braces are on the same line and no typing has occurred in the session. /// </summary> /// <param name="session">Current brace completion session.</param> public void OnReturn(IBraceCompletionSession session) { // Return in Repl window would just execute the current command if (session.SubjectBuffer.ContentType.TypeName.Equals(ReplConstants.ReplContentTypeName, StringComparison.OrdinalIgnoreCase)) { return; } var closingPointPosition = session.ClosingPoint.GetPosition(session.SubjectBuffer.CurrentSnapshot); Debug.Assert( condition: closingPointPosition > 0, message: "The closing point position should always be greater than zero", detailMessage: "The closing point position should always be greater than zero, " + "since there is also an opening point for this brace completion session"); // reshape code from // { // |} // // to // { // | // } // where | indicates caret position. using (var undo = _undoHistory.CreateTransaction("Insert new line.")) { _editorOperations.AddBeforeTextBufferChangePrimitive(); _editorOperations.MoveLineUp(false); _editorOperations.MoveToEndOfLine(false); _editorOperations.InsertNewLine(); _editorOperations.AddAfterTextBufferChangePrimitive(); undo.Complete(); } }
public void PreOverType(out bool handledCommand) { _threadingContext.ThrowIfNotOnUIThread(); handledCommand = false; if (ClosingPoint == null) { return; } // Brace completion is not cancellable. var cancellationToken = CancellationToken.None; var snapshot = this.SubjectBuffer.CurrentSnapshot; var closingSnapshotPoint = ClosingPoint.GetPoint(snapshot); if (!HasForwardTyping && AllowOverType()) { var caretPos = this.GetCaretPosition(); Debug.Assert(caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position); // ensure that we are within the session before clearing if (caretPos.HasValue && caretPos.Value.Position < closingSnapshotPoint.Position && closingSnapshotPoint.Position > 0) { using var undo = CreateUndoTransaction(); _editorOperations.AddBeforeTextBufferChangePrimitive(); var span = new SnapshotSpan(caretPos.Value, closingSnapshotPoint.Subtract(1)); using var edit = SubjectBuffer.CreateEdit(); edit.Delete(span); if (edit.HasFailedChanges) { Debug.Fail("Unable to clear closing brace"); edit.Cancel(); undo.Cancel(); } else { handledCommand = true; edit.ApplyAndLogExceptions(); MoveCaretToClosingPoint(); _editorOperations.AddAfterTextBufferChangePrimitive(); undo.Complete(); } } } return; bool AllowOverType() { var context = GetBraceCompletionContext(); return(context != null && _service.AllowOverTypeAsync(context.Value, cancellationToken).WaitAndGetResult(cancellationToken)); } }
private void TextBufferChanged(object sender, TextContentChangedEventArgs e) { if (!(e.EditTag is IUndoEditTag)) { if (this.TextBufferUndoHistory.State != TextUndoHistoryState.Idle) { Debug.Fail("We are doing a normal edit in a non-idle undo state. This is explicitly prohibited as it would corrupt the undo stack! Please fix your code."); } else { // With projection, we sometimes get Changed events with no changes, or for "" -> "". // We don't want to create undo actions for these. bool nonNullChange = false; foreach (ITextChange c in e.BeforeVersion.Changes) { if (c.OldLength != 0 || c.NewLength != 0) { nonNullChange = true; break; } } if (nonNullChange) { // If there's an open undo transaction, add our edit (turned into a primitive) to it. Otherwise, create and undo transaction. var currentTransaction = _undoHistory.CurrentTransaction; if (currentTransaction == null) { // TODO remove this // Hack to allow Cascade's local undo to light up if using v15.7 but behave using the old -- non-local -- undo before if running on 15.6. // Cascade should really be marking its edits with IInvisibleEditTag (and will once it can take a hard requirement of VS 15.7). if ((e.EditTag is IInvisibleEditTag) || ((e.EditTag != null) && (string.Equals(e.EditTag.ToString(), "CascadeRemoteEdit", StringComparison.Ordinal)))) { _createdTransaction = ((ITextUndoHistory2)_undoHistory).CreateInvisibleTransaction("<invisible>"); } #if false else if (e.EditTag is IUndoMetadataEditTag metadata) { _createdTransaction = _undoHistory.CreateTransaction(metadata.Description); if (_initiatingOperations == null) { var view = metadata.InitiatingView; if (view != null) { _initiatingOperations = _editorOperationsFactoryService.GetEditorOperations(view); _initiatingOperations.AddBeforeTextBufferChangePrimitive(); } } } #endif else { _createdTransaction = _undoHistory.CreateTransaction(Strings.TextBufferChanged); } currentTransaction = _createdTransaction; } currentTransaction.AddUndo(new TextBufferChangeUndoPrimitive(_undoHistory, e.BeforeVersion)); } } } }