1
Vote

Snippets Surround With works once

description

Snippets insertion using the Snippet Chooser inserts the selection only once on the $selected$ marker and the list contains all snippets, also the snippets without the IsSurroundsWith flag, in snippet list.

Any insertion thereafter the snippet is placed after the selection.

This was the code, including the diagnostic statement and a hack, to solve the loss of the selection
However as soon the list disappear, because the user clicks in the chooser field for another filtering
a new list appears, but hack does not work in that case.
    Private Sub mnuSnippetSurroundWith_Click(ByVal sender As Object, ByVal e As EventArgs) Handles mnuSnippetSurroundWith.Click
#If DEBUG Then
        Dim SelEnd As Integer = Scintilla1.Selection.End
        Dim SelStart As Integer = Scintilla1.Selection.Start
#End If
        Scintilla1.Snippets.ShowSurroundWithList()
#If DEBUG Then
        If SelStart <> Scintilla1.Selection.Start OrElse SelEnd <> Scintilla1.Selection.End Then
            Debug.WriteLine(String.Format("Snippet selection is CHANGED!!! Start b-{0} a-{1}  End b-{2} a-{3}", SelStart, Scintilla1.Selection.Start, SelEnd, Scintilla1.Selection.End))
        End If
#End If

'        ' HACK to reset the loss of selection
'        If SelEnd <> Scintilla1.Selection.End Then Scintilla1.Selection.End = SelEnd
    End Sub
Using the VS debugger I detected the culprit in the SnipperChooser.cs (version 2.6 round line 103)
The code looks like a kind of hack to solve the lost of the chooser.
The statement Scintilla.Caret.Goto(0) cause the selection to be lost.
So first I added some code to save the selection and restore it afterwards.
That solved the problem. The I removed everything except the statement
txtSnippet.AutoComplete.Show(0, _snippetList);
that worked also.
For me it is unclear why Goto was used.

Hereafter the total change I have added / changed to resolve the issue.
        private void txtSnippet_AutoCompleteAccepted(object sender, AutoCompleteAcceptedEventArgs e)
        {
            string shortcut = txtSnippet.AutoComplete.SelectedText;
            Hide();
            Scintilla.Snippets.InsertSnippet(shortcut);
            e.Cancel = true; // following the event rules, when handled return e.Cancel = true
        }


        private void txtSnippet_DocumentChange(object sender, NativeScintillaEventArgs e)
        {
            ////    If for any reason the window DOES manage to hide itself
            ////    we merely reshow it.
            if (!txtSnippet.AutoComplete.IsActive && Visible)
            {
                //int selstart = Scintilla.Selection.Start;
                //int selend = Scintilla.Selection.End;
                //int pos = Scintilla.Caret.Position;
                //Scintilla.Caret.Goto(0); // this resets any selection, which cause surround with to fail - if this is needed
                // then the selection should be saved and restored and the caret should be set to selstart
                txtSnippet.AutoComplete.Show(0, _snippetList);
                //Scintilla.Caret.Goto(selstart); //Scintilla.Caret.Goto(pos); 
                //Scintilla.Selection.End = selend;
            }
        }

The comment I have added hopefully clarifies what was/is done.
The issue of the complete list instead of snippets with the IsSurroundsWith flag is still there.
It looks like a racing condition. The event to handle is processing the list before the Snippermanager has completed the list.
        public void ShowSurroundWithList()
        {
            SnippetList sl = new SnippetList(null);
            foreach (Snippet s in _list)
            {
                if (s.IsSurroundsWith)
                    sl.Add(s);
            }

            if (sl.Count == 0)
                return;

            if (_snipperChooser == null)
            {
                _snipperChooser = new SnippetChooser();
                _snipperChooser.Scintilla = Scintilla;
                _snipperChooser.SnippetList = _list.ToString();   // <-------- the complete list
                _snipperChooser.Scintilla.Controls.Add(_snipperChooser);
            }
            _snipperChooser.SnippetList = sl.ToString(); // <------ the filtered list
            _snipperChooser.Show();
        }

comments