public override int Style(CodeEditor editor, int pos, int endPos) { ILexer lex = null; // Find a lexer that can continue lexing. // Use the previous state to select the right lexer. // As long as no lexer can be found, move the start position backward. while (pos >= 0 && lex == null) lex = FindLexerForStyle(editor.GetStyleAt(pos--)); // start lexing from the newly determined start position return (lex ?? lexer.First()).Style(editor, pos + 1, endPos); }
public override int ProcessDefaultState(CodeEditor editor, Region c) { switch (c.c) { case ')': return (int)BaseState.Braces; case '=': return (int)BaseState.Operator; case ',': return (int)BaseState.Punctuation; } // the beginning of a number if (char.IsDigit(c.c)) return (int)BaseState.Number; // the beginning of a qualifier keyword if (char.IsLetter(c.c)) return (int)State.Indicator; return (int)State.Default; }
/// <summary> /// Get debug variable from the specified text line in the code editor. /// </summary> /// <param name="editor">Source code editor.</param> /// <param name="line">Zero-based line number in the code.</param> /// <returns>Returns all debug variables in the specified line or /// <code>null</code> if no debug variable could be found.</returns> public static IEnumerable<DbgVar> GetDebugVariablesFromLine(CodeEditor editor, int line, int length = 1) { // find all debug variables var vars = RegexDbgVar.Matches(editor.Text); var from = line; var to = line + length; for (int i = 0; i < vars.Count; i++) { var varLine = editor.LineFromPosition(vars[i].Index); // is the debug variable in the same line if (from <= varLine && varLine < to) yield return new DbgVar(i, vars[i].Index, varLine, vars[i].Value); } }
public override int ProcessDefaultState(CodeEditor editor, Region c) { switch (c.c) { case '#': return (int)State.Preprocessor; case '_': return (int)State.Indicator; case '(': case ')': case '{': case '}': return (int)BaseState.Braces; case '.': case ';': return (int)BaseState.Punctuation; case '=': return (int)BaseState.Operator; case '/': if (c[1] == '/') return (int)BaseState.LineComment; if (c[1] == '*') return (int)BaseState.BlockComment; break; } // the beginning of a keyword if (char.IsLetter(c.c)) return (int)State.Indicator; return (int)State.Default; }
private int ProcessBracesState(CodeEditor editor, Region c, int endPos) { // get the lexer type of the body string type = null; switch (c[-1]) { case '(': // get preceding word from brace position var wordStart = editor.WordStartPosition(c.Pos - 1, false); type = editor.GetWordFromPosition(wordStart); if (type != "layout") type = "functionheader"; break; case '{': // get preceding non-whitespace position from brace position var bracePos = c.Pos - 2; while (bracePos >= 0 && (char)editor.GetCharAt(bracePos) != ';' && char.IsWhiteSpace((char)editor.GetCharAt(bracePos))) bracePos--; // if the preceding char is a closing brace, we have to lex a function body var braceChar = (char)editor.GetCharAt(bracePos); type = braceChar == ')' ? "function" : "struct"; break; case '}': return -1; default: return ProcessDefaultState(editor, c); } // find lexer that can lex this code block var lex = lexer.Where(x => x.IsLexerForType(type)).FirstOr(null); // re-lex body of the uniform block, struct, layout or function c.Pos = lex?.Style(editor, c.Pos, endPos) ?? c.Pos; // continue styling from the last position editor.StartStyling(c.Pos); return ProcessDefaultState(editor, c); }
public override int ProcessDefaultState(CodeEditor editor, Region c) { switch (c.c) { case '_': return (int)State.Indicator; case '"': return (int)BaseState.String; case '.': return (int)(char.IsNumber(c[1]) ? BaseState.Number : BaseState.Punctuation); case '\n': return DefaultProcessNewLine(editor, c); } // the beginning of a word or keyword if (char.IsLetter(c.c)) return (int)State.Indicator; // start of a number if(char.IsNumber(c.c)) return (int)BaseState.Number; return (int)State.Default; }
public override int ProcessDefaultState(CodeEditor editor, Region c) { switch (c.c) { case '"': case '\'': // the beginning of a string return (int)BaseState.String; case '.': // the beginning of a number or punctuation return (int)(char.IsNumber(c[1]) ? BaseState.Number : BaseState.Punctuation); case ',': case ';': // a punctuation return (int)BaseState.Punctuation; case '*': case '+': case '-': // an operator return (int)BaseState.Operator; case '/': // the beginning of a line comment if (c[1] == '/') return (int)BaseState.LineComment; // the beginning of a block comment if (c[1] == '*') return (int)BaseState.BlockComment; // an operator return (int)BaseState.Operator; case '(': case ')': case '[': case ']': // a brace return (int)BaseState.Braces; case '}': // exit lexer return -1; case '\n': // exit lexer if line does not end with "." return DefaultProcessNewLine(editor, c); } // the beginning of an operator if (char.IsSymbol(c.c)) return (int)BaseState.Operator; // the beginning of a number if (char.IsNumber(c.c) && !char.IsLetter(c[-1]) && c[-1] != '_') return (int)BaseState.Number; return (int)BaseState.Default; }
/// <summary> /// Default process block comment state. /// </summary> /// <param name="editor"></param> /// <param name="c"></param> /// <returns>The new state after processing the current state.</returns> protected int ProcessBlockCommentState(CodeEditor editor, Region c) => c[-2] == '*' && c[-1] == '/' ? ProcessDefaultState(editor, c) : (int)BaseState.BlockComment;
/// <summary> /// Default process indicator state. /// </summary> /// <param name="editor"></param> /// <param name="c"></param> /// <param name="IndicatorState"></param> /// <returns>The new state after processing the current state.</returns> protected int ProcessIndicatorState(CodeEditor editor, Region c, int IndicatorState) { // position still inside the word range if (char.IsLetterOrDigit(c.c) || c.c == '_') return IndicatorState; // relex last word RelexPreviousWord(editor, c.Pos); // continue from default state return ProcessDefaultState(editor, c); }
/// <summary> /// Default process number state method. /// </summary> /// <param name="editor"></param> /// <param name="c"></param> /// <returns>The new state after processing the current state.</returns> protected int ProcessNumberState(CodeEditor editor, Region c) => char.IsNumber(c.c) || c.c == '.' || c.c == 'x' || ('a' <= c.c && c.c <= 'f') || ('A' <= c.c && c.c <= 'F') ? (int)BaseState.Number : ProcessDefaultState(editor, c);
/// <summary> /// Default process line comment state. /// </summary> /// <param name="editor"></param> /// <param name="c"></param> /// <returns>The new state after processing the current state.</returns> protected int ProcessLineCommentState(CodeEditor editor, Region c) => c.c == '\n' ? ProcessDefaultState(editor, c) : (int)BaseState.LineComment;
/// <summary> /// Default process string state method. /// </summary> /// <param name="editor"></param> /// <param name="c"></param> /// <returns>The new state after processing the current state.</returns> protected int ProcessStringState(CodeEditor editor, Region c) => (c.c == '\n' || (c[-1] == '"' && c[-2] != '\\' && c.GetStyleAt(-2) == StringStyle)) ? ProcessDefaultState(editor, c) : (int)BaseState.String;
/// <summary> /// Default process default state method. /// </summary> /// <param name="e">unused</param> /// <param name="c">unused</param> /// <returns>The new state after processing the current state.</returns> public virtual int ProcessDefaultState(CodeEditor e, Region c) => 0;
/// <summary> /// Default process state method. /// </summary> /// <param name="e">unused</param> /// <param name="state"></param> /// <param name="c">unused</param> /// <param name="p">unused</param> /// <returns>The new state after processing the current state.</returns> public virtual int ProcessState(CodeEditor e, int state, Region c, int p) => state;
public override int ProcessDefaultState(CodeEditor editor, Region c) { switch (c.c) { case '/': if (c[1] == '/') return (int)BaseState.LineComment; if (c[1] == '*') return (int)BaseState.BlockComment; break; case '_': return (int)State.Indicator; case '.': return (int)BaseState.Punctuation; case '}': return (int)BaseState.Braces; // end of the block } // the beginning of a word or keyword if (char.IsLetter(c.c)) return (int)State.Indicator; return (int)State.Default; }
/// <summary> /// Default process new line state. /// </summary> /// <param name="editor"></param> /// <param name="c"></param> /// <returns>The new state after processing the current state.</returns> protected int DefaultProcessNewLine(CodeEditor editor, Region c) { // exit lexer if line does not end with "..." int i = c.Pos - 1; var C = (char)editor.GetCharAt(i); while (i > 0 && C != '\n' && char.IsWhiteSpace(C)) C = (char)editor.GetCharAt(--i); return editor.GetTextRange(i - 2, 3) != "..." ? -1 : (int)BaseState.Default; }
private new int ProcessIndicatorState(CodeEditor editor, Region c, int endPos) { // is still part of the command if (!char.IsWhiteSpace(c.c)) return (int)State.Indicator; // relex last word RelexPreviousWord(editor, c.Pos); // get header string from block position var cmd = editor.GetWordFromPosition(c.Pos - 1); // find lexer that can lex this code block var lex = lexer.Where(x => x.IsLexerForType(cmd)).FirstOr(defaultLexer); // re-lex code block c.Pos = lex.Style(editor, c.Pos, endPos); // continue lexing return ProcessDefaultState(editor, c); }
/// <summary> /// Relex the first word directly before the current position. /// </summary> /// <param name="editor"></param> /// <param name="pos"></param> protected void RelexPreviousWord(CodeEditor editor, int pos) { // get previous word and start position var start = editor.WordStartPosition(pos, false); var word = editor.GetWordFromPosition(start); // find out if the previous word is a keyword for (int i = 0; i < keywords.Length; i++) { // reset the style of the word if it is a keyword if (keywords[i]?[word].Any(x => x.word == word) ?? false) { editor.StartStyling(start); editor.SetStyling(pos - start, StateToStyle(i)); } } }
public override int ProcessState(CodeEditor editor, int state, Region c, int endPos) { switch (state) { case (int)BaseState.Number: return ProcessNumberState(editor, c); case (int)BaseState.String: return ProcessStringState(editor, c); case (int)BaseState.LineComment: return ProcessLineCommentState(editor, c); case (int)BaseState.BlockComment: return ProcessBlockCommentState(editor, c); } return ProcessDefaultState(editor, c); }
/// <summary> /// Find last position in the text that has the specified style. /// </summary> /// <param name="editor"></param> /// <param name="style"></param> /// <param name="from"></param> /// <returns></returns> protected int FindLastStyleOf(CodeEditor editor, int style, int from) { while (from > 0 && editor.GetStyleAt(from) != style) from--; return editor.GetStyleAt(from) == style ? from : -1; }
public override int ProcessState(CodeEditor editor, int state, Region c, int endPos) { switch (state) { case (int)BaseState.Braces: return ProcessBracesState(editor, c, endPos); case (int)BaseState.LineComment: return ProcessLineCommentState(editor, c); case (int)BaseState.BlockComment: return ProcessBlockCommentState(editor, c); case (int)State.Preprocessor: return ProcessPreprocessorState(editor, c, endPos); case (int)State.Indicator: return ProcessIndicatorState(editor, c, (int)State.Indicator); } return ProcessDefaultState(editor, c); }
public override int ProcessDefaultState(CodeEditor editor, Region c) { switch (c.c) { case '/': if (c[1] == '/') return (int)BaseState.LineComment; if (c[1] == '*') return (int)BaseState.BlockComment; break; case '#': return (int)State.Preprocessor; case '{': return (int)BaseState.Braces; case '_': return (int)State.Indicator; } if (char.IsLetter(c.c)) return (int)State.Indicator; return (int)State.Default; }
private int ProcessPreprocessorState(CodeEditor editor, Region c, int endPos) { if (c.c == '\n') return (int)State.Default; if (char.IsWhiteSpace(c.c)) { c.Pos = defaultLexer.Style(editor, c.Pos, endPos); return ProcessDefaultState(editor, c); } return (int)State.Preprocessor; }
private int ProcessBraceState(CodeEditor editor, Region c, int endPos) { if (c[-1] == '{') { // get header string from block position var typePos = FindLastStyleOf(editor, StateToStyle((int)State.Type), c.Pos); var typeName = typePos >= 0 ? editor.GetWordFromPosition(typePos) : null; // find lexer that can lex this code block var lex = lexer.Where(x => x.IsLexerForType(typeName)).FirstOr(null); // if no lexer found, skip this code block if (lex == null) { // go to matching brace int start = c.Pos; for (int n = 0; c.Pos < endPos && n >= 0; c.Pos++) { if (c.c == '{') n++; if (c.c == '}') n--; } // make code block invalid editor.SetStyling(--c.Pos - start, StateToStyle((int)BaseState.Default)); return (int)(c.c == '}' ? BaseState.Braces : BaseState.Default); } // re-lex code block c.Pos = lex.Style(editor, c.Pos, endPos); } return ProcessDefaultState(editor, c); }
public override int ProcessState(CodeEditor editor, int state, Region c, int endPos) { switch (state) { case (int)BaseState.Braces: return -1; // exit lexer case (int)State.Indicator: return ProcessIndicatorState(editor, c, (int)State.Indicator); case (int)BaseState.Number: return ProcessNumberState(editor, c); } return ProcessDefaultState(editor, c); }
private int ProcessPreprocessorState(CodeEditor editor, Region c) { if (c.c == '\n') return (int)State.Default; if (char.IsWhiteSpace(c.c)) return (int)State.PreprocessorBody; return (int)State.Preprocessor; }
/// <summary> /// Get debug variable from the specified text position in the code editor. /// </summary> /// <param name="editor">Source code editor.</param> /// <param name="position">Position in the code.</param> /// <returns>Returns the debug variable at the specified position or /// the default value if no debug variable could be found.</returns> public static DbgVar GetDebugVariableFromPosition(CodeEditor editor, int position) { // find all debug variables var vars = RegexDbgVar.Matches(editor.Text); for (int i = 0; i < vars.Count; i++) { var varLine = editor.LineFromPosition(vars[i].Index); // is the debug variable in the same line if (vars[i].Index <= position && position <= vars[i].Index + vars[i].Length) return new DbgVar(i, vars[i].Index, varLine, vars[i].Value); } return null; }
private int ProcessPreprocessorBodyState(CodeEditor editor, Region c) { // still inside the preprocessor body if (c.c != '\n') return (int)State.PreprocessorBody; // RE-LEX ALL PREPROCESSORCODE PARTS // get code region of the block var start = FindLastStyleOf(editor, StateToStyle((int)State.Preprocessor), c.Pos); // re-lex code block defaultLexer.Style(editor, start + 1, c.Pos); // continue styling from the last position editor.StartStyling(c.Pos); return (int)State.Default; }
/// <summary> /// Show variables of the currently selected line in the editor. /// </summary> /// <param name="editor"></param> private void UpdateDebugListView(CodeEditor editor) { // RESET DEBUG LIST VIEW debugListView.Clear(); debugListView.AddColumn("X", 80); debugListView.AddColumn("Y", 80); debugListView.AddColumn("Z", 80); debugListView.AddColumn("W", 80); // if the code has been edited no debug information can // be shown, because debug variables might have been // added or removed, which leads to invalid debug output if ((editor.Parent as TabPage).Text.EndsWith("*")) return; // get debug variables of the line where the caret is placed var first = editor.LineFromPosition(editor.SelectionStart); var last = editor.LineFromPosition(editor.SelectionEnd); var dbgVars = FxDebugger.GetDebugVariablesFromLine(editor, first, last - first + 1); dbgVars.Select(Var => FxDebugger.GetDebugVariableValue(Var.ID, glControl.Frame - 1)) .ForEach(dbgVars, (Val, Var) => { if (Val != null) NewVariableItem(Var.Name, Val); }); debugListView.Update(); }
public void Fold(CodeEditor editor, int pos, int endPos) { // setup state machine var line = editor.LineFromPosition(pos); var lastLine = -1; var lastCharPos = line; var foldLevel = editor.Lines[line].FoldLevel; var textLength = editor.TextLength; const int DEFAULT_FOLD_LEVEL = 1024; // for each character for (var state = FoldState.Unknown; state == FoldState.Unknown ? pos < endPos : pos < textLength; pos++) { var c = (char)editor.GetCharAt(pos); switch (c) { // open folding case '{': state = FoldState.StartFolding; break; // close folding case '}': state = FoldState.EndFolding; break; // next line case '\n': line++; break; // remember last character to place // fold icon in the last character line default: if (char.IsLetterOrDigit(c)) lastCharPos = pos; break; } switch (state) { // STATE: open folding case FoldState.StartFolding: var lastCharLine = editor.LineFromPosition(lastCharPos); // start folding at last character containing line editor.Lines[lastCharLine].FoldLevelFlags = FoldLevelFlags.Header; editor.Lines[lastCharLine].FoldLevel = foldLevel++; // for all other lines up to the current position also add folding for (int i = lastCharLine + 1; i <= line; i++) { editor.Lines[i].FoldLevelFlags = FoldLevelFlags.White; editor.Lines[i].FoldLevel = foldLevel; } lastLine = line; // switch to folding state state = FoldState.Foldable; break; // STATE: close folding case FoldState.EndFolding: // end folding editor.Lines[line].FoldLevel = foldLevel; // decrease fold level foldLevel = Math.Max(--foldLevel, DEFAULT_FOLD_LEVEL); lastLine = line; // switch to folding state (which will // switch to unknown state if the most // outer fold level is reached) state = FoldState.Foldable; break; // STATE: folding case FoldState.Foldable: // still in folding state if (foldLevel > DEFAULT_FOLD_LEVEL) { if (line != lastLine) { // set fold level for line editor.Lines[line].FoldLevel = foldLevel; lastLine = line; } } // end folding state else state = FoldState.Unknown; break; } } }