[python] České znaky v curses
Martin B.
spooky.ln na tbs-software.com
Pátek Červen 10 15:55:02 CEST 2011
Zdravím,
Potřeboval bych poradit s vkládáním českých znaků do terminálu.
Dočetl jsem se že a vyzkoušel že pythonské curses nepodporuje nic víc
než ascii. teda hlavně nejvíce používaná fce getch().Existuje i patch
rozširující curses o fci get_wch() která podporuje unicode ale to by
pak nebylo jaksi funkční tam kde bude nepatchovaná verze.
Jak už je u mě zvykem mám už kus kodu hotov a tohle mě docela
překvapilo,protože výstup pomocí addstr() fungoval se znaky bez
problému.
Protože jsem potřeboval nějaký jednoduchý editovací widget zkusil jsem
texpad.Textbox() ale jak říkam české znaky nic a ještě při zapnutí
insert_mode padá na šílené rekurzi.
zkusil jsem napsat 'děsnou' okliku použitím slovníku se scankody klaves
a při návratu z getch() je odchytit a poslat rovnou do terminálu.
Chvíli to fungovalo než jsem zjistil že pár kláves má stejný kod :(
Zkoušel už tohle někdo řešit ?
Nebo jinak, řeší to nějak CDK nebo Urwid ?
šílenej paskvil upravený z original textpad.Textbox zde.
#encoding: utf-8
import curses, locale
import curses.ascii
HackTable = {154: 'Ě', 155: 'ě', 160: 'Š', 161: 'š', 140: 'Č', 141: 'č', 152: 'Ř', 153: 'ř',
189: 'Ž', 190: 'ž', 169: 'é', 173: 'í', 175: 'ů', 186: 'ú'}
# 154: 'Ú'
# 174: 'Ů'
class TextEdit:
def __init__(self, win):
self.maxy = win.getmaxyx()[0] - 1
self.maxx = win.getmaxyx()[1] - 1
self.win = curses.newwin(self.maxy,self.maxx, 1, 0)
self.status = curses.newwin(1, self.maxx+1, self.maxy, 0)
self.top = curses.newwin(1, self.maxx+1, 0, 0)
self.insert_mode = True
self.lines = {}
self.win.keypad(1)
self.win.idlok(1)
def _insert_printable_char(self, ch):
y, x = self.win.getyx()
if y < self.maxy or x < self.maxx:
'''
if self.insert_mode:
oldch = self.win.inch()
'''
try:
if self.insert_mode:
if ch in HackTable:
self.win.insstr(str(HackTable[ch]))
else:
self.win.insstr(chr(ch))
self.win.move(y, x + 1)
else:
if ch in HackTable:
self.win.addstr(HackTable[ch])
else:
self.win.addch(chr(ch))
except curses.error:
pass
def _end_of_line(self, y):
last = self.maxx - 2
while True:
if curses.ascii.ascii(self.win.inch(y, last)) != curses.ascii.SP:
last = min(self.maxx, last + 1)
break
elif last == 0:
break
last -= 1
return last
def _getline(self, y, x):
result = ''
for xpos in range(x, self._end_of_line(y)):
result = result + chr(curses.ascii.ascii(self.win.inch(y, xpos)))
return result
def _gather(self):
result = ''
for y in range(self.maxy + 1):
self.win.move(y, 0)
stop = self._end_of_line(y)
if stop == 0: continue
for x in range(self.maxx + 1):
if x > stop: break
result = result + chr(curses.ascii.ascii(self.win.inch(y, x)))
if self.maxy > 0: result = result + '\n'
return result
def _run(self, ch):
y,x = self.win.getyx()
#self.win.keypad(1)
# key handling
if curses.ascii.isprint(ch) or ch in HackTable:
if y < self.maxy or x < self.maxx:
self._insert_printable_char(ch)
elif ch in (curses.KEY_LEFT, curses.ascii.BS, curses.KEY_BACKSPACE):
if x > 0:
self.win.move(y, x - 1)
elif y == 0:
pass
else:
self.win.move(y - 1, self._end_of_line(y-1))
if ch in (curses.ascii.BS, curses.KEY_BACKSPACE):
self.win.delch()
elif ch == curses.KEY_RIGHT:
if x < self.maxx:
self.win.move(y, x + 1)
elif y == self.maxy: pass
else: self.win.move(y + 1, 0)
elif ch == curses.KEY_DOWN:
if y < self.maxy-1:
self.win.move(y + 1, x)
if x > self._end_of_line(y + 1):
self.win.move(y + 1, self._end_of_line(y + 1))
elif ch == curses.KEY_UP:
if y > 0:
self.win.move(y - 1, x)
if x > self._end_of_line(y - 1):
self.win.move(y - 1, self._end_of_line(y - 1))
elif ch == curses.ascii.SI:
self.insert_mode = not self.insert_mode
#self.win.insertln()
elif ch == curses.ascii.NL: # novy radek
if self.maxy == 0:
return 0
elif y < self.maxy - 2:
self.win.move(y + 1, 0)
#self.lines[y] = self._getline(y, 0)
return 1
def edit(self):
ch = ''
while True:
y, x = self.win.getyx()
self.top.erase()
self.status.erase()
self.status.addstr(0, 0, ' ' * (self.maxx), curses.color_pair(1))
self.status.addstr(0, 1, '{0}/{1}'.format(y, x), curses.color_pair(1))
self.top.addstr(0, 0, ' ' * (self.maxx), curses.color_pair(1))
self.top.addstr(0, 1, "ScanCode: {0}".format(ch), curses.color_pair(1))
self.status.refresh()
self.top.refresh()
self.win.move(y, x)
ch = self.win.getch()
if not ch: continue
if not self._run(ch): break
self.win.refresh()
return self._gather()
def main(stdscr, code):
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
a = TextEdit(stdscr)
a.edit()
if __name__ == '__main__':
locale.setlocale(locale.LC_ALL, '')
enc = locale.getpreferredencoding()
curses.wrapper(main, enc)
zkoušeno v Py2.7 Linux
Další informace o konferenci Python