feat(prompt): readline line editing with per-session history
When stdin is a terminal the prompt is read with bash's readline, `IFS= read -e -r -p '> ' REPLY`, so the arrow keys no longer print escape garbage: Left/Right, Home/End, Ctrl-A/E, Backspace/Delete edit the line, and Up/Down walk the lines entered in this session (`history -s` for every line with a non-blank character; empty lines are not recorded). Down past the newest entry restores the line typed before Up, and Up at the oldest entry or Down on the new line ring the bell, as readline does by default. The Nx y/N answer is read the same way and never recorded. Nothing persists: HISTFILE is unset at startup and the history is never read or written. Verified on bash 4.3.48 and 5.2.15 that `read -e` and `history -s` share one history list in a non-interactive shell, that inherited HISTSIZE/HISTCONTROL/HISTIGNORE have no effect there, and that Ctrl-C at the prompt restores the terminal. readline draws the prompt on stderr, as bash does. Piped stdin keeps the plain `read -r` exactly, including the echo of each line and EOF => exit 2. New unit tests (tests/unit/lineedit.bats) drive a real pty with script(1): history recall, the bell at both ends, the stashed line, Left-arrow editing, the y/N answer kept out of the history, no history file under HOME/TMPDIR, ^D => exit 2. The E2E suite gets a pty smoke test (Up recalls 1?), skipped where the image has no script(1).
This commit is contained in:
1 parent
71d7f87aa3
commit
296c77e319
7 files changed
+183
-11
No files matched your search
@@ -114,6 +114,18 @@ prints an error, runs nothing of that line and re-prompts. EOF on stdin aborts w
|
||||
upgrading (exit 2) so a piped run can never upgrade by accident unless it sends an empty
|
||||
line. When purges leave no row at all, the session ends ("Nothing left to upgrade.", exit 0).
|
||||
|
||||
Line input. When stdin is a terminal every line is read with bash's readline,
|
||||
`IFS= read -e -r -p PROMPT`, with readline's defaults and nothing more: cursor movement and editing
|
||||
(Left/Right, Home/End, Ctrl-A/E, Backspace/Delete) and Up/Down over an in-memory history of this
|
||||
session's command lines. A line with a non-blank character is added with `history -s` (empty
|
||||
lines, the proceed command, are not); Down past the newest entry restores the line typed before Up
|
||||
(readline's saved line); Up at the oldest entry and Down on the new line ring the bell. The `Nx`
|
||||
`y/N` answer is read the same way and never added. Nothing persists: `HISTFILE` is unset at
|
||||
startup and `history -r`/`-w`/`-a` are never used (a non-interactive bash neither loads nor saves
|
||||
history by itself). readline draws the prompt and the line on stderr, as bash does. Any other
|
||||
stdin keeps the plain `IFS= read -r` with the prompt on stdout and each line echoed after it, so
|
||||
piped runs and their logs are unchanged.
|
||||
|
||||
Flags shown after a row: `[held]` = the package manager will not upgrade it on its own: on apt
|
||||
a hold (`apt-mark hold`) or a package apt keeps back (the "kept back" block of
|
||||
`apt-get -s --with-new-pkgs upgrade`), on pacman an `IgnorePkg` (`[ignored]` in `pacman -Qu`).
|
||||
|
||||
Reference in new issue
Block a user