Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vs-editor-api.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAaron Bockover <abock@microsoft.com>2019-07-11 20:57:31 +0300
committerAaron Bockover <abock@microsoft.com>2019-07-11 20:57:31 +0300
commit479099c95ba1012b7e6394ffac972cb77f55c4d5 (patch)
treecd8fb02444edd71f57e6fcb2dfe2863398bc7014 /src
parentc59f8388d157a4584c269631ab8cd49b482e4aab (diff)
Sync with vs-editor-core@41e40ddf
Diffstat (limited to 'src')
-rw-r--r--src/Editor/Text/Def/TextUI/Commanding/CommandSelector.cs9
-rw-r--r--src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs10
-rw-r--r--src/Editor/Text/Impl/EditorOperations/EditorOperations.cs157
3 files changed, 170 insertions, 6 deletions
diff --git a/src/Editor/Text/Def/TextUI/Commanding/CommandSelector.cs b/src/Editor/Text/Def/TextUI/Commanding/CommandSelector.cs
index 7e8ebd7..d6bfe08 100644
--- a/src/Editor/Text/Def/TextUI/Commanding/CommandSelector.cs
+++ b/src/Editor/Text/Def/TextUI/Commanding/CommandSelector.cs
@@ -275,6 +275,8 @@ namespace Microsoft.VisualStudio.Text.Editor.Commanding
/// <summary>⌘L</summary>
public const string GoToLine = "goToLine:";
+ public const string PerformFormatAction = "performFormatAction:";
+
public const string ToggleOutliningEnabled = "toggleOutliningEnabled:";
public const string ToggleOutliningExpansion = "toggleOutliningExpansion:";
@@ -283,6 +285,7 @@ namespace Microsoft.VisualStudio.Text.Editor.Commanding
public const string ToggleOutliningDefinitions = "toggleOutliningDefinitions:";
+
#endregion
}
@@ -302,4 +305,10 @@ namespace Microsoft.VisualStudio.Text.Editor.Commanding
ShowReplaceInterface,
HideReplaceInterface
}
+
+ public enum FormatAction
+ {
+ SortSelectedLines = 1,
+ JoinSelectedLines
+ }
} \ No newline at end of file
diff --git a/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs b/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs
index 47e482a..1cbfd40 100644
--- a/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs
+++ b/src/Editor/Text/Def/TextUI/Operations/IEditorOperations4.cs
@@ -33,5 +33,15 @@ namespace Microsoft.VisualStudio.Text.Operations
/// Resets the text view zoom level to 100%.
/// </summary>
void ZoomReset();
+
+ /// <summary>
+ /// Sorts the selected lines in alphabetical order.
+ /// </summary>
+ void SortSelectedLines();
+
+ /// <summary>
+ /// Joins the selected lines into a single one.
+ /// </summary>
+ void JoinSelectedLines();
}
} \ No newline at end of file
diff --git a/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs b/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs
index 7c01a8e..2791b72 100644
--- a/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs
+++ b/src/Editor/Text/Impl/EditorOperations/EditorOperations.cs
@@ -96,7 +96,7 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation
if (factory == null)
throw new ArgumentNullException(nameof(factory));
- _textView = (Microsoft.VisualStudio.Text.Editor.ITextView3)textView;
+ _textView = (Microsoft.VisualStudio.Text.Editor.ITextView3) textView;
_factory = factory;
_multiSelectionBroker = _textView.GetMultiSelectionBroker();
_editorPrimitives = factory.EditorPrimitivesProvider.GetViewPrimitives(textView);
@@ -113,7 +113,8 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation
_factory.TextDocumentFactoryService.TryGetTextDocument(_textView.TextDataModel.DocumentBuffer, out _textDocument);
- _textView.Closed += delegate {
+ _textView.Closed += delegate
+ {
_factory.UndoHistoryRegistry.RemoveHistory(_undoHistory);
_factory.TextBufferUndoManagerProvider.RemoveTextBufferUndoManager(_textView.TextBuffer);
};
@@ -1065,7 +1066,7 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation
// Get the span of the previous element
SnapshotSpan previousElementSpan = TextView.GetTextElementSpan(selection.InsertionPoint.Position - 1);
-
+
// Here we have some interesting decisions to make. If this is a collapsed region, we want to delete the whole thing.
// If this is a multi-byte character, we typically want to delete just one byte to allow for easier typing in chinese and other languages.
// However, if that multi-byte character is a surrogate pair or newline, we want to delete the whole thing.
@@ -2778,10 +2779,10 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation
return true;
}
- text = (string)dataObj.GetData(DataFormats.UnicodeText);
+ text = (string) dataObj.GetData(DataFormats.UnicodeText);
if (text == null)
{
- text = (string)dataObj.GetData(DataFormats.Text);
+ text = (string) dataObj.GetData(DataFormats.Text);
}
dataHasLineCutCopyTag = dataObj.GetDataPresent(_clipboardLineBasedCutCopyTag);
@@ -5037,7 +5038,7 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation
private static bool IsSpaceCharacter(char c)
{
return c == ' ' || c == '\t' ||
- (int)c == 0x200B ||
+ (int) c == 0x200B ||
char.GetUnicodeCategory(c) == UnicodeCategory.SpaceSeparator;
}
@@ -5205,6 +5206,150 @@ namespace Microsoft.VisualStudio.Text.Operations.Implementation
};
return ExecuteAction(Strings.DuplicateSelection, func, ensureVisible: true);
}
+
+ /// <summary>
+ /// Sorts the selected lines in alphabetical order.
+ /// </summary>
+ public void SortSelectedLines()
+ {
+ // we are technically caching the selections, although we need to
+ // be really careful - all we really care about are the positions
+ // as we'll want to recreate them when we finish modifying the text
+ var selectionCache = new List<Selection>();
+
+ using (var batchOp = _multiSelectionBroker.BeginBatchOperation())
+ {
+ _multiSelectionBroker.PerformActionOnAllSelections(transformer =>
+ {
+ // we start by getting all the lines that are in the current selection
+ var span = transformer.Selection.Extent.SnapshotSpan;
+
+ // we need the text view lines, specifically, so we ask for those
+ // that are intersecting the span that defines our selection
+ var lines = this.TextView
+ .TextViewLines
+ .GetTextViewLinesIntersectingSpan(span)
+ .Select(lx => new SnapshotSpan(lx.Start, lx.EndIncludingLineBreak))
+ .ToArray();
+
+ if (lines.Length <= 1) return;
+
+ var text = lines.Select(x => x.GetText()).ToArray();
+
+ // we only create this copy so that we can reverse it, in case the array
+ // is already sorted
+ var copy = (string[])text.Clone();
+ Array.Sort(text, StringComparer.Ordinal);
+
+ if (Enumerable.SequenceEqual(text, copy))
+ {
+ Array.Reverse(text);
+ }
+
+ selectionCache.Add(transformer.Selection);
+
+ ExecuteAction("SortLines", () =>
+ {
+ // we can simply replace the *entire* text, from the start of
+ // the first line, to the last, without caring about the
+ // lines themsleves (unlike in JoinSelectedLines),
+ // so this is much nicer!
+ var l = string.Concat(text);
+ var span = Span.FromBounds(lines.First().Start, lines.Last().End);
+
+ return ReplaceHelper(span, l);
+ }, SelectionUpdate.Ignore, true);
+ });
+ }
+
+ foreach (var item in selectionCache)
+ {
+ // we need to create a new snapshot point, otherwise the
+ // broker (rightfully) throws an exception about the selection
+ // existing in a different snapshot
+ var anchorPoint = new VirtualSnapshotPoint(_textView.TextSnapshot, item.AnchorPoint.Position);
+ var activePoint = new VirtualSnapshotPoint(_textView.TextSnapshot, item.ActivePoint.Position);
+
+ _multiSelectionBroker.AddSelection(new Selection(anchorPoint, activePoint));
+ }
+ }
+
+ /// <summary>
+ /// Joins the selected lines into a single one.
+ /// </summary>
+ public void JoinSelectedLines()
+ {
+ using (var batchOp = _multiSelectionBroker.BeginBatchOperation())
+ {
+ // since the user could have multiple selections, we should
+ // perform this merge/join on each of them separately, but
+ // we need to be careful to make sure the selections are
+ // maintained as we change the buffer underneath them, so we'll
+ // use the stuff built in
+ _multiSelectionBroker.PerformActionOnAllSelections(transformer =>
+ {
+ // we start by getting all the lines that are in the current selection
+ var span = transformer.Selection.Extent.SnapshotSpan;
+
+ // we need the text view lines, specifically, so we ask for those
+ // that are intersecting the span that defines our selection
+ var lines = this.TextView.TextViewLines.GetTextViewLinesIntersectingSpan(span);
+
+ // we are going to replace the line break, so we can include
+ // that/those particular character(s) in our array
+ var arLines = lines.Select(line =>
+ new SnapshotSpan(line.Start, line.EndIncludingLineBreak));
+
+ // we trim to get rid of spaces, tabs, etc., and replace them
+ var newLine = string.Join(" ", arLines.Select(x => x.GetText().Trim()));
+
+ // we are genuinely only interested in the first and last lines,
+ // as their start and end might differ from the extent of the
+ // selection that is defined. But to avoid iterating, we can
+ // store them in a variable here.
+ var firstLine = lines.First();
+ var lastLine = lines.Last();
+
+ // next, we need to leave the indent of the first line alone, as
+ // otherwise we need to be calling some weird functions and creating
+ // new edits, etc. Easiest way to do this is to simply go from
+ // the start position and move the position to the right until
+ // we find a non whitespace character (or reach the end of the line)
+ int startPosition = firstLine.Start.Position;
+
+ while (firstLine.End > startPosition &&
+ IsSpaceCharacter(firstLine.Snapshot[startPosition]))
+ {
+ startPosition++;
+ }
+
+ // to get the correct new line character(s), we need a snapshot
+ // line, which is obviously different, so let's get that one
+ VirtualSnapshotPoint caret = transformer.Selection.InsertionPoint;
+ ITextSnapshotLine snapshotLine = caret.Position.GetContainingLine();
+
+ // while this is not the prettiest thing in the world, it's going
+ // to likely be just as efficient as calling string.Join for
+ // just two strings
+ newLine += TextBufferOperationHelpers.GetNewLineCharacterToInsert(snapshotLine, _editorOptions);
+
+ // in order to preserve the selection, we need to call this method
+ // with SelectionUpdate.Ignore. This will ensure the following
+ // selections are left alone. Additionally, each call will create
+ // a new undo transaction - the user can then undo one by one.
+ ExecuteAction(Strings.ReplaceText, () =>
+ {
+ // while the extent of the selection is also a span, we likely
+ // moved the starting point, to match the first non-whitespace
+ // character, so we can just create a new span which will
+ // be used for replacing
+ var span = Span.FromBounds(startPosition,
+ lastLine.EndIncludingLineBreak.Position);
+ return ReplaceHelper(span, newLine);
+ }, SelectionUpdate.Ignore, true);
+ });
+ }
+ }
}
/// <summary>