Windows 10控制台VT-100转义序列

时间:2016-07-07 03:54:29

标签: batch-file windows-console ansi-escape

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

我使用批处理文件来测试这些功能,并且我能够使几乎所有记录的功能都能正常工作。但我在使用"视口定位"序列(向上/向下滚动) - 在我手中它们完全失效(没有效果)

ESC[<n>S  -  Scroll Up <n> lines
ESC[<n>T  -  Scroll Down <n> lines

任何人都可以在任何情况下让他们工作,或者MS文档是否完全错误?

此外,MicroSoft尚未记录标准查询序列,但似乎有效 特别是,报告当前光标位置的以下序列让我感兴趣。

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

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

但是,如果有人能够演示如何使用任何语言捕获变量,那么我可以使用该知识来开发有效的批处理文件策略。

我可以使用以下名为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!

- 输出 -

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

C:\test>

一旦我在变量中得到响应,我就可以使用FOR / F轻松地解析出值。我遇到的问题是我必须在屏幕上出现响应后手动按<Enter>键才能终止SET / P语句的输入。我很难过这里去的地方......

编辑 - 最后一项要求:我不希望查询响应出现在屏幕上,因为这会中断屏幕,并更改光标位置。我怀疑这可能是最难解决的问题,纯批次可能是不可能的。

2 个答案:

答案 0 :(得分:2)

我没有Windows 10,所以我无法完成任何测试。但是,如果Ansi ESC[6n序列的响应是ESC[<n>;<m>R个字符填充键盘输入缓冲区,则只需要按顺序将Enter键添加到此类输入中通过SET /P命令读取它,这可以通过SendKeys JScript方法完成。

我还使用了一种更简单的方法来获取变量中的ESC字符。

编辑:我根据评论修改了代码......

@if (@CodeSegment == @Batch) @then

@echo off
title Ansi Test
setlocal EnableDelayedExpansion

for /F %%a in ('echo prompt $E ^| cmd') do set "esc=%%a"
set "csi=%esc%["

echo Inquiry:%csi%6n
cscript //nologo //E:JScript "%~F0"
set /p "pos=" > NUL
echo response=!pos:%esc%=ESC!

@end

var sh = WScript.CreateObject("WScript.Shell");
sh.AppActivate("Ansi Test");
sh.SendKeys("{ENTER}");

请发布结果......

答案 1 :(得分:0)

我无法测试,我不想要W10。

但我想,它可以正常工作SET /P 它使用xcopy /W技巧收集字符,并在第一个R

处停止
@echo off
setlocal enableExtensions enableDelayedExpansion
call :inquiry
for /L %%n in (1 1 20) do (
    set "key="
    for /F "usebackq delims=" %%L in (`xcopy /L /w "%~f0" "%~f0" 2^>NUL`) do (
        if not defined key set "key=%%L"
    )
    set "key=!key:~-1!"
    set "response=!response!!key!"
    if !key!==R goto :break
)
:break
echo !response!

编辑:目前失败
这似乎是XCOPY的问题 我想,XCOPY从输入缓冲区中读取一个字符,然后清除输入缓冲区。