AcceptAndGetNext is skipping
When I set a hotkey for AcceptAndGetNext I expect to be able to replay a few commands from history in order, by just pressing it repeatedly, but it keeps skipping commands.
Environment data
PS version: 5.1.18950.1000 PSReadline version: 2.0.0-beta4 os: 10.0.18950.1000 (WinBuild.160101.0800) PS file version: 10.0.18950.1000 (WinBuild.160101.0800) BufferWidth: 130 BufferHeight: 6000
And Also
PS version: 7.0.0-preview.2 PSReadline version: 2.0.0-beta4 os: 10.0.18950.1000 (WinBuild.160101.0800) PS file version: 7.0.0.0 BufferWidth: 120 BufferHeight: 27
Steps to reproduce or exception report
When I set a hotkey (e.g. Ctrl+k or Ctrl+Enter) for AcceptAndGetNext
Then I type a few commands and hit enter after each:
Write-Host "One" Write-Host "Two" Write-Host "Three" Write-Host "Four" Write-Host "Five"
Then I hit up-arrow until I get back to "One" and hit the hotkey (e.g. Ctrl+k) a couple of times, it skips from "One" to "Three" to "Five" ...
Weird, I know this used to work and there are even unit tests for this binding that in theory are passing.
Adding some detail:
Set-PSReadLineKeyHandler ctrl+k AcceptAndGetNext
Write-Host "One"
Write-Host "Two"
Write-Host "Three"
Write-Host "Four"
Write-Host "Five"
UpArrow 5 times. Then CTRL+k 5 times, the results are ...
One
Three
Five
Three
Three
At this point there are no more commands left, so the prompt has no further command.
So it seems as though it must be running through the right commands by some index, but then places the wrong command in the buffer...
Quick guess ... AcceptLineImpl() is saving this new line in to the history, or changing up the history indexing, causing the next command to bump up one ?? Maybe a history item at the end is being bumped off? So until your history fills up, its not a problem, and the testing works as expected because its always starting with an empty history.
Not quite what I guessed, but I was close. Once the _history <HistoryQueue> fills, the _head moves, changing the index of every _history item. Every command is moved or copied to the _tail of the queue upon being accepted (but not in AcceptLineImpl(), instead its after returning to InputLoop() from ProcessOneKey()).
In this case, it is useless to save index's to <HistoryQueue>, because they will change once the queue is fully populated.
The problem here is probably that the index value for <HistoryQueue> is absolute, instead of relative. Currently, _history.Count represents the present, and values less than that represent fixed points in the past, but they are only fixed points until the entire history rotates in place when the queue fills.
For what it's worth, this only happens when the history buffer is full.
Still reproduces in PS 7.3.8 and PSReadLine 2.3.4