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

Re: cursor position in a variable




05.09.2015, 22:07, "Mikael Magnusson" <mikachu@xxxxxxxxx>:
> On Sat, Sep 5, 2015 at 8:36 PM, david sowerby <d_sowerby@xxxxxxxxx> wrote:
>>  I can get the cursor position by doing:
>>  print "\e[6n"
>>  this gives me the row and column. Though oddly the output appears after the next prompt, not on its own line. This
>>  may (or nor) be why when I do:
>>  pos=$(print "\e[6n")
>>  print $pos
>>  I get an empty line - and the output after the next prompt.
>>  I want to use the row the cursor is on in a script -- so how do I get that into a variable? If not this way is there a way using ZLE?
>>  thanks for any help --------------dave
>
> When you print a terminal control sequence, the terminal writes the
> reply on standard input, so you need something like
>
> print -n '\e[6n'
> read pos
>
> The problem here is that the terminal doesn't print a newline, so this
> will hang until you press enter. You can dance around with a loop
> reading one character at a time and checking if there is more pending
> input, but I'm not 100% sure what the best way to handle this is. If
> 'read' had an option "read all pending input", it would be easy, but
> it does not. :)
>
> print -n '\e[6n'
> pos=
> while IFS= read -rs -t 0.1 -k1; do pos+=$REPLY; done
> echo ${(V)pos}
>
> this "works", but the 0.1 feels hacky. With 0, the whole loop might
> abort before the terminal has time to write any characters back.
>
> print -n '\e[6n'
> until IFS= read -rs -k1 pos; do done
> while IFS= read -rs -t 0 -k1; do pos+=$REPLY; done
> echo ${(V)pos}
>
> this variant will spin until it gets one character back, then read the
> rest of the pending characters. You may also want to abort that loop
> when you get the "R" back.
> ...; do pos+=$REPLY; [[ $REPLY == R ]] && break; done
>
> --
> Mikael Magnusson

What’s the point of using IFS with read -k? If you know that terminal does print something the following works fine:

    print -n $'\e[6n' ; pos= ; while read -rs -k1 ; do pos+=$REPLY ; [[ $REPLY == R ]] && break ; done

. Timeout I removed will be needed if you don’t know that terminal will output anything though.



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