Beispiel #1
0
        /// <summary>
        /// Find a list of items in the completion and return it
        /// Uses the position to filter the list the same way the auto completion form would
        /// </summary>
        public static List <CompletionItem> FindInCompletionData(string keyword, int line, bool dontCheckLine = false)
        {
            int  charPos = 0;
            char?firstSeparator;
            var  firstKeyword             = GetWord(keyword, ref charPos, out firstSeparator);
            List <CompletionItem> outList = null;

            if (firstSeparator != null)
            {
                DoInLock(() => {
                    var filterClass = new CompletionFilterClass();
                    filterClass.UpdateConditions(line);
                    outList = GetWordsList(_savedAllItems.Where(filterClass.FilterPredicate), keyword, charPos, firstSeparator).ToList();
                });
                // special case for methods while we don't have a perfect system
                if (firstSeparator == ':' && (outList == null || outList.Count == 0))
                {
                    DoInLock(() => {
                        outList = _savedAllItems.Where(item => item.DisplayText.Equals(firstKeyword, FilterStringComparison)).ToList();
                    });
                }
            }
            else
            {
                outList = new List <CompletionItem>();
                DoInLock(() => {
                    var filterClass = new CompletionFilterClass();
                    filterClass.UpdateConditions(line);
                    foreach (var item in _savedAllItems)
                    {
                        if (filterClass.FilterPredicate(item) && item.DisplayText.Equals(firstKeyword, FilterStringComparison))
                        {
                            outList.Add(item);
                        }
                    }
                });
                return(outList);
            }
            return(outList == null ? null : outList.Where(data => data.DisplayText.Equals(firstKeyword, FilterStringComparison)).ToList());
        }
