Skip to content

Commit c9f044e

Browse files
committed
Lay some groundwork to support undo
1 parent 4b396ff commit c9f044e

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

PSReadLine/HistoryQueue.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ public bool Contains(T item)
5454

5555
public int Count { get; private set; }
5656

57+
public Action<T> OnDequeue { get; set; }
58+
public Action<T> OnEnqueue { get; set; }
59+
5760
public int IndexOf(T item)
5861
{
5962
// REVIEW: should we use case insensitive here?
@@ -78,6 +81,11 @@ public void Enqueue(T item)
7881
_array[_tail] = item;
7982
_tail = (_tail + 1) % _array.Length;
8083
Count += 1;
84+
85+
if (OnEnqueue != null)
86+
{
87+
OnEnqueue(item);
88+
}
8189
}
8290

8391
public T Dequeue()
@@ -88,6 +96,10 @@ public T Dequeue()
8896
_array[_head] = default(T);
8997
_head = (_head + 1) % _array.Length;
9098
Count -= 1;
99+
if (OnDequeue != null)
100+
{
101+
OnDequeue(obj);
102+
}
91103
return obj;
92104
}
93105

PSReadLine/ReadLine.cs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ class KeyHandler
9191
public string LongDescription;
9292
}
9393

94+
[DebuggerDisplay("{_buffer}")]
95+
class HistoryItem
96+
{
97+
public StringBuilder _buffer;
98+
}
99+
94100
static KeyHandler MakeKeyHandler(Action<ConsoleKeyInfo?, object> action, string briefDescription, string longDescription = null)
95101
{
96102
return new KeyHandler
@@ -124,7 +130,8 @@ static KeyHandler MakeKeyHandler(Action<ConsoleKeyInfo?, object> action, string
124130
private CHAR_INFO _space;
125131

126132
// History state
127-
private HistoryQueue<string> _history;
133+
private HistoryQueue<HistoryItem> _history;
134+
private readonly HashSet<string> _hashedHistory;
128135
private int _currentHistoryIndex;
129136
private int _searchHistoryCommandCount;
130137
private string _searchHistoryPrefix;
@@ -353,11 +360,11 @@ private string MaybeAddToHistory(string result)
353360
// REVIEW: should history be case sensitive - it is now.
354361
// A smart comparer could use the ast to ignore case on commands, parameters,
355362
// operators and keywords while remaining case sensitive on command arguments.
356-
addToHistory = !_history.Contains(result);
363+
addToHistory = !_hashedHistory.Contains(result);
357364
}
358365
if (addToHistory)
359366
{
360-
_history.Enqueue(result);
367+
_history.Enqueue(new HistoryItem { _buffer = new StringBuilder(_buffer.ToString()) });
361368
_currentHistoryIndex = _history.Count;
362369
}
363370
if (_demoMode)
@@ -367,6 +374,22 @@ private string MaybeAddToHistory(string result)
367374
return result;
368375
}
369376

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+
370393
static PSConsoleReadLine()
371394
{
372395
_cmdKeyMap = new Dictionary<ConsoleKeyInfo, KeyHandler>(new ConsoleKeyInfoComparer())
@@ -478,9 +501,14 @@ private PSConsoleReadLine()
478501
_addToHistoryHandler = null;
479502
_historyNoDuplicates = DefaultHistoryNoDuplicates;
480503
_maximumHistoryCount = DefaultMaximumHistoryCount;
481-
_history = new HistoryQueue<string>(_maximumHistoryCount);
504+
_history = new HistoryQueue<HistoryItem>(_maximumHistoryCount)
505+
{
506+
OnDequeue = HistoryOnDequeueHandler,
507+
OnEnqueue = HistoryOnEnqueueHandler
508+
};
482509
_currentHistoryIndex = 0;
483510
_historySearchCursorMovesToEnd = DefaultHistorySearchCursorMovesToEnd;
511+
_hashedHistory = new HashSet<string>();
484512

485513
_maximumKillRingCount = DefaultMaximumKillRingCount;
486514
_killIndex = -1; // So first add indexes 0.
@@ -822,13 +850,14 @@ public static void AddToHistory(string command)
822850
public static void ClearHistory()
823851
{
824852
_singleton._history.Clear();
853+
_singleton._hashedHistory.Clear();
825854
_singleton._currentHistoryIndex = 0;
826855
}
827856

828857
private void UpdateFromHistory(bool moveCursor)
829858
{
830859
_buffer.Clear();
831-
_buffer.Append(_history[_currentHistoryIndex]);
860+
_buffer.Append(_history[_currentHistoryIndex]._buffer);
832861
if (moveCursor)
833862
{
834863
_current = _buffer.Length;
@@ -871,7 +900,7 @@ private void HistorySearch(bool backward)
871900
int incr = backward ? -1 : +1;
872901
for (int i = _currentHistoryIndex + incr; i >=0 && i < _history.Count; i += incr)
873902
{
874-
if (_history[i].StartsWith(_searchHistoryPrefix))
903+
if (_history[i]._buffer.ToString().StartsWith(_searchHistoryPrefix))
875904
{
876905
_currentHistoryIndex = i;
877906
UpdateFromHistory(moveCursor: _historySearchCursorMovesToEnd);
@@ -1939,18 +1968,23 @@ private void SetOptionsInternal(SetPSReadlineOption options)
19391968
_historyNoDuplicates = options.HistoryNoDuplicates;
19401969
if (_historyNoDuplicates)
19411970
{
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);
19441975
while (_history.Count > 0)
19451976
{
19461977
var item = _history.Dequeue();
1947-
if (!historyItems.Contains(item))
1978+
var itemStr = item._buffer.ToString();
1979+
if (!_hashedHistory.Contains(itemStr))
19481980
{
19491981
newHistory.Enqueue(item);
1950-
historyItems.Add(item);
1982+
_hashedHistory.Add(itemStr);
19511983
}
19521984
}
19531985
_history = newHistory;
1986+
_history.OnEnqueue = HistoryOnEnqueueHandler;
1987+
_history.OnDequeue = HistoryOnDequeueHandler;
19541988
_currentHistoryIndex = _history.Count;
19551989
}
19561990
}
@@ -1965,16 +1999,20 @@ private void SetOptionsInternal(SetPSReadlineOption options)
19651999
if (options._maximumHistoryCount.HasValue)
19662000
{
19672001
_maximumHistoryCount = options.MaximumHistoryCount;
1968-
var newHistory = new HistoryQueue<string>(_maximumHistoryCount);
2002+
var newHistory = new HistoryQueue<HistoryItem>(_maximumHistoryCount);
19692003
while (_history.Count > _maximumHistoryCount)
19702004
{
19712005
_history.Dequeue();
19722006
}
2007+
_history.OnEnqueue = null;
2008+
_history.OnDequeue = null;
19732009
while (_history.Count > 0)
19742010
{
19752011
newHistory.Enqueue(_history.Dequeue());
19762012
}
19772013
_history = newHistory;
2014+
_history.OnEnqueue = HistoryOnEnqueueHandler;
2015+
_history.OnDequeue = HistoryOnDequeueHandler;
19782016
_currentHistoryIndex = _history.Count;
19792017
}
19802018
if (options._maximumKillRingCount.HasValue)

0 commit comments

Comments
 (0)