zsh-workers
 help / color / mirror / code / Atom feed
* 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
@ 2022-12-30  5:37 OG Code Poet
  2022-12-30  8:58 ` Mikael Magnusson
  2022-12-30 17:56 ` Bart Schaefer
  0 siblings, 2 replies; 8+ messages in thread
From: OG Code Poet @ 2022-12-30  5:37 UTC (permalink / raw)
  To: zsh-workers; +Cc: OG Code Poet

[-- Attachment #1: Type: text/plain, Size: 1323 bytes --]

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

How can this be achieved in zsh? I have tried two techniques; either it
clears screen below prompt or it does not allow using arrow to go back to
middle of line to edit it.

1. Using ``vared``:
```
tput cup 0 0; userinput=""; vared -p "Enter input: " userinput
```
``vared`` seems to clear screen below the prompt, so this clears the entire
screen before showing the prompt.

2. Using ``read``:

```
tput cup 0 0; printf "Enter input: "; read -r userinput
```
This does not clear the screen below the prompt, but does not allow using
arrow keys to go to middle of the line and make an edit ("delete" key
works, but is too much to ask users to delete and retype everything from
the point of typo).

Is there a way out? Perhaps it could be possible to trick vared to believe
there are no lines below, so it clears just 1 line (the line of prompt). If
it is not possible in zsh, I am open to an external POSIX way of getting
user input on first line of the screen.

P.S. Also posted in unix.stackexchange.com:
https://unix.stackexchange.com/q/730022/456507

[-- Attachment #2: Type: text/html, Size: 1671 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* 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
  2022-12-30  5:37 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 OG Code Poet
@ 2022-12-30  8:58 ` Mikael Magnusson
  2022-12-30 17:56 ` Bart Schaefer
  1 sibling, 0 replies; 8+ messages in thread
From: Mikael Magnusson @ 2022-12-30  8:58 UTC (permalink / raw)
  To: OG Code Poet; +Cc: zsh-workers

On 12/30/22, OG Code Poet <ogcodepoet@gmail.com> 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
>
> How can this be achieved in zsh? I have tried two techniques; either it
> clears screen below prompt or it does not allow using arrow to go back to
> middle of line to edit it.
>
> 1. Using ``vared``:
> ```
> tput cup 0 0; userinput=""; vared -p "Enter input: " userinput
> ```
> ``vared`` seems to clear screen below the prompt, so this clears the entire
> screen before showing the prompt.
>
> 2. Using ``read``:
>
> ```
> tput cup 0 0; printf "Enter input: "; read -r userinput
> ```
> This does not clear the screen below the prompt, but does not allow using
> arrow keys to go to middle of the line and make an edit ("delete" key
> works, but is too much to ask users to delete and retype everything from
> the point of typo).
>
> Is there a way out? Perhaps it could be possible to trick vared to believe
> there are no lines below, so it clears just 1 line (the line of prompt). If
> it is not possible in zsh, I am open to an external POSIX way of getting
> user input on first line of the screen.
>
> P.S. Also posted in unix.stackexchange.com:
> https://unix.stackexchange.com/q/730022/456507

Without more context this sounds like a very weird request, surely
printing stuff at 0,0 will just overlap whatever existing text was
there, resulting in a corrupted screen output? Perhaps you will have
better luck switching to the alternate screen while prompting for the
string, and then switching back, in effect giving you the appearance
of a full screen program (more likely to direct the user's attention
to the top of the terminal). (enable with echo -n '\e[?47h' and
disable with echo -n '\e[?47l')

PS
this is probably more of a zsh-users question than zsh-workers

-- 
Mikael Magnusson


^ permalink raw reply	[flat|nested] 8+ messages in thread

* 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
  2022-12-30  5:37 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 OG Code Poet
  2022-12-30  8:58 ` Mikael Magnusson
@ 2022-12-30 17:56 ` Bart Schaefer
  2022-12-31  3:52   ` OG Code Poet
  1 sibling, 1 reply; 8+ messages in thread
From: Bart Schaefer @ 2022-12-30 17:56 UTC (permalink / raw)
  To: OG Code Poet; +Cc: Zsh hackers list

(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@gmail.com> 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.)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* 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
  2022-12-30 17:56 ` Bart Schaefer
@ 2022-12-31  3:52   ` OG Code Poet
  2022-12-31  5:20     ` Bart Schaefer
  0 siblings, 1 reply; 8+ messages in thread
From: OG Code Poet @ 2022-12-31  3:52 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 3069 bytes --]

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@brasslantern.com>
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@gmail.com> 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.)
>

