|
|
|
@ -98,46 +98,70 @@ public class TextEditorCompletionBehavior : Behavior<TextEditor>
|
|
|
|
|
|
|
|
|
|
private void TextArea_TextEntered(object? sender, TextInputEventArgs e) |
|
|
|
|
{ |
|
|
|
|
if (!IsEnabled || CompletionProvider?.IsLoaded != true || e.Text is not { } triggerText) |
|
|
|
|
Logger.ConditionalTrace($"Text entered: {e.Text.ToRepr()}"); |
|
|
|
|
|
|
|
|
|
if (!IsEnabled || CompletionProvider?.IsLoaded != true) |
|
|
|
|
{ |
|
|
|
|
Logger.ConditionalTrace("Skipping, not enabled or not loaded"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (e.Text is not { } triggerText) |
|
|
|
|
{ |
|
|
|
|
Logger.ConditionalTrace("Skipping, null trigger text"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (triggerText.All(IsCompletionChar)) |
|
|
|
|
if (!triggerText.All(IsCompletionChar)) |
|
|
|
|
{ |
|
|
|
|
// Create completion window if its not already created |
|
|
|
|
if (completionWindow == null) |
|
|
|
|
if (completionWindow is { } window) |
|
|
|
|
{ |
|
|
|
|
// Get the segment of the token the caret is currently in |
|
|
|
|
if (GetCaretCompletionToken() is not { } completionRequest) |
|
|
|
|
{ |
|
|
|
|
Logger.Trace("Token segment not found"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Disallowed chars, close completion window if its open |
|
|
|
|
Logger.ConditionalTrace( |
|
|
|
|
$"Closing completion window: '{triggerText}' not a valid completion char" |
|
|
|
|
); |
|
|
|
|
window.Close(); |
|
|
|
|
completionWindow = null; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
Logger.ConditionalTrace($"Skipping, invalid trigger text: {triggerText.ToRepr()}"); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If window already open, skip since handled by completion window |
|
|
|
|
// Unless this is an end char, where we'll open a new window |
|
|
|
|
if (completionWindow != null && !triggerText.All(IsCompletionEndChar)) |
|
|
|
|
{ |
|
|
|
|
Logger.ConditionalTrace("Skipping, completion window already open"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var tokenSegment = completionRequest.Segment; |
|
|
|
|
// Get the segment of the token the caret is currently in |
|
|
|
|
if (GetCaretCompletionToken() is not { } completionRequest) |
|
|
|
|
{ |
|
|
|
|
Logger.Trace("Token segment not found"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var token = textEditor.Document.GetText(tokenSegment); |
|
|
|
|
Logger.Trace("Using token {Token} ({@Segment})", token, tokenSegment); |
|
|
|
|
var tokenSegment = completionRequest.Segment; |
|
|
|
|
|
|
|
|
|
completionWindow = CreateCompletionWindow(textEditor.TextArea); |
|
|
|
|
completionWindow.StartOffset = tokenSegment.Offset; |
|
|
|
|
completionWindow.EndOffset = tokenSegment.EndOffset; |
|
|
|
|
var token = textEditor.Document.GetText(tokenSegment); |
|
|
|
|
Logger.Trace("Using token {Token} ({@Segment})", token, tokenSegment); |
|
|
|
|
|
|
|
|
|
completionWindow.UpdateQuery(completionRequest); |
|
|
|
|
completionWindow = CreateCompletionWindow(textEditor.TextArea); |
|
|
|
|
completionWindow.StartOffset = tokenSegment.Offset; |
|
|
|
|
completionWindow.EndOffset = tokenSegment.EndOffset; |
|
|
|
|
|
|
|
|
|
completionWindow.Closed += delegate |
|
|
|
|
{ |
|
|
|
|
completionWindow = null; |
|
|
|
|
}; |
|
|
|
|
completionWindow.UpdateQuery(completionRequest); |
|
|
|
|
|
|
|
|
|
completionWindow.Show(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
completionWindow.Closed += delegate |
|
|
|
|
{ |
|
|
|
|
// Disallowed chars, close completion window if its open |
|
|
|
|
Logger.Trace($"Closing completion window: '{triggerText}' not a valid completion char"); |
|
|
|
|
completionWindow?.Close(); |
|
|
|
|
} |
|
|
|
|
completionWindow = null; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
completionWindow.Show(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
@ -154,6 +178,12 @@ public class TextEditorCompletionBehavior : Behavior<TextEditor>
|
|
|
|
|
return char.IsLetterOrDigit(c) || extraAllowedChars.Contains(c); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static bool IsCompletionEndChar(char c) |
|
|
|
|
{ |
|
|
|
|
const string endChars = ":"; |
|
|
|
|
return endChars.Contains(c); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// Gets a segment of the token the caret is currently in for completions. |
|
|
|
|
/// Returns null if caret is not on a valid completion token (i.e. comments) |
|
|
|
|