diff --git a/Codist/Helpers/TextEditorHelper.cs b/Codist/Helpers/TextEditorHelper.cs
index 8eb9de05..a3df69a7 100644
--- a/Codist/Helpers/TextEditorHelper.cs
+++ b/Codist/Helpers/TextEditorHelper.cs
@@ -79,10 +79,49 @@ public static StyleBase GetStyle(string classificationType) {
}
}
- public static void ExpandSelectionToLine(this IWpfTextView view) {
+ ///
+ /// Begins an edit operation to the .
+ ///
+ /// The type of the view.
+ /// The to be edited.
+ /// The edit operation.
+ /// Returns a new if returns , otherwise, returns .
+ public static ITextSnapshot Edit(this TView view, Action action)
+ where TView : ITextView {
+ using (var edit = view.TextSnapshot.TextBuffer.CreateEdit()) {
+ action(view, edit);
+ if (edit.HasEffectiveChanges) {
+ edit.Apply();
+ return edit.Snapshot;
+ }
+ return null;
+ }
+ }
+ ///
+ /// Performs edit operation to each selected spans in the .
+ ///
+ /// The type of the view.
+ /// The to be edited.
+ /// The edit operation against each selected span.
+ /// Returns a new if returns , otherwise, returns .
+ public static ITextSnapshot EditSelection(this TView view, Action action)
+ where TView : ITextView {
+ using (var edit = view.TextSnapshot.TextBuffer.CreateEdit()) {
+ foreach (var item in view.Selection.SelectedSpans) {
+ action(view, edit, item);
+ }
+ if (edit.HasEffectiveChanges) {
+ edit.Apply();
+ return edit.Snapshot;
+ }
+ return null;
+ }
+ }
+
+ public static void ExpandSelectionToLine(this ITextView view) {
view.ExpandSelectionToLine(true);
}
- public static void ExpandSelectionToLine(this IWpfTextView view, bool includeLineBreak) {
+ public static void ExpandSelectionToLine(this ITextView view, bool includeLineBreak) {
var start = view.TextSnapshot.GetLineFromPosition(view.Selection.Start.Position).Start;
var end = view.Selection.End.Position;
var endLine = view.TextSnapshot.GetLineFromPosition(end);
@@ -92,6 +131,12 @@ public static void ExpandSelectionToLine(this IWpfTextView view, bool includeLin
}
view.Selection.Select(new SnapshotSpan(start, end), false);
}
+ public static string GetFirstSelectionText(this ITextSelection selection) {
+ return selection.IsEmpty ? String.Empty : selection.SelectedSpans[0].GetText();
+ }
+ public static string GetFirstSelectionText(this ITextView view) {
+ return view.TryGetFirstSelectionSpan(out var span) ? span.GetText() : String.Empty;
+ }
public static bool TryGetFirstSelectionSpan(this ITextView view, out SnapshotSpan span) {
if (view.Selection.IsEmpty || view.Selection.SelectedSpans.Count < 1) {
span = new SnapshotSpan();
@@ -139,15 +184,15 @@ public static TokenType GetSelectedTokenType(this ITextView view) {
return t;
}
- public static SnapshotPoint GetCaretPosition(this IWpfTextView textView) {
+ public static SnapshotPoint GetCaretPosition(this ITextView textView) {
return textView.Caret.Position.BufferPosition;
}
- public static bool IsCaretInReadOnlyRegion(this IWpfTextView textView) {
+ public static bool IsCaretInReadOnlyRegion(this ITextView textView) {
return textView.TextBuffer.IsReadOnly(textView.Caret.Position.BufferPosition);
}
- public static bool IsMultilineSelected(this IWpfTextView textView) {
+ public static bool IsMultilineSelected(this ITextView textView) {
var s = textView.Selection;
if (s.IsEmpty || s.SelectedSpans.Count < 1) {
return false;
@@ -155,7 +200,7 @@ public static bool IsMultilineSelected(this IWpfTextView textView) {
return textView.GetTextViewLineContainingBufferPosition(s.Start.Position) != textView.GetTextViewLineContainingBufferPosition(s.End.Position);
}
- public static void SelectNode(this IWpfTextView view, Microsoft.CodeAnalysis.SyntaxNode node, bool includeTrivia) {
+ public static void SelectNode(this ITextView view, Microsoft.CodeAnalysis.SyntaxNode node, bool includeTrivia) {
var span = includeTrivia ? node.FullSpan : node.Span;
if (view.TextSnapshot.Length > span.End) {
SnapshotSpan ss;
@@ -178,7 +223,7 @@ public static void SelectNode(this IWpfTextView view, Microsoft.CodeAnalysis.Syn
}
}
- public static void SelectSpan(this IWpfTextView view, SnapshotSpan span) {
+ public static void SelectSpan(this ITextView view, SnapshotSpan span) {
view.ViewScroller.EnsureSpanVisible(span, EnsureSpanVisibleOptions.ShowStart);
view.Selection.Select(span, false);
view.Caret.MoveTo(span.End);
diff --git a/Codist/SmartBars/CSharpSmartBar.cs b/Codist/SmartBars/CSharpSmartBar.cs
index ab316d3f..a0b07fa2 100644
--- a/Codist/SmartBars/CSharpSmartBar.cs
+++ b/Codist/SmartBars/CSharpSmartBar.cs
@@ -166,7 +166,7 @@ void AddContextualCommands(CancellationToken cancellationToken) {
}
}
if (isDesignMode == false) {
- AddCommands(MyToolBar, KnownImageIds.BreakpointEnabled, "Debugger...\nLeft click: Toggle breakpoint\nRight click: Debugger menu...", ctx => TextEditorHelper.ExecuteEditorCommand("Debug.ToggleBreakpoint"), GetDebugCommands);
+ AddCommands(MyToolBar, KnownImageIds.BreakpointEnabled, "Debugger...\nLeft click: Toggle breakpoint\nRight click: Debugger menu...", ctx => TextEditorHelper.ExecuteEditorCommand("Debug.ToggleBreakpoint"), ctx => DebugCommands);
}
AddCommands(MyToolBar, KnownImageIds.SelectFrame, "Expand selection...\nRight click: Duplicate...\nCtrl click item: Copy\nShift click item: Exclude whitespaces and comments", null, GetExpandSelectionCommands);
}
@@ -178,30 +178,28 @@ void AddXmlDocCommands() {
AddCommand(MyToolBar, KnownImageIds.GoToNext, "Tag XML Doc with or ", ctx => {
// updates the semantic model before executing the command,
// for it could be modified by external editor commands or duplicated document windows
- if (UpdateSemanticModel()) {
- using (var edit = ctx.View.TextSnapshot.TextBuffer.CreateEdit()) {
- foreach (var item in View.Selection.SelectedSpans) {
- var t = item.GetText();
- var d = _Context.GetNode(item.Start, false, false).GetAncestorOrSelfDeclaration();
- if (d != null) {
- var mp = (d as BaseMethodDeclarationSyntax).FindParameter(t);
- if (mp != null) {
- edit.Replace(item, "");
- continue;
- }
- var tp = d.FindTypeParameter(t);
- if (tp != null) {
- edit.Replace(item, "");
- continue;
- }
+ if (UpdateSemanticModel() == false) {
+ return;
+ }
+ ctx.View.Edit((view, edit) => {
+ foreach (var item in view.Selection.SelectedSpans) {
+ var t = item.GetText();
+ var d = _Context.GetNode(item.Start, false, false).GetAncestorOrSelfDeclaration();
+ if (d != null) {
+ var mp = (d as BaseMethodDeclarationSyntax).FindParameter(t);
+ if (mp != null) {
+ edit.Replace(item, "");
+ continue;
+ }
+ var tp = d.FindTypeParameter(t);
+ if (tp != null) {
+ edit.Replace(item, "");
+ continue;
}
- edit.Replace(item, (SyntaxFacts.GetKeywordKind(t) != SyntaxKind.None ? "");
- }
- if (edit.HasEffectiveChanges) {
- edit.Apply();
}
+ edit.Replace(item, (SyntaxFacts.GetKeywordKind(t) != SyntaxKind.None ? "");
}
- }
+ });
});
AddCommand(MyToolBar, KnownImageIds.ParagraphHardReturn, "Tag XML Doc with ", ctx => {
SurroundWith(ctx, "", "", false);
@@ -461,14 +459,6 @@ void FindSymbolWithName(CommandContext ctx, MenuItem menuItem, ISymbol source) {
SortAndGroupSymbolByClass(menuItem, new List(result));
}
- CommandItem[] GetDebugCommands(CommandContext ctx) {
- return new CommandItem[] {
- new CommandItem(KnownImageIds.Watch, "Add Watch", c => TextEditorHelper.ExecuteEditorCommand("Debug.AddWatch")),
- new CommandItem(KnownImageIds.Watch, "Add Parallel Watch", c => TextEditorHelper.ExecuteEditorCommand("Debug.AddParallelWatch")),
- new CommandItem(KnownImageIds.DeleteBreakpoint, "Delete All Breakpoints", c => TextEditorHelper.ExecuteEditorCommand("Debug.DeleteAllBreakpoints"))
- };
- }
-
List GetExpandSelectionCommands(CommandContext ctx) {
var r = new List();
var duplicate = ctx.RightClick;
diff --git a/Codist/SmartBars/CppSmartBar.cs b/Codist/SmartBars/CppSmartBar.cs
index ab6a43e2..70d3779e 100644
--- a/Codist/SmartBars/CppSmartBar.cs
+++ b/Codist/SmartBars/CppSmartBar.cs
@@ -38,18 +38,10 @@ protected override void AddCommands(CancellationToken cancellationToken) {
AddEditorCommand(MyToolBar, KnownImageIds.UncommentCode, "Edit.UncommentSelection", "Uncomment selection");
}
else if (mode != DebuggerStatus.Design) {
- AddCommands(MyToolBar, KnownImageIds.BreakpointEnabled, "Debugger...\nLeft click: Toggle breakpoint\nRight click: Debugger menu...", ctx => TextEditorHelper.ExecuteEditorCommand("Debug.ToggleBreakpoint"), GetDebugCommands);
+ AddCommands(MyToolBar, KnownImageIds.BreakpointEnabled, "Debugger...\nLeft click: Toggle breakpoint\nRight click: Debugger menu...", ctx => TextEditorHelper.ExecuteEditorCommand("Debug.ToggleBreakpoint"), ctx => DebugCommands);
}
}
- CommandItem[] GetDebugCommands(CommandContext ctx) {
- return new CommandItem[] {
- new CommandItem(KnownImageIds.Watch, "Add Watch", c => TextEditorHelper.ExecuteEditorCommand("Debug.AddWatch")),
- new CommandItem(KnownImageIds.Watch, "Add Parallel Watch", c => TextEditorHelper.ExecuteEditorCommand("Debug.AddParallelWatch")),
- new CommandItem(KnownImageIds.DeleteBreakpoint, "Delete All Breakpoints", c => TextEditorHelper.ExecuteEditorCommand("Debug.DeleteAllBreakpoints"))
- };
- }
-
string GetCurrentWord(ITextView view) {
return _TextStructureNavigator.GetExtentOfWord(view.Selection.Start.Position).Span.GetText();
}
diff --git a/Codist/SmartBars/SmartBar.CommonEdit.cs b/Codist/SmartBars/SmartBar.CommonEdit.cs
index 68484191..42b8eac0 100644
--- a/Codist/SmartBars/SmartBar.CommonEdit.cs
+++ b/Codist/SmartBars/SmartBar.CommonEdit.cs
@@ -18,23 +18,22 @@ partial class SmartBar
static readonly CommandItem[] __CaseCommands = GetCaseCommands();
static readonly CommandItem[] __SurroundingCommands = GetSurroundingCommands();
static readonly CommandItem[] __FormatCommands = GetFormatCommands();
+ static readonly CommandItem[] __DebugCommands = GetDebugCommands();
- static void ExecuteAndFind(CommandContext ctx, string command) {
- ThreadHelper.ThrowIfNotOnUIThread();
+ protected static IEnumerable DebugCommands => __DebugCommands;
+
+ static void ExecuteAndFind(CommandContext ctx, string command, string text) {
if (ctx.RightClick) {
ctx.View.ExpandSelectionToLine(false);
}
- string t = null;
- if (Keyboard.Modifiers == ModifierKeys.Control && ctx.View.Selection.IsEmpty == false) {
- t = ctx.View.TextSnapshot.GetText(ctx.View.Selection.SelectedSpans[0]);
- }
ctx.KeepToolBar(false);
TextEditorHelper.ExecuteEditorCommand(command);
- FindNext(ctx, t);
+ if (Keyboard.Modifiers == ModifierKeys.Control) {
+ FindNext(ctx, text);
+ }
}
protected static void FindNext(CommandContext ctx, string t) {
- ThreadHelper.ThrowIfNotOnUIThread();
if (t != null) {
var r = ctx.TextSearchService.Find(ctx.View.Selection.StreamSelectionSpan.End.Position, t, FindOptions.MatchCase);
if (r.HasValue) {
@@ -47,31 +46,30 @@ protected static void FindNext(CommandContext ctx, string t) {
}
protected SnapshotSpan Replace(CommandContext ctx, Func replaceHandler, bool selectModified) {
+ ctx.KeepToolBar(false);
var firstModified = new SnapshotSpan();
int length = 0;
- string t = null;
- ctx.KeepToolBar(false);
- using (var edit = ctx.View.TextSnapshot.TextBuffer.CreateEdit()) {
- foreach (var item in View.Selection.SelectedSpans) {
- t = item.GetText();
- var replacement = replaceHandler(t);
- if (replacement != null
- && edit.Replace(item, replacement)
- && firstModified.Snapshot == null) {
- firstModified = item;
- length = replacement.Length;
- }
+ string t = ctx.View.GetFirstSelectionText();
+ if (t.Length == 0) {
+ return firstModified;
+ }
+ var edited = ctx.View.EditSelection((view, edit, item) => {
+ var replacement = replaceHandler(item.GetText());
+ if (replacement != null
+ && edit.Replace(item, replacement)
+ && firstModified.Snapshot == null) {
+ firstModified = item;
+ length = replacement.Length;
}
- if (edit.HasEffectiveChanges) {
- var snapsnot = edit.Apply();
- firstModified = new SnapshotSpan(snapsnot, firstModified.Start, length);
- if (t != null
- && Keyboard.Modifiers == ModifierKeys.Control) {
- FindNext(ctx, t);
- }
- else if (selectModified) {
- View.SelectSpan(firstModified);
- }
+ });
+ if (edited != null) {
+ firstModified = new SnapshotSpan(edited, firstModified.Start, length);
+ if (t != null
+ && Keyboard.Modifiers == ModifierKeys.Control) {
+ FindNext(ctx, t);
+ }
+ else if (selectModified) {
+ ctx.View.SelectSpan(firstModified);
}
}
return firstModified;
@@ -137,7 +135,10 @@ void AddCutCommand() {
void AddDeleteCommand() {
AddCommand(ToolBar, KnownImageIds.Cancel, "Delete selected text\nRight click: Delete line\nCtrl click: Delete and select next", ctx => {
var s = View.Selection;
- if (s.Mode == TextSelectionMode.Stream && ctx.RightClick == false && Keyboard.Modifiers != ModifierKeys.Control && s.IsEmpty == false) {
+ var t = s.GetFirstSelectionText();
+ if (s.Mode == TextSelectionMode.Stream
+ && ctx.RightClick == false
+ && s.IsEmpty == false) {
var end = s.End.Position;
// remove a trailing space
if (end < View.TextSnapshot.Length - 1) {
@@ -147,7 +148,7 @@ void AddDeleteCommand() {
}
}
}
- ExecuteAndFind(ctx, "Edit.Delete");
+ ExecuteAndFind(ctx, "Edit.Delete", t);
});
}
@@ -164,10 +165,8 @@ void AddDuplicateCommand() {
void AddFindAndReplaceCommands() {
AddCommands(ToolBar, KnownImageIds.FindNext, "Find next selected text\nCtrl click: Find match case\nRight click: Find and replace...", ctx => {
ThreadHelper.ThrowIfNotOnUIThread();
- string t = ctx.View.Selection.IsEmpty == false
- ? ctx.View.TextSnapshot.GetText(ctx.View.Selection.SelectedSpans[0])
- : null;
- if (t == null) {
+ string t = ctx.View.GetFirstSelectionText();
+ if (t.Length == 0) {
return;
}
ctx.KeepToolBar(false);
@@ -184,7 +183,7 @@ void AddFindAndReplaceCommands() {
void AddPasteCommand() {
if (Clipboard.ContainsText()) {
- AddCommand(ToolBar, KnownImageIds.Paste, "Paste text from clipboard\nRight click: Paste over line\nCtrl click: Paste and select next", ctx => ExecuteAndFind(ctx, "Edit.Paste"));
+ AddCommand(ToolBar, KnownImageIds.Paste, "Paste text from clipboard\nRight click: Paste over line\nCtrl click: Paste and select next", ctx => ExecuteAndFind(ctx, "Edit.Paste", ctx.View.GetFirstSelectionText()));
}
}
@@ -195,16 +194,17 @@ void AddSpecialFormatCommand() {
break;
case TokenType.Digit:
AddCommand(ToolBar, KnownImageIds.Counter, "Increment number", ctx => {
- var span = ctx.View.Selection.SelectedSpans[0];
- var t = span.GetText();
- long l;
- if (long.TryParse(t, out l)) {
- using (var ed = ctx.View.TextBuffer.CreateEdit()) {
- t = (++l).ToString(System.Globalization.CultureInfo.InvariantCulture);
- if (ed.Replace(span.Span, t)) {
- ed.Apply();
- ctx.View.Selection.Select(new SnapshotSpan(ctx.View.TextSnapshot, span.Start, t.Length), false);
- ctx.KeepToolBar(false);
+ if (ctx.View.TryGetFirstSelectionSpan(out var span)) {
+ var t = span.GetText();
+ long l;
+ if (long.TryParse(t, out l)) {
+ using (var ed = ctx.View.TextBuffer.CreateEdit()) {
+ t = (++l).ToString(System.Globalization.CultureInfo.InvariantCulture);
+ if (ed.Replace(span.Span, t)) {
+ ed.Apply();
+ ctx.View.Selection.Select(new SnapshotSpan(ctx.View.TextSnapshot, span.Start, t.Length), false);
+ ctx.KeepToolBar(false);
+ }
}
}
}
@@ -213,13 +213,14 @@ void AddSpecialFormatCommand() {
case TokenType.Guid:
case TokenType.GuidPlaceHolder:
AddCommand(ToolBar, KnownImageIds.NewNamedSet, "New GUID\nHint: To create a new GUID, type 'guid' (without quotes) and select it", ctx => {
- var span = ctx.View.Selection.SelectedSpans[0];
- using (var ed = ctx.View.TextBuffer.CreateEdit()) {
- var t = Guid.NewGuid().ToString(span.Length == 36 || span.Length == 4 ? "D" : span.GetText()[0] == '(' ? "P" : "B").ToUpperInvariant();
- if (ed.Replace(span, t)) {
- ed.Apply();
- ctx.View.Selection.Select(new SnapshotSpan(ctx.View.TextSnapshot, span.Start, t.Length), false);
- ctx.KeepToolBar(false);
+ if (ctx.View.TryGetFirstSelectionSpan(out var span)) {
+ using (var ed = ctx.View.TextBuffer.CreateEdit()) {
+ var t = Guid.NewGuid().ToString(span.Length == 36 || span.Length == 4 ? "D" : span.GetText()[0] == '(' ? "P" : "B").ToUpperInvariant();
+ if (ed.Replace(span, t)) {
+ ed.Apply();
+ ctx.View.Selection.Select(new SnapshotSpan(ctx.View.TextSnapshot, span.Start, t.Length), false);
+ ctx.KeepToolBar(false);
+ }
}
}
});
@@ -238,9 +239,10 @@ List GetFormatItems(CommandContext arg) {
r.AddRange(__SurroundingCommands);
r.AddRange(__FormatCommands);
if (View.IsMultilineSelected()) {
- r.Add(new CommandItem(KnownImageIds.Join, "Join lines", _ => {
- var span = View.Selection.SelectedSpans[0];
- View.TextBuffer.Replace(span, System.Text.RegularExpressions.Regex.Replace(span.GetText(), @"[ \t]*\r?\n[ \t]*", " "));
+ r.Add(new CommandItem(KnownImageIds.Join, "Join lines", ctx => {
+ if (ctx.View.TryGetFirstSelectionSpan(out var span)) {
+ ctx.View.TextBuffer.Replace(span, System.Text.RegularExpressions.Regex.Replace(span.GetText(), @"[ \t]*\r?\n[ \t]*", " "));
+ }
}));
}
var t = View.GetTextViewLineContainingBufferPosition(selection.Start.Position).Extent.GetText();
@@ -259,7 +261,6 @@ List GetFormatItems(CommandContext arg) {
return r;
}
-
static CommandItem[] GetCaseCommands() {
return new CommandItem[] {
new CommandItem(KnownImageIds.Font, "Capitalize", ctx => {
@@ -276,6 +277,14 @@ static CommandItem[] GetCaseCommands() {
}),
};
}
+ static CommandItem[] GetDebugCommands() {
+ return new CommandItem[] {
+ new CommandItem(KnownImageIds.Watch, "Add Watch", c => TextEditorHelper.ExecuteEditorCommand("Debug.AddWatch")),
+ new CommandItem(KnownImageIds.Watch, "Add Parallel Watch", c => TextEditorHelper.ExecuteEditorCommand("Debug.AddParallelWatch")),
+ new CommandItem(KnownImageIds.DeleteBreakpoint, "Delete All Breakpoints", c => TextEditorHelper.ExecuteEditorCommand("Debug.DeleteAllBreakpoints"))
+ };
+ }
+
static CommandItem[] GetFormatCommands() {
return new CommandItem[] {
new CommandItem(KnownImageIds.FormatSelection, "Format Selection", _ => TextEditorHelper.ExecuteEditorCommand("Edit.FormatSelection")),
@@ -296,7 +305,9 @@ static CommandItem[] GetSurroundingCommands() {
TextEditorHelper.ExecuteEditorCommand("Edit.SurroundWith");
}),
new CommandItem(KnownImageIds.MaskedTextBox, "Toggle Parentheses", ctx => {
- var span = ctx.View.Selection.SelectedSpans[0];
+ if (ctx.View.TryGetFirstSelectionSpan(out var span) == false) {
+ return;
+ }
using (var ed = ctx.View.TextBuffer.CreateEdit()) {
var t = span.GetText();
if (t.Length > 1
diff --git a/Codist/SmartBars/SmartBar.cs b/Codist/SmartBars/SmartBar.cs
index da4eee79..3876bfc0 100644
--- a/Codist/SmartBars/SmartBar.cs
+++ b/Codist/SmartBars/SmartBar.cs
@@ -285,16 +285,17 @@ void KeepToolbar() {
void SetToolBarPosition() {
// keep tool bar position when the selection is restored and the tool bar reappears after executing command
- if (DateTime.Now > _LastExecute.AddSeconds(1)) {
- var pos = Mouse.GetPosition(View.VisualElement);
- var rs = _ToolBarTray.RenderSize;
- var x = pos.X - 35;
- var y = pos.Y - rs.Height - 10;
- Canvas.SetLeft(_ToolBarTray, x < View.ViewportLeft ? View.ViewportLeft
- : x + rs.Width < View.ViewportRight ? x
- : View.ViewportRight - rs.Width);
- Canvas.SetTop(_ToolBarTray, (y < 0 || x < View.ViewportLeft && View.Selection.IsReversed == false ? y + rs.Height + 30 : y) + View.ViewportTop);
+ if (DateTime.Now < _LastExecute.AddSeconds(1)) {
+ return;
}
+ var pos = Mouse.GetPosition(View.VisualElement);
+ var rs = _ToolBarTray.RenderSize;
+ var x = pos.X - 35;
+ var y = pos.Y - rs.Height - 10;
+ Canvas.SetLeft(_ToolBarTray, x < View.ViewportLeft ? View.ViewportLeft
+ : x + rs.Width < View.ViewportRight ? x
+ : View.ViewportRight - rs.Width);
+ Canvas.SetTop(_ToolBarTray, (y < 0 || x < View.ViewportLeft && View.Selection.IsReversed == false ? y + rs.Height + 30 : y) + View.ViewportTop);
}
#region Event handlers