/// <summary> /// Find a list of items in the completion and return it /// Uses the position to filter the list the same way the autocompletion form would /// </summary> /// <returns></returns> public static List <CompletionItem> FindInCompletionData(string keyword, int position, bool dontCheckLine = false) { var filteredList = AutoCompletionForm.ExternalFilterItems(SavedAllItems.ToList(), Npp.LineFromPosition(position), dontCheckLine); if (filteredList == null || filteredList.Count <= 0) { return(null); } var found = filteredList.Where(data => data.DisplayText.EqualsCi(keyword)).ToList(); if (found.Count > 0) { return(found); } // search in tables fields var tableFound = ParserHandler.FindAnyTableOrBufferByName(Npp.GetFirstWordRightAfterPoint(position)); if (tableFound == null) { return(null); } var listOfFields = DataBase.GetFieldsList(tableFound).ToList(); return(listOfFields.Where(data => data.DisplayText.EqualsCi(keyword)).ToList()); }
/// <summary> /// Returns a keyword from the autocompletion list with the correct case /// </summary> /// <param name="keyword"></param> /// <param name="lastWordPos"></param> /// <returns></returns> public static string CorrectKeywordCase(string keyword, int lastWordPos) { string output = null; if (!Config.Instance.DisableAutoCaseCompletly) { var found = FindInSavedItems(keyword, Npp.Line.CurrentLine); if (found != null) { RememberUseOf(found); int caseMode; if (found.FromParser) { caseMode = 4; // use displayText case } else if (found.Type == CompletionType.Database || found.Type == CompletionType.Field || found.Type == CompletionType.FieldPk || found.Type == CompletionType.Sequence || found.Type == CompletionType.Table) { caseMode = Config.Instance.DatabaseChangeCaseMode; } else { caseMode = Config.Instance.KeywordChangeCaseMode; } output = keyword.ConvertCase(caseMode, found.DisplayText); } else { // search in tables fields var tableFound = ParserHandler.FindAnyTableOrBufferByName(Npp.GetFirstWordRightAfterPoint(lastWordPos)); if (tableFound != null) { var fieldFound = DataBase.FindFieldByName(keyword, tableFound); if (fieldFound != null) { RememberUseOf(new CompletionItem { FromParser = false, DisplayText = fieldFound.Name, Type = CompletionType.Field, Ranking = 0 }); RememberUseOfDatabaseItem(fieldFound.Name); output = keyword.ConvertCase(tableFound.IsTempTable ? 4 : Config.Instance.DatabaseChangeCaseMode, fieldFound.Name); } } } } return(output); }
/// <summary> /// Sets the content of the tooltip (when we want to descibe something present in the completionData list) /// </summary> private static void SetToolTip() { var popupMinWidth = 250; var toDisplay = new StringBuilder(); GoToDefinitionFile = null; // only select one item from the list var data = GetCurrentlyDisplayedCompletionData(); if (data == null) { return; } CurrentWord = data.DisplayText; // general stuff toDisplay.Append("<div class='InfoToolTip' id='ToolTip'>"); toDisplay.Append(@" <table width='100%' class='ToolTipName'> <tr style='vertical-align: top;'> <td> <table width='100%' style='margin: 0; padding: 0;'> <tr> <td rowspan='2' style='width: 25px;'> <img src='" + data.Type + @"'> </td> <td> " + data.DisplayText + @" </td> </tr> <tr> <td> <span class='ToolTipSubString'>" + data.Type + @"</span> </td> </tr> </table> </td>"); if (_currentCompletionList.Count > 1) { toDisplay.Append(@" <td class='ToolTipCount'>" + (IndexToShow + 1) + "/" + _currentCompletionList.Count + @" </td>"); } toDisplay.Append(@" </tr> </table>"); // the rest depends on the item type try { switch (data.Type) { case CompletionType.TempTable: case CompletionType.Table: popupMinWidth = Math.Min(500, Npp.NppScreen.WorkingArea.Width / 2); // buffer if (data.FromParser) { if (data.ParsedItem is ParsedDefine) { toDisplay.Append(FormatRowWithImg(ParseFlag.Buffer.ToString(), "BUFFER FOR " + FormatSubString(data.SubString))); } if (data.ParsedItem is ParsedTable && !string.IsNullOrEmpty(data.SubString)) { toDisplay.Append(FormatRow("Is like", (data.SubString.Contains("?")) ? "Unknow table [" + ((ParsedTable)data.ParsedItem).LcLikeTable + "]" : data.SubString.Replace("Like ", ""))); } } var tbItem = ParserHandler.FindAnyTableOrBufferByName(data.DisplayText); if (tbItem != null) { if (!string.IsNullOrEmpty(tbItem.Description)) { toDisplay.Append(FormatRow("Description", tbItem.Description)); } if (tbItem.Fields.Count > 0) { toDisplay.Append(FormatSubtitle("FIELDS [x" + tbItem.Fields.Count + "]")); toDisplay.Append("<table width='100%;'>"); foreach (var parsedField in tbItem.Fields) { toDisplay.Append("<tr><td><img src='" + (parsedField.Flag.HasFlag(ParsedFieldFlag.Primary) ? CompletionType.FieldPk.ToString() : CompletionType.Field.ToString()) + "'></td><td style='padding-right: 4px'>" + (parsedField.Flag.HasFlag(ParsedFieldFlag.Mandatory) ? "<img src='Mandatory'>" : "") + "</td><td style='padding-right: 8px'>" + parsedField.Name + "</td><td style='padding-right: 8px'>" + parsedField.Type + "</td><td style='padding-right: 8px'> = " + (parsedField.Type == ParsedPrimitiveType.Character ? parsedField.InitialValue.ProQuoter() : parsedField.InitialValue) + "</td><td style='padding-right: 8px'>" + parsedField.Description + "</td></tr>"); } toDisplay.Append("</table>"); } if (tbItem.Triggers.Count > 0) { toDisplay.Append(FormatSubtitle("TRIGGERS [x" + tbItem.Triggers.Count + "]")); foreach (var parsedTrigger in tbItem.Triggers) { toDisplay.Append(FormatRow(parsedTrigger.Event, "<a class='ToolGotoDefinition' href='trigger#" + parsedTrigger.ProcName + "'>" + parsedTrigger.ProcName + "</a>")); } } if (tbItem.Indexes.Count > 0) { toDisplay.Append(FormatSubtitle("INDEXES [x" + tbItem.Indexes.Count + "]")); foreach (var parsedIndex in tbItem.Indexes) { toDisplay.Append(FormatRow(parsedIndex.Name, ((parsedIndex.Flag != ParsedIndexFlag.None) ? parsedIndex.Flag + " - " : "") + parsedIndex.FieldsList.Aggregate((i, j) => i + ", " + j))); } } } break; case CompletionType.Sequence: toDisplay.Append(FormatRow("Database logical name", data.SubString)); break; case CompletionType.Database: var dbItem = DataBase.GetDb(data.DisplayText); toDisplay.Append(FormatRow("Logical name", dbItem.LogicalName)); toDisplay.Append(FormatRow("Physical name", dbItem.PhysicalName)); toDisplay.Append(FormatRow("Progress version", dbItem.ProgressVersion)); toDisplay.Append(FormatRow("Number of Tables", dbItem.Tables.Count.ToString())); break; case CompletionType.Field: case CompletionType.FieldPk: // find field var fieldFound = DataBase.FindFieldByName(data.DisplayText, (ParsedTable)data.ParsedItem); if (fieldFound != null) { if (fieldFound.AsLike == ParsedAsLike.Like) { toDisplay.Append(FormatRow("Is LIKE", fieldFound.TempType)); } toDisplay.Append(FormatRow("Type", FormatSubString(data.SubString))); toDisplay.Append(FormatRow("Owner table", ((ParsedTable)data.ParsedItem).Name)); if (!string.IsNullOrEmpty(fieldFound.Description)) { toDisplay.Append(FormatRow("Description", fieldFound.Description)); } if (!string.IsNullOrEmpty(fieldFound.Format)) { toDisplay.Append(FormatRow("Format", fieldFound.Format)); } if (!string.IsNullOrEmpty(fieldFound.InitialValue)) { toDisplay.Append(FormatRow("Initial value", fieldFound.InitialValue)); } toDisplay.Append(FormatRow("Order", fieldFound.Order.ToString())); } break; case CompletionType.Procedure: // find its parameters toDisplay.Append(FormatSubtitle("PARAMETERS")); var paramList = ParserHandler.FindProcedureParameters(data); if (paramList.Count > 0) { foreach (var parameter in paramList) { var defItem = (ParsedDefine)parameter.ParsedItem; toDisplay.Append(FormatRowParam(defItem.LcFlagString, parameter.DisplayText + " as <span class='ToolTipSubString'>" + defItem.PrimitiveType + "</span>")); } } else { toDisplay.Append("None"); } break; case CompletionType.Function: var funcItem = (ParsedFunction)data.ParsedItem; toDisplay.Append(FormatSubtitle("RETURN TYPE")); toDisplay.Append(FormatRowParam("output", "Returns " + FormatSubString(funcItem.ReturnType.ToString()))); toDisplay.Append(FormatSubtitle("PARAMETERS")); var param2List = ParserHandler.FindProcedureParameters(data); if (param2List.Count > 0) { foreach (var parameter in param2List) { var defItem = (ParsedDefine)parameter.ParsedItem; toDisplay.Append(FormatRowParam(defItem.LcFlagString, parameter.DisplayText + " as " + FormatSubString(defItem.PrimitiveType.ToString()))); } } else { toDisplay.Append("None"); } var funcImplem = data.ParsedItem as ParsedImplementation; if (funcImplem != null) { toDisplay.Append(FormatSubtitle("PROTOTYPE")); if (funcImplem.HasPrototype) { toDisplay.Append(FormatRowWithImg("Prototype", "<a class='ToolGotoDefinition' href='proto#" + funcItem.FilePath + "#" + funcImplem.PrototypeLine + "#" + funcImplem.PrototypeColumn + "'>Go to prototype</a>")); } else { toDisplay.Append("Has none"); } } else { toDisplay.Append(FormatSubtitle("DEFINED IN")); toDisplay.Append("Function defined in an external procedure or is a web service operation"); } break; case CompletionType.Keyword: case CompletionType.KeywordObject: toDisplay.Append(FormatRow("Type of keyword", FormatSubString(data.SubString))); // for abbreviations, find the complete keyword first string keyword = data.DisplayText; if (data.KeywordType == KeywordType.Abbreviation) { keyword = Keywords.GetFullKeyword(keyword); var associatedKeyword = AutoComplete.FindInCompletionData(keyword, 0); if (associatedKeyword != null && associatedKeyword.Count > 0) { data = associatedKeyword.First(); } } string keyToFind = null; // for the keywords define and create, we try to match the second keyword that goes with it if (data.KeywordType == KeywordType.Statement && (keyword.EqualsCi("define") || keyword.EqualsCi("create"))) { var lineStr = Npp.GetLine(Npp.LineFromPosition(Npp.GetPositionFromMouseLocation())).Text; var listOfSecWords = new List <string> { "ALIAS", "BROWSE", "BUFFER", "BUTTON", "CALL", "CLIENT-PRINCIPAL", "DATA-SOURCE", "DATABASE", "DATASET", "EVENT", "FRAME", "IMAGE", "MENU", "PARAMETER", "PROPERTY", "QUERY", "RECTANGLE", "SAX-ATTRIBUTES", "SAX-READER", "SAX-WRITER", "SERVER", "SERVER-SOCKET", "SOAP-HEADER", "SOAP-HEADER-ENTRYREF", "SOCKET", "STREAM", "SUB-MENU", "TEMP-TABLE", "VARIABLE", "WIDGET-POOL", "WORK-TABLE", "WORKFILE", "X-DOCUMENT", "X-NODEREF" }; foreach (var word in listOfSecWords) { if (lineStr.ContainsFast(word)) { keyToFind = string.Join(" ", keyword, word, data.SubString); break; } } } if (keyToFind == null) { keyToFind = string.Join(" ", keyword, data.SubString); } var dataHelp = Keywords.GetKeywordHelp(keyToFind); if (dataHelp != null) { toDisplay.Append(FormatSubtitle("DESCRIPTION")); toDisplay.Append(dataHelp.Description); // synthax if (dataHelp.Synthax.Count >= 1 && !string.IsNullOrEmpty(dataHelp.Synthax[0])) { toDisplay.Append(FormatSubtitle("SYNTAX")); toDisplay.Append(@"<div class='ToolTipcodeSnippet'>"); var i = 0; foreach (var synthax in dataHelp.Synthax) { if (i > 0) { toDisplay.Append(@"<br>"); } toDisplay.Append(synthax); i++; } toDisplay.Append(@"</div>"); } } else { toDisplay.Append(FormatSubtitle("404 NOT FOUND")); if (data.KeywordType == KeywordType.Option) { toDisplay.Append("<i><b>Sorry, this keyword doesn't have any help associated</b><br>Since this keyword is an option, try to hover the first keyword of the statement or refer to the 4GL help</i>"); } else { toDisplay.Append("<i><b>Sorry, this keyword doesn't have any help associated</b><br>Please refer to the 4GL help</i>"); } } CurrentWord = keyToFind; break; case CompletionType.Label: break; case CompletionType.Preprocessed: var preprocItem = (ParsedPreProc)data.ParsedItem; if (preprocItem.UndefinedLine > 0) { toDisplay.Append(FormatRow("Undefined line", preprocItem.UndefinedLine.ToString())); } toDisplay.Append(FormatSubtitle("VALUE")); toDisplay.Append(@"<div class='ToolTipcodeSnippet'>"); toDisplay.Append(preprocItem.Value); toDisplay.Append(@"</div>"); break; case CompletionType.Snippet: // TODO break; case CompletionType.VariableComplex: case CompletionType.VariablePrimitive: case CompletionType.Widget: var varItem = (ParsedDefine)data.ParsedItem; toDisplay.Append(FormatRow("Define type", FormatSubString(varItem.Type.ToString()))); if (!string.IsNullOrEmpty(varItem.TempPrimitiveType)) { toDisplay.Append(FormatRow("Variable type", FormatSubString(varItem.PrimitiveType.ToString()))); } if (varItem.AsLike == ParsedAsLike.Like) { toDisplay.Append(FormatRow("Is LIKE", varItem.TempPrimitiveType)); } if (!string.IsNullOrEmpty(varItem.ViewAs)) { toDisplay.Append(FormatRow("Screen representation", varItem.ViewAs)); } if (!string.IsNullOrEmpty(varItem.LcFlagString)) { toDisplay.Append(FormatRow("Define flags", varItem.LcFlagString)); } if (!string.IsNullOrEmpty(varItem.Left)) { toDisplay.Append(FormatSubtitle("END OF DECLARATION")); toDisplay.Append(@"<div class='ToolTipcodeSnippet'>"); toDisplay.Append(varItem.Left); toDisplay.Append(@"</div>"); } break; } } catch (Exception e) { toDisplay.Append("Error when appending info :<br>" + e + "<br>"); } // parsed item? if (data.FromParser) { toDisplay.Append(FormatSubtitle("ORIGINS")); toDisplay.Append(FormatRow("Scope name", data.ParsedItem.Scope.Name)); if (!Plug.CurrentFilePath.Equals(data.ParsedItem.FilePath)) { toDisplay.Append(FormatRow("Owner file", "<a class='ToolGotoDefinition' href='gotoownerfile#" + data.ParsedItem.FilePath + "'>" + data.ParsedItem.FilePath + "</a>")); } } // Flags var flagStrBuilder = new StringBuilder(); data.DoForEachFlag((name, flag) => { flagStrBuilder.Append(FormatRowWithImg(name, "<b>" + name + "</b>")); }); if (flagStrBuilder.Length > 0) { toDisplay.Append(FormatSubtitle("FLAGS")); toDisplay.Append(flagStrBuilder); } toDisplay.Append(@"<div class='ToolTipBottomGoTo'> [HIT CTRL ONCE] Prevent auto-close"); // parsed item? if (data.FromParser) { toDisplay.Append(@"<br>[" + Config.Instance.GetShortcutSpecFromName("Go_To_Definition").ToUpper() + "] <a class='ToolGotoDefinition' href='gotodefinition'>Go to definition</a>"); GoToDefinitionPoint = new Point(data.ParsedItem.Line, data.ParsedItem.Column); GoToDefinitionFile = data.ParsedItem.FilePath; } if (_currentCompletionList.Count > 1) { toDisplay.Append("<br>[CTRL + <span class='ToolTipDownArrow'>" + (char)242 + "</span>] <a class='ToolGotoDefinition' href='nexttooltip'>Read next tooltip</a>"); } toDisplay.Append("</div>"); toDisplay.Append("</div>"); _form.SetText(toDisplay.ToString(), popupMinWidth); }
/// <summary> /// Updates the CURRENT ITEMS LIST, /// handles the opening or the closing of the autocompletion form on key input, /// it is only called when the user adds or delete a char /// </summary> public static void UpdateAutocompletion() { if (!Config.Instance.AutoCompleteOnKeyInputShowSuggestions && !_openedFromShortCut) { return; } // dont show in string/comments..? if (!_openedFromShortCut && !IsVisible && !Config.Instance.AutoCompleteShowInCommentsAndStrings && !Style.IsCarretInNormalContext(Npp.CurrentPosition)) { return; } // get current word, current previous word (table or database name) int nbPoints; string previousWord = ""; var strOnLeft = Npp.GetTextOnLeftOfPos(Npp.CurrentPosition); var keyword = Abl.ReadAblWord(strOnLeft, false, out nbPoints); var splitted = keyword.Split('.'); string lastCharBeforeWord = ""; switch (nbPoints) { case 0: int startPos = strOnLeft.Length - 1 - keyword.Length; lastCharBeforeWord = startPos >= 0 ? strOnLeft.Substring(startPos, 1) : String.Empty; break; case 1: previousWord = splitted[0]; keyword = splitted[1]; break; case 2: previousWord = splitted[1]; keyword = splitted[2]; break; default: keyword = splitted[nbPoints]; break; } // list of fields or tables if (!string.IsNullOrEmpty(previousWord)) { // are we entering a field from a known table? var foundTable = ParserHandler.FindAnyTableOrBufferByName(previousWord); if (foundTable != null) { if (CurrentTypeOfList != TypeOfList.Fields) { CurrentTypeOfList = TypeOfList.Fields; SetCurrentItems(DataBase.GetFieldsList(foundTable).ToList()); } ShowSuggestionList(keyword); return; } // are we entering a table from a connected database? var foundDatabase = DataBase.FindDatabaseByName(previousWord); if (foundDatabase != null) { if (CurrentTypeOfList != TypeOfList.Tables) { CurrentTypeOfList = TypeOfList.Tables; SetCurrentItems(DataBase.GetTablesList(foundDatabase).ToList()); } ShowSuggestionList(keyword); return; } } // close if there is nothing to suggest if ((!_openedFromShortCut || _openedFromShortCutPosition != Npp.CurrentPosition) && (String.IsNullOrEmpty(keyword) || keyword != null && keyword.Length < Config.Instance.AutoCompleteStartShowingListAfterXChar)) { Close(); return; } // if the current is directly preceded by a :, we are entering an object field/method if (lastCharBeforeWord.Equals(":")) { if (CurrentTypeOfList != TypeOfList.KeywordObject) { CurrentTypeOfList = TypeOfList.KeywordObject; SetCurrentItems(SavedAllItems); } ShowSuggestionList(keyword); return; } // show normal complete list if (CurrentTypeOfList != TypeOfList.Complete) { CurrentTypeOfList = TypeOfList.Complete; SetCurrentItems(SavedAllItems); } ShowSuggestionList(keyword); }