private static int HandleBackspace( MultiCaretCommandFilter commandFilter, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { commandFilter.SelectionSwapExec( (tempSelections, targetSelections) => { using (var edit = commandFilter.CreateEdit()) { foreach (var selection in tempSelections) { var span = selection.GetSelectionSpan(); if (span.Length != 0) { edit.Delete(span.Span); } else if (span.Start.Position > 0) { // If this span is zero length then we should delete // the previous char - if it is an end of line char // then we should make sure we delete the full set // e.g. \r\n for windows line endings var position = span.Start.Position - 1; var length = 1; if (IsEndOfLineChar(span.Snapshot, position)) { while (position > 0 && IsEndOfLineChar(span.Snapshot, position - 1)) { --position; ++length; } } if (position >= 0) { edit.Delete(position, length); } } } edit.Apply(); } // The tracking spans should now be zero length // We add them back in here to ensure merging of overlaps foreach (var selection in tempSelections) { targetSelections.InsertExpectEnd(selection); } }); return(VSConstants.S_OK); }
private static int HandlePaste( MultiCaretCommandFilter commandFilter, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { var text = Clipboard.GetText(); if (string.IsNullOrEmpty(text)) { return(VSConstants.S_OK); } var pguidCmdGroupLocal = pguidCmdGroup; commandFilter.SelectionSwapExec( (tempSelections, targetSelections) => { var textParts = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); using (var edit = commandFilter.CreateEdit()) { if (textParts.Length != tempSelections.Count) { foreach (var selection in tempSelections) { edit.Replace(selection.GetSelectionSpan().Span, text); } } else { for (int i = 0; i < textParts.Length; ++i) { edit.Replace(tempSelections[i].GetSelectionSpan().Span, textParts[i]); } } edit.Apply(); } foreach (var selection in tempSelections) { // Add the selection into the list again - we do this so that we have // clean selection details in the list and can handle any merging targetSelections.InsertExpectEnd(selection); } }); pguidCmdGroup = pguidCmdGroupLocal; return(VSConstants.S_OK); }
private static int HandleTypeChar( MultiCaretCommandFilter commandFilter, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { var typed = ((char)Marshal.GetObjectForNativeVariant <ushort>(pvaIn)).ToString(); commandFilter.SelectionSwapExec( (tempSelections, targetSelections) => { using (var edit = commandFilter.CreateEdit()) { foreach (var selection in tempSelections) { edit.Replace(selection.GetSelectionSpan().Span, typed); } edit.Apply(); } // Whatever we typed the tracking spans should now end at the // end of our typing which is where our carets should be foreach (var selection in tempSelections) { var newSelection = SingleSelection.Create( commandFilter.textView.TextSnapshot, selection.GetSelectionSpan().Span.End, false); if (newSelection.HasValue) { targetSelections.InsertExpectEnd(newSelection.Value); } } }); return(VSConstants.S_OK); }
private static int HandleCut( MultiCaretCommandFilter commandFilter, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { commandFilter.SelectionSwapExec( (tempSelections, targetSelections) => { using (var edit = commandFilter.CreateEdit()) { var copyText = new StringBuilder(); foreach (var selection in tempSelections) { var span = selection.GetSelectionSpan(); if (span.Length != 0) { copyText.AppendLine(span.GetText()); edit.Delete(span.Span); } } Clipboard.SetText(copyText.ToString()); edit.Apply(); } // The tracking spans should now be zero length // We add them back in here to ensure merging of overlaps foreach (var selection in tempSelections) { targetSelections.InsertExpectEnd(selection); } }); return(VSConstants.S_OK); }