读取线被ANSI转义序列混淆

时间:2018-05-22 15:03:09

标签: python bash ansi-escape

我正在研究一个Python脚本,有时需要用户输入输入。我在macOS Sierra上使用bash。

为了接收输入,我写了以下内容:

import readline  # gnureadline 6.3.8

START = '\033[91m\033[1m'
END = '\033[0m'

response = raw_input(START + 'Enter text: ' + END)

我使用STARTEND中的ANSI转义序列来直观地区分脚本的提示与用户的文本条目。

不幸的是,一旦我开始输入文本,该程序就会丢失用户输入文本的开头实际所在的位置。下面的第一个克拉是 CTRL A 现在映射到的地方,第二个是 CTRL E 带我的地方。箭头键同样相信用户输入的开头和结尾都是偏移的,如图所示。

Enter text: hello my name is             
                         ^               ^  

我尝试了一些事情来调试它。

  1. 我尝试在提示符和文本条目之间添加换行符,但这只会使偏移量变差。

  2. 如果我使用箭头键,而不是 CTRL A CTRL < kbd> E ,用于浏览字符串的选项箭头,按预期工作。也就是说,考虑到用户输入的字符串的长度和复杂性,仅使用箭头键移动字符串对用户来说将是痛苦的。

  3. 最重要的是,如果我根本不使用STARTEND,那么效果非常好。也就是说,脚本的可用性下降了 - 很难从该脚本的完整版本中找出所有其他文本中的提示。

  4. 我是否有一些技巧可以使用ANSI转义序列格式化提示,而不会破坏用户使用 CTRL A CTRL E 和选项箭头?谢谢!

3 个答案:

答案 0 :(得分:0)

单独打印提示并要求输入两个命令。

Python 3.x

print(START + 'Enter text: ' + END, end='')
response = input()

Python 2.x

import sys

# Use sys.stdout.write to avoid printing a trailing newline.
sys.stdout.write(START + 'Enter text: ' + END)
response = raw_input()

答案 1 :(得分:-1)

对于我来说,接受的答案没有解决。

我从

开始
START = '\x1b[7m\x1b[37m' # white on black
END = '\x1b[0m'  # reset
response = input(START + 'QUERY ' + END)

类似的结果

QUERY hello my name is hello my name is
              ^                                ^
              hello my name is hello my name is

使用上述解决方案,

print(START + 'QUERY ' + END, end='')
response = input()

考虑到该行从头开始的结果

QUERY hello my name is hello my name is
^                                ^
hello my name is hello my name is

可能是由于input("")的长度为0个字符。

知道那些控制字符被算作偏移量,我们可以再次使用它们来创建偏移量。

我的文字QUERY 长6个字符,所以我可以使用

print(START + 'QUERY ' + END, end='')
response = input('\033[D\033[C')

因为Cursor Forward, Cursor Back '\033', '[', 'D''\033', '[', 'C' 正在欺骗readline来偏移6个字符。

QUERY hello my name is hello my name is
\[D\[C^                                ^
      hello my name is hello my name is

答案 2 :(得分:-1)

Readline期望\001\002作为围绕不可见字符的标记:

import readline  # gnureadline 6.3.8

START = '\001\033[91m\033[1m\002'
END = '\001\033[0m\002'

response = raw_input(START + 'Enter text: ' + END)

使用以\001为前缀并以\002为后缀的ANSI转义序列,GNU readline将知道在确定提示字符串的长度时应排除这些字符。