[-- Attachment #2: Type: text/html, Size: 3864 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* 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
  2022-12-31  3:52   ` OG Code Poet
@ 2022-12-31  5:20     ` Bart Schaefer
  2022-12-31  5:44       ` OG Code Poet
  2022-12-31 13:13       ` Oliver Kiddle
  0 siblings, 2 replies; 8+ messages in thread
From: Bart Schaefer @ 2022-12-31  5:20 UTC (permalink / raw)
  To: OG Code Poet; +Cc: Zsh hackers list

On Fri, Dec 30, 2022 at 7:52 PM OG Code Poet <ogcodepoet@gmail.com> wrote:
>
> Here's some more context.

So ... vared sends the clear-to-end-of-screen before printing the
prompt, then starts ZLE and clears again after ZLE exits.  This means
your job, in creating a workaround, is to move the cursor to the lower
right corner of the screen before calling vared, move it to the
desired position before printing the prompt, and move back to the
lower right again before ending ZLE.

This translates approximately to:

to-lower-right() { tput cup $LINES $((COLUMNS-1)) }
zle -N to-lower-right
tput sc
to-lower-right
vared -f to-lower-right -p "%{$(tput cup 0 0)%}Enter something: " ...
tput rc

Other tricks may be needed to keep a newline from being output when
pressing ENTER to accept the edit.

If this is unsatisfactory, you could try using zcurses to manage the
display, which I think would allow you to always redraw whatever vared
erased.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* 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
  2022-12-31  5:20     ` Bart Schaefer
@ 2022-12-31  5:44       ` OG Code Poet
  2022-12-31 13:13       ` Oliver Kiddle
  1 sibling, 0 replies; 8+ messages in thread
From: OG Code Poet @ 2022-12-31  5:44 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 1558 bytes --]

I had tried tput cup $LINES $((COLUMNS-1)) and tput cup $LINES $COLUMNS.
Vared seems to clear the entire line of cursor, not just from
cursor position to the end of line. Not sure if this has something to do
with xterm-256color and tmux-256color, unlike the description of tput el
"clear to end of line". On all the terminals I have tested this on, they
clear from beginning of current line to the end. My machine is: Apple
Silicon macOS 13.1. Did that really work on your machine?

On Fri, Dec 30, 2022 at 9:20 PM Bart Schaefer <schaefer@brasslantern.com>
wrote:

> On Fri, Dec 30, 2022 at 7:52 PM OG Code Poet <ogcodepoet@gmail.com> wrote:
> >
> > Here's some more context.
>
> So ... vared sends the clear-to-end-of-screen before printing the
> prompt, then starts ZLE and clears again after ZLE exits.  This means
> your job, in creating a workaround, is to move the cursor to the lower
> right corner of the screen before calling vared, move it to the
> desired position before printing the prompt, and move back to the
> lower right again before ending ZLE.
>
> This translates approximately to:
>
> to-lower-right() { tput cup $LINES $((COLUMNS-1)) }
> zle -N to-lower-right
> tput sc
> to-lower-right
> vared -f to-lower-right -p "%{$(tput cup 0 0)%}Enter something: " ...
> tput rc
>
> Other tricks may be needed to keep a newline from being output when
> pressing ENTER to accept the edit.
>
> If this is unsatisfactory, you could try using zcurses to manage the
> display, which I think would allow you to always redraw whatever vared
> erased.
>

[-- Attachment #2: Type: text/html, Size: 2065 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* 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
  2022-12-31  5:20     ` Bart Schaefer
  2022-12-31  5:44       ` OG Code Poet
@ 2022-12-31 13:13       ` Oliver Kiddle
  2023-01-01  0:10         ` Bart Schaefer
  1 sibling, 1 reply; 8+ messages in thread
From: Oliver Kiddle @ 2022-12-31 13:13 UTC (permalink / raw)
  To: OG Code Poet, Zsh hackers list

Bart Schaefer wrote:
> If this is unsatisfactory, you could try using zcurses to manage the
> display, which I think would allow you to always redraw whatever vared
> erased.

The first idea that came into my mind was to try setopt singlelinezle
Unfortunately, that doesn't especially help. I think the clearing from
the cursor to the end of the window serves a purpose in general. It may
be that this could be relaxed for singlelinezle without breaking
anything. A script has control of anything like completion that
potentially results in further printing of characters.

Another option would be to provide zle with control of the text you want
to appear after the input by putting it in POSTDISPLAY:

  other-stuff() { POSTDISPLAY=$'\none\ntwo\nthree' }
  zle -N other-stuff
  vared -i other-stuff -c out


Oliver


^ permalink raw reply	[flat|nested] 8+ messages in thread

* 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
  2022-12-31 13:13       ` Oliver Kiddle
@ 2023-01-01  0:10         ` Bart Schaefer
  0 siblings, 0 replies; 8+ messages in thread
From: Bart Schaefer @ 2023-01-01  0:10 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: OG Code Poet, Zsh hackers list

On Sat, Dec 31, 2022 at 5:14 AM Oliver Kiddle <opk@zsh.org> wrote:
>
> The first idea that came into my mind was to try setopt singlelinezle

That was my first thought too, and I also tried setting LINES=1 along
with it, but no help.

> I think the clearing from
> the cursor to the end of the window serves a purpose in general.

In fact I think it's issuing both move-to-first-column as well as
clear-to-end.  It wants to know exactly what positions the prompt
occupies and have free rein over the rest.

Seems like it should be possible to do something with a tweaked
read-from-minibuffer as the vared initial-widget, but I think vared is
going to end up clearing at least the entire last line of the screen
no matter what.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-01-01  0:10 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-30  5:37 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 OG Code Poet
2022-12-30  8:58 ` Mikael Magnusson
2022-12-30 17:56 ` Bart Schaefer
2022-12-31  3:52   ` OG Code Poet
2022-12-31  5:20     ` Bart Schaefer
2022-12-31  5:44       ` OG Code Poet
2022-12-31 13:13       ` Oliver Kiddle
2023-01-01  0:10         ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).