2021-05-11 19:15:46 +10:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using UnityEngine;
|
2021-05-12 20:48:56 +10:00
|
|
|
|
using UnityExplorer.UI.CSConsole.Lexers;
|
2021-05-11 19:15:46 +10:00
|
|
|
|
using UnityExplorer.UI.Widgets.AutoComplete;
|
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
namespace UnityExplorer.UI.CSConsole
|
2021-05-11 19:15:46 +10:00
|
|
|
|
{
|
|
|
|
|
public class CSAutoCompleter : ISuggestionProvider
|
|
|
|
|
{
|
2021-05-12 20:48:56 +10:00
|
|
|
|
public InputFieldRef InputField => ConsoleController.Input;
|
2021-05-11 19:15:46 +10:00
|
|
|
|
|
|
|
|
|
public bool AnchorToCaretPosition => true;
|
|
|
|
|
|
2021-05-15 01:41:03 +10:00
|
|
|
|
bool ISuggestionProvider.AllowNavigation => true;
|
|
|
|
|
|
2021-05-11 19:15:46 +10:00
|
|
|
|
public void OnSuggestionClicked(Suggestion suggestion)
|
|
|
|
|
{
|
2021-05-12 20:48:56 +10:00
|
|
|
|
ConsoleController.InsertSuggestionAtCaret(suggestion.UnderlyingValue);
|
|
|
|
|
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
2021-05-11 19:15:46 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
// Delimiters for completions, notably does not include '.'
|
2021-05-11 19:15:46 +10:00
|
|
|
|
private readonly HashSet<char> delimiters = new HashSet<char>
|
|
|
|
|
{
|
|
|
|
|
'{', '}', ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&', '?'
|
|
|
|
|
};
|
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
private readonly List<Suggestion> suggestions = new List<Suggestion>();
|
2021-05-11 19:15:46 +10:00
|
|
|
|
|
|
|
|
|
public void CheckAutocompletes()
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(InputField.Text))
|
|
|
|
|
{
|
|
|
|
|
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
suggestions.Clear();
|
|
|
|
|
|
2021-05-11 19:15:46 +10:00
|
|
|
|
int caret = Math.Max(0, Math.Min(InputField.Text.Length - 1, InputField.Component.caretPosition - 1));
|
2021-05-12 20:48:56 +10:00
|
|
|
|
int start = caret;
|
2021-05-11 19:15:46 +10:00
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
// If the character at the caret index is whitespace or delimiter,
|
|
|
|
|
// or if the next character (if it exists) is not whitespace,
|
|
|
|
|
// then we don't want to provide suggestions.
|
|
|
|
|
if (char.IsWhiteSpace(InputField.Text[caret])
|
|
|
|
|
|| delimiters.Contains(InputField.Text[caret])
|
|
|
|
|
|| (InputField.Text.Length > caret + 1 && !char.IsWhiteSpace(InputField.Text[caret + 1])))
|
2021-05-11 19:15:46 +10:00
|
|
|
|
{
|
2021-05-12 20:48:56 +10:00
|
|
|
|
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-15 01:21:07 +10:00
|
|
|
|
// get the current composition string (from caret back to last delimiter)
|
2021-05-12 20:48:56 +10:00
|
|
|
|
while (start > 0)
|
|
|
|
|
{
|
|
|
|
|
start--;
|
|
|
|
|
char c = InputField.Text[start];
|
2021-05-15 01:21:07 +10:00
|
|
|
|
if (delimiters.Contains(c))
|
2021-05-11 19:15:46 +10:00
|
|
|
|
{
|
2021-05-12 20:48:56 +10:00
|
|
|
|
start++;
|
2021-05-11 19:15:46 +10:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-12 20:48:56 +10:00
|
|
|
|
string input = InputField.Text.Substring(start, caret - start + 1);
|
|
|
|
|
|
|
|
|
|
// Get MCS completions
|
2021-05-11 19:15:46 +10:00
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
string[] evaluatorCompletions = ConsoleController.Evaluator.GetCompletions(input, out string prefix);
|
2021-05-15 01:21:07 +10:00
|
|
|
|
|
|
|
|
|
if (evaluatorCompletions != null && evaluatorCompletions.Any())
|
2021-05-12 20:48:56 +10:00
|
|
|
|
{
|
|
|
|
|
suggestions.AddRange(from completion in evaluatorCompletions
|
2021-05-15 01:21:07 +10:00
|
|
|
|
select new Suggestion(GetHighlightString(prefix, completion), completion));
|
2021-05-12 20:48:56 +10:00
|
|
|
|
}
|
2021-05-11 19:15:46 +10:00
|
|
|
|
|
2021-05-17 23:20:06 +10:00
|
|
|
|
// Get manual namespace completions
|
|
|
|
|
|
|
|
|
|
foreach (var ns in ReflectionUtility.AllNamespaces)
|
|
|
|
|
{
|
|
|
|
|
if (ns.StartsWith(input))
|
|
|
|
|
{
|
|
|
|
|
if (!namespaceHighlights.ContainsKey(ns))
|
|
|
|
|
namespaceHighlights.Add(ns, $"<color=#CCCCCC>{ns}</color>");
|
|
|
|
|
|
|
|
|
|
string completion = ns.Substring(input.Length, ns.Length - input.Length);
|
|
|
|
|
suggestions.Add(new Suggestion(namespaceHighlights[ns], completion));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
// Get manual keyword completions
|
2021-05-11 19:15:46 +10:00
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
foreach (var kw in KeywordLexer.keywords)
|
2021-05-11 19:15:46 +10:00
|
|
|
|
{
|
2021-05-17 23:20:06 +10:00
|
|
|
|
if (kw.StartsWith(input))// && kw.Length > input.Length)
|
2021-05-12 20:48:56 +10:00
|
|
|
|
{
|
2021-05-15 01:21:07 +10:00
|
|
|
|
if (!keywordHighlights.ContainsKey(kw))
|
|
|
|
|
keywordHighlights.Add(kw, $"<color=#{SignatureHighlighter.keywordBlueHex}>{kw}</color>");
|
|
|
|
|
|
2021-05-12 20:48:56 +10:00
|
|
|
|
string completion = kw.Substring(input.Length, kw.Length - input.Length);
|
2021-05-15 01:21:07 +10:00
|
|
|
|
suggestions.Add(new Suggestion(keywordHighlights[kw], completion));
|
2021-05-12 20:48:56 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (suggestions.Any())
|
|
|
|
|
{
|
2021-05-11 19:15:46 +10:00
|
|
|
|
AutoCompleteModal.Instance.TakeOwnership(this);
|
|
|
|
|
AutoCompleteModal.Instance.SetSuggestions(suggestions);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
AutoCompleteModal.Instance.ReleaseOwnership(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-15 01:21:07 +10:00
|
|
|
|
|
2021-05-17 23:20:06 +10:00
|
|
|
|
|
|
|
|
|
private readonly Dictionary<string, string> namespaceHighlights = new Dictionary<string, string>();
|
|
|
|
|
|
2021-05-15 01:21:07 +10:00
|
|
|
|
private readonly Dictionary<string, string> keywordHighlights = new Dictionary<string, string>();
|
|
|
|
|
|
|
|
|
|
private readonly StringBuilder highlightBuilder = new StringBuilder();
|
|
|
|
|
private const string OPEN_HIGHLIGHT = "<color=cyan>";
|
|
|
|
|
|
|
|
|
|
private string GetHighlightString(string prefix, string completion)
|
|
|
|
|
{
|
|
|
|
|
highlightBuilder.Clear();
|
|
|
|
|
highlightBuilder.Append(OPEN_HIGHLIGHT);
|
|
|
|
|
highlightBuilder.Append(prefix);
|
|
|
|
|
highlightBuilder.Append(SignatureHighlighter.CLOSE_COLOR);
|
|
|
|
|
highlightBuilder.Append(completion);
|
|
|
|
|
return highlightBuilder.ToString();
|
|
|
|
|
}
|
2021-05-11 19:15:46 +10:00
|
|
|
|
}
|
|
|
|
|
}
|