Beispiel #2
0
        /// <summary>
        /// Updates the CURRENT ITEMS LIST,
        /// handles the opening or the closing of the auto completion form on key input
        /// (externally called when a new char is entered or when a char is deleted)
        /// </summary>
        public static void UpdateAutocompletion(char c = char.MinValue, int insertPosition = -1)
        {
            if (_insertingWord)
            {
                return;
            }

            var typing    = IsCharPartOfWord(c);
            var isVisible = IsVisible;

            // currently continuing to type a word in a visible auto completion, return asap
            if (typing && isVisible)
            {
                // the auto completion is already visible, this means the _currentWord is set
                // we only have to filter the current list even more
                ShowSuggestionList(_currentWord + c);
                return;
            }

            var    nppCurrentPosition = Sci.CurrentPosition;
            var    nppCurrentLine     = Sci.Line.CurrentLine;
            var    isNormalContext    = Style.IsCarretInNormalContext(nppCurrentPosition);
            string strOnLeft          = null;

            //----------------------
            // we finished entering a word (we typed a char that is not part of a word, a space of new line or separator...)
            //----------------------
            if (c != char.MinValue && !typing && isNormalContext)
            {
                strOnLeft = Sci.GetTextOnLeftOfPos(nppCurrentPosition, 61);
                var strOnLeftLength = strOnLeft.Length;

                // we finished entering a word, find the offset at which we can find said word
                int offset = 1;
                if (c == '\r' || c == '\n')
                {
                    offset = nppCurrentPosition - insertPosition;
                    if (offset > 40)
                    {
                        // case of an extremely hard tabbed line
                        strOnLeft = Sci.GetTextOnLeftOfPos(nppCurrentPosition - offset, 61);
                    }
                }

                bool textHasChanged = false;

                if (offset > 0 && strOnLeftLength > offset)
                {
                    bool hasAtLeastOneLetter = false;
                    var  checkOffset         = offset;
                    while (IsCharPartOfWord(strOnLeft[strOnLeftLength - 1 - checkOffset]))
                    {
                        var ch = strOnLeft[strOnLeftLength - 1 - checkOffset];
                        if (char.IsLetter(ch))
                        {
                            hasAtLeastOneLetter = true;
                            break;
                        }
                        checkOffset++;
                    }

                    // See if the char of the "word" we finished entering is actually part of a word
                    // (maybe not if, for instance, we just input 2 spaces consecutively)
                    if (hasAtLeastOneLetter)
                    {
                        // automatically insert selected keyword of the completion list?
                        if (InsertSelectedSuggestionOnWordEnd && isVisible)
                        {
                            InsertSuggestion(_form.GetCurrentCompletionItem(), -offset);
                            textHasChanged = true;
                        }

                        // automatically change the case of the keyword?
                        else if (AutoCase && (nppCurrentPosition - offset) != _positionOfLastInsertion)
                        {
                            var candidates = FindInCompletionData(strOnLeft.Substring(0, strOnLeftLength - offset), nppCurrentLine);
                            // we matched the word in the list, correct the case
                            if (candidates != null && candidates.Count > 0)
                            {
                                InsertSuggestion(candidates.First(), -offset);
                                textHasChanged = true;
                            }
                        }
                    }
                }

                // replace semicolon by a point
                if (c == ';' && Config.Instance.AutoCompleteReplaceSemicolon && Npp.CurrentFile.IsProgress)
                {
                    _insertingWord           = true;
                    _positionOfLastInsertion = Sci.ModifyTextAroundCaret(-1, 0, ".");
                    _insertingWord           = false;
                    textHasChanged           = true;
                }

                // need to update the strOnLeft since we use it again in this method
                if (textHasChanged)
                {
                    nppCurrentPosition = Sci.CurrentPosition;
                    strOnLeft          = Sci.GetTextOnLeftOfPos(nppCurrentPosition, 61);
                }
            }

            //----------------------
            // We are here if the auto completion is hidden or if the user is not continuing to type a word,
            // So we have the opportunity to change the list of items in the auto completion if needed
            //----------------------

            if (!_openedFromShortCut)
            {
                // don't automatically show the auto completion on input?
                if (!Config.Instance.AutoCompleteOnKeyInputShowSuggestions)
                {
                    return;
                }

                // don't show in string/comments..?
                if (!isVisible && !isNormalContext && !Config.Instance.AutoCompleteShowInCommentsAndStrings)
                {
                    return;
                }
            }
            else
            {
                // the caret changed line (happens when we trigger the auto comp manually on the first position of a line
                // and we press backspace, we return to the previous line but the form would still be visible)
                if (isVisible && nppCurrentLine != _openedFromShortcutLine)
                {
                    Cloak();
                    return;
                }
            }

            // get current word
            if (strOnLeft == null)
            {
                strOnLeft = Sci.GetTextOnLeftOfPos(nppCurrentPosition, 61);
            }
            int  charPos = 0;
            char?firstSeparator;
            var  firstKeyword = GetWord(strOnLeft, ref charPos, out firstSeparator);

            if (typing)
            {
                // (form is not visible if we are here) Min length is not reached?
                if (!_openedFromShortCut && firstKeyword.Length < Config.Instance.AutoCompleteStartShowingListAfterXChar)
                {
                    return;
                }
            }

            if (firstSeparator == null)
            {
                // we didn't match a known separator just before the keyword;
                // this means we want to display the entire list of keywords

                if (CurrentActiveTypes != ActiveTypes.All)
                {
                    CurrentActiveTypes = ActiveTypes.All;
                    DoInLock(() => { CurrentItems = _savedAllItems; });
                }
            }
            else
            {
                // return the list of children that should be used in the auto completion, filtered by the previous keywords
                List <CompletionItem> outList = null;
                DoInLock(() => {
                    var filterClass = new CompletionFilterClass();
                    filterClass.UpdateConditions(nppCurrentLine);
                    outList = GetWordsList(_savedAllItems.Where(filterClass.FilterPredicate), strOnLeft, charPos, firstSeparator).ToList();
                });

                // empty list?
                if (outList == null || outList.Count == 0)
                {
                    // if the current word is directly preceded by a :, we are entering an object field/method
                    // for now, we then display the whole list of object keywords
                    if (firstSeparator == ':' && Npp.CurrentFile.IsProgress)
                    {
                        if (CurrentActiveTypes != ActiveTypes.KeywordObject)
                        {
                            CurrentActiveTypes = ActiveTypes.KeywordObject;
                            DoInLock(() => { CurrentItems = _savedAllItems; });
                        }
                        ShowSuggestionList(firstKeyword);
                        return;
                    }

                    // we should consider the first separator found not as a child separator, display the whole list
                    if (CurrentActiveTypes != ActiveTypes.All)
                    {
                        CurrentActiveTypes = ActiveTypes.All;
                        DoInLock(() => { CurrentItems = _savedAllItems; });
                    }
                }
                else
                {
                    // we will display the list filtered with all the needed children
                    CurrentActiveTypes = ActiveTypes.Filtered;
                    DoInLock(() => {
                        CurrentItems = outList.ToList();
                        CurrentItems.Sort(CompletionSortingClass <CompletionItem> .Instance);
                    });

                    // we want to show the list no matter how long the filter keyword
                    if (Config.Instance.AutoCompleteShowChildrenAfterSeparator)
                    {
                        ShowSuggestionList(firstKeyword);
                        return;
                    }
                }
            }

            // check if the minimum length of word is ok
            if (isVisible)
            {
                // close if (we didn't open from shortcut or we are not at the opening position) and the min length is not reached
                if ((!_openedFromShortCut || nppCurrentPosition < _shownPosition) && firstKeyword.Length < Config.Instance.AutoCompleteStartShowingListAfterXChar)
                {
                    Cloak();
                    return;
                }
                // auto completion from shortcut at the end of a word and we press space, we need to close it!
                if (_openedFromShortCut && nppCurrentPosition > _shownPosition && c != char.MinValue)
                {
                    Cloak();
                    return;
                }
            }
            else
            {
                // Min length is not reached?
                if (!_openedFromShortCut && firstKeyword.Length < Config.Instance.AutoCompleteStartShowingListAfterXChar)
                {
                    return;
                }
            }

            ShowSuggestionList(firstKeyword);
        }