mirror of
https://github.com/wassname/pyreadline.git
synced 2026-06-30 16:40:09 +08:00
reformatted pyreadline/console
This commit is contained in:
@@ -1,21 +1,22 @@
|
||||
import glob,sys
|
||||
|
||||
success=False
|
||||
in_ironpython="IronPython" in sys.version
|
||||
success = False
|
||||
in_ironpython = "IronPython" in sys.version
|
||||
|
||||
if in_ironpython:
|
||||
try:
|
||||
from ironpython_console import *
|
||||
success=True
|
||||
success = True
|
||||
except ImportError:
|
||||
raise
|
||||
else:
|
||||
try:
|
||||
from console import *
|
||||
success=True
|
||||
success = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
if not success:
|
||||
raise ImportError("Could not find a console implementation for your platform")
|
||||
raise ImportError(
|
||||
"Could not find a console implementation for your platform")
|
||||
|
||||
+56
-54
@@ -7,61 +7,63 @@ escape_parts = re.compile(u'\001?\033\\[([0-9;]*)m\002?')
|
||||
|
||||
class AnsiState(object):
|
||||
def __init__(self,bold=False,inverse=False,color=u"white",background=u"black",backgroundbold=False):
|
||||
self.bold=bold
|
||||
self.inverse=inverse
|
||||
self.color=color
|
||||
self.background=background
|
||||
self.backgroundbold=backgroundbold
|
||||
self.bold = bold
|
||||
self.inverse = inverse
|
||||
self.color = color
|
||||
self.background = background
|
||||
self.backgroundbold = backgroundbold
|
||||
|
||||
trtable={u"black":0,u"red":4,u"green":2,u"yellow":6,u"blue":1,u"magenta":5,u"cyan":3,u"white":7}
|
||||
revtable=dict(zip(trtable.values(),trtable.keys()))
|
||||
trtable = {u"black":0, u"red":4, u"green":2, u"yellow":6,
|
||||
u"blue":1, u"magenta":5, u"cyan":3, u"white":7}
|
||||
revtable = dict(zip(trtable.values(),trtable.keys()))
|
||||
def get_winattr(self):
|
||||
attr=0
|
||||
attr = 0
|
||||
if self.bold:
|
||||
attr|=0x0008
|
||||
attr |= 0x0008
|
||||
if self.backgroundbold:
|
||||
attr|=0x0080
|
||||
attr |= 0x0080
|
||||
if self.inverse:
|
||||
attr|=0x4000
|
||||
attr|=self.trtable[self.color]
|
||||
attr|=(self.trtable[self.background]<<4)
|
||||
attr |= 0x4000
|
||||
attr |= self.trtable[self.color]
|
||||
attr |= (self.trtable[self.background] << 4)
|
||||
return attr
|
||||
|
||||
def set_winattr(self,attr):
|
||||
self.bold=bool(attr&0x0008)
|
||||
self.backgroundbold=bool(attr&0x0080)
|
||||
self.inverse=bool(attr&0x4000)
|
||||
self.color=self.revtable[attr&0x0007]
|
||||
self.background=self.revtable[(attr&0x0070)>>4]
|
||||
def set_winattr(self, attr):
|
||||
self.bold = bool(attr & 0x0008)
|
||||
self.backgroundbold = bool(attr & 0x0080)
|
||||
self.inverse = bool(attr & 0x4000)
|
||||
self.color = self.revtable[attr & 0x0007]
|
||||
self.background = self.revtable[(attr & 0x0070) >> 4]
|
||||
|
||||
winattr=property(get_winattr,set_winattr)
|
||||
def __repr__(self):
|
||||
return u'AnsiState(bold=%s,inverse=%s,color=%9s,background=%9s,backgroundbold=%s)# 0x%x'%(self.bold,
|
||||
self.inverse,
|
||||
'"%s"'%self.color,
|
||||
'"%s"'%self.background,
|
||||
self.backgroundbold,
|
||||
self.winattr)
|
||||
return u'AnsiState(bold=%s,inverse=%s,color=%9s,' \
|
||||
u'background=%9s,backgroundbold=%s)# 0x%x'% \
|
||||
(self.bold, self.inverse, '"%s"'%self.color,
|
||||
'"%s"'%self.background, self.backgroundbold,
|
||||
self.winattr)
|
||||
|
||||
def copy(self):
|
||||
x=AnsiState()
|
||||
x.bold=self.bold
|
||||
x.inverse=self.inverse
|
||||
x.color=self.color
|
||||
x.background=self.background
|
||||
x.backgroundbold=self.backgroundbold
|
||||
x = AnsiState()
|
||||
x.bold = self.bold
|
||||
x.inverse = self.inverse
|
||||
x.color = self.color
|
||||
x.background = self.background
|
||||
x.backgroundbold = self.backgroundbold
|
||||
return x
|
||||
defaultstate=AnsiState(False,False,u"white")
|
||||
|
||||
trtable={0:u"black",1:u"red",2:u"green",3:u"yellow",4:u"blue",5:u"magenta",6:u"cyan",7:u"white"}
|
||||
defaultstate = AnsiState(False,False,u"white")
|
||||
|
||||
trtable = {0:u"black", 1:u"red", 2:u"green", 3:u"yellow",
|
||||
4:u"blue", 5:u"magenta", 6:u"cyan", 7:u"white"}
|
||||
|
||||
class AnsiWriter(object):
|
||||
def __init__(self,default=defaultstate):
|
||||
if isinstance(defaultstate,AnsiState):
|
||||
self.defaultstate=default
|
||||
def __init__(self, default=defaultstate):
|
||||
if isinstance(defaultstate, AnsiState):
|
||||
self.defaultstate = default
|
||||
else:
|
||||
self.defaultstate=AnsiState()
|
||||
self.defaultstate.winattr=defaultstate
|
||||
self.defaultstate.winattr = defaultstate
|
||||
|
||||
|
||||
def write_color(self,text, attr=None):
|
||||
@@ -70,21 +72,21 @@ class AnsiWriter(object):
|
||||
return the number of characters written.
|
||||
'''
|
||||
if isinstance(attr,AnsiState):
|
||||
defaultstate=attr
|
||||
defaultstate = attr
|
||||
elif attr is None: #use attribute form initial console
|
||||
attr = self.defaultstate.copy()
|
||||
else:
|
||||
defaultstate=AnsiState()
|
||||
defaultstate.winattr=attr
|
||||
attr=defaultstate
|
||||
defaultstate = AnsiState()
|
||||
defaultstate.winattr = attr
|
||||
attr = defaultstate
|
||||
chunks = terminal_escape.split(text)
|
||||
n = 0 # count the characters we actually write, omitting the escapes
|
||||
res=[]
|
||||
for chunk in chunks:
|
||||
m = escape_parts.match(chunk)
|
||||
if m:
|
||||
parts=m.group(1).split(u";")
|
||||
if len(parts)==1 and parts[0]==u"0":
|
||||
parts = m.group(1).split(u";")
|
||||
if len(parts) == 1 and parts[0] == u"0":
|
||||
attr = self.defaultstate.copy()
|
||||
continue
|
||||
for part in parts:
|
||||
@@ -96,29 +98,29 @@ class AnsiWriter(object):
|
||||
elif part == u"1": # switch on bold (i.e. intensify foreground color)
|
||||
attr.bold=True
|
||||
elif len(part) == 2 and u"30" <= part <= u"37": # set foreground color
|
||||
attr.color = trtable[int(part)-30]
|
||||
attr.color = trtable[int(part) - 30]
|
||||
elif len(part) == 2 and u"40" <= part <= u"47": # set background color
|
||||
attr.color = trtable[int(part)-40]
|
||||
attr.color = trtable[int(part) - 40]
|
||||
continue
|
||||
n += len(chunk)
|
||||
if True:
|
||||
res.append((attr.copy(),chunk))
|
||||
res.append((attr.copy(), chunk))
|
||||
return n,res
|
||||
|
||||
def parse_color(self,text, attr=None):
|
||||
n,res=self.write_color(text,attr)
|
||||
return n,[attr.winattr for attr,text in res]
|
||||
n,res=self.write_color(text, attr)
|
||||
return n, [attr.winattr for attr, text in res]
|
||||
|
||||
def write_color(text,attr=None):
|
||||
a=AnsiWriter(defaultstate)
|
||||
return a.write_color(text,attr)
|
||||
def write_color(text, attr=None):
|
||||
a = AnsiWriter(defaultstate)
|
||||
return a.write_color(text, attr)
|
||||
|
||||
def write_color_old( text, attr=None):
|
||||
u'''write text at current cursor position and interpret color escapes.
|
||||
|
||||
return the number of characters written.
|
||||
'''
|
||||
res=[]
|
||||
res = []
|
||||
chunks = terminal_escape.split(text)
|
||||
n = 0 # count the characters we actually write, omitting the escapes
|
||||
if attr is None:#use attribute from initial console
|
||||
@@ -138,14 +140,14 @@ def write_color_old( text, attr=None):
|
||||
# we have to mirror bits
|
||||
attr = (attr & ~0x07) | ((part & 0x1) << 2) | (part & 0x2) | ((part & 0x4) >> 2)
|
||||
elif len(part) == 2 and u"40" <= part <= u"47": # set background color
|
||||
part = int(part)-40
|
||||
part = int(part) - 40
|
||||
# we have to mirror bits
|
||||
attr = (attr & ~0x70) | ((part & 0x1) << 6) | ((part & 0x2) << 4) | ((part & 0x4) << 2)
|
||||
# ignore blink, underline and anything we don't understand
|
||||
continue
|
||||
n += len(chunk)
|
||||
if chunk:
|
||||
res.append((u"0x%x"%attr,chunk))
|
||||
res.append((u"0x%x"%attr, chunk))
|
||||
return res
|
||||
|
||||
|
||||
|
||||
@@ -156,14 +156,14 @@ funcs = [
|
||||
]
|
||||
|
||||
# I don't want events for these keys, they are just a bother for my application
|
||||
key_modifiers = { VK_SHIFT:1,
|
||||
VK_CONTROL:1,
|
||||
VK_MENU:1, # alt key
|
||||
0x5b:1, # windows key
|
||||
key_modifiers = { VK_SHIFT : 1,
|
||||
VK_CONTROL : 1,
|
||||
VK_MENU : 1, # alt key
|
||||
0x5b : 1, # windows key
|
||||
}
|
||||
|
||||
def split_block(text,size=1000):
|
||||
return [text[start:start+size] for start in range(0, len(text), size)]
|
||||
def split_block(text, size=1000):
|
||||
return [text[start:start + size] for start in range(0, len(text), size)]
|
||||
|
||||
|
||||
|
||||
@@ -184,8 +184,9 @@ class Console(object):
|
||||
#self.AllocConsole()
|
||||
|
||||
if newbuffer:
|
||||
self.hout = self.CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
|
||||
0, None, 1, None)
|
||||
self.hout = self.CreateConsoleScreenBuffer(
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, None, 1, None)
|
||||
self.SetConsoleActiveScreenBuffer(self.hout)
|
||||
else:
|
||||
self.hout = self.GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
@@ -199,10 +200,9 @@ class Console(object):
|
||||
self.attr = info.wAttributes
|
||||
self.saveattr = info.wAttributes # remember the initial colors
|
||||
|
||||
self.defaultstate=AnsiState()
|
||||
self.defaultstate.winattr=info.wAttributes
|
||||
self.ansiwriter=AnsiWriter(self.defaultstate)
|
||||
# self.ansiwriter.defaultstate.bold=False
|
||||
self.defaultstate = AnsiState()
|
||||
self.defaultstate.winattr = info.wAttributes
|
||||
self.ansiwriter = AnsiWriter(self.defaultstate)
|
||||
|
||||
background = self.attr & 0xf0
|
||||
for escape in self.escape_to_color:
|
||||
@@ -212,8 +212,10 @@ class Console(object):
|
||||
self.softspace = 0 # this is for using it as a file-like object
|
||||
self.serial = 0
|
||||
|
||||
self.pythondll = CDLL(u'python%s%s' % (sys.version[0], sys.version[2]))
|
||||
self.inputHookPtr = c_int.from_address(addressof(self.pythondll.PyOS_InputHook)).value
|
||||
self.pythondll = \
|
||||
CDLL(u'python%s%s' % (sys.version[0], sys.version[2]))
|
||||
self.inputHookPtr = \
|
||||
c_int.from_address(addressof(self.pythondll.PyOS_InputHook)).value
|
||||
setattr(Console, u'PyMem_Malloc', self.pythondll.PyMem_Malloc)
|
||||
|
||||
def __del__(self):
|
||||
@@ -232,7 +234,8 @@ class Console(object):
|
||||
return top,bot
|
||||
|
||||
def fixcoord(self, x, y):
|
||||
u'''Return a long with x and y packed inside, also handle negative x and y.'''
|
||||
u'''Return a long with x and y packed inside,
|
||||
also handle negative x and y.'''
|
||||
if x < 0 or y < 0:
|
||||
info = CONSOLE_SCREEN_BUFFER_INFO()
|
||||
self.GetConsoleScreenBufferInfo(self.hout, byref(info))
|
||||
@@ -240,8 +243,8 @@ class Console(object):
|
||||
x = info.srWindow.Right - x
|
||||
y = info.srWindow.Bottom + y
|
||||
|
||||
# this is a hack! ctypes won't pass structures but COORD is just like a
|
||||
# long, so this works.
|
||||
# this is a hack! ctypes won't pass structures but COORD is
|
||||
# just like a long, so this works.
|
||||
return c_int(y << 16 | x)
|
||||
|
||||
def pos(self, x=None, y=None):
|
||||
@@ -251,11 +254,12 @@ class Console(object):
|
||||
self.GetConsoleScreenBufferInfo(self.hout, byref(info))
|
||||
return (info.dwCursorPosition.X, info.dwCursorPosition.Y)
|
||||
else:
|
||||
return self.SetConsoleCursorPosition(self.hout, self.fixcoord(x, y))
|
||||
return self.SetConsoleCursorPosition(self.hout,
|
||||
self.fixcoord(x, y))
|
||||
|
||||
def home(self):
|
||||
u'''Move to home.'''
|
||||
self.pos(0,0)
|
||||
self.pos(0, 0)
|
||||
|
||||
# Map ANSI color escape sequences into Windows Console Attributes
|
||||
|
||||
@@ -312,7 +316,7 @@ class Console(object):
|
||||
elif chunk[0] == u'\r': # carriage return
|
||||
x = 0
|
||||
elif chunk[0] == u'\t': # tab
|
||||
x = 8*(int(x/8)+1)
|
||||
x = 8 * (int(x / 8) + 1)
|
||||
if x > w: # newline
|
||||
x -= w
|
||||
y += 1
|
||||
@@ -342,25 +346,27 @@ class Console(object):
|
||||
|
||||
def write_color(self, text, attr=None):
|
||||
text = ensure_unicode(text)
|
||||
n,res= self.ansiwriter.write_color(text,attr)
|
||||
n, res= self.ansiwriter.write_color(text, attr)
|
||||
junk = c_int(0)
|
||||
for attr,chunk in res:
|
||||
log(u"console.attr:%s"%unicode(attr))
|
||||
log(u"console.chunk:%s"%unicode(chunk))
|
||||
self.SetConsoleTextAttribute(self.hout, attr.winattr)
|
||||
for short_chunk in split_block(chunk):
|
||||
self.WriteConsoleW(self.hout, short_chunk, len(short_chunk), byref(junk), None)
|
||||
self.WriteConsoleW(self.hout, short_chunk,
|
||||
len(short_chunk), byref(junk), None)
|
||||
return n
|
||||
|
||||
def write_plain(self, text, attr=None):
|
||||
u'''write text at current cursor position.'''
|
||||
log(u'write("%s", %s)' %(text,attr))
|
||||
log(u'write("%s", %s)' %(text, attr))
|
||||
if attr is None:
|
||||
attr = self.attr
|
||||
n = c_int(0)
|
||||
self.SetConsoleTextAttribute(self.hout, attr)
|
||||
for short_chunk in split_block(chunk):
|
||||
self.WriteConsoleW(self.hout, ensure_unicode(short_chunk), len(short_chunk), byref(junk), None)
|
||||
self.WriteConsoleW(self.hout, ensure_unicode(short_chunk),
|
||||
len(short_chunk), byref(junk), None)
|
||||
return len(text)
|
||||
|
||||
#This function must be used to ensure functioning with EMACS
|
||||
@@ -368,7 +374,7 @@ class Console(object):
|
||||
if os.environ.has_key(u"EMACS"):
|
||||
def write_color(self, text, attr=None):
|
||||
junk = c_int(0)
|
||||
self.WriteFile(self.hout, text, len(text), byref(junk),None)
|
||||
self.WriteFile(self.hout, text, len(text), byref(junk), None)
|
||||
return len(text)
|
||||
write_plain = write_color
|
||||
|
||||
@@ -399,8 +405,10 @@ class Console(object):
|
||||
w = info.dwSize.X
|
||||
n = c_int(0)
|
||||
for y in range(info.dwSize.Y):
|
||||
self.FillConsoleOutputAttribute(self.hout, attr, w, self.fixcoord(0, y), byref(n))
|
||||
self.FillConsoleOutputCharacterW(self.hout, ord(fill[0]), w, self.fixcoord(0, y), byref(n))
|
||||
self.FillConsoleOutputAttribute(self.hout, attr,
|
||||
w, self.fixcoord(0, y), byref(n))
|
||||
self.FillConsoleOutputCharacterW(self.hout, ord(fill[0]),
|
||||
w, self.fixcoord(0, y), byref(n))
|
||||
|
||||
self.attr = attr
|
||||
|
||||
@@ -411,16 +419,17 @@ class Console(object):
|
||||
|
||||
pos = self.fixcoord(x, y)
|
||||
n = c_int(0)
|
||||
self.WriteConsoleOutputCharacterW(self.hout, text, len(text), pos, byref(n))
|
||||
self.WriteConsoleOutputCharacterW(self.hout, text,
|
||||
len(text), pos, byref(n))
|
||||
self.FillConsoleOutputAttribute(self.hout, attr, n, pos, byref(n))
|
||||
|
||||
def clear_to_end_of_window(self):
|
||||
top,bot=self._get_top_bot()
|
||||
pos=self.pos()
|
||||
w,h=self.size()
|
||||
self.rectangle( (pos[0],pos[1],w,pos[1]+1))
|
||||
if pos[1]<bot:
|
||||
self.rectangle((0,pos[1]+1,w,bot+1))
|
||||
top, bot = self._get_top_bot()
|
||||
pos = self.pos()
|
||||
w, h = self.size()
|
||||
self.rectangle( (pos[0], pos[1], w, pos[1] + 1))
|
||||
if pos[1] < bot:
|
||||
self.rectangle((0, pos[1] + 1, w, bot + 1))
|
||||
|
||||
def rectangle(self, rect, attr=None, fill=u' '):
|
||||
u'''Fill Rectangle.'''
|
||||
@@ -430,23 +439,24 @@ class Console(object):
|
||||
attr = self.attr
|
||||
for y in range(y0, y1):
|
||||
pos = self.fixcoord(x0, y)
|
||||
self.FillConsoleOutputAttribute(self.hout, attr, x1-x0, pos, byref(n))
|
||||
self.FillConsoleOutputCharacterW(self.hout, ord(fill[0]), x1-x0, pos, byref(n))
|
||||
self.FillConsoleOutputAttribute(self.hout, attr, x1 - x0,
|
||||
pos, byref(n))
|
||||
self.FillConsoleOutputCharacterW(self.hout, ord(fill[0]), x1 - x0,
|
||||
pos, byref(n))
|
||||
|
||||
def scroll(self, rect, dx, dy, attr=None, fill=' '):
|
||||
u'''Scroll a rectangle.'''
|
||||
if attr is None:
|
||||
attr = self.attr
|
||||
|
||||
x0, y0, x1, y1 = rect
|
||||
source = SMALL_RECT(x0, y0, x1-1, y1-1)
|
||||
dest = self.fixcoord(x0+dx, y0+dy)
|
||||
source = SMALL_RECT(x0, y0, x1 - 1, y1 - 1)
|
||||
dest = self.fixcoord(x0 + dx, y0 + dy)
|
||||
style = CHAR_INFO()
|
||||
style.Char.AsciiChar = ensure_str(fill[0])
|
||||
style.Attributes = attr
|
||||
|
||||
return self.ScrollConsoleScreenBufferW(self.hout, byref(source), byref(source),
|
||||
dest, byref(style))
|
||||
return self.ScrollConsoleScreenBufferW(self.hout, byref(source),
|
||||
byref(source), dest, byref(style))
|
||||
|
||||
def scroll_window(self, lines):
|
||||
u'''Scroll the window by the indicated number of lines.'''
|
||||
@@ -470,7 +480,7 @@ class Console(object):
|
||||
nrect.Bottom = bot
|
||||
nrect.Left = rect.Left
|
||||
nrect.Right = rect.Right
|
||||
log(u'sn: top=%d bot=%d' % (top,bot))
|
||||
log(u'sn: top=%d bot=%d' % (top, bot))
|
||||
r=self.SetConsoleWindowInfo(self.hout, True, byref(nrect))
|
||||
log(u'r=%d' % r)
|
||||
|
||||
@@ -483,7 +493,8 @@ class Console(object):
|
||||
while 1:
|
||||
if inputHookFunc:
|
||||
call_function(inputHookFunc, ())
|
||||
status = self.ReadConsoleInputW(self.hin, byref(Cevent), 1, byref(count))
|
||||
status = self.ReadConsoleInputW(self.hin,
|
||||
byref(Cevent), 1, byref(count))
|
||||
if status and count.value == 1:
|
||||
e = event(self, Cevent)
|
||||
log(u"console.get %s"%ensure_unicode(e.keyinfo))
|
||||
@@ -501,8 +512,9 @@ class Console(object):
|
||||
self.scroll_window(-12)
|
||||
else:
|
||||
return e
|
||||
elif e.type == u'KeyRelease' and e.keyinfo==(True, False, False, 83):
|
||||
log(u"getKeypress:%s,%s,%s"%(e.keyinfo,e.keycode,e.type))
|
||||
elif ((e.type == u'KeyRelease') and
|
||||
(e.keyinfo == (True, False, False, 83))):
|
||||
log(u"getKeypress:%s,%s,%s"%(e.keyinfo, e.keycode, e.type))
|
||||
return e
|
||||
|
||||
def getchar(self):
|
||||
@@ -511,9 +523,12 @@ class Console(object):
|
||||
Cevent = INPUT_RECORD()
|
||||
count = c_int(0)
|
||||
while 1:
|
||||
status = self.ReadConsoleInputW(self.hin, byref(Cevent), 1, byref(count))
|
||||
if (status and count.value==1 and Cevent.EventType == 1 and
|
||||
Cevent.Event.KeyEvent.bKeyDown):
|
||||
status = self.ReadConsoleInputW(self.hin,
|
||||
byref(Cevent), 1, byref(count))
|
||||
if (status and
|
||||
(count.value == 1) and
|
||||
(Cevent.EventType == 1) and
|
||||
Cevent.Event.KeyEvent.bKeyDown):
|
||||
sym = keysym(Cevent.Event.KeyEvent.wVirtualKeyCode)
|
||||
if len(sym) == 0:
|
||||
sym = Cevent.Event.KeyEvent.uChar.AsciiChar
|
||||
@@ -523,7 +538,8 @@ class Console(object):
|
||||
u'''Check event queue.'''
|
||||
Cevent = INPUT_RECORD()
|
||||
count = c_int(0)
|
||||
status = self.PeekConsoleInputW(self.hin, byref(Cevent), 1, byref(count))
|
||||
status = self.PeekConsoleInputW(self.hin,
|
||||
byref(Cevent), 1, byref(count))
|
||||
if status and count == 1:
|
||||
return event(self, Cevent)
|
||||
|
||||
@@ -550,7 +566,8 @@ class Console(object):
|
||||
width = max(width, wmin)
|
||||
height = max(height, hmin)
|
||||
#print width, height
|
||||
self.SetConsoleScreenBufferSize(self.hout, self.fixcoord(width, height))
|
||||
self.SetConsoleScreenBufferSize(self.hout,
|
||||
self.fixcoord(width, height))
|
||||
else:
|
||||
return (info.dwSize.X, info.dwSize.Y)
|
||||
|
||||
@@ -575,8 +592,8 @@ class Console(object):
|
||||
# add the functions from the dll to the class
|
||||
for func in funcs:
|
||||
setattr(Console, func, getattr(windll.kernel32, func))
|
||||
windll.kernel32.SetConsoleTitleW.argtypes=[c_wchar_p]
|
||||
windll.kernel32.GetConsoleTitleW.argtypes=[c_wchar_p,c_short]
|
||||
windll.kernel32.SetConsoleTitleW.argtypes = [c_wchar_p]
|
||||
windll.kernel32.GetConsoleTitleW.argtypes = [c_wchar_p,c_short]
|
||||
|
||||
from event import Event
|
||||
|
||||
@@ -607,7 +624,7 @@ class event(Event):
|
||||
self.char = input.Event.KeyEvent.uChar.UnicodeChar
|
||||
self.keycode = input.Event.KeyEvent.wVirtualKeyCode
|
||||
self.state = input.Event.KeyEvent.dwControlKeyState
|
||||
self.keyinfo=make_KeyPress(self.char,self.state,self.keycode)
|
||||
self.keyinfo = make_KeyPress(self.char,self.state,self.keycode)
|
||||
|
||||
elif input.EventType == MOUSE_EVENT:
|
||||
if input.Event.MouseEvent.dwEventFlags & MOUSE_MOVED:
|
||||
@@ -661,7 +678,7 @@ HOOKFUNC22 = CFUNCTYPE(c_char_p, c_char_p)
|
||||
HOOKFUNC23 = CFUNCTYPE(c_char_p, c_void_p, c_void_p, c_char_p)
|
||||
|
||||
readline_hook = None # the python hook goes here
|
||||
readline_ref = None # this holds a reference to the c-callable to keep it alive
|
||||
readline_ref = None # reference to the c-callable to keep it alive
|
||||
|
||||
def hook_wrapper_23(stdin, stdout, prompt):
|
||||
u'''Wrap a Python readline so it behaves like GNU readline.'''
|
||||
@@ -683,8 +700,8 @@ def hook_wrapper_23(stdin, stdout, prompt):
|
||||
res = u'\n'
|
||||
# we have to make a copy because the caller expects to free the result
|
||||
n = len(res)
|
||||
p = Console.PyMem_Malloc(n+1)
|
||||
cdll.msvcrt.strncpy(p, res, n+1)
|
||||
p = Console.PyMem_Malloc(n + 1)
|
||||
cdll.msvcrt.strncpy(p, res, n + 1)
|
||||
return p
|
||||
|
||||
def hook_wrapper(prompt):
|
||||
@@ -710,13 +727,14 @@ def hook_wrapper(prompt):
|
||||
return p
|
||||
|
||||
def install_readline(hook):
|
||||
'''Set up things for the interpreter to call our function like GNU readline.'''
|
||||
'''Set up things for the interpreter to call
|
||||
our function like GNU readline.'''
|
||||
global readline_hook, readline_ref
|
||||
# save the hook so the wrapper can call it
|
||||
readline_hook = hook
|
||||
# get the address of PyOS_ReadlineFunctionPointer so we can update it
|
||||
PyOS_RFP = c_int.from_address(Console.GetProcAddress(sys.dllhandle,
|
||||
"PyOS_ReadlineFunctionPointer"))
|
||||
"PyOS_ReadlineFunctionPointer"))
|
||||
# save a reference to the generated C-callable so it doesn't go away
|
||||
if sys.version < '2.3':
|
||||
readline_ref = HOOKFUNC22(hook_wrapper)
|
||||
@@ -738,11 +756,11 @@ if __name__ == '__main__':
|
||||
sys.stdout = c
|
||||
sys.stderr = c
|
||||
c.page()
|
||||
print p("d"),p("D")
|
||||
print p("d"), p("D")
|
||||
c.pos(5, 10)
|
||||
c.write('hi there')
|
||||
print 'some printed output'
|
||||
for i in range(10):
|
||||
q=c.getkeypress()
|
||||
q = c.getkeypress()
|
||||
print q
|
||||
del c
|
||||
|
||||
@@ -2,12 +2,13 @@ class Event(object):
|
||||
u'''Represent events from the console.'''
|
||||
def __init__(self, console, input):
|
||||
pass
|
||||
|
||||
def __repr__(self):
|
||||
u'''Display an event for debugging.'''
|
||||
if self.type in [u'KeyPress', u'KeyRelease']:
|
||||
chr=self.char
|
||||
chr = self.char
|
||||
if ord(chr)<ord(u"A"):
|
||||
chr=u"?"
|
||||
chr = u"?"
|
||||
s = u"%s char='%s'%d keysym='%s' keycode=%d:%x state=%x keyinfo=%s" % \
|
||||
(self.type, chr, ord(self.char), self.keysym, self.keycode, self.keycode,
|
||||
self.state, self.keyinfo)
|
||||
|
||||
@@ -37,10 +37,10 @@ import System
|
||||
from event import Event
|
||||
from pyreadline.logger import log
|
||||
|
||||
#print "Codepage",System.Console.InputEncoding.CodePage
|
||||
from pyreadline.keysyms import make_keysym, make_keyinfo,make_KeyPress,make_KeyPress_from_keydescr
|
||||
from pyreadline.keysyms import \
|
||||
make_keysym, make_keyinfo, make_KeyPress, make_KeyPress_from_keydescr
|
||||
from pyreadline.console.ansi import AnsiState
|
||||
color=System.ConsoleColor
|
||||
color = System.ConsoleColor
|
||||
|
||||
ansicolor={u"0;30": color.Black,
|
||||
u"0;31": color.DarkRed,
|
||||
@@ -60,14 +60,14 @@ ansicolor={u"0;30": color.Black,
|
||||
u"1;37": color.White
|
||||
}
|
||||
|
||||
winattr={u"black":0,u"darkgray":0+8,
|
||||
u"darkred":4,u"red":4+8,
|
||||
u"darkgreen":2,u"green":2+8,
|
||||
u"darkyellow":6,u"yellow":6+8,
|
||||
u"darkblue":1,u"blue":1+8,
|
||||
u"darkmagenta":5, u"magenta":5+8,
|
||||
u"darkcyan":3,u"cyan":3+8,
|
||||
u"gray":7,u"white":7+8}
|
||||
winattr = {u"black" : 0, u"darkgray" : 0+8,
|
||||
u"darkred" : 4, u"red" : 4+8,
|
||||
u"darkgreen" : 2, u"green" : 2+8,
|
||||
u"darkyellow" : 6, u"yellow" : 6+8,
|
||||
u"darkblue" : 1, u"blue" : 1+8,
|
||||
u"darkmagenta" : 5, u"magenta" : 5+8,
|
||||
u"darkcyan" : 3, u"cyan" : 3+8,
|
||||
u"gray" : 7, u"white" : 7+8}
|
||||
|
||||
class Console(object):
|
||||
u'''Console driver for Windows.
|
||||
@@ -80,21 +80,23 @@ class Console(object):
|
||||
newbuffer=1 will allocate a new buffer so the old content will be restored
|
||||
on exit.
|
||||
'''
|
||||
self.serial=0
|
||||
self.serial = 0
|
||||
self.attr = System.Console.ForegroundColor
|
||||
self.saveattr = winattr[str(System.Console.ForegroundColor).lower()]
|
||||
self.savebg=System.Console.BackgroundColor
|
||||
self.savebg = System.Console.BackgroundColor
|
||||
log(u'initial attr=%s' % self.attr)
|
||||
|
||||
def _get(self):
|
||||
top=System.Console.WindowTop
|
||||
top = System.Console.WindowTop
|
||||
log(u"WindowTop:%s"%top)
|
||||
return top
|
||||
def _set(self,value):
|
||||
top=System.Console.WindowTop
|
||||
log(u"Set WindowTop:old:%s,new:%s"%(top,value))
|
||||
WindowTop=property(_get,_set)
|
||||
del _get,_set
|
||||
|
||||
def _set(self, value):
|
||||
top = System.Console.WindowTop
|
||||
log(u"Set WindowTop:old:%s,new:%s"%(top, value))
|
||||
|
||||
WindowTop = property(_get, _set)
|
||||
del _get, _set
|
||||
|
||||
def __del__(self):
|
||||
u'''Cleanup the console when finished.'''
|
||||
@@ -106,16 +108,16 @@ class Console(object):
|
||||
if x is not None:
|
||||
System.Console.CursorLeft=x
|
||||
else:
|
||||
x=System.Console.CursorLeft
|
||||
x = System.Console.CursorLeft
|
||||
if y is not None:
|
||||
System.Console.CursorTop=y
|
||||
else:
|
||||
y=System.Console.CursorTop
|
||||
return x,y
|
||||
y = System.Console.CursorTop
|
||||
return x, y
|
||||
|
||||
def home(self):
|
||||
u'''Move to home.'''
|
||||
self.pos(0,0)
|
||||
self.pos(0, 0)
|
||||
|
||||
# Map ANSI color escape sequences into Windows Console Attributes
|
||||
|
||||
@@ -155,7 +157,7 @@ class Console(object):
|
||||
elif chunk[0] == u'\r': # carriage return
|
||||
x = 0
|
||||
elif chunk[0] == u'\t': # tab
|
||||
x = 8*(int(x/8)+1)
|
||||
x = 8 * (int(x / 8) + 1)
|
||||
if x > w: # newline
|
||||
x -= w
|
||||
y += 1
|
||||
@@ -183,10 +185,12 @@ class Console(object):
|
||||
y = h - 1
|
||||
return scroll
|
||||
|
||||
trtable={0:color.Black,4:color.DarkRed,2:color.DarkGreen,6:color.DarkYellow,
|
||||
1:color.DarkBlue,5:color.DarkMagenta,3:color.DarkCyan,7:color.Gray,
|
||||
8:color.DarkGray,4+8:color.Red,2+8:color.Green,6+8:color.Yellow,
|
||||
1+8:color.Blue,5+8:color.Magenta,3+8:color.Cyan,7+8:color.White}
|
||||
trtable = {0 : color.Black, 4 : color.DarkRed, 2 : color.DarkGreen,
|
||||
6 : color.DarkYellow, 1 : color.DarkBlue, 5 : color.DarkMagenta,
|
||||
3 : color.DarkCyan, 7 : color.Gray, 8 : color.DarkGray,
|
||||
4+8 : color.Red, 2+8 : color.Green, 6+8 : color.Yellow,
|
||||
1+8 : color.Blue, 5+8 : color.Magenta,3+8 : color.Cyan,
|
||||
7+8 : color.White}
|
||||
|
||||
def write_color(self, text, attr=None):
|
||||
'''write text at current cursor position and interpret color escapes.
|
||||
@@ -196,31 +200,30 @@ class Console(object):
|
||||
log(u'write_color("%s", %s)' % (text, attr))
|
||||
chunks = self.terminal_escape.split(text)
|
||||
log(u'chunks=%s' % repr(chunks))
|
||||
bg=self.savebg
|
||||
bg = self.savebg
|
||||
n = 0 # count the characters we actually write, omitting the escapes
|
||||
if attr is None:#use attribute from initial console
|
||||
attr = self.attr
|
||||
try:
|
||||
fg=self.trtable[(0x000f&attr)]
|
||||
bg=self.trtable[(0x00f0&attr)>>4]
|
||||
fg = self.trtable[(0x000f&attr)]
|
||||
bg = self.trtable[(0x00f0&attr)>>4]
|
||||
except TypeError:
|
||||
fg=attr
|
||||
fg = attr
|
||||
|
||||
for chunk in chunks:
|
||||
m = self.escape_parts.match(chunk)
|
||||
if m:
|
||||
log(m.group(1))
|
||||
attr=ansicolor.get(m.group(1),self.attr)
|
||||
attr = ansicolor.get(m.group(1), self.attr)
|
||||
n += len(chunk)
|
||||
System.Console.ForegroundColor=fg
|
||||
System.Console.BackgroundColor=bg
|
||||
#self.WriteConsoleA(self.hout, chunk, len(chunk), byref(junk), None)
|
||||
System.Console.ForegroundColor = fg
|
||||
System.Console.BackgroundColor = bg
|
||||
System.Console.Write(chunk)
|
||||
return n
|
||||
|
||||
def write_plain(self, text, attr=None):
|
||||
u'''write text at current cursor position.'''
|
||||
log(u'write("%s", %s)' %(text,attr))
|
||||
log(u'write("%s", %s)' %(text, attr))
|
||||
if attr is None:
|
||||
attr = self.attr
|
||||
n = c_int(0)
|
||||
@@ -254,92 +257,87 @@ class Console(object):
|
||||
|
||||
def text(self, x, y, text, attr=None):
|
||||
u'''Write text at the given position.'''
|
||||
self.pos(x,y)
|
||||
self.write_color(text,attr)
|
||||
self.pos(x, y)
|
||||
self.write_color(text, attr)
|
||||
|
||||
def clear_to_end_of_window(self):
|
||||
oldtop=self.WindowTop
|
||||
lastline=self.WindowTop+System.Console.WindowHeight
|
||||
pos=self.pos()
|
||||
w,h=self.size()
|
||||
length=w-pos[0]+min((lastline-pos[1]-1),5)*w-1
|
||||
self.write_color(length*u" ")
|
||||
oldtop = self.WindowTop
|
||||
lastline = self.WindowTop+System.Console.WindowHeight
|
||||
pos = self.pos()
|
||||
w, h = self.size()
|
||||
length = w - pos[0] + min((lastline - pos[1] - 1), 5) * w - 1
|
||||
self.write_color(length * u" ")
|
||||
self.pos(*pos)
|
||||
self.WindowTop=oldtop
|
||||
self.WindowTop = oldtop
|
||||
|
||||
def rectangle(self, rect, attr=None, fill=u' '):
|
||||
u'''Fill Rectangle.'''
|
||||
pass
|
||||
oldtop=self.WindowTop
|
||||
oldpos=self.pos()
|
||||
oldtop = self.WindowTop
|
||||
oldpos = self.pos()
|
||||
#raise NotImplementedError
|
||||
x0, y0, x1, y1 = rect
|
||||
if attr is None:
|
||||
attr = self.attr
|
||||
if fill:
|
||||
rowfill=fill[:1]*abs(x1-x0)
|
||||
rowfill = fill[:1] * abs(x1 - x0)
|
||||
else:
|
||||
rowfill=u' '*abs(x1-x0)
|
||||
rowfill = u' ' * abs(x1 - x0)
|
||||
for y in range(y0, y1):
|
||||
System.Console.SetCursorPosition(x0,y)
|
||||
self.write_color(rowfill,attr)
|
||||
System.Console.SetCursorPosition(x0, y)
|
||||
self.write_color(rowfill, attr)
|
||||
self.pos(*oldpos)
|
||||
|
||||
def scroll(self, rect, dx, dy, attr=None, fill=' '):
|
||||
u'''Scroll a rectangle.'''
|
||||
pass
|
||||
raise NotImplementedError
|
||||
|
||||
def scroll_window(self, lines):
|
||||
u'''Scroll the window by the indicated number of lines.'''
|
||||
top=self.WindowTop+lines
|
||||
if top<0:
|
||||
top=0
|
||||
if top+System.Console.WindowHeight>System.Console.BufferHeight:
|
||||
top=System.Console.BufferHeight
|
||||
self.WindowTop=top
|
||||
top = self.WindowTop + lines
|
||||
if top < 0:
|
||||
top = 0
|
||||
if top + System.Console.WindowHeight > System.Console.BufferHeight:
|
||||
top = System.Console.BufferHeight
|
||||
self.WindowTop = top
|
||||
|
||||
def getkeypress(self):
|
||||
u'''Return next key press event from the queue, ignoring others.'''
|
||||
ck=System.ConsoleKey
|
||||
ck = System.ConsoleKey
|
||||
while 1:
|
||||
e = System.Console.ReadKey(True)
|
||||
if e.Key == System.ConsoleKey.PageDown: #PageDown
|
||||
self.scroll_window(12)
|
||||
elif e.Key == System.ConsoleKey.PageUp:#PageUp
|
||||
self.scroll_window(-12)
|
||||
elif str(e.KeyChar)==u"\000":#Drop deadkeys
|
||||
elif str(e.KeyChar) == u"\000":#Drop deadkeys
|
||||
log(u"Deadkey: %s"%e)
|
||||
return event(self,e)
|
||||
pass
|
||||
return event(self, e)
|
||||
else:
|
||||
return event(self,e)
|
||||
return event(self, e)
|
||||
|
||||
def title(self, txt=None):
|
||||
u'''Set/get title.'''
|
||||
if txt:
|
||||
System.Console.Title=txt
|
||||
System.Console.Title = txt
|
||||
else:
|
||||
return System.Console.Title
|
||||
|
||||
def size(self, width=None, height=None):
|
||||
u'''Set/get window size.'''
|
||||
sc=System.Console
|
||||
|
||||
|
||||
sc = System.Console
|
||||
if width is not None and height is not None:
|
||||
sc.BufferWidth,sc.BufferHeight=width,height
|
||||
sc.BufferWidth, sc.BufferHeight = width,height
|
||||
else:
|
||||
return sc.BufferWidth,sc.BufferHeight
|
||||
return sc.BufferWidth, sc.BufferHeight
|
||||
|
||||
if width is not None and height is not None:
|
||||
sc.WindowWidth,sc.WindowHeight=width,height
|
||||
sc.WindowWidth, sc.WindowHeight = width,height
|
||||
else:
|
||||
return sc.WindowWidth-1,sc.WindowHeight-1
|
||||
return sc.WindowWidth - 1, sc.WindowHeight - 1
|
||||
|
||||
def cursor(self, visible=True, size=None):
|
||||
u'''Set cursor on or off.'''
|
||||
System.Console.CursorVisible=visible
|
||||
System.Console.CursorVisible = visible
|
||||
|
||||
def bell(self):
|
||||
System.Console.Beep()
|
||||
@@ -362,22 +360,22 @@ class event(Event):
|
||||
self.char = str(input.KeyChar)
|
||||
self.keycode = input.Key
|
||||
self.state = input.Modifiers
|
||||
log(u"%s,%s,%s"%(input.Modifiers,input.Key,input.KeyChar))
|
||||
self.type="KeyRelease"
|
||||
log(u"%s,%s,%s"%(input.Modifiers, input.Key, input.KeyChar))
|
||||
self.type = "KeyRelease"
|
||||
self.keysym = make_keysym(self.keycode)
|
||||
self.keyinfo = make_KeyPress(self.char, self.state, self.keycode)
|
||||
|
||||
def make_event_from_keydescr(keydescr):
|
||||
def input():
|
||||
return 1
|
||||
input.KeyChar=u"a"
|
||||
input.Key=System.ConsoleKey.A
|
||||
input.Modifiers=System.ConsoleModifiers.Shift
|
||||
input.next_serial=input
|
||||
e=event(input,input)
|
||||
input.KeyChar = u"a"
|
||||
input.Key = System.ConsoleKey.A
|
||||
input.Modifiers = System.ConsoleModifiers.Shift
|
||||
input.next_serial = input
|
||||
e = event(input,input)
|
||||
del input.next_serial
|
||||
keyinfo=make_KeyPress_from_keydescr(keydescr)
|
||||
e.keyinfo=keyinfo
|
||||
keyinfo = make_KeyPress_from_keydescr(keydescr)
|
||||
e.keyinfo = keyinfo
|
||||
return e
|
||||
|
||||
CTRL_C_EVENT=make_event_from_keydescr(u"Control-c")
|
||||
@@ -385,21 +383,21 @@ CTRL_C_EVENT=make_event_from_keydescr(u"Control-c")
|
||||
def install_readline(hook):
|
||||
def hook_wrap():
|
||||
try:
|
||||
res=hook()
|
||||
res = hook()
|
||||
except KeyboardInterrupt,x: #this exception does not seem to be caught
|
||||
res=u""
|
||||
res = u""
|
||||
except EOFError:
|
||||
return None
|
||||
if res[-1:]==u"\n":
|
||||
if res[-1:] == u"\n":
|
||||
return res[:-1]
|
||||
else:
|
||||
return res
|
||||
class IronPythonWrapper(IronPythonConsole.IConsole):
|
||||
def ReadLine(self,autoIndentSize):
|
||||
def ReadLine(self, autoIndentSize):
|
||||
return hook_wrap()
|
||||
def Write(self,text, style):
|
||||
def Write(self, text, style):
|
||||
System.Console.Write(text)
|
||||
def WriteLine(self,text, style):
|
||||
def WriteLine(self, text, style):
|
||||
System.Console.WriteLine(text)
|
||||
IronPythonConsole.PythonCommandLine.MyConsole = IronPythonWrapper()
|
||||
|
||||
@@ -416,11 +414,11 @@ if __name__ == u'__main__':
|
||||
c.title(u"Testing console")
|
||||
# c.bell()
|
||||
print
|
||||
print u"size",c.size()
|
||||
print u"size", c.size()
|
||||
print u' some printed output'
|
||||
for i in range(10):
|
||||
e=c.getkeypress()
|
||||
print e.Key,chr(e.KeyChar),ord(e.KeyChar),e.Modifiers
|
||||
e = c.getkeypress()
|
||||
print e.Key, chr(e.KeyChar), ord(e.KeyChar), e.Modifiers
|
||||
del c
|
||||
|
||||
System.Console.Clear()
|
||||
|
||||
Reference in New Issue
Block a user