فهرست منبع

Script Editors now only show completions on Ctrl+Space, not every. single. stupid. keystroke.

frogsoftware 1 ماه پیش
والد
کامیت
757e603a5d

+ 29 - 2
inabox.wpf/DynamicGrid/Controls/ScriptEditor.xaml.cs

@@ -44,6 +44,7 @@ namespace InABox.DynamicGrid
         }
 
         private RoslynHost _host;
+        private ManualOnlyCompletionProvider? _manual;
 
         private readonly SyntaxLanguage _language = SyntaxLanguage.CSharp;
 
@@ -76,9 +77,10 @@ namespace InABox.DynamicGrid
             EditorTitle = scriptTitle;
 
             InitializeComponent();
-
+            
             // Not Sure if we need Roslyn for XAML - need to research this
             if (language == SyntaxLanguage.CSharp || language == SyntaxLanguage.XAML)
+            {
                 try
                 {
                     if (ScriptDocument.Host == null)
@@ -88,7 +90,8 @@ namespace InABox.DynamicGrid
                 {
                     MessageBox.Show("Unable to initialize Script Editor!\nPlease try again.\n\n" + e.Message);
                 }
-
+            }
+            
             Editor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition(
                 language == SyntaxLanguage.HTML
                     ? "HTML"
@@ -98,6 +101,19 @@ namespace InABox.DynamicGrid
                             ? "CSS"
                             : "C#"
             );
+                        
+
+            // Arm on Ctrl+Space, but don't handle the key so the editor's command still runs.
+            Editor.PreviewKeyDown += (s, e) =>
+            {
+                if (e.Key == System.Windows.Input.Key.Space &&
+                    (System.Windows.Input.Keyboard.Modifiers & System.Windows.Input.ModifierKeys.Control) != 0)
+                {
+                    _manual?.AllowNextCompletionOnce();
+                    // IMPORTANT: do not set e.Handled = true
+                }
+            };
+
 
             Editor.TextArea.TextEntering += TextArea_TextEntering;
 
@@ -308,6 +324,17 @@ namespace InABox.DynamicGrid
 
         private void Timer_Tick(object sender, EventArgs e)
         {
+            if ((_manual == null) && (Editor.CompletionProvider != null))
+            {
+                _manual  = new ManualOnlyCompletionProvider(Editor.CompletionProvider)
+                {
+                    AllowSignatureHelp = false,
+                    TreatNullTriggerAsManualInvoke = true,
+                    AllowDotTrigger = false
+                };
+                Editor.CompletionProvider = _manual;
+            }
+            
             CheckButton(CopyButton, !string.IsNullOrEmpty(Editor.SelectedText), copy);
             CheckButton(CutButton, !string.IsNullOrEmpty(Editor.SelectedText), cut);
             CheckButton(PasteButton, Clipboard.ContainsText(), paste);

+ 63 - 0
inabox.wpf/DynamicGrid/Editors/ScriptEditor/ManualOnlyCompletionProvider.cs

@@ -0,0 +1,63 @@
+using System.Threading;
+using System.Threading.Tasks;
+using RoslynPad.Editor;
+
+public sealed class ManualOnlyCompletionProvider : ICodeEditorCompletionProvider
+{
+    private readonly ICodeEditorCompletionProvider _inner;
+
+    // 0 = blocked, 1 = allow exactly one completion request
+    private int _allowOnce;
+
+    public ManualOnlyCompletionProvider(ICodeEditorCompletionProvider inner)
+        => _inner = inner;
+
+    /// <summary>
+    /// Call this immediately before letting the editor execute its completion action (Ctrl + Space).
+    /// </summary>
+    public void AllowNextCompletionOnce()
+        => Interlocked.Exchange(ref _allowOnce, 1);
+
+    /// <summary>
+    /// If false, blocks signature help popups (parameter hints).
+    /// </summary>
+    public bool AllowSignatureHelp { get; set; } = false;
+
+    /// <summary>
+    /// If true, a request with triggerChar == null is treated as a manual invoke
+    /// even if you didn't call AllowNextCompletionOnce().
+    /// </summary>
+    public bool TreatNullTriggerAsManualInvoke { get; set; } = true;
+
+    /// <summary>
+    /// If true, allows '.' to trigger completion while typing (classic IDE feel),
+    /// while still blocking letter-by-letter popups.
+    /// </summary>
+    public bool AllowDotTrigger { get; set; } = false;
+
+    public Task<CompletionResult> GetCompletionData(int position, char? triggerChar, bool useSignatureHelp)
+    {
+        // No results object for this build:
+        static CompletionResult EmptyResult() => new CompletionResult(null, null, useHardSelection: false);
+
+        // 1) Signature help requested?
+        if (useSignatureHelp && !AllowSignatureHelp)
+            return Task.FromResult(EmptyResult());
+
+        // 2) Typed character triggers (auto popup on keystrokes)
+        if (triggerChar is not null)
+        {
+            if (!(AllowDotTrigger && triggerChar == '.'))
+                return Task.FromResult(EmptyResult());
+        }
+
+        // 3) Manual gating: either explicitly armed once, or inferred from null trigger
+        if (Interlocked.Exchange(ref _allowOnce, 0) == 1)
+            return _inner.GetCompletionData(position, triggerChar, useSignatureHelp);
+
+        if (TreatNullTriggerAsManualInvoke && triggerChar is null && !useSignatureHelp)
+            return _inner.GetCompletionData(position, triggerChar, useSignatureHelp);
+
+        return Task.FromResult(EmptyResult());
+    }
+}