@@ -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 ;
0 commit comments