Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Read a line from user without clearing screen below the prompt while allowing user to use arrow keys to make edits in middle of line



Here's some more context. I have an interactive CLI application built using zsh, and am already using alternate screen to draw contents in it. vared's default behavior (of clearing current line of cursor and below) makes sense when a script calling vared does not use alternate screen. This is because screen contents on and below the current cursor position (after vared is called) in an interactive shell are mostly not exciting (generally empty). But the same is not true for applications that use alternate screen and paint entire screen with text. Let's say the application designer wants to use the first line on screen to get user input. They might not want any other line on screen to get cleared or moved when vared is called. But that doesn't seem possible with vared, as vared clears from current line the cursor is on to everything below. IMO, vared makes an assumption that is limiting (something that ``bash -e -p`` doesn't). It would be nice to have a switch that disables vared's clearing behavior, and leaves it on developer to insert commands to clear line/s. Till such a switch exists, is it possible to zle and bypass such clearing?

Here's an example that shows vared always clears lines on and below the cursor position on the screen.

```
tput smcup; tput clear; tput cup 0 0
for ((i=1;i<LINES;i=i+1)); do
    printf '%s\n' "$i. Hello world"
done
printf "\e[31m$i. Hello World\e[0m"
tput cup $((RANDOM%LINES)) 0
sleep 1
vared -f vared-finish -c -p "%{$(tput cup 0 0)%}Enter input: " userinput
tput rmcup
echo "User entered: $userinput"
```

P.S. I posted this to zsh-workers with an imagining that this likely will turn into a feature request or bug report.


On Fri, Dec 30, 2022 at 9:56 AM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
(Leaving this on -workers because of the possible bug mentioned at the end.)

On Thu, Dec 29, 2022 at 9:38 PM OG Code Poet <ogcodepoet@xxxxxxxxx> wrote:
>
> Using Bash ``tput cup 0 0; read -e -p "Enter input: " userinput`` works well for getting a line of user input:
>
> * It does not clear screen below the prompt
> * It allows user to use arrow keys to go to middle of line and edit a mistake they might have made while typing

Bash is invoking the GNU "readline" library for the "read" builtin.
Unlike ZLE, which despite having "line" in its name attempts to be a
reasonable multi-line editor, readline is designed to do exactly what
its name says, so it doesn't do any other screen prep.

> How can this be achieved in zsh?

Closest I can come up with is this:

vared-finish() { tput rc }
zle -N vared-finish
tput sc
vared -f vared-finish -c -p "%{$(tput cup 0 0)%}Enter input: " userinput

However, this is not entirely satisfactory because the finish widget
is not invoked if this is interrupted by ^C or ^G (send-break), and
vared then clears the screen before exiting.  This is possibly a bug?
Shouldn't the finish widget(s) always be run when the line editor
exits, even if it exits "abnormally"?  (This affects the PS1 ZLE as
well.)


Messages sorted by: Reverse Date, Date, Thread, Author