Skip to content
This repository was archived by the owner on May 9, 2023. It is now read-only.

Commit aef4e11

Browse files
committed
C# Console: Implement Home and End keys
1 parent af7e32e commit aef4e11

File tree

2 files changed

+134
-87
lines changed

2 files changed

+134
-87
lines changed

src/CSConsole/ConsoleController.cs

Lines changed: 133 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,33 @@ namespace UnityExplorer.CSConsole
2323
{
2424
public static class ConsoleController
2525
{
26-
public static ScriptEvaluator Evaluator;
27-
public static LexerBuilder Lexer;
28-
public static CSAutoCompleter Completer;
29-
30-
private static HashSet<string> usingDirectives;
31-
private static StringBuilder evaluatorOutput;
32-
private static StringWriter evaluatorStringWriter;
33-
34-
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
35-
public static InputFieldRef Input => Panel.Input;
26+
public static ScriptEvaluator Evaluator { get; private set; }
27+
public static LexerBuilder Lexer { get; private set; }
28+
public static CSAutoCompleter Completer { get; private set; }
3629

30+
public static bool SRENotSupported { get; private set; }
3731
public static int LastCaretPosition { get; private set; }
38-
internal static float defaultInputFieldAlpha;
32+
public static float DefaultInputFieldAlpha { get; set; }
3933

40-
// Todo save as config?
4134
public static bool EnableCtrlRShortcut { get; private set; } = true;
4235
public static bool EnableAutoIndent { get; private set; } = true;
4336
public static bool EnableSuggestions { get; private set; } = true;
4437

45-
internal static string ScriptsFolder => Path.Combine(ExplorerCore.ExplorerFolder, "Scripts");
38+
public static CSConsolePanel Panel => UIManager.GetPanel<CSConsolePanel>(UIManager.Panels.CSConsole);
39+
public static InputFieldRef Input => Panel.Input;
40+
41+
public static string ScriptsFolder => Path.Combine(ExplorerCore.ExplorerFolder, "Scripts");
4642

47-
internal static readonly string[] DefaultUsing = new string[]
43+
static HashSet<string> usingDirectives;
44+
static StringBuilder evaluatorOutput;
45+
static StringWriter evaluatorStringWriter;
46+
static float timeOfLastCtrlR;
47+
48+
static bool settingCaretCoroutine;
49+
static string previousInput;
50+
static int previousContentLength = 0;
51+
52+
static readonly string[] DefaultUsing = new string[]
4853
{
4954
"System",
5055
"System.Linq",
@@ -59,9 +64,10 @@ public static class ConsoleController
5964
#endif
6065
};
6166

67+
const int CSCONSOLE_LINEHEIGHT = 18;
68+
6269
public static void Init()
6370
{
64-
// Make sure console is supported on this platform
6571
try
6672
{
6773
ResetConsole(false);
@@ -111,31 +117,10 @@ public static void Init()
111117
}
112118
}
113119

114-
#region UI Listeners and options
115-
116-
// TODO save
117-
118-
private static void OnToggleAutoIndent(bool value)
119-
{
120-
EnableAutoIndent = value;
121-
}
122-
123-
private static void OnToggleCtrlRShortcut(bool value)
124-
{
125-
EnableCtrlRShortcut = value;
126-
}
127-
128-
private static void OnToggleSuggestions(bool value)
129-
{
130-
EnableSuggestions = value;
131-
}
132-
133-
#endregion
134-
135120

136121
#region Evaluating
137122

138-
private static void GenerateTextWriter()
123+
static void GenerateTextWriter()
139124
{
140125
evaluatorOutput = new StringBuilder();
141126
evaluatorStringWriter = new StringWriter(evaluatorOutput);
@@ -247,16 +232,45 @@ public static void Evaluate(string input, bool supressLog = false)
247232
#endregion
248233

249234

250-
// Updating and event listeners
235+
#region Update loop and event listeners
251236

252-
private static bool settingCaretCoroutine;
237+
public static void Update()
238+
{
239+
if (SRENotSupported)
240+
return;
253241

254-
private static void OnInputScrolled() => HighlightVisibleInput();
242+
if (InputManager.GetKeyDown(KeyCode.Home))
243+
JumpToStartOrEndOfLine(true);
244+
else if (InputManager.GetKeyDown(KeyCode.End))
245+
JumpToStartOrEndOfLine(false);
246+
247+
UpdateCaret(out bool caretMoved);
255248

256-
private static string previousInput;
249+
if (!settingCaretCoroutine && EnableSuggestions)
250+
{
251+
if (AutoCompleteModal.CheckEscape(Completer))
252+
{
253+
OnAutocompleteEscaped();
254+
return;
255+
}
257256

258-
// Invoked at most once per frame
259-
private static void OnInputChanged(string value)
257+
if (caretMoved)
258+
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
259+
}
260+
261+
if (EnableCtrlRShortcut
262+
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
263+
&& InputManager.GetKeyDown(KeyCode.R)
264+
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
265+
{
266+
timeOfLastCtrlR = Time.realtimeSinceStartup;
267+
Evaluate(Panel.Input.Text);
268+
}
269+
}
270+
271+
static void OnInputScrolled() => HighlightVisibleInput(out _);
272+
273+
static void OnInputChanged(string value)
260274
{
261275
if (SRENotSupported)
262276
return;
@@ -283,7 +297,7 @@ private static void OnInputChanged(string value)
283297
DoAutoIndent();
284298
}
285299

286-
bool inStringOrComment = HighlightVisibleInput();
300+
HighlightVisibleInput(out bool inStringOrComment);
287301

288302
if (!settingCaretCoroutine)
289303
{
@@ -299,40 +313,27 @@ private static void OnInputChanged(string value)
299313
UpdateCaret(out _);
300314
}
301315

302-
private static float timeOfLastCtrlR;
303-
304-
public static void Update()
316+
static void OnToggleAutoIndent(bool value)
305317
{
306-
if (SRENotSupported)
307-
return;
318+
EnableAutoIndent = value;
319+
}
308320

309-
UpdateCaret(out bool caretMoved);
321+
static void OnToggleCtrlRShortcut(bool value)
322+
{
323+
EnableCtrlRShortcut = value;
324+
}
310325

311-
if (!settingCaretCoroutine && EnableSuggestions)
312-
{
313-
if (AutoCompleteModal.CheckEscape(Completer))
314-
{
315-
OnAutocompleteEscaped();
316-
return;
317-
}
326+
static void OnToggleSuggestions(bool value)
327+
{
328+
EnableSuggestions = value;
329+
}
318330

319-
if (caretMoved)
320-
AutoCompleteModal.Instance.ReleaseOwnership(Completer);
321-
}
331+
#endregion
322332

323-
if (EnableCtrlRShortcut
324-
&& (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.RightControl))
325-
&& InputManager.GetKeyDown(KeyCode.R)
326-
&& timeOfLastCtrlR.OccuredEarlierThanDefault())
327-
{
328-
timeOfLastCtrlR = Time.realtimeSinceStartup;
329-
Evaluate(Panel.Input.Text);
330-
}
331-
}
332333

333-
private const int CSCONSOLE_LINEHEIGHT = 18;
334+
#region Caret position
334335

335-
private static void UpdateCaret(out bool caretMoved)
336+
static void UpdateCaret(out bool caretMoved)
336337
{
337338
int prevCaret = LastCaretPosition;
338339
caretMoved = false;
@@ -377,14 +378,18 @@ private static void UpdateCaret(out bool caretMoved)
377378
}
378379
}
379380

380-
private static void SetCaretPosition(int caretPosition)
381+
public static void SetCaretPosition(int caretPosition)
381382
{
383+
Input.Component.caretPosition = caretPosition;
384+
385+
// Fix to make sure we always really set the caret position.
386+
// Yields a frame and fixes text-selection issues.
382387
settingCaretCoroutine = true;
383388
Input.Component.readOnly = true;
384-
RuntimeHelper.StartCoroutine(SetCaretCoroutine(caretPosition));
389+
RuntimeHelper.StartCoroutine(DoSetCaretCoroutine(caretPosition));
385390
}
386391

387-
private static IEnumerator SetCaretCoroutine(int caretPosition)
392+
static IEnumerator DoSetCaretCoroutine(int caretPosition)
388393
{
389394
Color color = Input.Component.selectionColor;
390395
color.a = 0f;
@@ -399,25 +404,71 @@ private static IEnumerator SetCaretCoroutine(int caretPosition)
399404
Input.Component.selectionFocusPosition = caretPosition;
400405
LastCaretPosition = Input.Component.caretPosition;
401406

402-
color.a = defaultInputFieldAlpha;
407+
color.a = DefaultInputFieldAlpha;
403408
Input.Component.selectionColor = color;
404409

405410
Input.Component.readOnly = false;
406411
settingCaretCoroutine = false;
407412
}
408413

414+
// For Home and End keys
415+
static void JumpToStartOrEndOfLine(bool toStart)
416+
{
417+
// Determine the current and next line
418+
UILineInfo thisline = default;
419+
UILineInfo nextLine = default;
420+
for (int i = 0; i < Input.Component.cachedInputTextGenerator.lineCount; i++)
421+
{
422+
UILineInfo line = Input.Component.cachedInputTextGenerator.lines[i];
423+
424+
if (line.startCharIdx > LastCaretPosition)
425+
{
426+
nextLine = line;
427+
break;
428+
}
429+
thisline = line;
430+
}
431+
432+
if (toStart)
433+
{
434+
// Determine where the non-whitespace text begins
435+
int nonWhitespaceStartIdx = thisline.startCharIdx;
436+
while (char.IsWhiteSpace(Input.Text[nonWhitespaceStartIdx]))
437+
nonWhitespaceStartIdx++;
438+
439+
// Jump to either the true start or the non-whitespace position,
440+
// depending on which one we are not at.
441+
if (LastCaretPosition == nonWhitespaceStartIdx)
442+
SetCaretPosition(thisline.startCharIdx);
443+
else // jump to the next line start index - 1, ie. end of this line
444+
SetCaretPosition(nonWhitespaceStartIdx);
445+
}
446+
else
447+
{
448+
// If there is no next line, jump to the end of this line (+1, to the invisible next character position)
449+
if (nextLine.startCharIdx <= 0)
450+
SetCaretPosition(Input.Text.Length);
451+
else
452+
SetCaretPosition(nextLine.startCharIdx - 1);
453+
}
454+
}
455+
456+
#endregion
457+
458+
409459
#region Lexer Highlighting
410460

411461
/// <summary>
412462
/// Returns true if caret is inside string or comment, false otherwise
413463
/// </summary>
414-
private static bool HighlightVisibleInput()
464+
private static void HighlightVisibleInput(out bool inStringOrComment)
415465
{
466+
inStringOrComment = false;
416467
if (string.IsNullOrEmpty(Input.Text))
417468
{
418469
Panel.HighlightText.text = "";
419470
Panel.LineNumberText.text = "1";
420-
return false;
471+
return;
421472
}
422473

423474
// Calculate the visible lines
@@ -452,7 +503,7 @@ private static bool HighlightVisibleInput()
452503

453504
// Highlight the visible text with the LexerBuilder
454505

455-
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out bool ret);
506+
Panel.HighlightText.text = Lexer.BuildHighlightedString(Input.Text, startIdx, endIdx, topLine, LastCaretPosition, out inStringOrComment);
456507

457508
// Set the line numbers
458509

@@ -490,7 +541,7 @@ private static bool HighlightVisibleInput()
490541

491542
Panel.LineNumberText.text = sb.ToString();
492543

493-
return ret;
544+
return;
494545
}
495546

