使用Python curses高亮和选择文本
这是我第一次在Stack Overflow发帖。我在这个网站上潜水了好多年,获取了很多有用的信息,所以我想发个问题。
我一直在找一些类似的例子,但似乎找不到任何相关的内容。
最终,我想写一个简单的文本用户界面,用来查找文本提取程序中的假阳性和假阴性。假阳性模块是一个简单的选择题,显示彩色文本和使用getch()还算简单。但是,假阴性部分就变得有点困难了。
所以我想做的是:
- 在屏幕上显示一串文字(暂时不考虑滚动……唉),这只是一串没有换行的文字。
- 用户看到文本后,按'h'进入高亮模式。
- 用户可以控制光标,移动到文本的某个部分(文本仍然显示),然后按'v'开始高亮(我想尽量让这个过程接近vi编辑器)。
- 用户使用控制键(箭头键,hjkl)将光标从起始点移动到结束点,同时高亮经过的文本。这段高亮的文本应该是一个假阴性。
- 用户按下某个键(可能是'y'),选中的文本就会变色或者保持高亮,并且高亮的文本会保存到一个变量中,后面我会处理这个变量。
- 用户退出高亮模式,继续进行。
有没有什么建议可以让我开始?我在尝试一些简单的事情,比如保持文本在屏幕上并移动光标,但都没有成功。
我知道有curses.textpad.TextBox()模块,但它执行的是插入和删除等编辑操作,而我不想这样做。也许有办法禁用这些功能。
我还有其他问题,但我现在就先问这些。
谢谢!!
Neal
编辑:更具体一点,我不是在寻找编写整个程序的帮助,只是想要帮助我在显示的文本上移动光标、高亮文本、选择文本并将其保存到变量中。
2 个回答
我对ncurses并不熟悉,但如果用Tkinter或者其他图形界面工具包,可以通过画布来实现。首先,你需要设置一个滚动区域,然后把“h”键绑定到一个功能上,这样按下这个键时就会把一个高亮变量设置为真。接着,把鼠标点击绑定到一个函数上,这个函数可以获取开始的位置,再把左右箭头键绑定到移动光标的功能上,让光标左右移动一个字母,同时反转下一个字母的颜色,并记录你距离起始点有多少个字母,这样也能知道结束的位置。最后,把“y”键绑定到复制文本的功能。
其实这并没有看起来那么复杂,因为每个部分都是相对简单的功能。当然,这一切都要根据字体大小来调整,我建议使用固定宽度的字体,这样每个字母占用的空间都是一样的。再次强调,我对ncurses不太了解,但用任何工具包实现的方式都差不多。如果你能让用户通过鼠标点击选择整行文本,那编码起来会简单很多。如果你决定使用Tkinter或wxPython,并且需要更多帮助,可以发一些代码过来。
我想更新一下这个问题,以防其他人上网搜索时碰到这个问题。
其实答案非常简单,只需要看一下Python curses文档中列出的所有函数。
我做了一个三种状态的机器:状态1:普通模式(只显示文本),状态2:高亮模式,允许光标在窗口中移动,状态3:高亮器模式,只能在文本之间左右移动,并在移动时高亮文本。
要完成这个任务,只需要一些基本的curses函数调用。
我创建了多个窗口,但为了方便解释,我就假设只有一个窗口。
要在窗口中显示文本,可以使用:
window.addstr()
window.refresh()
要移动光标,可以使用:
#get current cursor position
curr_y, curr_x = window.getyx()
# depending on direction, update the cursor with
next_y, next_x = get_next_direction()
# place cursor in new position
window.move(next_y, next_x)
window.refresh()
当光标移动到高亮的起始点时,按下'v'键进入高亮状态,并限制光标的移动,同时改变选中文本的属性:
# get current cursor position
curr_y, curr_x = window.getyx()
# save position for later use
start_y = curr_y; start_x = curr_x
# loop until 'v' is pressed again
while highlight_state:
# change the attribute of the current character, for 1 character only, to reverse
window.chgat(curr_y,curr_x, 1, curses.A_REVERSE)
curr_y, curr_x = get_next_direction()
# save end state, this is buggy obviously, but you get the point
end_y = curr_y; end_x = curr_X
现在从开始到结束提取这些信息:
# get integer representation of char at positiong
outstr = ''
#from start to end
char_as_int = windows.inch(y,x)
char = char_as_int & 0000FF
attr = char_as_int & FFFF00 #not useful here, but maybe later
outstr += char
就这样!我还尝试了另一种保存高亮内容的方法,基本上是把x,y坐标转换为正在显示的字符串的索引,但那样会导致字符串表示的问题(换行、制表符等等),而且也更难实现。
如果有人有更高效或更简洁的方法,请回复!