diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs
index 1ca93a3bb3..c81726df9c 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs
@@ -73,7 +73,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
public ICompletionItem CreateCompletionItem(ITextEditor context)
{
- return new SnippetCompletionItem(context, this);
+ return new SnippetCompletionItem(context, this) { AlwaysInsertSnippet = context.SelectionLength > 0 };
}
readonly static Regex pattern = new Regex(@"\$\{([^\}]*)\}", RegexOptions.CultureInvariant);
@@ -104,8 +104,8 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
if (pos < snippetText.Length) {
snippet.Elements.Add(new SnippetTextElement { Text = snippetText.Substring(pos) });
}
- if (!snippet.Elements.Any(e2 => e2 is SnippetCaretElement)) {
- int index = snippet.Elements.IndexOf(e => e is SnippetSelectionElement);
+ if (!snippet.Elements.Any(e => e is SnippetCaretElement)) {
+ int index = snippet.Elements.FindIndex(e2 => e2 is SnippetSelectionElement);
if (index > -1)
snippet.Elements.Insert(index + 1, new SnippetCaretElement());
}
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetCompletionItem.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetCompletionItem.cs
index d67484b2b5..f181b5f0e4 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetCompletionItem.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetCompletionItem.cs
@@ -40,6 +40,8 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
this.codeSnippet = codeSnippet;
}
+ public bool AlwaysInsertSnippet { get; set; }
+
public string Text {
get { return codeSnippet.Name; }
}
@@ -62,7 +64,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
if (context.Editor != this.textEditor)
throw new ArgumentException("wrong editor");
using (context.Editor.Document.OpenUndoGroup()) {
- if (context.CompletionChar == '\t') {
+ if (context.CompletionChar == '\t' || AlwaysInsertSnippet) {
context.Editor.Document.Remove(context.StartOffset, context.Length);
CreateSnippet().Insert(textArea);
} else {
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs
index 1a2f66e10c..34d5f81629 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs
@@ -53,7 +53,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
new CodeSnippet {
Name = "prop",
Description = "Property",
- Text = "${type} ${toFieldName(name)};\n\npublic ${type=int} ${name=Property} {\n\tget { return ${toFieldName(name)}; }\n\tset { ${toFieldName(name)} = value; }\n}"
+ Text = "${type} ${toFieldName(name)};\n\npublic ${type=int} ${name=Property} {\n\tget { return ${toFieldName(name)}; }\n\tset { ${toFieldName(name)} = value; }\n}${Caret}"
},
new CodeSnippet {
Name = "propdp",
@@ -65,17 +65,22 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
+ "public ${type=int} ${name=Property} {" + Environment.NewLine
+ "\tget { return (${type})GetValue(${name}Property); }" + Environment.NewLine
+ "\tset { SetValue(${name}Property, value); }"
- + Environment.NewLine + "}"
+ + Environment.NewLine + "}${Caret}"
+ },
+ new CodeSnippet {
+ Name = "props",
+ Description = "Property",
+ Text = "public ${Type=object} ${Property=Property} { get; set; }${Caret}"
},
new CodeSnippet {
Name = "ctor",
Description = "Constructor",
- Text = "public ${ClassName}()\n{\t\n${Selection}\n}"
+ Text = "public ${ClassName}(${Caret})\n{\t\n${Selection}\n}"
},
new CodeSnippet {
Name = "switch",
Description = "Switch statement",
- Text = "switch (${condition}) {\n\tcase ${firstcase=0}:\n\t\tbreak;\n\tdefault:\n\t\t${Selection}\n\t\tbreak;\n}"
+ Text = "switch (${condition}) {\n\tcase ${firstcase=0}:\n\t\t${Caret}\n\t\tbreak;\n\tdefault:\n\t\t${Selection}\n\t\tbreak;\n}"
},
new CodeSnippet {
Name = "try",
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
index d67fba149a..607d66718e 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
@@ -279,6 +279,7 @@
VisualLine.cs
+
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/InsertionContext.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/InsertionContext.cs
index 3be38b9c1a..1a8b5e6a68 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/InsertionContext.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/InsertionContext.cs
@@ -188,7 +188,7 @@ namespace ICSharpCode.AvalonEdit.Snippets
currentStatus = Status.Interactive;
if (registeredElements.Count == 0) {
// deactivate immediately if there are no interactive elements
- Deactivate(EventArgs.Empty);
+ Deactivate(new SnippetEventArgs(DeactivateReason.NoActiveElements));
} else {
myInputHandler = new SnippetInputHandler(this);
// disable existing snippet input handlers - there can be only 1 active snippet
@@ -211,14 +211,14 @@ namespace ICSharpCode.AvalonEdit.Snippets
/// Calls the method on all registered active elements.
///
/// The EventArgs to use
- public void Deactivate(EventArgs e)
+ public void Deactivate(SnippetEventArgs e)
{
if (currentStatus == Status.Deactivated || currentStatus == Status.RaisingDeactivated)
return;
if (currentStatus != Status.Interactive)
throw new InvalidOperationException("Cannot call Deactivate() until RaiseInsertionCompleted() has finished.");
if (e == null)
- e = EventArgs.Empty;
+ e = new SnippetEventArgs(DeactivateReason.Unknown);
TextDocumentWeakEventManager.UpdateFinished.RemoveListener(Document, this);
currentStatus = Status.RaisingDeactivated;
@@ -234,7 +234,7 @@ namespace ICSharpCode.AvalonEdit.Snippets
///
/// Occurs when the interactive mode is deactivated.
///
- public event EventHandler Deactivated;
+ public event EventHandler Deactivated;
bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
@@ -248,7 +248,7 @@ namespace ICSharpCode.AvalonEdit.Snippets
// Deactivate if snippet is deleted. This is necessary for correctly leaving interactive
// mode if Undo is pressed after a snippet insertion.
if (wholeSnippetAnchor.Length == 0)
- Deactivate(e);
+ Deactivate(new SnippetEventArgs(DeactivateReason.Deleted));
return true;
}
return false;
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetCaretElement.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetCaretElement.cs
index 8fed95701e..b2b97ca67e 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetCaretElement.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetCaretElement.cs
@@ -19,12 +19,17 @@ namespace ICSharpCode.AvalonEdit.Snippets
{
///
public override void Insert(InsertionContext context)
+ {
+ if (!string.IsNullOrEmpty(context.SelectedText))
+ SetCaret(context);
+ }
+
+ internal static void SetCaret(InsertionContext context)
{
TextAnchor pos = context.Document.CreateAnchor(context.InsertionPosition);
pos.SurviveDeletion = true;
context.Deactivated += (sender, e) => {
- KeyEventArgs ke = e as KeyEventArgs;
- if (ke != null && ke.Key == Key.Return) {
+ if (e.Reason == DeactivateReason.ReturnPressed || e.Reason == DeactivateReason.NoActiveElements) {
context.TextArea.Caret.Offset = pos.Offset;
}
};
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetEventArgs.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetEventArgs.cs
new file mode 100644
index 0000000000..ea7f362cf8
--- /dev/null
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetEventArgs.cs
@@ -0,0 +1,61 @@
+//
+//
+//
+//
+// $Revision$
+//
+
+using System;
+
+namespace ICSharpCode.AvalonEdit.Snippets
+{
+ ///
+ /// Provides information about the event that occured during use of snippets.
+ ///
+ public class SnippetEventArgs : EventArgs
+ {
+ ///
+ /// Gets the reason for deactivation.
+ ///
+ public DeactivateReason Reason { get; private set; }
+
+ ///
+ /// Creates a new SnippetEventArgs object, with a DeactivateReason.
+ ///
+ public SnippetEventArgs(DeactivateReason reason)
+ {
+ this.Reason = reason;
+ }
+ }
+
+ ///
+ /// Describes the reason for deactivation of a .
+ ///
+ public enum DeactivateReason
+ {
+ ///
+ /// Unknown reason.
+ ///
+ Unknown,
+ ///
+ /// Snippet was deleted.
+ ///
+ Deleted,
+ ///
+ /// There are no active elements in the snippet.
+ ///
+ NoActiveElements,
+ ///
+ /// The SnippetInputHandler was detached.
+ ///
+ InputHandlerDetached,
+ ///
+ /// Return was pressed by the user.
+ ///
+ ReturnPressed,
+ ///
+ /// Escape was pressed by the user.
+ ///
+ EscapePressed
+ }
+}
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetInputHandler.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetInputHandler.cs
index a1273b5587..d32450e2bb 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetInputHandler.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetInputHandler.cs
@@ -36,14 +36,17 @@ namespace ICSharpCode.AvalonEdit.Snippets
public override void Detach()
{
base.Detach();
- context.Deactivate(EventArgs.Empty);
+ context.Deactivate(new SnippetEventArgs(DeactivateReason.InputHandlerDetached));
}
public override void OnPreviewKeyDown(KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
- if (e.Key == Key.Escape || e.Key == Key.Return) {
- context.Deactivate(e);
+ if (e.Key == Key.Escape) {
+ context.Deactivate(new SnippetEventArgs(DeactivateReason.EscapePressed));
+ e.Handled = true;
+ } else if (e.Key == Key.Return) {
+ context.Deactivate(new SnippetEventArgs(DeactivateReason.ReturnPressed));
e.Handled = true;
} else if (e.Key == Key.Tab) {
bool backwards = e.KeyboardDevice.Modifiers == ModifierKeys.Shift;
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetReplaceableTextElement.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetReplaceableTextElement.cs
index 875d0697af..75a42eee8b 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetReplaceableTextElement.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetReplaceableTextElement.cs
@@ -71,7 +71,7 @@ namespace ICSharpCode.AvalonEdit.Snippets
void AnchorDeleted(object sender, EventArgs e)
{
- context.Deactivate(EventArgs.Empty);
+ context.Deactivate(new SnippetEventArgs(DeactivateReason.Deleted));
}
public void OnInsertionCompleted()
diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetSelectionElement.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetSelectionElement.cs
index a067ace6db..f8410f6685 100644
--- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetSelectionElement.cs
+++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Snippets/SnippetSelectionElement.cs
@@ -21,6 +21,8 @@ namespace ICSharpCode.AvalonEdit.Snippets
public override void Insert(InsertionContext context)
{
context.InsertText(context.SelectedText);
+ if (string.IsNullOrEmpty(context.SelectedText))
+ SnippetCaretElement.SetCaret(context);
}
}
}
diff --git a/src/Main/Base/Project/Src/Util/ExtensionMethods.cs b/src/Main/Base/Project/Src/Util/ExtensionMethods.cs
index d30c09d565..0a00f553d3 100644
--- a/src/Main/Base/Project/Src/Util/ExtensionMethods.cs
+++ b/src/Main/Base/Project/Src/Util/ExtensionMethods.cs
@@ -410,7 +410,7 @@ namespace ICSharpCode.SharpDevelop
/// Returns the index of the first element for which constraint returns true.
/// If none of the items in the list fits the constraint -1 is returned.
///
- public static int IndexOf(this IList list, Func constraint) {
+ public static int FindIndex(this IList list, Func constraint) {
for (int i = 0; i < list.Count; i++) {
if (constraint(list[i]))
return i;