/// <summary> /// When the user click the error margin but no error is cleaned, it goes to the next line with error instead /// </summary> public static void GoToNextError(int line) { var currentFilePath = Npp.CurrentFileInfo.Path; if (!_sessionInfo.ContainsKey(currentFilePath)) { return; } int nextLine = Sci.GetLine(line).MarkerNext(EveryMarkersMask); if (nextLine == -1 && _sessionInfo[currentFilePath].FileErrors.Exists(error => error.Line == 0)) { nextLine = 0; } if (nextLine == -1) { nextLine = Sci.GetLine(0).MarkerNext(EveryMarkersMask); } if (nextLine != -1) { var errInfo = _sessionInfo[currentFilePath].FileErrors.FirstOrDefault(error => error.Line == nextLine); if (errInfo != null) { Npp.Goto(currentFilePath, errInfo.Line, errInfo.Column); } else { Npp.Goto(currentFilePath, nextLine, 0); } } }
/// <summary> /// Go to the previous error /// </summary> public static void GoToPrevError(int line) { var currentFilePath = Npp.CurrentFileInfo.Path; var nbLines = Sci.Line.Count; if (!_sessionInfo.ContainsKey(currentFilePath)) { return; } int prevLine = Sci.GetLine(line).MarkerPrevious(EveryMarkersMask); if (prevLine == -1 && _sessionInfo[currentFilePath].FileErrors.Exists(error => error.Line == nbLines)) { prevLine = nbLines; } if (prevLine == -1) { prevLine = Sci.GetLine(nbLines).MarkerPrevious(EveryMarkersMask); } if (prevLine != -1) { var errInfo = _sessionInfo[currentFilePath].FileErrors.FirstOrDefault(error => error.Line == prevLine); if (errInfo != null) { Npp.Goto(currentFilePath, errInfo.Line, errInfo.Column); } else { Npp.Goto(currentFilePath, prevLine, 0); } } }
public static void SetFolding(Dictionary <int, LineInfo> lineInfos) { var i = 0; var lastIdent = 0; while (lineInfos.ContainsKey(i)) { var line = Sci.GetLine(i); line.SetFoldLevel(lineInfos[i].BlockDepth + lineInfos[i].ExtraStatementDepth, FoldLevelFlags.None); if (lineInfos[i].BlockDepth + lineInfos[i].ExtraStatementDepth > lastIdent) { if (i > 0) { Sci.GetLine(i - 1).FoldLevelFlags = FoldLevelFlags.Header; } lastIdent = lineInfos[i].BlockDepth + lineInfos[i].ExtraStatementDepth; } else { if (lineInfos[i].BlockDepth < lastIdent) { lastIdent = lineInfos[i].BlockDepth + lineInfos[i].ExtraStatementDepth; } } i++; } }
/// <summary> /// Clears all the annotations and the markers from scintilla /// </summary> public static void ClearAnnotationsAndMarkers() { if (Sci.GetLine(0).MarkerGet() != 0) { if (!_sessionInfo.ContainsKey(Npp.CurrentFileInfo.Path) || _sessionInfo[Npp.CurrentFileInfo.Path].FileErrors == null || !_sessionInfo[Npp.CurrentFileInfo.Path].FileErrors.Exists(error => error.Line == 0)) { // The line 0 has an error marker when it shouldn't ClearLine(0); } } int nextLine = Sci.GetLine(0).MarkerNext(EveryMarkersMask); while (nextLine > -1) { if (!_sessionInfo.ContainsKey(Npp.CurrentFileInfo.Path) || _sessionInfo[Npp.CurrentFileInfo.Path].FileErrors == null || !_sessionInfo[Npp.CurrentFileInfo.Path].FileErrors.Exists(error => error.Line == nextLine)) { // The line 0 has an error marker when it shouldn't ClearLine(nextLine); } nextLine = Sci.GetLine(nextLine + 1).MarkerNext(EveryMarkersMask); } // We should be able to use the lines below, but the experience proves that they sometimes crash... /* * Npp.AnnotationClearAll(); // <- this shit tends to be unstable for some reasons * foreach (var errorLevelMarker in Enum.GetValues(typeof(ErrorLevel))) * Npp.Marker.MarkerDeleteAll((int)errorLevelMarker); */ }
/// <summary> /// Tries to re-indent the code of the whole document /// </summary> public static void CorrectCodeIndentation() { // handle spam (1s min between 2 indent) if (Utils.IsSpamming("CorrectCodeIndentation", 1000)) { return; } var parser = new Parser.Parser(Sci.Text, Npp.CurrentFile.Path, null, false); // in case of an incorrect document, warn the user var parserErrors = parser.ParseErrorsInHtml; if (!string.IsNullOrEmpty(parserErrors)) { if (UserCommunication.Message("The internal parser of 3P has found inconsistencies in your document :<br>" + parserErrors + "<br>You can still try to format your code but the result is not guaranteed (worst case scenario you can press CTRL+Z).<br>Please confirm that you want to proceed", MessageImg.MsgQuestion, "Correct indentation", "Problems spotted", new List <string> { "Continue", "Abort" }) != 0) { return; } } var linesLogFile = Path.Combine(Config.FolderTemp, "lines.log"); var canIndentSafely = string.IsNullOrEmpty(parserErrors); // start indenting Sci.BeginUndoAction(); StringBuilder x = new StringBuilder(); var indentWidth = Sci.TabWidth; var i = 0; var dic = parser.LineInfo; while (dic.ContainsKey(i)) { Sci.GetLine(i).Indentation = dic[i].BlockDepth * indentWidth; if (!canIndentSafely) { x.AppendLine(i + 1 + " > " + dic[i].BlockDepth + " , " + dic[i].Scope.ScopeType + " , " + dic[i].Scope.Name); } i++; } Sci.EndUndoAction(); // if we didn't parse the code correctly or if there are grammar errors if (!canIndentSafely) { Utils.FileWriteAllText(linesLogFile, x.ToString()); UserCommunication.Notify("If the code compiles successfully and the document is incorrectly formatted, please make sure to create an issue on the project's github and (if possible) include the incriminating code so i can fix this problem : <br>" + Config.IssueUrl.ToHtmlLink() + (Config.IsDevelopper ? "<br><br>Lines report log :<br>" + linesLogFile.ToHtmlLink() : ""), MessageImg.MsgRip, "Correct indentation", "Incorrect grammar", null, 10); } }
/// <summary> /// Visually clear all the annotations and markers from a line /// </summary> /// <param name="line"></param> public static void ClearLine(int line) { var lineObj = Sci.GetLine(line); lineObj.AnnotationText = null; foreach (var errorLevelMarker in Enum.GetValues(typeof(ErrorLevel))) { if (((int)lineObj.MarkerGet()).IsBitSet((int)errorLevelMarker)) { lineObj.MarkerDelete((int)errorLevelMarker); } } }
public static bool TriggerCodeSnippetInsertion() { if (InsertionActive) { return(false); // do no insert a snippet within a snippet! } string token = Sci.GetWord(null, Sci.CurrentPosition); var curPos = Sci.CurrentPosition; Point tokenPoints = new Point(curPos - token.Length, curPos); if (Contains(token)) { string replacement = GetTemplate(token); if (replacement != null) { int line = Sci.Line.CurrentLine; int lineStartPos = Sci.GetLine(line).Position; int horizontalOffset = tokenPoints.X - lineStartPos; //relative selection in the replacement text PrepareForIncertion(replacement, horizontalOffset, tokenPoints.X); var indic = Sci.GetIndicator(SnippetContext.IndicatorId); indic.IndicatorStyle = IndicatorStyle.Box; indic.ForeColor = Color.Blue; foreach (var point in LocSnippetContext.Parameters) { indic.Add(point.X, point.Y); } if (LocSnippetContext.CurrentParameter.HasValue) { Sci.SetSelection(LocSnippetContext.CurrentParameter.Value.X, LocSnippetContext.CurrentParameter.Value.Y); LocSnippetContext.CurrentParameterValue = Sci.GetTextBetween(LocSnippetContext.CurrentParameter.Value); } AutoCompletion.Cloak(); if (LocSnippetContext.Parameters.Count <= 1) { FinalizeCurrent(); } } return(true); } return(false); }
/// <summary> /// Called on STYLENEEDED notification /// </summary> public static void Colorize(int startPos, int endPos) { var startLine = Sci.LineFromPosition(startPos); var startLinePos = Sci.GetLine(startLine).Position; var startingLineInfo = _lineInfo.ContainsKey(startLine) ? _lineInfo[startLine] : new LexerLineInfo(0, 0, false, false); ProTokenizer tok = new ProTokenizer(Sci.GetTextByRange(startLinePos, endPos), startLinePos, startLine, 0, startingLineInfo.CommentDepth, startingLineInfo.IncludeDepth, startingLineInfo.InDoubleQuoteString, startingLineInfo.InSimpleQuoteString, PushLineInfo); var vis = new SyntaxHighlightVisitor { NormedVariablesPrefixes = Config.Instance.NormedVariablesPrefixes.Split(',') }; vis.PreVisit(tok); tok.Accept(vis); vis.PostVisit(); }
/// <summary> /// Switch to a document, can be already opened or not, can decide to remember the current position to jump back to it /// </summary> public static void Goto(string document, int position, int line, int column, bool saveHistoric) { if (!File.Exists(document)) { UserCommunication.Notify(@"Can't find/open the following file :<br>" + document, MessageImg.MsgHighImportance, "Warning", "File not found", 5); return; } if (saveHistoric) { _goToHistory.Push(new Tuple <string, int, Point>(CurrentFileInfo.Path, Sci.FirstVisibleLine, Sci.CurrentPoint)); } if (!String.IsNullOrEmpty(document) && !document.Equals(CurrentFileInfo.Path)) { if (GetOpenedFiles.Contains(document)) { SwitchToDocument(document); } else { OpenFile(document); } } if (position >= 0) { Sci.GoToLine(Sci.LineFromPosition(position)); Sci.SetSel(position); } else if (line >= 0) { Sci.GoToLine(line); if (column >= 0) { Sci.SetSel(Sci.GetPosFromLineColumn(line, column)); } else { Sci.SetSel(Sci.GetLine(line).Position); } } Sci.GrabFocus(); Plug.OnUpdateSelection(); }
/// <summary> /// Tries to re-indent the code of the whole document /// </summary> public static void CorrectCodeIndentation() { // handle spam (1s min between 2 indent) if (Utils.IsSpamming("CorrectCodeIndentation", 1000)) { return; } var parser = new Parser.Pro.Parse.Parser(Sci.Text, Npp.CurrentFileInfo.Path, null, false); // in case of an incorrect document, warn the user var parserErrors = parser.ParseErrorsInHtml; if (!string.IsNullOrEmpty(parserErrors)) { if (UserCommunication.Message("The internal parser of 3P has found inconsistencies in your document :<br>" + parserErrors + "<br>You can still try to format your code but the result is not guaranteed (worst case scenario you can press CTRL+Z).<br>If the code compiles successfully and the document is incorrectly formatted, please make sure to create an issue on the project's github and (if possible) include the incriminating code so i can fix this problem : <br>" + Config.UrlIssues.ToHtmlLink() + "<br><br>Please confirm that you want to proceed", MessageImg.MsgQuestion, "Correct indentation", "Problems spotted", new List <string> { "Continue", "Abort" }) != 0) { return; } } // start indenting Sci.BeginUndoAction(); var indentStartLine = Sci.LineFromPosition(Sci.SelectionStart); var indentEndLine = Sci.LineFromPosition(Sci.SelectionEnd); var indentWidth = Sci.TabWidth; var i = 0; var dic = GetIndentation(parser.LineInfo); while (dic.ContainsKey(i)) { if (indentStartLine == indentEndLine || (i >= indentStartLine && i <= indentEndLine)) { var line = Sci.GetLine(i); line.Indentation = (dic[i].BlockDepth + dic[i].ExtraStatementDepth) * indentWidth; } i++; } Sci.EndUndoAction(); }
/// <summary> /// Allows the user to surround its selection with custom modification tags /// </summary> public static void SurroundSelectionWithTag() { CommonTagAction(fileInfo => { var output = new StringBuilder(); Sci.TargetFromSelection(); var indent = new String(' ', Sci.GetLine(Sci.LineFromPosition(Sci.TargetStart)).Indentation); var opener = ReplaceTokens(fileInfo, Config.Instance.TagModifOpener); var eol = Sci.GetEolString; output.Append(opener); output.Append(eol); output.Append(indent); output.Append(Sci.SelectedText); output.Append(eol); output.Append(indent); output.Append(ReplaceTokens(fileInfo, Config.Instance.TagModifCloser)); Sci.TargetFromSelection(); Sci.ReplaceTarget(output.ToString()); Sci.SetSel(Sci.TargetStart + opener.Length + eol.Length); }); }
/// <summary> /// Displays the errors for the current file (if any) /// display an annotation with the message below the line + display a marker in the margin /// </summary> public static void UpdateErrorsInScintilla() { // Updates the number of errors in the FileExplorer form and the file status UpdateFileStatus(); var currentFilePath = Npp.CurrentFileInfo.Path; var marginError = Sci.GetMargin(ErrorMarginNumber); // need to clear scintilla for this file? if (_sessionInfo.ContainsKey(currentFilePath) && _sessionInfo[currentFilePath].NeedToCleanScintilla) { ClearAnnotationsAndMarkers(); _sessionInfo[currentFilePath].NeedToCleanScintilla = false; } // check if current file is a progress and if we got info on it if (!Npp.CurrentFileInfo.IsProgress || !_sessionInfo.ContainsKey(currentFilePath) || _sessionInfo[currentFilePath].FileErrors == null || _sessionInfo[currentFilePath].FileErrors.Count == 0) { if (marginError.Width > 0) { marginError.Width = 1; marginError.Width = 0; } // reset annotation to default Sci.AnnotationVisible = Plug.AnnotationMode; return; } // activate annotation (if not already done) Plug.AnnotationMode = Annotation.Indented; // show margin if (marginError.Sensitive == false) { marginError.Sensitive = true; } if (marginError.Type != MarginType.Symbol) { marginError.Type = MarginType.Symbol; } if (marginError.Mask != EveryMarkersMask) { marginError.Mask = EveryMarkersMask; } // only show the new errors if (_sessionInfo[currentFilePath].HasErrorsNotDisplayed) { _sessionInfo[currentFilePath].HasErrorsNotDisplayed = false; StylerHelper stylerHelper = new StylerHelper(); int lastLine = -2; StringBuilder lastMessage = new StringBuilder(); foreach (var fileError in _sessionInfo[currentFilePath].FileErrors) { // new line if (lastLine != fileError.Line) { stylerHelper.Clear(); lastMessage.Clear(); // set marker style now (the first error encountered for a given line is the highest anyway) if (!((int)Sci.GetLine(fileError.Line).MarkerGet()).IsBitSet((int)fileError.Level)) { Sci.GetLine(fileError.Line).MarkerAdd((int)fileError.Level); } } else { // append to existing annotation stylerHelper.Style("\n", (byte)fileError.Level); lastMessage.Append("\n"); } lastLine = fileError.Line; var mess = fileError.FromProlint ? "Prolint (level " + fileError.ErrorNumber : ("Compilation " + (fileError.Level == ErrorLevel.Critical ? "error" : "warning") + " (n°" + fileError.ErrorNumber); mess += fileError.FromProlint ? "): " : ", col " + fileError.Column + "): "; stylerHelper.Style(mess, (byte)(ScintillaTheme.ErrorAnnotBoldStyleOffset + fileError.Level)); lastMessage.Append(mess); mess = fileError.Message.BreakText(140); stylerHelper.Style(mess, (byte)(ScintillaTheme.ErrorAnnotStandardStyleOffset + fileError.Level)); lastMessage.Append(mess); if (Config.Instance.GlobalShowDetailedHelpForErrors && !string.IsNullOrEmpty(fileError.Help)) { mess = "\nDetailed help: " + fileError.Help.BreakText(140); stylerHelper.Style(mess, (byte)(ScintillaTheme.ErrorAnnotItalicStyleOffset + fileError.Level)); lastMessage.Append(mess); } if (fileError.Times > 0) { mess = "\nThis message above appeared " + fileError.Times + " times in the compiler log"; stylerHelper.Style(mess, (byte)(ScintillaTheme.ErrorAnnotBoldStyleOffset + fileError.Level)); lastMessage.Append(mess); } // set annotation Sci.GetLine(lastLine).AnnotationText = lastMessage.ToString(); Sci.GetLine(lastLine).AnnotationStyles = stylerHelper.GetStyleArray(); } } marginError.Width = ErrorMarginWidth + 1; marginError.Width = ErrorMarginWidth; }
public override string ToString() { var toDisplay = new StringBuilder(); toDisplay.Append(HtmlHelper.FormatRow("Type of keyword", HtmlHelper.FormatSubString(SubText))); // for abbreviations, find the complete keyword first string keyword = DisplayText; if (!string.IsNullOrEmpty(_fullWord)) { toDisplay.Append(HtmlHelper.FormatRow("Abbreviation of", HtmlHelper.FormatSubString(FullWord))); } string keyToFind = string.Join(" ", DisplayText, KeywordType); // for the keywords define and create, we try to match the second keyword that goes with it if (KeywordType == KeywordType.Statement && (keyword.EqualsCi("define") || keyword.EqualsCi("create"))) { var lineStr = Sci.GetLine(Sci.LineFromPosition(Sci.GetPositionFromMouseLocation())).LineText; 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, KeywordType); break; } } } var dataHelp = Keywords.Instance.GetKeywordHelp(keyToFind); if (dataHelp != null) { toDisplay.Append(HtmlHelper.FormatSubtitle("DESCRIPTION")); toDisplay.Append(dataHelp.Description); // synthax if (dataHelp.Synthax.Count >= 1 && !string.IsNullOrEmpty(dataHelp.Synthax[0])) { toDisplay.Append(HtmlHelper.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(HtmlHelper.FormatSubtitle("404 NOT FOUND")); if (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>"); } } return(toDisplay.ToString()); }