Skip to content

Commit

Permalink
History recall should ignore other sesions
Browse files Browse the repository at this point in the history
When using UpArrow, people prefer not recalling commands
from other currently running sessions.

It's still useful to avoid entering commands that have
might have been entered in another currently running session,
so those commands can still be found when *searching*
history, either interactively, or if the search string
is not empty when using HistorySearch[Backward|Forward].

Also fixed in this change - an obscure bug where
HistoryNoDuplicates did not work well with a DigitArgument
when recalling history.

Fixes #179
  • Loading branch information
lzybkr committed Jan 21, 2015
1 parent e2311b0 commit 49a4c4c
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 34 deletions.
2 changes: 2 additions & 0 deletions PSReadLine/Changes.txt
Expand Up @@ -17,6 +17,8 @@ Bug fixes:
* Fix exception on error input during rendering after certain keywords like process, begin, or end.
* Fix exception after undo from menu completion
* Support CancelLine (Ctrl+C) and Abort (Ctrl+G in emacs) to cancel DigitArgument
* History recall now ignores command lines from other currently running sessions, but you can
still find command lines from those sessions when searching history.

New functions:
* ValidateAndAcceptLine
Expand Down
100 changes: 67 additions & 33 deletions PSReadLine/History.cs
Expand Up @@ -17,6 +17,7 @@ class HistoryItem
public List<EditItem> _edits;
public int _undoEditIndex;
public bool _saved;
public bool _fromDifferentLiveSession;
}

// History state
Expand All @@ -39,7 +40,7 @@ class HistoryItem
private const string _failedForwardISearchPrompt = "failed-fwd-i-search: ";
private const string _failedBackwardISearchPrompt = "failed-bck-i-search: ";

private string MaybeAddToHistory(string result, List<EditItem> edits, int undoEditIndex, bool readingHistoryFile)
private string MaybeAddToHistory(string result, List<EditItem> edits, int undoEditIndex, bool readingHistoryFile, bool fromDifferentSession)
{
bool addToHistory = !string.IsNullOrWhiteSpace(result) && ((Options.AddToHistoryHandler == null) || Options.AddToHistoryHandler(result));
if (addToHistory)
Expand All @@ -50,6 +51,7 @@ private string MaybeAddToHistory(string result, List<EditItem> edits, int undoEd
_edits = edits,
_undoEditIndex = undoEditIndex,
_saved = readingHistoryFile,
_fromDifferentLiveSession = fromDifferentSession,
});
_currentHistoryIndex = _history.Count;

Expand Down Expand Up @@ -168,7 +170,7 @@ private void MaybeReadHistoryFile()
historyLines.Add(sr.ReadLine());
}
}
UpdateHistoryFromFile(historyLines);
UpdateHistoryFromFile(historyLines, fromDifferentSession: true);

_historyFileLastSavedSize = fileInfo.Length;
}
Expand Down Expand Up @@ -197,7 +199,7 @@ private void ReadHistoryFile()
}

var historyLines = File.ReadAllLines(Options.HistorySavePath);
UpdateHistoryFromFile(historyLines);
UpdateHistoryFromFile(historyLines, fromDifferentSession: false);
var fileInfo = new FileInfo(Options.HistorySavePath);
_historyFileLastSavedSize = fileInfo.Length;
}
Expand All @@ -208,7 +210,7 @@ private void ReadHistoryFile()
}
}

void UpdateHistoryFromFile(IEnumerable<string> historyLines)
void UpdateHistoryFromFile(IEnumerable<string> historyLines, bool fromDifferentSession)
{
var sb = new StringBuilder();
foreach (var line in historyLines)
Expand All @@ -223,13 +225,13 @@ void UpdateHistoryFromFile(IEnumerable<string> historyLines)
sb.Append(line);
var l = sb.ToString();
var editItems = new List<EditItem> {EditItemInsertString.Create(l, 0)};
MaybeAddToHistory(l, editItems, 1, readingHistoryFile: true);
MaybeAddToHistory(l, editItems, 1, /*readingHistoryFile*/ true, fromDifferentSession);
sb.Clear();
}
else
{
var editItems = new List<EditItem> {EditItemInsertString.Create(line, 0)};
MaybeAddToHistory(line, editItems, 1, readingHistoryFile: true);
MaybeAddToHistory(line, editItems, 1, /*readingHistoryFile*/ true, fromDifferentSession);
}
}
}
Expand All @@ -242,7 +244,7 @@ public static void AddToHistory(string command)
{
command = command.Replace("\r\n", "\n");
var editItems = new List<EditItem> {EditItemInsertString.Create(command, 0)};
_singleton.MaybeAddToHistory(command, editItems, 1, readingHistoryFile: false);
_singleton.MaybeAddToHistory(command, editItems, 1, readingHistoryFile: false, fromDifferentSession: false);
}