496547
#endregion
@@ -530,13 +581,11 @@ private static void OnAutocompleteEscaped()
530581

531582
#region Auto indenting
532583

533-
private static int prevContentLen = 0;
534-
535584
private static void DoAutoIndent()
536585
{
537-
if (Input.Text.Length > prevContentLen)
586+
if (Input.Text.Length > previousContentLength)
538587
{
539-
int inc = Input.Text.Length - prevContentLen;
588+
int inc = Input.Text.Length - previousContentLength;
540589

541590
if (inc == 1)
542591
{
@@ -555,16 +604,14 @@ private static void DoAutoIndent()
555604
}
556605
}
557606

558-
prevContentLen = Input.Text.Length;
607+
previousContentLength = Input.Text.Length;
559608
}
560609

561610
#endregion
562611

563612

564613
#region "Help" interaction
565614

566-
private static bool SRENotSupported;
567-
568615
private static void DisableConsole(Exception ex)
569616
{
570617
SRENotSupported = true;

src/UI/Panels/CSConsolePanel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ protected override void ConstructPanelContent()
145145
GameObject inputObj = UIFactory.CreateScrollInputField(inputArea, "ConsoleInput", ConsoleController.STARTUP_TEXT,
146146
out InputFieldScroller inputScroller, fontSize);
147147
InputScroller = inputScroller;
148-
ConsoleController.defaultInputFieldAlpha = Input.Component.selectionColor.a;
148+
ConsoleController.DefaultInputFieldAlpha = Input.Component.selectionColor.a;
149149
Input.OnValueChanged += InvokeOnValueChanged;
150150

151151
// move line number text with input field

0 commit comments

Comments
 (0)