7
7
using System . Management . Automation ;
8
8
using System . Management . Automation . Language ;
9
9
using System . Text ;
10
+ using System . Threading ;
10
11
11
12
namespace PSConsoleUtilities
12
13
{
@@ -134,6 +135,8 @@ static KeyHandler MakeKeyHandler(Action<ConsoleKeyInfo?, object> action, string
134
135
private ConsoleColor _initialBackgroundColor ;
135
136
private ConsoleColor _initialForegroundColor ;
136
137
private CHAR_INFO _space ;
138
+ private readonly Queue < ConsoleKeyInfo > _queuedKeys ;
139
+ private DateTime _lastRenderTime ;
137
140
138
141
// History state
139
142
private HistoryQueue < HistoryItem > _history ;
@@ -184,7 +187,20 @@ public PSConsoleReadlineOptions Options
184
187
[ ExcludeFromCodeCoverage ]
185
188
private static ConsoleKeyInfo ReadKey ( )
186
189
{
187
- var key = Console . ReadKey ( true ) ;
190
+ var start = DateTime . Now ;
191
+ while ( Console . KeyAvailable )
192
+ {
193
+ _singleton . _queuedKeys . Enqueue ( Console . ReadKey ( true ) ) ;
194
+ if ( ( DateTime . Now - start ) . Milliseconds > 2 )
195
+ {
196
+ // Don't spend too long in this loop if there are lots of queued keys
197
+ break ;
198
+ }
199
+ }
200
+
201
+ var key = _singleton . _queuedKeys . Count > 0
202
+ ? _singleton . _queuedKeys . Dequeue ( )
203
+ : Console . ReadKey ( true ) ;
188
204
_singleton . _log . Key ( key . KeyChar , key . Key , key . Modifiers ) ;
189
205
return key ;
190
206
}
@@ -426,8 +442,9 @@ private PSConsoleReadLine()
426
442
_dispatchTable = new Dictionary < ConsoleKeyInfo , KeyHandler > ( _cmdKeyMap ) ;
427
443
_chordDispatchTable = new Dictionary < ConsoleKeyInfo , Dictionary < ConsoleKeyInfo , KeyHandler > > ( ) ;
428
444
429
- _buffer = new StringBuilder ( ) ;
445
+ _buffer = new StringBuilder ( 8 * 1024 ) ;
430
446
_savedCurrentLine = new HistoryItem ( ) ;
447
+ _queuedKeys = new Queue < ConsoleKeyInfo > ( ) ;
431
448
432
449
_pushedEditGroupCount = new Stack < int > ( ) ;
433
450
@@ -468,6 +485,7 @@ private void Initialize()
468
485
_tabCommandCount = 0 ;
469
486
470
487
_consoleBuffer = ReadBufferLines ( _initialY , 1 + Options . ExtraPromptLineCount ) ;
488
+ _lastRenderTime = DateTime . Now ;
471
489
}
472
490
473
491
private static void Chord ( ConsoleKeyInfo ? key = null , object arg = null )
@@ -1394,7 +1412,16 @@ private void MoveCursor(int offset)
1394
1412
public static void Insert ( char c )
1395
1413
{
1396
1414
_singleton . SaveEditItem ( EditItemInsertChar . Create ( c , _singleton . _current ) ) ;
1397
- _singleton . _buffer . Insert ( _singleton . _current , c ) ;
1415
+
1416
+ // Use Append if possible because Insert at end makes StringBuilder quite slow.
1417
+ if ( _singleton . _current == _singleton . _buffer . Length )
1418
+ {
1419
+ _singleton . _buffer . Append ( c ) ;
1420
+ }
1421
+ else
1422
+ {
1423
+ _singleton . _buffer . Insert ( _singleton . _current , c ) ;
1424
+ }
1398
1425
_singleton . _current += 1 ;
1399
1426
_singleton . Render ( ) ;
1400
1427
}
@@ -1406,7 +1433,16 @@ public static void Insert(char c)
1406
1433
public static void Insert ( string s )
1407
1434
{
1408
1435
_singleton . SaveEditItem ( EditItemInsertString . Create ( s , _singleton . _current ) ) ;
1409
- _singleton . _buffer . Insert ( _singleton . _current , s ) ;
1436
+
1437
+ // Use Append if possible because Insert at end makes StringBuilder quite slow.
1438
+ if ( _singleton . _current == _singleton . _buffer . Length )
1439
+ {
1440
+ _singleton . _buffer . Append ( s ) ;
1441
+ }
1442
+ else
1443
+ {
1444
+ _singleton . _buffer . Insert ( _singleton . _current , s ) ;
1445
+ }
1410
1446
_singleton . _current += s . Length ;
1411
1447
_singleton . Render ( ) ;
1412
1448
}
@@ -1650,8 +1686,12 @@ private string ParseInput()
1650
1686
1651
1687
private void Render ( )
1652
1688
{
1653
- // This function is not very effecient when pasting large chunks of text
1654
- // into the console.
1689
+ // If there are a bunch of keys queued up, skip rendering if we've rendered
1690
+ // recently.
1691
+ if ( _queuedKeys . Count > 10 && ( DateTime . Now - _lastRenderTime ) . Milliseconds < 50 )
1692
+ {
1693
+ return ;
1694
+ }
1655
1695
1656
1696
_renderForDemoNeeded = false ;
1657
1697
@@ -1805,6 +1845,8 @@ private void Render()
1805
1845
{
1806
1846
Console . WindowTop = _initialY + bufferLineCount + 1 - Console . WindowHeight ;
1807
1847
}
1848
+
1849
+ _lastRenderTime = DateTime . Now ;
1808
1850
}
1809
1851
1810
1852
private static void WriteBufferLines ( CHAR_INFO [ ] buffer , ref int top )
@@ -1968,16 +2010,18 @@ private COORD ConvertOffsetToCoordinates(int offset)
1968
2010
int y = _initialY + Options . ExtraPromptLineCount ;
1969
2011
1970
2012
int bufferWidth = Console . BufferWidth ;
2013
+ var continuationPromptLength = Options . ContinuationPrompt . Length ;
1971
2014
for ( int i = 0 ; i < offset ; i ++ )
1972
2015
{
1973
- if ( _buffer [ i ] == '\n ' )
2016
+ char c = _buffer [ i ] ;
2017
+ if ( c == '\n ' )
1974
2018
{
1975
2019
y += 1 ;
1976
- x = Options . ContinuationPrompt . Length ;
2020
+ x = continuationPromptLength ;
1977
2021
}
1978
2022
else
1979
2023
{
1980
- x += char . IsControl ( _buffer [ i ] ) ? 2 : 1 ;
2024
+ x += char . IsControl ( c ) ? 2 : 1 ;
1981
2025
// Wrap? No prompt when wrapping
1982
2026
if ( x >= bufferWidth )
1983
2027
{
0 commit comments