/// <summary>
Expand Down Expand Up @@ -307,38 +309,45 @@ private void HistoryRecall(int direction)
return;
}

int newHistoryIndex;
if (Options.HistoryNoDuplicates)
if (Options.HistoryNoDuplicates && _recallHistoryCommandCount == 0)
{
_hashedHistory = new Dictionary<string, int>();
}

int count = Math.Abs(direction);
direction = direction < 0 ? -1 : +1;
int newHistoryIndex = _currentHistoryIndex;
while (count > 0)
{
if (_recallHistoryCommandCount == 0)
newHistoryIndex += direction;
if (newHistoryIndex < 0 || newHistoryIndex >= _history.Count)
{
_hashedHistory = new Dictionary<string, int>();
break;
}

newHistoryIndex = _currentHistoryIndex;
while (true)
if (_history[newHistoryIndex]._fromDifferentLiveSession)
{
continue;
}

if (Options.HistoryNoDuplicates)
{
newHistoryIndex = newHistoryIndex + direction;
if (newHistoryIndex < 0 || newHistoryIndex >= _history.Count)
{
break;
}
var line = _history[newHistoryIndex]._line;
int index;
if (!_hashedHistory.TryGetValue(line, out index))
{
_hashedHistory.Add(line, newHistoryIndex);
break;
--count;
}
if (index == newHistoryIndex)
else if (newHistoryIndex == index)
{
break;
--count;
}
}
}
else
{
newHistoryIndex = _currentHistoryIndex + direction;
else
{
--count;
}
}
_recallHistoryCommandCount += 1;
if (newHistoryIndex >= 0 && newHistoryIndex <= _history.Count)
Expand Down Expand Up @@ -378,6 +387,14 @@ public static void NextHistory(ConsoleKeyInfo? key = null, object arg = null)

private void HistorySearch(int direction)
{
if (_current == 0)
{
// If we aren't actually searching, use HistoryRecall
// because it ignores command lines from other running sessions.
HistoryRecall(direction);
return;
}

if (_searchHistoryCommandCount == 0)
{
if (LineIsMultiLine())
Expand All @@ -396,28 +413,45 @@ private void HistorySearch(int direction)
}
_searchHistoryCommandCount += 1;

for (int i = _currentHistoryIndex + direction; i >= 0 && i <= _history.Count; i += direction)
int count = Math.Abs(direction);
direction = direction < 0 ? -1 : +1;
int newHistoryIndex = _currentHistoryIndex;
while (count > 0)
{
var line = i == _history.Count ? _savedCurrentLine._line : _history[i]._line;
newHistoryIndex += direction;
if (newHistoryIndex < 0 || newHistoryIndex >= _history.Count)
{
break;
}

var line = newHistoryIndex == _history.Count ? _savedCurrentLine._line : _history[newHistoryIndex]._line;
if (line.StartsWith(_searchHistoryPrefix, Options.HistoryStringComparison))
{
if (Options.HistoryNoDuplicates)
{
int index;
if (!_hashedHistory.TryGetValue(line, out index))
{
_hashedHistory.Add(line, i);
_hashedHistory.Add(line, newHistoryIndex);
--count;
}
else if (index != i)
else if (index == newHistoryIndex)
{
continue;
--count;
}
}
_currentHistoryIndex = i;
UpdateFromHistory(moveCursor: true);
break;
else
{
--count;
}
}
}

if (newHistoryIndex >= 0 && newHistoryIndex <= _history.Count)
{
_currentHistoryIndex = newHistoryIndex;
UpdateFromHistory(moveCursor: true);
}
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion PSReadLine/ReadLine.cs
Expand Up @@ -325,7 +325,7 @@ private string InputLoop()
ProcessOneKey(key, _dispatchTable, ignoreIfNoAction: false, arg: null);
if (_inputAccepted)
{
return MaybeAddToHistory(_buffer.ToString(), _edits, _undoEditIndex, readingHistoryFile: false);
return MaybeAddToHistory(_buffer.ToString(), _edits, _undoEditIndex, readingHistoryFile: false, fromDifferentSession: false);
}

if (killCommandCount == _killCommandCount)
Expand Down

0 comments on commit 49a4c4c

Please sign in to comment.