通过Windows 10控制台VT-100转义序列获取光标位置 [英] Get cursor position via Windows 10 console VT-100 escape sequence

查看:378
本文介绍了通过Windows 10控制台VT-100转义序列获取光标位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试用Windows 10控制台中对VT-100转义序列的新(有限)支持。在 https中记录了受支持的序列。 ://msdn.microsoft.com/zh-cn/library/windows/desktop/mt638032(v = vs.85).aspx



  ESC [6n-用ESC [n]响应。 ;< m> R,
,其中< n>是行号,< m>列号

响应作为键盘输入传递出去,并出现在屏幕上,但是我有不知道如何以编程方式利用这些信息。理想情况下,我想将< n> < m> 的值从批处理中获取到环境变量中



但是,如果有人可以演示如何使用任何语言捕获变量,那么我也许就能利用这些知识来制定有效的批处理文件策略。

p>

我可以使用下面称为ANSI.BAT的简单脚本来接近

  @echo off 
setlocal enableDelayedExpansion

for / f delims = %% C in(
'forfiles / p%〜dp0。 / m%〜nx0 / c cmd / c echo(0x1B'
)确实设置了 esc = %% C
设置了 csi =%esc%[

echo(查询: %csi%6n
set / p pos =
echo response =!pos:%esc%= ESC!

-输出-

  C:\test> ansi 
查询:
^ [[3; 9R
response = ESC [3; 9R

C:\test>

一旦将响应包含在变量中,就可以使用FOR / F轻松解析出值。他遇到的问题是我必须在响应出现在屏幕上后手动按< Enter> 键,才能终止SET / P语句的输入。我很困惑从这里去哪里……



编辑-最后一个要求:我不希望查询回复出现在屏幕上显示,因为这样会打乱屏幕,并更改光标位置。我怀疑这可能是最难破解的螺母,对于纯批处理来说可能是不可能的。

解决方案

三年后的重大更改



通过使用 XCOPY REPLACE



我在这里使用 replace 以避免语言相关的问题。

  @echo off 
for / F delims =# %% a in('提示#$ E#& for %% a in(1 )do rem')做set ESC = %% a

调用:get_cursor_pos
exit / b

:get_cursor_pos
set response =
set pos = 2

:_get_loop
REM ***请求光标位置
< nul set / p =%ESC%[6n
FOR / L %%#in(1 1%pos%)做暂停< CON> / F的NUL

令牌= 1跳过= 1 eol = %% C in(' REPLACE / W?。< con')DO(
set char = %% C

set response =%response %% char%
set / a pos + = 1
如果%char% NEQ R转到: _get_loop

设置响应
退出/ b

主要问题是, XCOPY REPLACE 允许我从输入流中读取一个字符,然后清除剩余的缓冲区。 / p>

相反, PAUSE 读取一个字符,保留剩余的缓冲区,但不显示读取的字符。



为了解决这个问题,我多次发出查询,每次都读取不同的响应字符。对于每次迭代,我使用2个或多个 PAUSE 语句的组合,后跟 REPLACE 来读取响应的特定字符。每次迭代使用的 PAUSE 比上一次迭代多,直到我能够读取终止的R。



I开发了这项技术,并将其最初发布在 DosTips-使用控制台虚拟终端序列查询状态。


I'm playing around with the new (limited) support for VT-100 escape sequences within the Windows 10 console. The supported sequences are documented at https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx.

In particular, the following sequence that reports the current cursor position interests me.

ESC[6n - responds with ESC[<n>;<m>R, 
         where <n> is the row number, and <m> the column number

The response is passed off as keyboard input, and appears on the screen, but I have no idea how to programmatically make use of the information. Ideally I would like to get the <n> and <m> values into environment variables from within a batch file.

But if anyone can demonstrate how to capture the variables using any language, then I may be able to use that knowledge to develop an effective batch file strategy.

I can get close with the following simple script called ANSI.BAT

@echo off
setlocal enableDelayedExpansion

for /f "delims=" %%C in (
  'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x1B"'
) do set "esc=%%C"
set "csi=%esc%["

echo(Inquiry:%csi%6n
set /p "pos="
echo response=!pos:%esc%=ESC!

--OUTPUT--

C:\test>ansi
Inquiry:
^[[3;9R
response=ESC[3;9R

C:\test>

I can easily parse out the values using FOR /F, once I have the response in a variable. The problem I am having is I must manually press the <Enter> key after the response appears on the screen in order to terminate the input for my SET /P statement. I am stumped on where to go from here...

EDIT - One last requirement: I don't want the inquiry response to appear on the screen, as that disrupts the screen, and changes the cursor position. I suspect this may be the toughest nut to crack, perhaps impossible with pure batch.

解决方案

Major change after three years

It works with reading the response by using XCOPY or REPLACE.

I'm using replace here, to avoid language dependent problems.

@echo off
for /F "delims=#" %%a in ('"prompt #$E# & for %%a in (1) do rem"') do set "ESC=%%a"

call :get_cursor_pos
exit /b

:get_cursor_pos
set "response="
set pos=2

:_get_loop
REM *** Request Cursor position
<nul set /p "=%ESC%[6n" 
FOR /L %%# in (1 1 %pos%) DO pause < CON > NUL

for /F "tokens=1 skip=1 eol=" %%C in ('"REPLACE /W ? . < con"') DO (
    set "char=%%C"
)
set "response=%response%%char%"
set /a pos+=1
if "%char%" NEQ "R" goto :_get_loop

set response
exit /b

The main problem is, XCOPY or REPLACE allows me to read one character from the input stream, but then clears the remaining buffer.

Conversely, PAUSE reads one character, preserving the remaining buffer, but does not reveal what character was read.

To solve this, I issue the query multiple times, reading a different character of the response each time. For each iteration I use a combination of 2 or more PAUSE statements followed by REPLACE to read a specific character of the response. Each iteration uses one more PAUSE than the prior iteration, until I am able to read the terminating R.

I developed this technique and initially posted it at DosTips - Query States using Console Virtual Terminal Sequences.

这篇关于通过Windows 10控制台VT-100转义序列获取光标位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