mirror of
https://github.com/GrahamKracker/UnityExplorer.git
synced 2025-01-10 10:59:36 +08:00
cleanup and refactor C# lexer classes
This commit is contained in:
parent
9c077b3aa3
commit
70a1570441
@ -133,7 +133,7 @@ namespace UnityExplorer.Console
|
|||||||
{
|
{
|
||||||
var editor = ConsolePage.Instance.m_codeEditor;
|
var editor = ConsolePage.Instance.m_codeEditor;
|
||||||
|
|
||||||
var textGen = editor.inputText.cachedTextGenerator;
|
var textGen = editor.InputText.cachedTextGenerator;
|
||||||
|
|
||||||
//if (textGen.characters.Count < 1)
|
//if (textGen.characters.Count < 1)
|
||||||
// return;
|
// return;
|
||||||
|
@ -1,19 +1,45 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityExplorer.Console.Lexer;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityExplorer.Console.Lexer;
|
||||||
|
|
||||||
namespace UnityExplorer.Console
|
namespace UnityExplorer.Console
|
||||||
{
|
{
|
||||||
public static class CSharpLexer
|
public struct LexerMatchInfo
|
||||||
{
|
{
|
||||||
public static char indentIncreaseCharacter = '{';
|
public int startIndex;
|
||||||
public static char indentDecreaseCharacter = '}';
|
public int endIndex;
|
||||||
|
public string htmlColor;
|
||||||
|
}
|
||||||
|
|
||||||
public static string delimiterSymbols = "[ ] ( ) { } ; : , .";
|
public enum DelimiterType
|
||||||
|
{
|
||||||
|
Start,
|
||||||
|
End,
|
||||||
|
};
|
||||||
|
|
||||||
|
public class CSharpLexer
|
||||||
|
{
|
||||||
|
private string inputString;
|
||||||
|
private readonly Matcher[] matchers;
|
||||||
|
private readonly HashSet<char> startDelimiters;
|
||||||
|
private readonly HashSet<char> endDelimiters;
|
||||||
|
private int currentIndex;
|
||||||
|
private int currentLookaheadIndex;
|
||||||
|
|
||||||
|
public char Current { get; private set; } = ' ';
|
||||||
|
public char Previous { get; private set; } = ' ';
|
||||||
|
|
||||||
|
public bool EndOfStream => currentLookaheadIndex >= inputString.Length;
|
||||||
|
|
||||||
|
public static char indentOpen = '{';
|
||||||
|
public static char indentClose = '}';
|
||||||
private static readonly StringBuilder indentBuilder = new StringBuilder();
|
private static readonly StringBuilder indentBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
public static char[] delimiters = new[]
|
||||||
|
{
|
||||||
|
'[', ']', '(', ')', '{', '}', ';', ':', ',', '.'
|
||||||
|
};
|
||||||
public static CommentMatch commentMatcher = new CommentMatch();
|
public static CommentMatch commentMatcher = new CommentMatch();
|
||||||
public static SymbolMatch symbolMatcher = new SymbolMatch();
|
public static SymbolMatch symbolMatcher = new SymbolMatch();
|
||||||
public static NumberMatch numberMatcher = new NumberMatch();
|
public static NumberMatch numberMatcher = new NumberMatch();
|
||||||
@ -22,65 +48,30 @@ namespace UnityExplorer.Console
|
|||||||
public static KeywordMatch validKeywordMatcher = new KeywordMatch
|
public static KeywordMatch validKeywordMatcher = new KeywordMatch
|
||||||
{
|
{
|
||||||
highlightColor = new Color(0.33f, 0.61f, 0.83f, 1.0f),
|
highlightColor = new Color(0.33f, 0.61f, 0.83f, 1.0f),
|
||||||
keywords = @"add as ascending await bool break by byte
|
Keywords = new[] { "add", "as", "ascending", "await", "bool", "break", "by", "byte",
|
||||||
case catch char checked const continue decimal default descending do dynamic
|
"case", "catch", "char", "checked", "const", "continue", "decimal", "default", "descending", "do", "dynamic",
|
||||||
else equals false finally float for foreach from global goto group
|
"else", "equals", "false", "finally", "float", "for", "foreach", "from", "global", "goto", "group",
|
||||||
if in int into is join let lock long new null object on orderby out
|
"if", "in", "int", "into", "is", "join", "let", "lock", "long", "new", "null", "object", "on", "orderby", "out",
|
||||||
ref remove return sbyte select short sizeof stackalloc string
|
"ref", "remove", "return", "sbyte", "select", "short", "sizeof", "stackalloc", "string",
|
||||||
switch throw true try typeof uint ulong ushort
|
"switch", "throw", "true", "try", "typeof", "uint", "ulong", "ushort", "var", "where", "while", "yield" }
|
||||||
var where while yield"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static KeywordMatch invalidKeywordMatcher = new KeywordMatch()
|
public static KeywordMatch invalidKeywordMatcher = new KeywordMatch()
|
||||||
{
|
{
|
||||||
highlightColor = new Color(0.95f, 0.10f, 0.10f, 1.0f),
|
highlightColor = new Color(0.95f, 0.10f, 0.10f, 1.0f),
|
||||||
keywords = @"abstract async base class delegate enum explicit extern fixed get
|
Keywords = new[] { "abstract", "async", "base", "class", "delegate", "enum", "explicit", "extern", "fixed", "get",
|
||||||
implicit interface internal namespace operator override params private protected public
|
"implicit", "interface", "internal", "namespace", "operator", "override", "params", "private", "protected", "public",
|
||||||
using partial readonly sealed set static struct this unchecked unsafe value virtual volatile void"
|
"using", "partial", "readonly", "sealed", "set", "static", "struct", "this", "unchecked", "unsafe", "value", "virtual", "volatile", "void" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static char[] delimiterSymbolCache = null;
|
// ~~~~~~~ ctor ~~~~~~~
|
||||||
internal static char[] DelimiterSymbols
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (delimiterSymbolCache == null)
|
|
||||||
{
|
|
||||||
string[] symbols = delimiterSymbols.Split(' ');
|
|
||||||
|
|
||||||
int count = 0;
|
public CSharpLexer()
|
||||||
|
{
|
||||||
|
startDelimiters = new HashSet<char>(delimiters);
|
||||||
|
endDelimiters = new HashSet<char>(delimiters);
|
||||||
|
|
||||||
for (int i = 0; i < symbols.Length; i++)
|
this.matchers = new Matcher[]
|
||||||
{
|
|
||||||
if (symbols[i].Length == 1)
|
|
||||||
{
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delimiterSymbolCache = new char[count];
|
|
||||||
|
|
||||||
for (int i = 0, index = 0; i < symbols.Length; i++)
|
|
||||||
{
|
|
||||||
if (symbols[i].Length == 1)
|
|
||||||
{
|
|
||||||
delimiterSymbolCache[index] = symbols[i][0];
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return delimiterSymbolCache;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Matcher[] matchers = null;
|
|
||||||
internal static Matcher[] Matchers
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (matchers == null)
|
|
||||||
{
|
|
||||||
List<Matcher> matcherList = new List<Matcher>
|
|
||||||
{
|
{
|
||||||
commentMatcher,
|
commentMatcher,
|
||||||
symbolMatcher,
|
symbolMatcher,
|
||||||
@ -90,11 +81,75 @@ namespace UnityExplorer.Console
|
|||||||
invalidKeywordMatcher,
|
invalidKeywordMatcher,
|
||||||
};
|
};
|
||||||
|
|
||||||
matchers = matcherList.ToArray();
|
foreach (Matcher lexer in matchers)
|
||||||
|
{
|
||||||
|
foreach (char c in lexer.StartChars)
|
||||||
|
{
|
||||||
|
if (!startDelimiters.Contains(c))
|
||||||
|
startDelimiters.Add(c);
|
||||||
}
|
}
|
||||||
return matchers;
|
|
||||||
|
foreach (char c in lexer.EndChars)
|
||||||
|
{
|
||||||
|
if (!endDelimiters.Contains(c))
|
||||||
|
endDelimiters.Add(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~~~~ Lex Matching ~~~~~~~
|
||||||
|
|
||||||
|
public IEnumerable<LexerMatchInfo> GetMatches(string input)
|
||||||
|
{
|
||||||
|
if (input == null || matchers == null || matchers.Length == 0)
|
||||||
|
{
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputString = input;
|
||||||
|
Current = ' ';
|
||||||
|
Previous = ' ';
|
||||||
|
currentIndex = 0;
|
||||||
|
currentLookaheadIndex = 0;
|
||||||
|
|
||||||
|
while (!EndOfStream)
|
||||||
|
{
|
||||||
|
bool didMatchLexer = false;
|
||||||
|
|
||||||
|
ReadWhiteSpace();
|
||||||
|
|
||||||
|
foreach (Matcher matcher in matchers)
|
||||||
|
{
|
||||||
|
int startIndex = currentIndex;
|
||||||
|
|
||||||
|
bool isMatched = matcher.IsMatch(this);
|
||||||
|
|
||||||
|
if (isMatched)
|
||||||
|
{
|
||||||
|
int endIndex = currentIndex;
|
||||||
|
|
||||||
|
didMatchLexer = true;
|
||||||
|
|
||||||
|
yield return new LexerMatchInfo
|
||||||
|
{
|
||||||
|
startIndex = startIndex,
|
||||||
|
endIndex = endIndex,
|
||||||
|
htmlColor = matcher.HexColor,
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!didMatchLexer)
|
||||||
|
{
|
||||||
|
ReadNext();
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~~~~ Indent ~~~~~~~
|
||||||
|
|
||||||
public static string GetIndentForInput(string input, int indent, out int caretPosition)
|
public static string GetIndentForInput(string input, int indent, out int caretPosition)
|
||||||
{
|
{
|
||||||
@ -123,14 +178,14 @@ namespace UnityExplorer.Console
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!stringState && input[i] == indentIncreaseCharacter)
|
else if (!stringState && input[i] == indentOpen)
|
||||||
{
|
{
|
||||||
indentBuilder.Append(indentIncreaseCharacter);
|
indentBuilder.Append(indentOpen);
|
||||||
indent++;
|
indent++;
|
||||||
}
|
}
|
||||||
else if (!stringState && input[i] == indentDecreaseCharacter)
|
else if (!stringState && input[i] == indentClose)
|
||||||
{
|
{
|
||||||
indentBuilder.Append(indentDecreaseCharacter);
|
indentBuilder.Append(indentClose);
|
||||||
indent--;
|
indent--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -177,5 +232,77 @@ namespace UnityExplorer.Console
|
|||||||
|
|
||||||
return indent;
|
return indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lexer reading
|
||||||
|
|
||||||
|
public char ReadNext()
|
||||||
|
{
|
||||||
|
if (EndOfStream)
|
||||||
|
{
|
||||||
|
return '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Previous = Current;
|
||||||
|
|
||||||
|
Current = inputString[currentLookaheadIndex];
|
||||||
|
currentLookaheadIndex++;
|
||||||
|
|
||||||
|
return Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Rollback(int amount = -1)
|
||||||
|
{
|
||||||
|
if (amount == -1)
|
||||||
|
{
|
||||||
|
currentLookaheadIndex = currentIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentLookaheadIndex > currentIndex)
|
||||||
|
{
|
||||||
|
currentLookaheadIndex -= amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int previousIndex = currentLookaheadIndex - 1;
|
||||||
|
|
||||||
|
if (previousIndex >= inputString.Length)
|
||||||
|
{
|
||||||
|
Previous = inputString[inputString.Length - 1];
|
||||||
|
}
|
||||||
|
else if (previousIndex >= 0)
|
||||||
|
{
|
||||||
|
Previous = inputString[previousIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Previous = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Commit()
|
||||||
|
{
|
||||||
|
currentIndex = currentLookaheadIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSpecialSymbol(char character, DelimiterType position = DelimiterType.Start)
|
||||||
|
{
|
||||||
|
if (position == DelimiterType.Start)
|
||||||
|
{
|
||||||
|
return startDelimiters.Contains(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
return endDelimiters.Contains(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadWhiteSpace()
|
||||||
|
{
|
||||||
|
while (char.IsWhiteSpace(ReadNext()) == true)
|
||||||
|
{
|
||||||
|
Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rollback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,22 +18,21 @@ using UnhollowerRuntimeLib;
|
|||||||
|
|
||||||
namespace UnityExplorer.Console
|
namespace UnityExplorer.Console
|
||||||
{
|
{
|
||||||
|
// Handles most of the UI side of the C# console, including syntax highlighting.
|
||||||
|
|
||||||
public class CodeEditor
|
public class CodeEditor
|
||||||
{
|
{
|
||||||
private readonly InputLexer inputLexer = new InputLexer();
|
|
||||||
|
|
||||||
public InputField InputField { get; internal set; }
|
public InputField InputField { get; internal set; }
|
||||||
|
public Text InputText { get; internal set; }
|
||||||
|
public int CurrentIndent { get; private set; }
|
||||||
|
|
||||||
public Text inputText;
|
|
||||||
private Text inputHighlightText;
|
private Text inputHighlightText;
|
||||||
private Image background;
|
private Image background;
|
||||||
private Image scrollbar;
|
private Image scrollbar;
|
||||||
|
|
||||||
public int LineCount { get; private set; }
|
public string HighlightedText => inputHighlightText.text;
|
||||||
public int CurrentLine { get; private set; }
|
private readonly CSharpLexer highlightLexer;
|
||||||
public int CurrentIndent { get; private set; }
|
private readonly StringBuilder sbHighlight;
|
||||||
|
|
||||||
private static readonly StringBuilder highlightedBuilder = new StringBuilder(4096);
|
|
||||||
|
|
||||||
private static readonly KeyCode[] onFocusKeys =
|
private static readonly KeyCode[] onFocusKeys =
|
||||||
{
|
{
|
||||||
@ -41,28 +40,6 @@ namespace UnityExplorer.Console
|
|||||||
KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow
|
KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow
|
||||||
};
|
};
|
||||||
|
|
||||||
public string HighlightedText => inputHighlightText.text;
|
|
||||||
|
|
||||||
public string Text
|
|
||||||
{
|
|
||||||
get { return InputField.text; }
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
InputField.text = value;
|
|
||||||
inputHighlightText.text = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
InputField.text = string.Empty;
|
|
||||||
inputHighlightText.text = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
//inputText.ForceMeshUpdate(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal const string STARTUP_TEXT = @"Welcome to the UnityExplorer C# Console.
|
internal const string STARTUP_TEXT = @"Welcome to the UnityExplorer C# Console.
|
||||||
|
|
||||||
The following helper methods are available:
|
The following helper methods are available:
|
||||||
@ -86,14 +63,14 @@ The following helper methods are available:
|
|||||||
|
|
||||||
public CodeEditor()
|
public CodeEditor()
|
||||||
{
|
{
|
||||||
ConstructUI();
|
sbHighlight = new StringBuilder();
|
||||||
|
highlightLexer = new CSharpLexer();
|
||||||
|
|
||||||
ApplyTheme();
|
ConstructUI();
|
||||||
inputLexer.UseMatchers(CSharpLexer.DelimiterSymbols, CSharpLexer.Matchers);
|
|
||||||
|
|
||||||
// subscribe to text input changing
|
// subscribe to text input changing
|
||||||
#if CPP
|
#if CPP
|
||||||
InputField.onValueChanged.AddListener(new Action<string>((string s) => { OnInputChanged(); }));
|
InputField.onValueChanged.AddListener(new Action<string>((string s) => { OnInputChanged(s); }));
|
||||||
#else
|
#else
|
||||||
this.InputField.onValueChanged.AddListener((string s) => { OnInputChanged(s); });
|
this.InputField.onValueChanged.AddListener((string s) => { OnInputChanged(s); });
|
||||||
#endif
|
#endif
|
||||||
@ -166,10 +143,10 @@ The following helper methods are available:
|
|||||||
{
|
{
|
||||||
char character = newText[i];
|
char character = newText[i];
|
||||||
|
|
||||||
if (character == CSharpLexer.indentIncreaseCharacter)
|
if (character == CSharpLexer.indentOpen)
|
||||||
CurrentIndent++;
|
CurrentIndent++;
|
||||||
|
|
||||||
if (character == CSharpLexer.indentDecreaseCharacter)
|
if (character == CSharpLexer.indentClose)
|
||||||
CurrentIndent--;
|
CurrentIndent--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,33 +160,33 @@ The following helper methods are available:
|
|||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
highlightedBuilder.Length = 0;
|
sbHighlight.Length = 0;
|
||||||
|
|
||||||
foreach (LexerMatchInfo match in inputLexer.LexInputString(inputText))
|
foreach (LexerMatchInfo match in highlightLexer.GetMatches(inputText))
|
||||||
{
|
{
|
||||||
for (int i = offset; i < match.startIndex; i++)
|
for (int i = offset; i < match.startIndex; i++)
|
||||||
{
|
{
|
||||||
highlightedBuilder.Append(inputText[i]);
|
sbHighlight.Append(inputText[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
highlightedBuilder.Append($"{match.htmlColor}");
|
sbHighlight.Append($"{match.htmlColor}");
|
||||||
|
|
||||||
for (int i = match.startIndex; i < match.endIndex; i++)
|
for (int i = match.startIndex; i < match.endIndex; i++)
|
||||||
{
|
{
|
||||||
highlightedBuilder.Append(inputText[i]);
|
sbHighlight.Append(inputText[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
highlightedBuilder.Append(CLOSE_COLOR_TAG);
|
sbHighlight.Append(CLOSE_COLOR_TAG);
|
||||||
|
|
||||||
offset = match.endIndex;
|
offset = match.endIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = offset; i < inputText.Length; i++)
|
for (int i = offset; i < inputText.Length; i++)
|
||||||
{
|
{
|
||||||
highlightedBuilder.Append(inputText[i]);
|
sbHighlight.Append(inputText[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inputText = highlightedBuilder.ToString();
|
inputText = sbHighlight.ToString();
|
||||||
|
|
||||||
return inputText;
|
return inputText;
|
||||||
}
|
}
|
||||||
@ -242,8 +219,8 @@ The following helper methods are available:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if should add auto-close }
|
// check if should add auto-close }
|
||||||
int numOpen = InputField.text.Where(x => x == CSharpLexer.indentIncreaseCharacter).Count();
|
int numOpen = InputField.text.Where(x => x == CSharpLexer.indentOpen).Count();
|
||||||
int numClose = InputField.text.Where(x => x == CSharpLexer.indentDecreaseCharacter).Count();
|
int numClose = InputField.text.Where(x => x == CSharpLexer.indentClose).Count();
|
||||||
|
|
||||||
if (numOpen > numClose)
|
if (numOpen > numClose)
|
||||||
{
|
{
|
||||||
@ -263,13 +240,13 @@ The following helper methods are available:
|
|||||||
// Update line column and indent positions
|
// Update line column and indent positions
|
||||||
UpdateIndent(InputField.text);
|
UpdateIndent(InputField.text);
|
||||||
|
|
||||||
inputText.text = InputField.text;
|
InputText.text = InputField.text;
|
||||||
//inputText.SetText(InputField.text, true);
|
//inputText.SetText(InputField.text, true);
|
||||||
inputText.Rebuild(CanvasUpdate.Prelayout);
|
InputText.Rebuild(CanvasUpdate.Prelayout);
|
||||||
InputField.ForceLabelUpdate();
|
InputField.ForceLabelUpdate();
|
||||||
InputField.Rebuild(CanvasUpdate.Prelayout);
|
InputField.Rebuild(CanvasUpdate.Prelayout);
|
||||||
|
|
||||||
OnInputChanged(inputText.text, true);
|
OnInputChanged(InputText.text, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetAutoIndentTab(int amount)
|
private string GetAutoIndentTab(int amount)
|
||||||
@ -284,26 +261,6 @@ The following helper methods are available:
|
|||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============== Theme ============== //
|
|
||||||
|
|
||||||
private static Color backgroundColor = new Color32(37, 37, 37, 255);
|
|
||||||
private static Color scrollbarColor = new Color32(45, 50, 50, 255);
|
|
||||||
|
|
||||||
private void ApplyTheme()
|
|
||||||
{
|
|
||||||
var highlightTextRect = inputHighlightText.GetComponent<RectTransform>();
|
|
||||||
highlightTextRect.anchorMin = Vector2.zero;
|
|
||||||
highlightTextRect.anchorMax = Vector2.one;
|
|
||||||
highlightTextRect.offsetMin = Vector2.zero;
|
|
||||||
highlightTextRect.offsetMax = Vector2.zero;
|
|
||||||
|
|
||||||
InputField.caretColor = Color.white;
|
|
||||||
inputText.color = new Color(1, 1, 1, 0.51f);
|
|
||||||
inputHighlightText.color = Color.white;
|
|
||||||
background.color = backgroundColor;
|
|
||||||
scrollbar.color = scrollbarColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== UI CONSTRUCTION =========== //
|
// ========== UI CONSTRUCTION =========== //
|
||||||
|
|
||||||
public void ConstructUI()
|
public void ConstructUI()
|
||||||
@ -523,14 +480,27 @@ The following helper methods are available:
|
|||||||
mainTextInput.font = UIManager.ConsoleFont;
|
mainTextInput.font = UIManager.ConsoleFont;
|
||||||
highlightTextInput.font = UIManager.ConsoleFont;
|
highlightTextInput.font = UIManager.ConsoleFont;
|
||||||
|
|
||||||
|
// reset this after formatting finalized
|
||||||
|
highlightTextRect.anchorMin = Vector2.zero;
|
||||||
|
highlightTextRect.anchorMax = Vector2.one;
|
||||||
|
highlightTextRect.offsetMin = Vector2.zero;
|
||||||
|
highlightTextRect.offsetMax = Vector2.zero;
|
||||||
|
|
||||||
// assign references
|
// assign references
|
||||||
|
|
||||||
this.InputField = inputField;
|
this.InputField = inputField;
|
||||||
|
|
||||||
this.inputText = mainTextInput;
|
this.InputText = mainTextInput;
|
||||||
this.inputHighlightText = highlightTextInput;
|
this.inputHighlightText = highlightTextInput;
|
||||||
this.background = mainBgImage;
|
this.background = mainBgImage;
|
||||||
this.scrollbar = scrollImage;
|
this.scrollbar = scrollImage;
|
||||||
|
|
||||||
|
// set some colors
|
||||||
|
InputField.caretColor = Color.white;
|
||||||
|
InputText.color = new Color(1, 1, 1, 0.51f);
|
||||||
|
inputHighlightText.color = Color.white;
|
||||||
|
background.color = new Color32(37, 37, 37, 255);
|
||||||
|
scrollbar.color = new Color32(45, 50, 50, 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace UnityExplorer.Console.Lexer
|
namespace UnityExplorer.Console.Lexer
|
||||||
{
|
{
|
||||||
public sealed class CommentMatch : Matcher
|
public class CommentMatch : Matcher
|
||||||
{
|
{
|
||||||
public string lineCommentStart = @"//";
|
public string lineCommentStart = @"//";
|
||||||
public string blockCommentStart = @"/*";
|
public string blockCommentStart = @"/*";
|
||||||
@ -12,9 +12,9 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
public override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f);
|
public override Color HighlightColor => new Color(0.34f, 0.65f, 0.29f, 1.0f);
|
||||||
public override IEnumerable<char> StartChars => new char[] { lineCommentStart[0], blockCommentStart[0] };
|
public override IEnumerable<char> StartChars => new char[] { lineCommentStart[0], blockCommentStart[0] };
|
||||||
public override IEnumerable<char> EndChars => new char[] { blockCommentEnd[0] };
|
public override IEnumerable<char> EndChars => new char[] { blockCommentEnd[0] };
|
||||||
public override bool IsImplicitMatch(InputLexer lexer) => IsMatch(lexer, lineCommentStart) || IsMatch(lexer, blockCommentStart);
|
public override bool IsImplicitMatch(CSharpLexer lexer) => IsMatch(lexer, lineCommentStart) || IsMatch(lexer, blockCommentStart);
|
||||||
|
|
||||||
private bool IsMatch(InputLexer lexer, string commentType)
|
private bool IsMatch(CSharpLexer lexer, string commentType)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(commentType))
|
if (!string.IsNullOrEmpty(commentType))
|
||||||
{
|
{
|
||||||
@ -32,11 +32,8 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
|
|
||||||
if (match)
|
if (match)
|
||||||
{
|
{
|
||||||
// Read until end
|
// Read until end of line or file
|
||||||
while (!IsEndLineOrEndFile(lexer, lexer.ReadNext()))
|
while (!IsEndLineOrEndFile(lexer, lexer.ReadNext())) { }
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -44,6 +41,6 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsEndLineOrEndFile(InputLexer lexer, char character) => lexer.EndOfStream || character == '\n' || character == '\r';
|
private bool IsEndLineOrEndFile(CSharpLexer lexer, char character) => lexer.EndOfStream || character == '\n' || character == '\r';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,201 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace UnityExplorer.Console.Lexer
|
|
||||||
{
|
|
||||||
public struct LexerMatchInfo
|
|
||||||
{
|
|
||||||
public int startIndex;
|
|
||||||
public int endIndex;
|
|
||||||
public string htmlColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SpecialCharacterPosition
|
|
||||||
{
|
|
||||||
Start,
|
|
||||||
End,
|
|
||||||
};
|
|
||||||
|
|
||||||
public class InputLexer
|
|
||||||
{
|
|
||||||
private string inputString = null;
|
|
||||||
private Matcher[] matchers = null;
|
|
||||||
private readonly HashSet<char> specialStartSymbols = new HashSet<char>();
|
|
||||||
private readonly HashSet<char> specialEndSymbols = new HashSet<char>();
|
|
||||||
private int currentIndex = 0;
|
|
||||||
private int currentLookaheadIndex = 0;
|
|
||||||
|
|
||||||
private char current = ' ';
|
|
||||||
public char Previous { get; private set; } = ' ';
|
|
||||||
|
|
||||||
public bool EndOfStream
|
|
||||||
{
|
|
||||||
get { return currentLookaheadIndex >= inputString.Length; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UseMatchers(char[] delimiters, Matcher[] matchers)
|
|
||||||
{
|
|
||||||
this.matchers = matchers;
|
|
||||||
|
|
||||||
specialStartSymbols.Clear();
|
|
||||||
specialEndSymbols.Clear();
|
|
||||||
|
|
||||||
if (delimiters != null)
|
|
||||||
{
|
|
||||||
foreach (char character in delimiters)
|
|
||||||
{
|
|
||||||
if (!specialStartSymbols.Contains(character))
|
|
||||||
{
|
|
||||||
specialStartSymbols.Add(character);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!specialEndSymbols.Contains(character))
|
|
||||||
{
|
|
||||||
specialEndSymbols.Add(character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchers != null)
|
|
||||||
{
|
|
||||||
foreach (Matcher lexer in matchers)
|
|
||||||
{
|
|
||||||
foreach (char special in lexer.StartChars)
|
|
||||||
{
|
|
||||||
if (!specialStartSymbols.Contains(special))
|
|
||||||
{
|
|
||||||
specialStartSymbols.Add(special);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (char special in lexer.EndChars)
|
|
||||||
{
|
|
||||||
if (!specialEndSymbols.Contains(special))
|
|
||||||
{
|
|
||||||
specialEndSymbols.Add(special);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<LexerMatchInfo> LexInputString(string input)
|
|
||||||
{
|
|
||||||
if (input == null || matchers == null || matchers.Length == 0)
|
|
||||||
{
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputString = input;
|
|
||||||
current = ' ';
|
|
||||||
Previous = ' ';
|
|
||||||
currentIndex = 0;
|
|
||||||
currentLookaheadIndex = 0;
|
|
||||||
|
|
||||||
while (!EndOfStream)
|
|
||||||
{
|
|
||||||
bool didMatchLexer = false;
|
|
||||||
|
|
||||||
ReadWhiteSpace();
|
|
||||||
|
|
||||||
foreach (Matcher matcher in matchers)
|
|
||||||
{
|
|
||||||
int startIndex = currentIndex;
|
|
||||||
|
|
||||||
bool isMatched = matcher.IsMatch(this);
|
|
||||||
|
|
||||||
if (isMatched)
|
|
||||||
{
|
|
||||||
int endIndex = currentIndex;
|
|
||||||
|
|
||||||
didMatchLexer = true;
|
|
||||||
|
|
||||||
yield return new LexerMatchInfo
|
|
||||||
{
|
|
||||||
startIndex = startIndex,
|
|
||||||
endIndex = endIndex,
|
|
||||||
htmlColor = matcher.HexColor,
|
|
||||||
};
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!didMatchLexer)
|
|
||||||
{
|
|
||||||
ReadNext();
|
|
||||||
Commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public char ReadNext()
|
|
||||||
{
|
|
||||||
if (EndOfStream)
|
|
||||||
{
|
|
||||||
return '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
Previous = current;
|
|
||||||
|
|
||||||
current = inputString[currentLookaheadIndex];
|
|
||||||
currentLookaheadIndex++;
|
|
||||||
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Rollback(int amount = -1)
|
|
||||||
{
|
|
||||||
if (amount == -1)
|
|
||||||
{
|
|
||||||
currentLookaheadIndex = currentIndex;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (currentLookaheadIndex > currentIndex)
|
|
||||||
{
|
|
||||||
currentLookaheadIndex -= amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int previousIndex = currentLookaheadIndex - 1;
|
|
||||||
|
|
||||||
if (previousIndex >= inputString.Length)
|
|
||||||
{
|
|
||||||
Previous = inputString[inputString.Length - 1];
|
|
||||||
}
|
|
||||||
else if (previousIndex >= 0)
|
|
||||||
{
|
|
||||||
Previous = inputString[previousIndex];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Previous = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Commit()
|
|
||||||
{
|
|
||||||
currentIndex = currentLookaheadIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSpecialSymbol(char character, SpecialCharacterPosition position = SpecialCharacterPosition.Start)
|
|
||||||
{
|
|
||||||
if (position == SpecialCharacterPosition.Start)
|
|
||||||
{
|
|
||||||
return specialStartSymbols.Contains(character);
|
|
||||||
}
|
|
||||||
|
|
||||||
return specialEndSymbols.Contains(character);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReadWhiteSpace()
|
|
||||||
{
|
|
||||||
while (char.IsWhiteSpace(ReadNext()) == true)
|
|
||||||
{
|
|
||||||
Commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
Rollback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,23 +3,22 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace UnityExplorer.Console.Lexer
|
namespace UnityExplorer.Console.Lexer
|
||||||
{
|
{
|
||||||
public sealed class KeywordMatch : Matcher
|
// I use two different KeywordMatch instances (valid and invalid).
|
||||||
|
// This class just contains common implementations.
|
||||||
|
public class KeywordMatch : Matcher
|
||||||
{
|
{
|
||||||
public string keywords;
|
public string[] Keywords;
|
||||||
|
|
||||||
public override Color HighlightColor => highlightColor;
|
public override Color HighlightColor => highlightColor;
|
||||||
public Color highlightColor;
|
public Color highlightColor;
|
||||||
|
|
||||||
private readonly HashSet<string> shortlist = new HashSet<string>();
|
private readonly HashSet<string> shortlist = new HashSet<string>();
|
||||||
private readonly Stack<string> removeList = new Stack<string>();
|
private readonly Stack<string> removeList = new Stack<string>();
|
||||||
public string[] keywordCache = null;
|
|
||||||
|
|
||||||
public override bool IsImplicitMatch(InputLexer lexer)
|
public override bool IsImplicitMatch(CSharpLexer lexer)
|
||||||
{
|
{
|
||||||
BuildKeywordCache();
|
|
||||||
|
|
||||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||||
!lexer.IsSpecialSymbol(lexer.Previous, SpecialCharacterPosition.End))
|
!lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -29,11 +28,11 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
int currentIndex = 0;
|
int currentIndex = 0;
|
||||||
char currentChar = lexer.ReadNext();
|
char currentChar = lexer.ReadNext();
|
||||||
|
|
||||||
for (int i = 0; i < keywordCache.Length; i++)
|
for (int i = 0; i < Keywords.Length; i++)
|
||||||
{
|
{
|
||||||
if (keywordCache[i][0] == currentChar)
|
if (Keywords[i][0] == currentChar)
|
||||||
{
|
{
|
||||||
shortlist.Add(keywordCache[i]);
|
shortlist.Add(Keywords[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
currentIndex++;
|
currentIndex++;
|
||||||
|
|
||||||
if (char.IsWhiteSpace(currentChar) ||
|
if (char.IsWhiteSpace(currentChar) ||
|
||||||
lexer.IsSpecialSymbol(currentChar, SpecialCharacterPosition.Start))
|
lexer.IsSpecialSymbol(currentChar, DelimiterType.Start))
|
||||||
{
|
{
|
||||||
RemoveLongStrings(currentIndex);
|
RemoveLongStrings(currentIndex);
|
||||||
lexer.Rollback(1);
|
lexer.Rollback(1);
|
||||||
@ -94,23 +93,5 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
shortlist.Remove(removeList.Pop());
|
shortlist.Remove(removeList.Pop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildKeywordCache()
|
|
||||||
{
|
|
||||||
if (keywordCache == null)
|
|
||||||
{
|
|
||||||
string[] kwSplit = keywords.Split(' ');
|
|
||||||
|
|
||||||
List<string> list = new List<string>();
|
|
||||||
foreach (string kw in kwSplit)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(kw) && kw.Length > 0)
|
|
||||||
{
|
|
||||||
list.Add(kw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keywordCache = list.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityExplorer.Unstrip;
|
using UnityExplorer.Unstrip;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace UnityExplorer.Console.Lexer
|
namespace UnityExplorer.Console.Lexer
|
||||||
{
|
{
|
||||||
@ -9,14 +10,14 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
public abstract Color HighlightColor { get; }
|
public abstract Color HighlightColor { get; }
|
||||||
|
|
||||||
public string HexColor => htmlColor ?? (htmlColor = "<color=#" + HighlightColor.ToHex() + ">");
|
public string HexColor => htmlColor ?? (htmlColor = "<color=#" + HighlightColor.ToHex() + ">");
|
||||||
private string htmlColor = null;
|
private string htmlColor;
|
||||||
|
|
||||||
public virtual IEnumerable<char> StartChars { get { yield break; } }
|
public virtual IEnumerable<char> StartChars => Enumerable.Empty<char>();
|
||||||
public virtual IEnumerable<char> EndChars { get { yield break; } }
|
public virtual IEnumerable<char> EndChars => Enumerable.Empty<char>();
|
||||||
|
|
||||||
public abstract bool IsImplicitMatch(InputLexer lexer);
|
public abstract bool IsImplicitMatch(CSharpLexer lexer);
|
||||||
|
|
||||||
public bool IsMatch(InputLexer lexer)
|
public bool IsMatch(CSharpLexer lexer)
|
||||||
{
|
{
|
||||||
if (IsImplicitMatch(lexer))
|
if (IsImplicitMatch(lexer))
|
||||||
{
|
{
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
namespace UnityExplorer.Console.Lexer
|
namespace UnityExplorer.Console.Lexer
|
||||||
{
|
{
|
||||||
public sealed class NumberMatch : Matcher
|
public class NumberMatch : Matcher
|
||||||
{
|
{
|
||||||
public override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f);
|
public override Color HighlightColor => new Color(0.58f, 0.33f, 0.33f, 1.0f);
|
||||||
|
|
||||||
public override bool IsImplicitMatch(InputLexer lexer)
|
public override bool IsImplicitMatch(CSharpLexer lexer)
|
||||||
{
|
{
|
||||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||||
!lexer.IsSpecialSymbol(lexer.Previous, SpecialCharacterPosition.End))
|
!lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,24 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace UnityExplorer.Console.Lexer
|
namespace UnityExplorer.Console.Lexer
|
||||||
{
|
{
|
||||||
public sealed class StringMatch : Matcher
|
public class StringMatch : Matcher
|
||||||
{
|
{
|
||||||
public override Color HighlightColor => new Color(0.79f, 0.52f, 0.32f, 1.0f);
|
public override Color HighlightColor => new Color(0.79f, 0.52f, 0.32f, 1.0f);
|
||||||
|
|
||||||
public override IEnumerable<char> StartChars { get { yield return '"'; } }
|
public override IEnumerable<char> StartChars => new[] { '"' };
|
||||||
public override IEnumerable<char> EndChars { get { yield return '"'; } }
|
public override IEnumerable<char> EndChars => new[] { '"' };
|
||||||
|
|
||||||
public override bool IsImplicitMatch(InputLexer lexer)
|
public override bool IsImplicitMatch(CSharpLexer lexer)
|
||||||
{
|
{
|
||||||
if (lexer.ReadNext() == '"')
|
if (lexer.ReadNext() == '"')
|
||||||
{
|
{
|
||||||
while (!IsClosingQuoteOrEndFile(lexer, lexer.ReadNext()))
|
while (!IsClosingQuoteOrEndFile(lexer, lexer.ReadNext())) { }
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsClosingQuoteOrEndFile(InputLexer lexer, char character)
|
private bool IsClosingQuoteOrEndFile(CSharpLexer lexer, char character) => lexer.EndOfStream || character == '"';
|
||||||
{
|
|
||||||
if (lexer.EndOfStream == true ||
|
|
||||||
character == '"')
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,54 +4,32 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace UnityExplorer.Console.Lexer
|
namespace UnityExplorer.Console.Lexer
|
||||||
{
|
{
|
||||||
public sealed class SymbolMatch : Matcher
|
public class SymbolMatch : Matcher
|
||||||
{
|
{
|
||||||
public override Color HighlightColor => new Color(0.58f, 0.47f, 0.37f, 1.0f);
|
public override Color HighlightColor => new Color(0.58f, 0.47f, 0.37f, 1.0f);
|
||||||
|
|
||||||
public string Symbols => @"[ ] ( ) . ? : + - * / % & | ^ ~ = < > ++ -- && || << >> == != <= >=
|
private readonly string[] symbols = new[]
|
||||||
+= -= *= /= %= &= |= ^= <<= >>= -> ?? =>";
|
{
|
||||||
|
"[", "]", "(", ")", ".", "?", ":", "+", "-", "*", "/", "%", "&", "|", "^", "~", "=", "<", ">",
|
||||||
|
"++", "--", "&&", "||", "<<", ">>", "==", "!=", "<=", ">=", "+=", "-=", "*=", "/=", "%=", "&=",
|
||||||
|
"|=", "^=", "<<=", ">>=", "->", "??", "=>",
|
||||||
|
};
|
||||||
|
|
||||||
private static readonly List<string> shortlist = new List<string>();
|
private static readonly List<string> shortlist = new List<string>();
|
||||||
private static readonly Stack<string> removeList = new Stack<string>();
|
private static readonly Stack<string> removeList = new Stack<string>();
|
||||||
private string[] symbolCache = null;
|
|
||||||
|
|
||||||
public override IEnumerable<char> StartChars
|
public override IEnumerable<char> StartChars => symbols.Select(s => s[0]);
|
||||||
{
|
public override IEnumerable<char> EndChars => symbols.Select(s => s[0]);
|
||||||
get
|
|
||||||
{
|
|
||||||
BuildSymbolCache();
|
|
||||||
foreach (string symbol in symbolCache.Where(x => x.Length > 0))
|
|
||||||
{
|
|
||||||
yield return symbol[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<char> EndChars
|
public override bool IsImplicitMatch(CSharpLexer lexer)
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
BuildSymbolCache();
|
|
||||||
foreach (string symbol in symbolCache.Where(x => x.Length > 0))
|
|
||||||
{
|
|
||||||
yield return symbol[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsImplicitMatch(InputLexer lexer)
|
|
||||||
{
|
{
|
||||||
if (lexer == null)
|
if (lexer == null)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
BuildSymbolCache();
|
|
||||||
|
|
||||||
if (!char.IsWhiteSpace(lexer.Previous) &&
|
if (!char.IsWhiteSpace(lexer.Previous) &&
|
||||||
!char.IsLetter(lexer.Previous) &&
|
!char.IsLetter(lexer.Previous) &&
|
||||||
!char.IsDigit(lexer.Previous) &&
|
!char.IsDigit(lexer.Previous) &&
|
||||||
!lexer.IsSpecialSymbol(lexer.Previous, SpecialCharacterPosition.End))
|
!lexer.IsSpecialSymbol(lexer.Previous, DelimiterType.End))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -61,18 +39,14 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
int currentIndex = 0;
|
int currentIndex = 0;
|
||||||
char currentChar = lexer.ReadNext();
|
char currentChar = lexer.ReadNext();
|
||||||
|
|
||||||
for (int i = symbolCache.Length - 1; i >= 0; i--)
|
for (int i = symbols.Length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (symbolCache[i][0] == currentChar)
|
if (symbols[i][0] == currentChar)
|
||||||
{
|
shortlist.Add(symbols[i]);
|
||||||
shortlist.Add(symbolCache[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shortlist.Count == 0)
|
if (shortlist.Count == 0)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -88,7 +62,7 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
if (char.IsWhiteSpace(currentChar) ||
|
if (char.IsWhiteSpace(currentChar) ||
|
||||||
char.IsLetter(currentChar) ||
|
char.IsLetter(currentChar) ||
|
||||||
char.IsDigit(currentChar) ||
|
char.IsDigit(currentChar) ||
|
||||||
lexer.IsSpecialSymbol(currentChar, SpecialCharacterPosition.Start))
|
lexer.IsSpecialSymbol(currentChar, DelimiterType.Start))
|
||||||
{
|
{
|
||||||
RemoveLongStrings(currentIndex);
|
RemoveLongStrings(currentIndex);
|
||||||
lexer.Rollback(1);
|
lexer.Rollback(1);
|
||||||
@ -128,24 +102,5 @@ namespace UnityExplorer.Console.Lexer
|
|||||||
shortlist.Remove(removeList.Pop());
|
shortlist.Remove(removeList.Pop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildSymbolCache()
|
|
||||||
{
|
|
||||||
if (symbolCache != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] symSplit = Symbols.Split(' ');
|
|
||||||
List<string> list = new List<string>();
|
|
||||||
foreach (string sym in symSplit)
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(sym) && sym.Length > 0)
|
|
||||||
{
|
|
||||||
list.Add(sym);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
symbolCache = list.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,25 +9,22 @@ namespace UnityExplorer.Console
|
|||||||
{
|
{
|
||||||
public struct Suggestion
|
public struct Suggestion
|
||||||
{
|
{
|
||||||
public string Full => Prefix + Addition;
|
public enum Contexts
|
||||||
|
{
|
||||||
|
Namespace,
|
||||||
|
Keyword,
|
||||||
|
Other
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~ Instance ~~~~
|
||||||
|
|
||||||
public readonly string Prefix;
|
public readonly string Prefix;
|
||||||
public readonly string Addition;
|
public readonly string Addition;
|
||||||
public readonly Contexts Context;
|
public readonly Contexts Context;
|
||||||
|
|
||||||
public Color TextColor
|
public string Full => Prefix + Addition;
|
||||||
{
|
|
||||||
get
|
public Color TextColor => GetTextColor();
|
||||||
{
|
|
||||||
switch (Context)
|
|
||||||
{
|
|
||||||
case Contexts.Namespace: return Color.grey;
|
|
||||||
case Contexts.Keyword: return systemBlue;
|
|
||||||
default: return Color.white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static readonly Color systemBlue = new Color(80f / 255f, 150f / 255f, 215f / 255f);
|
|
||||||
|
|
||||||
public Suggestion(string addition, string prefix, Contexts type)
|
public Suggestion(string addition, string prefix, Contexts type)
|
||||||
{
|
{
|
||||||
@ -36,16 +33,26 @@ namespace UnityExplorer.Console
|
|||||||
Context = type;
|
Context = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Contexts
|
private Color GetTextColor()
|
||||||
{
|
{
|
||||||
Namespace,
|
switch (Context)
|
||||||
Keyword,
|
{
|
||||||
Other
|
case Contexts.Namespace: return Color.grey;
|
||||||
|
case Contexts.Keyword: return keywordColor;
|
||||||
|
default: return Color.white;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~~ Static ~~~~
|
||||||
|
|
||||||
public static HashSet<string> Namespaces => m_namspaces ?? GetNamespaces();
|
public static HashSet<string> Namespaces => m_namspaces ?? GetNamespaces();
|
||||||
private static HashSet<string> m_namspaces;
|
private static HashSet<string> m_namspaces;
|
||||||
|
|
||||||
|
public static HashSet<string> Keywords => m_keywords ?? (m_keywords = new HashSet<string>(CSharpLexer.validKeywordMatcher.Keywords));
|
||||||
|
private static HashSet<string> m_keywords;
|
||||||
|
|
||||||
|
private static readonly Color keywordColor = new Color(80f / 255f, 150f / 255f, 215f / 255f);
|
||||||
|
|
||||||
private static HashSet<string> GetNamespaces()
|
private static HashSet<string> GetNamespaces()
|
||||||
{
|
{
|
||||||
HashSet<string> set = new HashSet<string>(
|
HashSet<string> set = new HashSet<string>(
|
||||||
@ -58,25 +65,5 @@ namespace UnityExplorer.Console
|
|||||||
|
|
||||||
IEnumerable<Type> GetTypes(Assembly asm) => asm.TryGetTypes();
|
IEnumerable<Type> GetTypes(Assembly asm) => asm.TryGetTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HashSet<string> Keywords => m_keywords ?? GetKeywords();
|
|
||||||
private static HashSet<string> m_keywords;
|
|
||||||
|
|
||||||
private static HashSet<string> GetKeywords()
|
|
||||||
{
|
|
||||||
if (CSharpLexer.validKeywordMatcher.keywordCache == null)
|
|
||||||
{
|
|
||||||
return new HashSet<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet<string> set = new HashSet<string>();
|
|
||||||
|
|
||||||
foreach (string keyword in CSharpLexer.validKeywordMatcher.keywordCache)
|
|
||||||
{
|
|
||||||
set.Add(keyword);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_keywords = set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,18 +78,15 @@ namespace UnityExplorer.UI
|
|||||||
if (selectable is Button button)
|
if (selectable is Button button)
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
button.onClick.AddListener(new Action(() =>
|
button.onClick.AddListener(new Action(Deselect));
|
||||||
{
|
|
||||||
button.OnDeselect(null);
|
|
||||||
}));
|
|
||||||
#else
|
#else
|
||||||
button.onClick.AddListener(Deselect);
|
button.onClick.AddListener(Deselect);
|
||||||
|
#endif
|
||||||
void Deselect()
|
void Deselect()
|
||||||
{
|
{
|
||||||
button.OnDeselect(null);
|
button.OnDeselect(null);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selectable.colors = colors;
|
selectable.colors = colors;
|
||||||
|
@ -355,9 +355,8 @@
|
|||||||
<Compile Include="UI\PageModel\ConsolePage.cs" />
|
<Compile Include="UI\PageModel\ConsolePage.cs" />
|
||||||
<Compile Include="Console\AutoCompleter.cs" />
|
<Compile Include="Console\AutoCompleter.cs" />
|
||||||
<Compile Include="Console\CodeEditor.cs" />
|
<Compile Include="Console\CodeEditor.cs" />
|
||||||
<Compile Include="Console\CSharpLexer.cs" />
|
|
||||||
<Compile Include="Console\Lexer\CommentMatch.cs" />
|
<Compile Include="Console\Lexer\CommentMatch.cs" />
|
||||||
<Compile Include="Console\Lexer\InputLexer.cs" />
|
<Compile Include="Console\CSharpLexer.cs" />
|
||||||
<Compile Include="Console\Lexer\KeywordMatch.cs" />
|
<Compile Include="Console\Lexer\KeywordMatch.cs" />
|
||||||
<Compile Include="Console\Lexer\StringMatch.cs" />
|
<Compile Include="Console\Lexer\StringMatch.cs" />
|
||||||
<Compile Include="Console\Lexer\Matcher.cs" />
|
<Compile Include="Console\Lexer\Matcher.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user