diff --git a/PSReadLine/History.cs b/PSReadLine/History.cs index c1490a23..19c09fa0 100644 --- a/PSReadLine/History.cs +++ b/PSReadLine/History.cs @@ -98,6 +98,8 @@ public class HistoryItem private int _getNextHistoryIndex; private int _searchHistoryCommandCount; private int _recallHistoryCommandCount; + // Indicating the count of history operation already executed, + // its value is incremented on SaveCurrentLine which is called on most history recall functions e.g. NextHistory private int _anyHistoryCommandCount; private string _searchHistoryPrefix; // When cycling through history, the current line (not yet added to history) @@ -874,6 +876,8 @@ private void SaveCurrentLine() MaybeReadHistoryFile(); _anyHistoryCommandCount += 1; + // can only have one drafted line instance + // if the drafted line isn't consumed, do not reassign if (_savedCurrentLine.CommandLine == null) { _savedCurrentLine.CommandLine = _buffer.ToString(); diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index da890bbb..c10116de 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -69,6 +69,7 @@ public partial class PSConsoleReadLine : IPSConsoleReadLineMockableMethods private bool _statusIsErrorMessage; private string _statusLinePrompt; private string _acceptedCommandLine; + // edits of current loaded line, this reference gets updated in UpdateFromHistory private List _edits; private int _editGroupStart; private int _undoEditIndex; @@ -549,6 +550,8 @@ private string InputLoop() var visualSelectionCommandCount = _visualSelectionCommandCount; var moveToLineCommandCount = _moveToLineCommandCount; var moveToEndOfLineCommandCount = _moveToEndOfLineCommandCount; + var currentHistoryIndex = _currentHistoryIndex; + var prevLine = _buffer.ToString(); // We attempt to handle window resizing only once per a keybinding processing, because we assume the // window resizing cannot and shouldn't happen within the processing of a given keybinding. @@ -610,16 +613,34 @@ private string InputLoop() { _recallHistoryCommandCount = 0; } + // if the latest input didn't trigger a SaveCurrentLine call if (anyHistoryCommandCount == _anyHistoryCommandCount) { if (_anyHistoryCommandCount > 0) { - ClearSavedCurrentLine(); - _hashedHistory = null; - _currentHistoryIndex = _history.Count; + // _savedCurrentLine should be consumed only if current line has the same content + if (_savedCurrentLine.CommandLine == _buffer.ToString()) + { + ClearSavedCurrentLine(); + _hashedHistory = null; + _currentHistoryIndex = _history.Count; + } } + // this might not be desired sometimes as non-editing inputs e.g. moving cursor also trigger this _anyHistoryCommandCount = 0; } + // if any edit happened on same history + if (currentHistoryIndex == _currentHistoryIndex && prevLine != _buffer.ToString()) + { + // once edited, we should reset the _savedCurrentLine + ClearSavedCurrentLine(); + // if the current line is recalled and edited, + // it become effectively a new command, we should reset _currentHistoryIndex + if (_currentHistoryIndex != _history.Count) + { + _currentHistoryIndex = _history.Count; + } + } if (visualSelectionCommandCount == _visualSelectionCommandCount && _visualSelectionCommandCount > 0) { _visualSelectionCommandCount = 0;