UTF-8 でエンコードされた文字列を curses ウィンドウに出力しようとすると、非常に奇妙な問題に遭遇しました。これがコードです。正確な問題と、以下で試したことについて説明します。
# coding=UTF-8
import curses
import locale
import time
locale.setlocale(locale.LC_ALL, '')
code = locale.getpreferredencoding()
class AddCharCommand(object):
def __init__(self, window, line_start, y, x, character):
"""
Command class for adding the specified character, to the specified
window, at the specified coordinates.
"""
self.window = window
self.line_start = line_start
self.x = x
self.y = y
self.character = character
def write(self):
if self.character > 127:
# curses somehow returns a keycode that is 64 lower than what it
# should be, this takes care of the problem.
self.character += 64
self.string = unichr(self.character).encode(code)
self.window.addstr(self.y, self.x, self.string)
else:
self.window.addch(self.y, self.x, self.character)
def delete(self):
"""
Erase characters usually print two characters to the curses window.
As such both the character at these coordinates and the one next to it
(that is the one self.x + 1) must be replaced with the a blank space.
Move to cursor the original coordinates when done.
"""
for i in xrange(2):
self.window.addch(self.y, self.x + i, ord(' '))
self.window.move(self.y, self.x)
def main(screen):
maxy, maxx = screen.getmaxyx()
q = 0
commands = list()
x = 0
erase = ord(curses.erasechar())
while q != 27:
q = screen.getch()
if q == erase:
command = commands.pop(-1).delete()
x -= 1
continue
command = AddCharCommand(screen, 0, maxy/2, x, q)
commands.append(command)
command.write()
x += 1
curses.wrapper(main)
ここにGistへのリンクがあります。
問題は、è
キー (ASCII コード 232 を持つ) を押しても、その文字だけが出力されないことです。代わりに、文字列ăè
は指定された座標に出力されます。使用してみself.window.addstr(self.x, self.y, self.string[1])
ましたが、意味不明な印刷が行われました。
次に、Python プロンプトを起動して戻り値を確認しましたunichr(232).encode('utf-8')
が、実際には長さ 2 の文字列です。
非常に予期しない動作は、それを入れると、screen.addstr(4, 4, unichr(232).encode(code))
文字main
が正しく表示され、è
その文字のみが表示されることです。なんとしてでも文字を出力するクラスのwrite
メソッドを作った場合も同様です。AddCharCommand
è
もちろん、問題はè
これだけに限定されているわけではなく、ほとんどすべての拡張 ASCII 文字に当てはまります。
curses を使用した拡張 ASCII が少し不安定であることは知っていますが、この動作をまったく理解できません。ASCII コードをハードコーディングしても、コードが期待どおりに機能することは (私には) 意味がありませんが、そうしないと別の文字が追加されます。
私は周りを見回して、呪いに関するかなり多くのことを読みましたが、これに対する解決策を見つけることができませんでした. この問題について何か助けていただければ幸いです。それは私を怒らせています。
screen.getch()
あまり重要ではないかもしれませんが、127 を超える文字に対して誤った ASCII コードを返す理由と、実際の ASCII コードと curses によって返されるコードの違いが 64 である理由を誰かが説明してくれれば幸いです。
事前にどうもありがとうございました。