@@ -91,6 +91,12 @@ class KeyHandler
91
91
public string LongDescription ;
92
92
}
93
93
94
+ [ DebuggerDisplay ( "{_buffer}" ) ]
95
+ class HistoryItem
96
+ {
97
+ public StringBuilder _buffer ;
98
+ }
99
+
94
100
static KeyHandler MakeKeyHandler ( Action < ConsoleKeyInfo ? , object > action , string briefDescription , string longDescription = null )
95
101
{
96
102
return new KeyHandler
@@ -124,7 +130,8 @@ static KeyHandler MakeKeyHandler(Action<ConsoleKeyInfo?, object> action, string
124
130
private CHAR_INFO _space ;
125
131
126
132
// History state
127
- private HistoryQueue < string > _history ;
133
+ private HistoryQueue < HistoryItem > _history ;
134
+ private readonly HashSet < string > _hashedHistory ;
128
135
private int _currentHistoryIndex ;
129
136
private int _searchHistoryCommandCount ;
130
137
private string _searchHistoryPrefix ;
@@ -353,11 +360,11 @@ private string MaybeAddToHistory(string result)
353
360
// REVIEW: should history be case sensitive - it is now.
354
361
// A smart comparer could use the ast to ignore case on commands, parameters,
355
362
// operators and keywords while remaining case sensitive on command arguments.
356
- addToHistory = ! _history . Contains ( result ) ;
363
+ addToHistory = ! _hashedHistory . Contains ( result ) ;
357
364
}
358
365
if ( addToHistory )
359
366
{
360
- _history . Enqueue ( result ) ;
367
+ _history . Enqueue ( new HistoryItem { _buffer = new StringBuilder ( _buffer . ToString ( ) ) } ) ;
361
368
_currentHistoryIndex = _history . Count ;
362
369
}
363
370
if ( _demoMode )
@@ -367,6 +374,22 @@ private string MaybeAddToHistory(string result)
367
374
return result ;
368
375
}
369
376
377
+ private void HistoryOnEnqueueHandler ( HistoryItem obj )
378
+ {
379
+ if ( _historyNoDuplicates )
380
+ {
381
+ _hashedHistory . Add ( obj . _buffer . ToString ( ) ) ;
382
+ }
383
+ }
384
+
385
+ private void HistoryOnDequeueHandler ( HistoryItem obj )
386
+ {
387
+ if ( _historyNoDuplicates )
388
+ {
389
+ _hashedHistory . Remove ( obj . _buffer . ToString ( ) ) ;
390
+ }
391
+ }
392
+
370
393
static PSConsoleReadLine ( )
371
394
{
372
395
_cmdKeyMap = new Dictionary < ConsoleKeyInfo , KeyHandler > ( new ConsoleKeyInfoComparer ( ) )
@@ -478,9 +501,14 @@ private PSConsoleReadLine()
478
501
_addToHistoryHandler = null ;
479
502
_historyNoDuplicates = DefaultHistoryNoDuplicates ;
480
503
_maximumHistoryCount = DefaultMaximumHistoryCount ;
481
- _history = new HistoryQueue < string > ( _maximumHistoryCount ) ;
504
+ _history = new HistoryQueue < HistoryItem > ( _maximumHistoryCount )
505
+ {
506
+ OnDequeue = HistoryOnDequeueHandler ,
507
+ OnEnqueue = HistoryOnEnqueueHandler
508
+ } ;
482
509
_currentHistoryIndex = 0 ;
483
510
_historySearchCursorMovesToEnd = DefaultHistorySearchCursorMovesToEnd ;
511
+ _hashedHistory = new HashSet < string > ( ) ;
484
512
485
513
_maximumKillRingCount = DefaultMaximumKillRingCount ;
486
514
_killIndex = - 1 ; // So first add indexes 0.
@@ -822,13 +850,14 @@ public static void AddToHistory(string command)
822
850
public static void ClearHistory ( )
823
851
{
824
852
_singleton . _history . Clear ( ) ;
853
+ _singleton . _hashedHistory . Clear ( ) ;
825
854
_singleton . _currentHistoryIndex = 0 ;
826
855
}
827
856
828
857
private void UpdateFromHistory ( bool moveCursor )
829
858
{
830
859
_buffer . Clear ( ) ;
831
- _buffer . Append ( _history [ _currentHistoryIndex ] ) ;
860
+ _buffer . Append ( _history [ _currentHistoryIndex ] . _buffer ) ;
832
861
if ( moveCursor )
833
862
{
834
863
_current = _buffer . Length ;
@@ -871,7 +900,7 @@ private void HistorySearch(bool backward)
871
900
int incr = backward ? - 1 : + 1 ;
872
901
for ( int i = _currentHistoryIndex + incr ; i >= 0 && i < _history . Count ; i += incr )
873
902
{
874
- if ( _history [ i ] . StartsWith ( _searchHistoryPrefix ) )
903
+ if ( _history [ i ] . _buffer . ToString ( ) . StartsWith ( _searchHistoryPrefix ) )
875
904
{
876
905
_currentHistoryIndex = i ;
877
906
UpdateFromHistory ( moveCursor : _historySearchCursorMovesToEnd ) ;
@@ -1939,18 +1968,23 @@ private void SetOptionsInternal(SetPSReadlineOption options)
1939
1968
_historyNoDuplicates = options . HistoryNoDuplicates ;
1940
1969
if ( _historyNoDuplicates )
1941
1970
{
1942
- var historyItems = new HashSet < string > ( ) ;
1943
- var newHistory = new HistoryQueue < string > ( _maximumHistoryCount ) ;
1971
+ _hashedHistory . Clear ( ) ;
1972
+ _history . OnEnqueue = null ;
1973
+ _history . OnDequeue = null ;
1974
+ var newHistory = new HistoryQueue < HistoryItem > ( _maximumHistoryCount ) ;
1944
1975
while ( _history . Count > 0 )
1945
1976
{
1946
1977
var item = _history . Dequeue ( ) ;
1947
- if ( ! historyItems . Contains ( item ) )
1978
+ var itemStr = item . _buffer . ToString ( ) ;
1979
+ if ( ! _hashedHistory . Contains ( itemStr ) )
1948
1980
{
1949
1981
newHistory . Enqueue ( item ) ;
1950
- historyItems . Add ( item ) ;
1982
+ _hashedHistory . Add ( itemStr ) ;
1951
1983
}
1952
1984
}
1953
1985
_history = newHistory ;
1986
+ _history . OnEnqueue = HistoryOnEnqueueHandler ;
1987
+ _history . OnDequeue = HistoryOnDequeueHandler ;
1954
1988
_currentHistoryIndex = _history . Count ;
1955
1989
}
1956
1990
}
@@ -1965,16 +1999,20 @@ private void SetOptionsInternal(SetPSReadlineOption options)
1965
1999
if ( options . _maximumHistoryCount . HasValue )
1966
2000
{
1967
2001
_maximumHistoryCount = options . MaximumHistoryCount ;
1968
- var newHistory = new HistoryQueue < string > ( _maximumHistoryCount ) ;
2002
+ var newHistory = new HistoryQueue < HistoryItem > ( _maximumHistoryCount ) ;
1969
2003
while ( _history . Count > _maximumHistoryCount )
1970
2004
{
1971
2005
_history . Dequeue ( ) ;
1972
2006
}
2007
+ _history . OnEnqueue = null ;
2008
+ _history . OnDequeue = null ;
1973
2009
while ( _history . Count > 0 )
1974
2010
{
1975
2011
newHistory . Enqueue ( _history . Dequeue ( ) ) ;
1976
2012
}
1977
2013
_history = newHistory ;
2014
+ _history . OnEnqueue = HistoryOnEnqueueHandler ;
2015
+ _history . OnDequeue = HistoryOnDequeueHandler ;
1978
2016
_currentHistoryIndex = _history . Count ;
1979
2017
}
1980
2018
if ( options . _maximumKillRingCount . HasValue )
0 commit comments