Vt escape codes and cursor hide / show

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Vt escape codes and cursor hide / show

#1 Post by T3RRY » 15 Oct 2020 15:42

I've been using these for controlling various aspects of output for a while now, and somehow missed that Hide / show cursor sequences are effective in cmd.exe

A short demo script utilizing %\E[%?25l to hide the cursor

Code: Select all

@Echo off
If Not "%~1" == "" (Exit /B)Else CLS
(For /F %%a in ('echo prompt $E ^| cmd')do (Set "\E[=%%a["&Set "\E=%%a")
%= Ascii Escape Character. Do Not Modify. =%)
(Set LF=^


%= LineFeed - Do Not Modify =%)
 Echo/%\E[%?25l
 Set "Roll=(For /F "Delims=" %%R in ('Set /A "D=!random! %%6 + 1"')Do (Set "#=%%R"&(!D[%%R]!)))"
 Set "Roll.Anim=For %%n in (1 2) Do if %%n==2 ((If "!Repeat!"=="" Set "Repeat=15")&For /L %%x in (1 1 !Repeat!) do (%ROLL% & %Roll% & (For /L %%D in (1 1 Delay)Do Call "%~F0" 1) & CLS))Else Set "
 Set "DefArr=For %%n in (1 2)Do if %%n==2 ((For /F "Tokens=1,2 Delims==" %%v in ('2^> Nul Set #[')Do Set "%%~v=" & Set "#{i}=0") & For %%G in (!list!)Do (Set /a "#{i}=!#{i}!+1" & Set "#[!#{i}!]=%%~G"))Else Set List="
 Set "Select=CLS&(Title Enter a number [2-12] or [E]xit & Set "Guess=" & (For %%n in (1 2)Do If not !Guess! GTR 1 (For /F "Delims=" %%G in ('Choice /N /C:E0123456789')Do If "%%G"=="E" (TITLE & Echo/%\E[%?25h & Endlocal & Exit /B 0) Else (<nul Set /P "=%%G"& Set "Guess=!Guess!%%G")))& (if !Guess! GTR 12 (Goto :Guess)))& (If "!Guess:~0,1!"=="0" (Set "Guess=!Guess:~1,1!"))& (If !Guess! LEQ 1 Goto :Guess) & CLS"
 Set "Total=(Set /A "Sum=#"&Echo/You rolled: [%\E[%33m!Sum!%\E[%0m])& (If "!Guess!" == "!Sum!" (Echo/Congrats)Else (Echo/Your Guess: [%\E[%31m!Guess!%\E[%0m] was wrong.)) & Pause > Nul & CLS & Goto :Guess )"
 Setlocal EnableDelayedExpansion
 %DefArr:#=D% "Echo/%\E[%31m---!LF!!LF! o!LF!!LF!---%\E[%0m!LF!" "Echo/%\E[%32m---!LF!  o!LF!!LF!o!LF!---%\E[%0m!LF!" "Echo/%\E[%33m---!LF!o!LF! o !LF!  o!LF!---%\E[%0m!LF!" "Echo/%\E[%34m---!LF!o o!LF!!LF!o o!LF!---%\E[%0m!LF!" "Echo/%\E[%35m---!LF!o o!LF! o!LF!o o!LF!---%\E[%0m!LF!" "Echo/%\E[%36m---!LF!o o!LF!o o!LF!o o!LF!---%\E[%0m!LF!"
:Guess
 %Select%
 %Roll.Anim:Delay=5%Repeat=20
 %Roll:#=R[1]%&%Roll:#=R[2]%
 %Total:#=R[1]+R[2]%
Last edited by T3RRY on 16 Oct 2020 05:59, edited 2 times in total.

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Vt escape codes and cursor hide / show

#2 Post by ShadowThief » 15 Oct 2020 16:23

Everything that's listed here will work: https://docs.microsoft.com/en-us/window ... -sequences

T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Re: Vt escape codes and cursor hide / show

#3 Post by T3RRY » 15 Oct 2020 17:23

ShadowThief wrote:
15 Oct 2020 16:23
Everything that's listed here will work: https://docs.microsoft.com/en-us/window ... -sequences
yet to figure out how to get cursor position using the ESC[6n Query myself.

ShadowThief
Expert
Posts: 1166
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Vt escape codes and cursor hide / show

#4 Post by ShadowThief » 15 Oct 2020 21:08

T3RRY wrote:
15 Oct 2020 17:23
ShadowThief wrote:
15 Oct 2020 16:23
Everything that's listed here will work: https://docs.microsoft.com/en-us/window ... -sequences
yet to figure out how to get cursor position using the ESC[6n Query myself.
The closest I've been able to get so far is

Code: Select all

echo [5;2H[6n
set /p cpos=
echo Cursor at %cpos:~2,-1%
but that requires the user to press enter when the ^[[5;2R is displayed. Any time I try to redirect the echo to a text file or run it through a for loop, it sends the initial ANSI sequence instead.
https://github.com/PowerShell/PSReadLine/issues/799 suggests that I should be able to just read in the data from the console, but I can't seem to pick it up programmatically since it gets sent to CON (I think) instead of STDIN or STDERR.

T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Re: Vt escape codes and cursor hide / show

#5 Post by T3RRY » 16 Oct 2020 02:37

ShadowThief wrote:
15 Oct 2020 21:08
The closest I've been able to get so far is

Code: Select all

echo [5;2H[6n
set /p cpos=
echo Cursor at %cpos:~2,-1%
but that requires the user to press enter when the ^[[5;2R is displayed. Any time I try to redirect the echo to a text file or run it through a for loop, it sends the initial ANSI sequence instead.
https://github.com/PowerShell/PSReadLine/issues/799 suggests that I should be able to just read in the data from the console, but I can't seem to pick it up programmatically since it gets sent to CON (I think) instead of STDIN or STDERR.
That's gotten me closer - It does indeed go to con:

Code: Select all

@Echo off(For /F %%a in ('echo prompt $E ^| cmd')do (Set "/E=%%a[")
%= Ascii Escape Character. Do Not Modify. =%)
 <nul Set /P "=/%/E%5;2H."
 Set "catchPos=(<Con Set /P"Cpos=%/E%6n") & (Set "Cpos=!Cpos:~2,-1!")&Echo/!Cpos!"
 Setlocal EnableDelayedExpansion
 %catchpos%
Pause > Nul
I haven't devised a means to redirect or pipe the output in a non blocking way as yet

miskox
Posts: 630
Joined: 28 Jun 2010 03:46

Re: Vt escape codes and cursor hide / show

#6 Post by miskox » 16 Oct 2020 04:30

What I remember from using DEC Video Terminals (VT 420 and VT 520): Correct sequence is:

Code: Select all

CSI   Pl ; Pc H

CSI = ESC + [
So you should
set ESC to 27decimal
echo %esc%[4;2HThis is test.
to set cursor position. This should work.

EDIT: this works for me:

(instead of X I patched it with 0x1B) - you could use viewtopic.php?f=3&t=5326 )

Code: Select all

@echo off
cls
set ESC=X
echo %esc%[4;2HThis is test.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.

(windows 10, version 1903, build 18362.1082), x64, slovenian)

Saso

T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Re: Vt escape codes and cursor hide / show

#7 Post by T3RRY » 16 Oct 2020 05:47

miskox wrote:
16 Oct 2020 04:30
What I remember from using DEC Video Terminals (VT 420 and VT 520): Correct sequence is:

Code: Select all

CSI   Pl ; Pc H

CSI = ESC + [
So you should
set ESC to 27decimal
echo %esc%[4;2HThis is test.
to set cursor position. This should work.

EDIT: this works for me:

Code: Select all

@echo off
cls
set ESC=X
echo %esc%[4;2HThis is test.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.
echo.

(windows 10, version 1903, build 18362.1082), x64, slovenian)

Saso
I'm not certain what your trying to add to the conversation here. ESC[l;cH is already known as the sequence syntax for setting cursor position line;column - as well as being described well in the documentation already referenced:
ShadowThief wrote:
15 Oct 2020 16:23
Everything that's listed here will work: https://docs.microsoft.com/en-us/window ... -sequences
As for :
miskox wrote:
16 Oct 2020 04:30
(instead of X I patched it with 0x1B) - you could use viewtopic.php?f=3&t=5326 )
The following is a suitable way to define the ESC control character. two variables are defined, one for sequences requiring [, one for squences that don't require [

Code: Select all

(For /F %%a in ('echo prompt $E ^| cmd')do (Set "\E[=%%a["&Set "\E=%%a")
The discussion around ESC[6n is about capturing the current position when the value is unknown, Idealy in a manner that is non blocking and doesn't result in output to the console.
The reason I myself am intersted in this is to develop a means of positional control using Escape sequences:

ESCA Cursor Up
ESCB Cursor Down
ESCC Cursor Forward (Right)
ESCD Cursor Backward (Left)

Without having to resort to intermediary values to adjust line/column positions, but simply test the current cursor postion against a table of permitted values for the axis of movement.
Last edited by T3RRY on 16 Oct 2020 05:56, edited 1 time in total.

miskox
Posts: 630
Joined: 28 Jun 2010 03:46

Re: Vt escape codes and cursor hide / show

#8 Post by miskox » 16 Oct 2020 05:53

There is a post that cursor positiooning is not working.

Saso

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Vt escape codes and cursor hide / show

#9 Post by penpen » 16 Oct 2020 06:01

You might find viewtopic.php?f=3&t=9454 usefull:
It contains a c# solution and a pure batch solution to get the cursor position and the device attribute.


penpen

T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Re: Vt escape codes and cursor hide / show

#10 Post by T3RRY » 16 Oct 2020 06:12

miskox wrote:
16 Oct 2020 05:53
There is a post that cursor positiooning is not working.

Saso
Post #3 ? Perhaps a simple misunderstanding. Get Cursor position using ESC[6n

That's is: get the current cursor position using escape code DECXCPR to query the state of the cursor position, and Set it to a variable.
This is a differs from setting the cursor position using the CUP escape code.

The issue with assigning the result of the querry to a varible stems from it being returned via the con stream - it cant be read directly from stdout, nor have I found means of redirecting it that allows it to be captured in a non blocking manner

T3RRY
Posts: 250
Joined: 06 May 2020 10:14

Re: Vt escape codes and cursor hide / show

#11 Post by T3RRY » 16 Oct 2020 07:43

penpen wrote:
16 Oct 2020 06:01
You might find viewtopic.php?f=3&t=9454 usefull:
It contains a c# solution and a pure batch solution to get the cursor position and the device attribute.


penpen
Brilliant! As always, the wheel has already been invented, by smarter minds than mine. Macro adapted :

Code: Select all

@echo off
(Set \n=^^^
%=Do not modify=%
)
for /F "delims=#" %%a in ('"prompt #$E# & for %%a in (1) do rem"') do set "\E=%%a"
<Nul Set /p "=%\E%[20;20H"
Set GetPos=For %%n in (1 2)Do if %%n==2 (%\n%
 For /L %%l in (2 1 12)Do (%\n%
  If not "!Char!" == "R" (%\n%
   ^<nul set /p "=%\E%[6n" %\n%
   FOR /L %%# in (1 1 %%l) DO pause ^< CON ^> NUL%\n%
    Set "Char=;"%\n%
    for /F "tokens=1 skip=1 delims=*" %%C in ('"REPLACE /W ? . < con"') DO (%\n%
     Set "char=%%C"%\n%
    )%\n%
   If "!Cpos!" == "" (Set "Cpos=!Char!")Else set "Cpos=!Cpos!!char:R=!"%\n%
  )%\n%
 )%\n%
)Else set "Cpos=" ^&Set "Char="
Setlocal EnableDelayedExpansion
%GetPos%
 <Nul Set /P "=!Cpos!"
Endlocal
exit /b
A proof of concept regarding Positional movement by comparing a move from a current position in a given direction with a list of allowed move positions:

Code: Select all

==========================================================================================================
::: * Proof of concept script for moving cursor along a permitted path only using ASCII escape codes * :::
==========================================================================================================
@echo off & CLS  & CD "%userprofile%"
Rem [* Ensure safe temporary working directory - Failed Redirections can cause issues in the working directory *]
 If exist "%TEMP%\%~n0\Guard" (RMDIR "%TEMP%\%~n0\Guard" /S /Q 2> Nul || (Echo/Cleanup failed & Exit /B 1))
 Timeout 2 > Nul & CLS
 If not exist "%TEMP%\%~n0\Guard" MD "%TEMP%\%~n0\Guard"
 PUSHD "%TEMP%\%~n0\Guard" || (Echo/Safe working directory required & Exit /B)
(Set \n=^^^
%=Do not modify=%
)

 for /F "delims=#" %%a in ('"prompt #$E# & for %%a in (1) do rem"') do set "\E=%%a"
Rem [* max expected return length is 11 characters: "^]]###;###R". R is disregarded. only 10 iterations required *]
Rem [* Additional redirections or piping within the CHKmove macro or any (code block) it's used in may cause failure. *]
Set CHKmove=(Set "Opos=!Cpos!" ^& set "Cpos=" ^&Set "Char=" ^& For %%n in (1 2)Do if %%n==2 (%\n%
 For /L %%l in (2 1 12)Do (%\n%
  If not "!Char!" == "R" (%\n%
   ^<nul set /p "=%\E%[6n" %\n%
   FOR /L %%# in (1 1 %%l) DO pause ^< CON ^> NUL%\n%
   Set "Char=;"%\n%
   for /F "tokens=1 skip=1 delims=*" %%C in ('"REPLACE /W ? . < con"') DO (Set "char=%%C")%\n%
   If "!Cpos!" == "" (Set "Cpos=!Char!")Else set "Cpos=!Cpos!!char:R=!"%\n%
  )%\n%
 )%\n%
 Set "_V=F"^&(For %%G in (!Valid!)Do If /I "%%~G" == "!Cpos!" (Set "_V=T"))%\n%
))
Rem [* 'Valid' variable is used as the source of valid positions to compare against in CHKmove macro *]
 Set Valid="20;21" "20;22" "20;23" "20;24" "20;25" "19;25" "18;25" "17;25" "16;25"  "15;25" "15;24" "15;23" "15;22" "15;21" "15;21" "16;21" "17;21" "18;21" "19;21"
Rem [* On [E]xit: restor cursor - return to previous WD - Delete scripts TEMP folder - End the local Environment *]
 Set "CLEANUP=ECHO/%\E%[?25h%\E%[21;1HDone. & POPD & RMDIR "%TEMP%\%~n0\Guard" /S /Q 2> Nul & Endlocal & Exit /B"
 Set "RestorePos=(set "Cpos=!Opos!"& <Nul Set /P "=%\E%[!Opos!H%\E%[!Col!mx%\E%[0m" &Set "_V=T")"
Setlocal EnableDelayedExpansion
 For %%v in (!Valid!) Do <Nul Set /P "=%\E%[%%~vH%\E%[90m.%\E%[0m"
Rem [* Hide cursor; Set and display Intial position *]
 <Nul Set /p "=%\E%[?25l%\E%[20;21Hx"&Set "Cpos=20;21"
Rem [* Directional 'cursor move' sequences *]
 Set "D="&Set "W=%\E%D%\E%A"& Set "A=%\E%D%\E%D"& Set "S=%\E%B%\E%D"
 Set "Col=30"
:loop
 If %COL% EQU 37 Set "Col=30"
 Set /A "Col+=1" & TITLE Move: [WASD] Exit: [E]
Rem [* User input attempt move *]
 For /F "Delims=" %%O in ('Choice /N /C:WASDE')Do If "%%O" == "E" (%CLEANUP%)Else ( <Nul Set /p "=!%%O!")
Rem [* move cursor using escape codes; test if position is valid -T:Display move -F:Restore Cursor to last saved valid position *]
 %CHKmove% & If "!_V!"=="T" (<Nul Set /p "=%\E%[!Col!mx%\E%[0m") Else (%RestorePos%)
Goto :loop

Post Reply