@@ -23,28 +23,33 @@ namespace UnityExplorer.CSConsole
23
23
{
24
24
public static class ConsoleController
25
25
{
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 ; }
36
29
30
+ public static bool SRENotSupported { get ; private set ; }
37
31
public static int LastCaretPosition { get ; private set ; }
38
- internal static float defaultInputFieldAlpha ;
32
+ public static float DefaultInputFieldAlpha { get ; set ; }
39
33
40
- // Todo save as config?
41
34
public static bool EnableCtrlRShortcut { get ; private set ; } = true ;
42
35
public static bool EnableAutoIndent { get ; private set ; } = true ;
43
36
public static bool EnableSuggestions { get ; private set ; } = true ;
44
37
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" ) ;
46
42
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 [ ]
48
53
{
49
54
"System" ,
50
55
"System.Linq" ,
@@ -59,9 +64,10 @@ public static class ConsoleController
59
64
#endif
60
65
} ;
61
66
67
+ const int CSCONSOLE_LINEHEIGHT = 18 ;
68
+
62
69
public static void Init ( )
63
70
{
64
- // Make sure console is supported on this platform
65
71
try
66
72
{
67
73
ResetConsole ( false ) ;
@@ -111,31 +117,10 @@ public static void Init()
111
117
}
112
118
}
113
119
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
-
135
120
136
121
#region Evaluating
137
122
138
- private static void GenerateTextWriter ( )
123
+ static void GenerateTextWriter ( )
139
124
{
140
125
evaluatorOutput = new StringBuilder ( ) ;
141
126
evaluatorStringWriter = new StringWriter ( evaluatorOutput ) ;
@@ -247,16 +232,45 @@ public static void Evaluate(string input, bool supressLog = false)
247
232
#endregion
248
233
249
234
250
- // Updating and event listeners
235
+ #region Update loop and event listeners
251
236
252
- private static bool settingCaretCoroutine ;
237
+ public static void Update ( )
238
+ {
239
+ if ( SRENotSupported )
240
+ return ;
253
241
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 ) ;
255
248
256
- private static string previousInput ;
249
+ if ( ! settingCaretCoroutine && EnableSuggestions )
250
+ {
251
+ if ( AutoCompleteModal . CheckEscape ( Completer ) )
252
+ {
253
+ OnAutocompleteEscaped ( ) ;
254
+ return ;
255
+ }
257
256
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 )
260
274
{
261
275
if ( SRENotSupported )
262
276
return ;
@@ -283,7 +297,7 @@ private static void OnInputChanged(string value)
283
297
DoAutoIndent ( ) ;
284
298
}
285
299
286
- bool inStringOrComment = HighlightVisibleInput ( ) ;
300
+ HighlightVisibleInput ( out bool inStringOrComment ) ;
287
301
288
302
if ( ! settingCaretCoroutine )
289
303
{
@@ -299,40 +313,27 @@ private static void OnInputChanged(string value)
299
313
UpdateCaret ( out _ ) ;
300
314
}
301
315
302
- private static float timeOfLastCtrlR ;
303
-
304
- public static void Update ( )
316
+ static void OnToggleAutoIndent ( bool value )
305
317
{
306
- if ( SRENotSupported )
307
- return ;
318
+ EnableAutoIndent = value ;
319
+ }
308
320
309
- UpdateCaret ( out bool caretMoved ) ;
321
+ static void OnToggleCtrlRShortcut ( bool value )
322
+ {
323
+ EnableCtrlRShortcut = value ;
324
+ }
310
325
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
+ }
318
330
319
- if ( caretMoved )
320
- AutoCompleteModal . Instance . ReleaseOwnership ( Completer ) ;
321
- }
331
+ #endregion
322
332
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
- }
332
333
333
- private const int CSCONSOLE_LINEHEIGHT = 18 ;
334
+ #region Caret position
334
335
335
- private static void UpdateCaret ( out bool caretMoved )
336
+ static void UpdateCaret ( out bool caretMoved )
336
337
{
337
338
int prevCaret = LastCaretPosition ;
338
339
caretMoved = false ;
@@ -377,14 +378,18 @@ private static void UpdateCaret(out bool caretMoved)
377
378
}
378
379
}
379
380
380
- private static void SetCaretPosition ( int caretPosition )
381
+ public static void SetCaretPosition ( int caretPosition )
381
382
{
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.
382
387
settingCaretCoroutine = true ;
383
388
Input . Component . readOnly = true ;
384
- RuntimeHelper . StartCoroutine ( SetCaretCoroutine ( caretPosition ) ) ;
389
+ RuntimeHelper . StartCoroutine ( DoSetCaretCoroutine ( caretPosition ) ) ;
385
390
}
386
391
387
- private static IEnumerator SetCaretCoroutine ( int caretPosition )
392
+ static IEnumerator DoSetCaretCoroutine ( int caretPosition )
388
393
{
389
394
Color color = Input . Component . selectionColor ;
390
395
color . a = 0f ;
@@ -399,25 +404,71 @@ private static IEnumerator SetCaretCoroutine(int caretPosition)
399
404
Input . Component . selectionFocusPosition = caretPosition ;
400
405
LastCaretPosition = Input . Component . caretPosition ;
401
406
402
- color . a = defaultInputFieldAlpha ;
407
+ color . a = DefaultInputFieldAlpha ;
403
408
Input . Component . selectionColor = color ;
404
409
405
410
Input . Component . readOnly = false ;
406
411
settingCaretCoroutine = false ;
407
412
}
408
413
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
+
409
459
#region Lexer Highlighting
410
460
411
461
/// <summary>
412
462
/// Returns true if caret is inside string or comment, false otherwise
413
463
/// </summary>
414
- private static bool HighlightVisibleInput ( )
464
+ private static void HighlightVisibleInput ( out bool inStringOrComment )
415
465
{
466
+ inStringOrComment = false ;
416
467
if ( string . IsNullOrEmpty ( Input . Text ) )
417
468
{
418
469
Panel . HighlightText . text = "" ;
419
470
Panel . LineNumberText . text = "1" ;
420
- return false ;
471
+ return ;
421
472
}
422
473
423
474
// Calculate the visible lines
@@ -452,7 +503,7 @@ private static bool HighlightVisibleInput()
452
503
453
504
// Highlight the visible text with the LexerBuilder
454
505
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 ) ;
456
507
457
508
// Set the line numbers
458
509
@@ -490,7 +541,7 @@ private static bool HighlightVisibleInput()
490
541
491
542
Panel . LineNumberText . text = sb . ToString ( ) ;
492
543
493
- return ret ;
544
+ return ;
494
545
}
495
546
496
547
#endregion
@@ -530,13 +581,11 @@ private static void OnAutocompleteEscaped()
530
581
531
582
#region Auto indenting
532
583
533
- private static int prevContentLen = 0 ;
534
-
535
584
private static void DoAutoIndent ( )
536
585
{
537
- if ( Input . Text . Length > prevContentLen )
586
+ if ( Input . Text . Length > previousContentLength )
538
587
{
539
- int inc = Input . Text . Length - prevContentLen ;
588
+ int inc = Input . Text . Length - previousContentLength ;
540
589
541
590
if ( inc == 1 )
542
591
{
@@ -555,16 +604,14 @@ private static void DoAutoIndent()
555
604
}
556
605
}
557
606
558
- prevContentLen = Input . Text . Length ;
607
+ previousContentLength = Input . Text . Length ;
559
608
}
560
609
561
610
#endregion
562
611
563
612
564
613
#region "Help" interaction
565
614
566
- private static bool SRENotSupported ;
567
-
568
615
private static void DisableConsole ( Exception ex )
569
616
{
570
617
SRENotSupported = true ;
0 commit comments