Esempio n. 1
0
    public void Show(SciCode doc, int position, List <CiComplItem> a, List <string> groups)
    {
        if (a.NE_())
        {
            Hide();
            return;
        }

        _a             = a;
        _groups        = groups;
        _groupsEnabled = _groups != null && _groupButton.IsChecked == true;
        _doc           = doc;

        foreach (var v in _kindButtons)
        {
            v.IsChecked = false;
        }
        _groupButton.Visibility = _groups != null ? Visibility.Visible : Visibility.Collapsed;
        UpdateVisibleItems();

        var r = CiUtil.GetCaretRectFromPos(_doc, position, inScreen: true);

        r.left -= Dpi.Scale(50, _doc);

        _popup.ShowByRect(_doc, Dock.Bottom, r);
    }
Esempio n. 2
0
    public async void SciMouseDwellStarted(SciCode doc, int pos8, bool isDiag)
    {
        var pi = Panels.Info;

        if (!pi.Visible)
        {
            pi = null;
        }
        if (isDiag && pi == null)
        {
            return;
        }

        if (pos8 <= 0)
        {
            pi?.ZSetAboutInfo(); return;
        }

        //APerf.First();
        int pos16 = doc.Pos16(pos8);

        if (!CodeInfo.GetContextAndDocument(out var cd, pos16))
        {
            pi?.ZSetAboutInfo(cd.metaEnd > 0); return;
        }

        //APerf.Next();
        var context = new QuickInfoContext(cd.document, pos16, default);

        //APerf.Next();
        var provider = new CSharpSemanticQuickInfoProvider();
        //var r = await provider.GetQuickInfoAsync(context); //not async
        var r = await Task.Run(async() => await provider.GetQuickInfoAsync(context));

        //APerf.Next();
        if (r == null)
        {
            pi?.ZSetAboutInfo(); return;
        }

        //AOutput.Write(r.Span, r.RelatedSpans);
        //AOutput.Write(r.Tags);

        var b = new StringBuilder("<body><div>");

        //image
        CiUtil.TagsToKindAndAccess(r.Tags, out var kind, out var access);
        if (kind != CiItemKind.None)
        {
            if (access != default)
            {
                b.AppendFormat("<img src='@a{0}' style='padding-top: 6px' />", (int)access);
            }
            b.AppendFormat("<img src='@k{0}' style='padding-top: 2px' />", (int)kind);
        }

        //bool hasDocComm = false;
        //QuickInfoSection descr = null;
        POINT excRange = default, retRange = default;
Esempio n. 3
0
    unsafe void _Styling()
    {
        var styles8 = CiUtil.GetScintillaStylingBytes(zText);

        Call(Sci.SCI_STARTSTYLING);

        fixed(byte *p = styles8) Call(Sci.SCI_SETSTYLINGEX, styles8.Length, p);
    }
Esempio n. 4
0
    public void Show(SciCode doc, int position)
    {
        _doc = doc;

        var r = CiUtil.GetCaretRectFromPos(doc, position);

        r.X -= _tb.Width + _TextHorzOffset + 6;

        _SetRect(r);
        _w.ZShow(doc);
    }
Esempio n. 5
0
    public void Help_Context()
    {
        var c = AWnd.ThisThread.FocusedControl;

        if (c == null)
        {
            return;
        }
        if (c == Panels.Editor.ZActiveDoc)
        {
            CiUtil.OpenSymbolFromPosHelp();
        }
    }
Esempio n. 6
0
        public static void Context_help()
        {
            var w = Api.GetFocus();

            if (w.ClassNameIs("HwndWrapper*"))
            {
                //var e = Keyboard.FocusedElement as FrameworkElement;
            }
            else if (w == Panels.Editor.ZActiveDoc.Hwnd)
            {
                CiUtil.OpenSymbolOrKeywordFromPosHelp();
            }
        }
Esempio n. 7
0
    public void KeysWindowShow(SciCode doc, string code, int pos16, TextSpan stringSpan)
    {
        if (_keysWindow == null)
        {
            _keysWindow             = new KeysWindow();
            _keysWindow.Window.Name = "Ci.Keys";             //prevent hiding when activated
        }
        var r = CiUtil.GetCaretRectFromPos(doc, pos16);
        int i = Au.Util.ADpi.ScaleInt(100);

        r.Width = i;
        r.Inflate(i, 0);
        _keysWindow.Show(doc, r, false, PopupAlignment.TPM_CENTERALIGN | PopupAlignment.TPM_VERTICAL);
        _keysWindow.InsertInControl = doc;
        int vi = _StringPrefixLength(code, stringSpan.Start);

        doc.ZTempRanges_Add(this, stringSpan.Start + vi + 1, stringSpan.End - 1, onLeave: () => _keysWindow.Hide());
    }
Esempio n. 8
0
    public void RegexWindowShow(SciCode doc, string code, int pos16, TextSpan stringSpan, bool replace)
    {
        int j = stringSpan.Start, vi = _StringPrefixLength(code, j);

        if (!replace && (vi == 0 || !(code[j] == '@' || code[j + 1] == '@')))
        {
            ADialog.ShowInfo(null, "Regular expression string should be like @\"text\", not like \"text\". The Regex tool will not escape \\ when inserting text.");
        }

        if (_regexWindow == null)
        {
            _regexWindow             = new RegexWindow();
            _regexWindow.Window.Name = "Ci.Regex";             //prevent hiding when activated
        }

        var r = CiUtil.GetCaretRectFromPos(doc, pos16);
        int i = Au.Util.ADpi.ScaleInt(100);

        r.Width = i;
        r.Inflate(i, 0);
        _regexWindow.Show(doc, r, false, PopupAlignment.TPM_CENTERALIGN | PopupAlignment.TPM_VERTICAL);
        _regexWindow.InsertInControl = doc;
        var s = _regexWindow.CurrentTopic;

        if (s == "replace")
        {
            if (!replace)
            {
                _regexWindow.CurrentTopic = _regexTopic;
            }
        }
        else if (replace)
        {
            _regexTopic = s;
            _regexWindow.CurrentTopic = "replace";
        }
        doc.ZTempRanges_Add(this, stringSpan.Start + vi + 1, stringSpan.End - 1, onLeave: () => _regexWindow.Hide());
    }
Esempio n. 9
0
    static void _ShowRegexOrKeysWindow(bool regex)
    {
        bool retry = false;

g1:
        if (!CodeInfo.GetDocumentAndFindNode(out var cd, out var node))
        {
            return;
        }
        var pos16 = cd.pos16;

        if (!CiUtil.IsInString(ref node, pos16))
        {
            if (regex || retry)
            {
                ADialog.ShowInfo("The text cursor must be in a string.");
                return;
            }
            InsertCode.Statements("AKeys.Key(\"%\");", goToPercent: true);
            retry = true;
            goto g1;
        }
        var doc        = cd.sciDoc;
        var stringSpan = node.Span;

        var t = CodeInfo._tools;

        if (regex)
        {
            t.RegexWindowShow(doc, cd.code, pos16, stringSpan, replace: false);
        }
        else
        {
            t.KeysWindowShow(doc, cd.code, pos16, stringSpan);
        }
    }
Esempio n. 10
0
    ///// <summary>
    ///// The child list control.
    ///// </summary>
    //public AuListControl ListControl => _list;

    public CiPopupList(CiCompletion compl)
    {
        _compl = compl;

        _w = new _Window(this);
        _w.SuspendLayout();
        _w.Size = Au.Util.ADpi.ScaleSize((300, 360));

        _list = new _FastListBox();
        _list.SuspendLayout();
        _list.AccessibleName         = _list.Name = "Codein_list";
        _list.Dock                   = DockStyle.Fill;
        _list.BackColor              = Color.White;
        _list.ZItemClick            += _list_ItemClick;
        _list.ZSelectedIndexChanged += _list_SelectedIndexChanged;

        _tb = new Au.Util.AToolStrip();
        _tb.SuspendLayout();
        _tb.AccessibleName = _tb.Name = "Codein_listFilter";
        _tb.Renderer       = new AuDockPanel.ZDockedToolStripRenderer();
        _tb.GripStyle      = ToolStripGripStyle.Hidden;
        _tb.LayoutStyle    = ToolStripLayoutStyle.VerticalStackWithOverflow;
        int tbWidth = 0;

        var kindNames = CiUtil.ItemKindNames;

        _nKindButtons = kindNames.Length;
        for (int i = 0; i < kindNames.Length; i++)
        {
            _AddButton(kindNames[i], CiUtil.GetKindImage((CiItemKind)i));
        }
        _tb.Items.Add(new ToolStripSeparator());
        _groupButton = _AddButton("Group by namespace or inheritance", EdResources.GetImageNoCacheDpi(nameof(Au.Editor.Resources.Resources.ciGroupBy)));
        if (Program.Settings.ci_complGroup)
        {
            _groupButton.Checked = true;
        }

        ToolStripButton _AddButton(string text, Image image)
        {
            var b = _tb.Items.Add(image) as ToolStripButton;

            b.DisplayStyle = ToolStripItemDisplayStyle.Image;
            b.ImageScaling = ToolStripItemImageScaling.None;
            b.Name         = b.AccessibleName = b.ToolTipText = text;
            b.Margin       = new Padding(1, 1, 0, 0);
            if (tbWidth == 0)
            {
                tbWidth = 4 + b.ContentRectangle.Left * 2 + image.Width;
            }
            return(b);
        }

        _tb.Width        = tbWidth; _tb.AutoSize = false;  //does not work well with autosize, eg width too small when high DPI
        _tb.Dock         = DockStyle.Left;
        _tb.ItemClicked += _tb_ItemClicked;

        _w.Controls.Add(_list);
        _w.Controls.Add(_tb);
        _tb.ResumeLayout();
        _list.ResumeLayout();
        _w.ResumeLayout(true);

        _imgStatic   = EdResources.GetImageNoCacheDpi(nameof(Au.Editor.Resources.Resources.ciOverlayStatic));
        _imgAbstract = EdResources.GetImageNoCacheDpi(nameof(Au.Editor.Resources.Resources.ciOverlayAbstract));

        _popupHtml  = new CiPopupHtml(CiPopupHtml.UsedBy.PopupList);
        _popupTimer = new ATimer(_ShowPopupHtml);
    }
Esempio n. 11
0
    void _ShowSignature(SciCode doc, char ch)
    {
        //APerf.First();
        if (!CodeInfo.GetContextAndDocument(out var cd, -2))
        {
            return;                                                         //returns false if position is in meta comments
        }
        //APerf.Next();
        var trigger   = new SignatureHelpTriggerInfo(ch == default ? SignatureHelpTriggerReason.InvokeSignatureHelpCommand : SignatureHelpTriggerReason.TypeCharCommand, ch);
        var providers = _SignatureHelpProviders;
        //AOutput.Write(providers);
        //APerf.Next();
        SignatureHelpItems r = null;

        foreach (var p in providers)
        {
            //APerf.First();
            var r2 = p.GetItemsAsync(cd.document, cd.pos16, trigger, default).Result;
            //APerf.NW(); //quite fast, don't need async. But in the future can try to wrap this foreach+SignatureHelpProviders in async Task. Need to test with large files.
            if (r2 == null)
            {
                continue;
            }
            if (r == null || r2.ApplicableSpan.Start > r.ApplicableSpan.Start)
            {
                r = r2;
            }
            //Example: 'AOutput.Write(new Something())'.
            //	The first provider probably is for Write (invocation).
            //	Then the second is for Something (object creation).
            //	We need the innermost, in this case Something.
        }

        if (r == null)
        {
            Cancel();
            return;
        }
        //APerf.NW('s');
        //AOutput.Write($"<><c orange>pos={de.position}, span={r.ApplicableSpan},    nItems={r.Items.Count},  argCount={r.ArgumentCount}, argIndex={r.ArgumentIndex}, argName={r.ArgumentName}, sel={r.SelectedItemIndex},    provider={provider}<>");

        //var node = document.GetSyntaxRootAsync().Result;
        var span = new _Span(r.ApplicableSpan, cd.code);
        int iSel = _data?.GetUserSelectedItemIfSameSpan(span, r) ?? -1;         //preserve user selection in same session

        _data = new _Data {
            r             = r,
            span          = span,
            iUserSelected = iSel,
            sciDoc        = doc,
        };

        if (iSel < 0)
        {
            iSel = r.SelectedItemIndex ?? (r.ArgumentCount == 0 ? 0 : -1);
            if (iSel < 0)
            {
                for (int i = 0; i < r.Items.Count; i++)
                {
                    if (r.Items[i].Parameters.Length >= r.ArgumentCount)
                    {
                        iSel = i; break;
                    }
                }
                if (iSel < 0)
                {
                    for (int i = 0; i < r.Items.Count; i++)
                    {
                        if (r.Items[i].IsVariadic)
                        {
                            iSel = i; break;
                        }
                    }
                    if (iSel < 0)
                    {
                        iSel = 0;
                    }
                }
            }
        }

        string html = _FormatHtml(iSel, userSelected: false);

        doc.ZTempRanges_Add(this, r.ApplicableSpan.Start, r.ApplicableSpan.End, onLeave: () => {
            if (doc.ZTempRanges_Enum(doc.Z.CurrentPos8, this, utf8: true).Any())
            {
                return;
            }
            Cancel();
        }, SciCode.ZTempRangeFlags.NoDuplicate);

        var rect1 = CiUtil.GetCaretRectFromPos(doc, r.ApplicableSpan.Start);
        var rect2 = CiUtil.GetCaretRectFromPos(doc, cd.pos16);
        var rect  = doc.RectangleToScreen(Rectangle.Union(rect1, rect2));

        rect.Width += Au.Util.ADpi.ScaleInt(200);
        rect.X     -= 6;

        _popupHtml ??= new CiPopupHtml(CiPopupHtml.UsedBy.Signature, onHiddenOrDestroyed: _ => _data = null)
        {
            OnLinkClick = (ph, e) => ph.Html = _FormatHtml(e.Link.ToInt(1), userSelected: true)
        };
        _popupHtml.Html = html;
        _popupHtml.Show(Panels.Editor.ZActiveDoc, rect, PopupAlignment.TPM_VERTICAL);
        //APerf.NW();
    }
Esempio n. 12
0
    public async Task <Section> GetTextAt(int pos16)
    {
        //using var p1 = perf.local();
        if (!CodeInfo.GetContextAndDocument(out var cd, pos16))
        {
            return(null);
        }

        //don't include <remarks>. Sometimes it takes too much space. Badly formatted if eg contains markdown.
        var opt1 = QuickInfoOptions.Default with {
            ShowRemarksInQuickInfo = false, IncludeNavigationHintsInQuickInfo = false
        };
        var opt2 = new Microsoft.CodeAnalysis.LanguageServices.SymbolDescriptionOptions(opt1, Microsoft.CodeAnalysis.Classification.ClassificationOptions.Default);

        var service = QuickInfoService.GetService(cd.document);
        var r       = await Task.Run(async() => await service.GetQuickInfoAsync(cd.document, pos16, opt2, default));

        //p1.Next();
        if (r == null)
        {
            return(null);
        }
        //this oveload is internal, but:
        //	- The public overload does not have an options parameter. Used to set options for workspace, but it stopped working.
        //	- Roslyn in Debug config asserts "don't use this function".

        //print.it(r.Span, r.RelatedSpans);
        //print.it(r.Tags);

        var a = r.Sections;

        if (a.Length == 0)
        {
            return(null);                       //when cursor is on }. //SHOULDDO: display block start code, like in VS.
        }
        //don't show some useless quickinfos, eg for literals
        if (r.Tags.Length == 2 && a.Length == 2 && a[1].Kind == QuickInfoSectionKinds.DocumentationComments)
        {
            //print.it(r.Tags[0], a[1].Kind, a[1].Text);
            var s = a[1].Text;
            if (s.Starts("Represents "))
            {
                switch (r.Tags[0])
                {
                case "Class":
                    if (s == "Represents text as a sequence of UTF-16 code units.")
                    {
                        return(null);
                    }
                    break;

                case "Structure":
                    if (s.RxIsMatch(@"^Represents a (\d+-bit u?n?signed integer|[\w+-]+ floating-point number)\.$"))
                    {
                        return(null);
                    }
                    break;
                }
            }
        }

        var x = new CiText();

        //bool hasDocComm = false;
        //QuickInfoSection descr = null;
        for (int i = 0; i < a.Length; i++)
        {
            var se = a[i];
            //print.it(se.Kind, se.Text);

            //if (se.Kind == QuickInfoSectionKinds.RemarksDocumentationComments) continue;

            x.StartParagraph();

            //if (se.Kind == QuickInfoSectionKinds.RemarksDocumentationComments) {
            //	x.Append("More info in Remarks (click and press F1)."); //no, because the DB does not contain Au and .NET remarks; would show this info only for others (local, XML files).
            //} else {
            if (i == 0)               //image
            {
                CiUtil.TagsToKindAndAccess(r.Tags, out var kind, out var access);
                if (kind != CiItemKind.None)
                {
                    if (access != default)
                    {
                        x.Image(access);
                    }
                    x.Image(kind);
                    x.Append(" ");
                }
            }

            var tp = se.TaggedParts;
            if (tp[0].Tag == TextTags.LineBreak)               //remove/replace some line breaks in returns and exceptions
            {
                int lessNewlines = se.Kind switch { QuickInfoSectionKinds.ReturnsDocumentationComments => 1, QuickInfoSectionKinds.Exception => 2, _ => 0 };
                var k            = new List <TaggedText>(tp.Length - 1);
                for (int j = 1; j < tp.Length; j++)
                {
                    var v = tp[j];
                    if (lessNewlines > 0 && j > 1)
                    {
                        if (v.Tag == TextTags.LineBreak)
                        {
                            if (j == 2)
                            {
                                continue;                                     //remove line break after "Returns:" etc
                            }
                            if (lessNewlines == 2)                            //in list of exceptions replace "\n  " with ", "
                            {
                                if (++j == tp.Length || tp[j].Tag != TextTags.Space)
                                {
                                    j--; continue;
                                }
                                v = new(TextTags.Text, ", ");
                            }
                        }
                    }
                    k.Add(v);
                }
                x.AppendTaggedParts(k, false);
            }
            else
            {
                x.AppendTaggedParts(tp);
            }
            //}

            x.EndParagraph();
        }

        return(x.Result);
    }
}
Esempio n. 13
0
    async void _ShowSignature(SciCode doc, char ch, bool methodCompletion = false)
    {
        //using var p1 = perf.local();
        if (!CodeInfo.GetContextAndDocument(out var cd, -2) || cd.pos < 2)
        {
            return;                                                                        //returns false if position is in meta comments
        }
        _cancelTS?.Cancel();
        _cancelTS = new CancellationTokenSource();
        var cancelTS    = _cancelTS;
        var cancelToken = cancelTS.Token;

#if DEBUG
        if (Debugger.IsAttached)
        {
            cancelToken = default; _cancelTS = null;
        }
#endif

        SyntaxNode root = null;
        //ISignatureHelpProvider provider = null;
        SignatureHelpItems r = null;
        try {
            //could be sync, quite fast, but then sometimes reenters (GetItemsAsync waits/dispatches) and sometimes hangs
            r = await Task.Run(async() => {
                //p1.Next();
                root = cd.syntaxRoot;
                //p1.Next('r');
                var providers = _SignatureHelpProviders;
                //print.it(providers);
                SignatureHelpItems r = null;
                var trigger          = new SignatureHelpTriggerInfo(ch == default ? SignatureHelpTriggerReason.InvokeSignatureHelpCommand : SignatureHelpTriggerReason.TypeCharCommand, ch);
                foreach (var p in providers)
                {
                    //print.it(p);
                    var r2 = await p.GetItemsAsync(cd.document, cd.pos, trigger, SignatureHelpOptions.Default, cancelToken).ConfigureAwait(false);
                    if (cancelToken.IsCancellationRequested) /*print.it("IsCancellationRequested");*/ return {
                        (null);
                    }                                                                                                                      //often
                    if (r2 == null)
                    {
                        continue;
                    }
                    if (r == null || r2.ApplicableSpan.Start > r.ApplicableSpan.Start)
                    {
                        r = r2;
                        //provider = p;
                    }
                    //Example: 'print.it(new Something())'.
                    //	The first provider probably is for Write (invocation).
                    //	Then the second is for Something (object creation).
                    //	We need the innermost, in this case Something.
                }
                return(r);
            });
        }
        catch (OperationCanceledException) { /*Debug_.Print("canceled");*/ return; }         //never noticed
        //catch (AggregateException e1) when (e1.InnerException is TaskCanceledException) { return; }
        finally {
            cancelTS.Dispose();
            if (cancelTS == _cancelTS)
            {
                _cancelTS = null;
            }
        }
        //print.it(r, cancelToken.IsCancellationRequested);

        if (cancelToken.IsCancellationRequested)
        {
            return;
        }
        if (r == null)
        {
            _CancelUI();
            return;
        }
        Debug.Assert(doc == Panels.Editor.ZActiveDoc);         //when active doc changed, cancellation must be requested
        if (cd.pos != doc.zCurrentPos16 || (object)cd.code != doc.zText)
        {
            return;                                                                      //changed while awaiting
        }
        //p1.Next('s');

        //print.it($"<><c orange>pos={cd.pos}, span={r.ApplicableSpan},    nItems={r.Items.Count},  argCount={r.ArgumentCount}, argIndex={r.ArgumentIndex}, argName={r.ArgumentName}, sel={r.SelectedItemIndex},    provider={provider}<>");

        //get span of the arglist. r.ApplicableSpan.Start is of the statement, not of the arglist. In chained methods it is the chain start.
        var fullSpan = r.ApplicableSpan;
        //CiUtil.HiliteRange(fullSpan); wait.doEvents(500);
        var start = fullSpan.Start;
        var tok   = root.FindToken(cd.pos);
        if (tok.Kind() is SyntaxKind.OpenParenToken or SyntaxKind.OpenBracketToken or SyntaxKind.LessThanToken)
        {
            tok = tok.GetPreviousToken();
        }
        var argNode = tok.Parent;
        while (argNode != null)
        {
            int i = argNode.SpanStart; if (i <= start)
            {
                break;
            }
            if (argNode is BaseArgumentListSyntax or AttributeArgumentListSyntax or TypeArgumentListSyntax)
            {
                start = i + 1;
                break;
            }
            //CiUtil.PrintNode(argNode);
            argNode = argNode.Parent;
        }
        var argSpan = new TextSpan(start, fullSpan.End - start);
        //CiUtil.PrintNode(argNode); CiUtil.HiliteRange(argSpan); //print.it(argSpan);

        var span = new _Span(argSpan, cd.code);
        int iSel = 0, iSel2 = 0;
        if (r.Items.Count > 1)
        {
            iSel2 = r.SelectedItemIndex ?? -1;
            if (_data?.IsSameArglist(span, r) ?? false)
            {
                iSel = _data.iUserSelected;                 //preserve user selection in same session
                if (iSel2 < 0)
                {
                    iSel2 = _data.iRoslynSelected;                            //on error use last good Roslyn selection in same session, like in VS
                }
            }
            else
            {
                iSel = -1;
            }
        }

        _data = new _Data {
            r               = r,
            span            = span,
            iUserSelected   = iSel,
            iRoslynSelected = iSel2,
            sci             = doc,
        };

        if (iSel < 0)
        {
            iSel = iSel2;
        }
        if (iSel < 0)
        {
            //r.SelectedItemIndex is null when cannot resolve overloads, eg when arglist is partially typed. Example: wnd.find(1, );
            iSel = r.SelectedItemIndex ?? (r.ArgumentCount == 0 ? 0 : -1);
            if (iSel < 0)
            {
                for (int i = 0; i < r.Items.Count; i++)
                {
                    if (r.Items[i].Parameters.Length >= r.ArgumentCount)
                    {
                        iSel = i; break;
                    }
                }
                if (iSel < 0)
                {
                    for (int i = 0; i < r.Items.Count; i++)
                    {
                        if (r.Items[i].IsVariadic)
                        {
                            iSel = i; break;
                        }
                    }
                    if (iSel < 0)
                    {
                        iSel = 0;
                    }
                }
            }
        }

        doc.ZTempRanges_Add(this, argSpan.Start, argSpan.End, onLeave: () => {
            if (doc.ZTempRanges_Enum(doc.zCurrentPos8, this, utf8: true).Any())
            {
                return;
            }
            _CancelUI();
        }, SciCode.ZTempRangeFlags.NoDuplicate);

        var rect = RECT.Union(CiUtil.GetCaretRectFromPos(doc, fullSpan.Start), CiUtil.GetCaretRectFromPos(doc, cd.pos));
        doc.Hwnd.MapClientToScreen(ref rect);
        rect.Width += Dpi.Scale(200, doc.Hwnd);
        rect.left  -= 6;

        _textPopup ??= new CiPopupText(CiPopupText.UsedBy.Signature, onHiddenOrDestroyed: (_, _) => _data = null)
        {
            OnLinkClick = (ph, e) => ph.Text = _FormatText(e.ToInt(1), userSelected: true)
        };
        _textPopup.Text = _FormatText(iSel, userSelected: false);

        if (!_textPopup.IsVisible)
        {
            CodeInfo.HideTextPopupAndTempWindows();
            if (CodeInfo._compl.IsVisibleUI)             //without this does not show completions with selected enum when typed Function( when first parameter is enum
            {
                CodeInfo._compl.Cancel();
            }
            if (methodCompletion)
            {
                CodeInfo._compl.ShowList(ch);                               //when autocompletion added (); may need to show enum list
            }
        }

        _textPopup.Show(Panels.Editor.ZActiveDoc, rect, System.Windows.Controls.Dock.Bottom);

        //also show Keys/Regex tool?
        //CiUtil.PrintNode(node);
        if (argNode is ArgumentListSyntax or BracketedArgumentListSyntax && cd.code.Eq(cd.pos - 1, "\"\""))
        {
            //print.it("string");
            var semo  = cd.semanticModel;
            var token = root.FindToken(cd.pos);
            if (true == token.IsInString(cd.pos, cd.code, out var stringInfo))
            {
                var stringFormat = CiUtil.GetParameterStringFormat(stringInfo.stringNode, semo, true);
                if (stringFormat != 0)
                {
                    CodeInfo._tools.ShowForStringParameter(stringFormat, cd, stringInfo, _textPopup.PopupWindow.Hwnd);
                }
            }
        }
    }