m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
13 KiB

6 months ago
  1. # -*- coding: utf-8 -*-
  2. #*****************************************************************************
  3. # Copyright (C) 2003-2006 Gary Bishop.
  4. # Copyright (C) 2006 Jorgen Stenarson. <jorgen.stenarson@bostream.nu>
  5. #
  6. # Distributed under the terms of the BSD License. The full license is in
  7. # the file COPYING, distributed as part of this software.
  8. #*****************************************************************************
  9. from __future__ import print_function, unicode_literals, absolute_import
  10. '''Cursor control and color for the .NET console.
  11. '''
  12. #
  13. # Ironpython requires a patch to work do:
  14. #
  15. # In file PythonCommandLine.cs patch line:
  16. # class PythonCommandLine
  17. # {
  18. # to:
  19. # public class PythonCommandLine
  20. # {
  21. #
  22. #
  23. #
  24. # primitive debug printing that won't interfere with the screen
  25. import clr,sys
  26. clr.AddReferenceToFileAndPath(sys.executable)
  27. import IronPythonConsole
  28. import sys
  29. import re
  30. import os
  31. import System
  32. from .event import Event
  33. from pyreadline.logger import log
  34. from pyreadline.keysyms import \
  35. make_keysym, make_keyinfo, make_KeyPress, make_KeyPress_from_keydescr
  36. from pyreadline.console.ansi import AnsiState
  37. color = System.ConsoleColor
  38. ansicolor={"0;30": color.Black,
  39. "0;31": color.DarkRed,
  40. "0;32": color.DarkGreen,
  41. "0;33": color.DarkYellow,
  42. "0;34": color.DarkBlue,
  43. "0;35": color.DarkMagenta,
  44. "0;36": color.DarkCyan,
  45. "0;37": color.DarkGray,
  46. "1;30": color.Gray,
  47. "1;31": color.Red,
  48. "1;32": color.Green,
  49. "1;33": color.Yellow,
  50. "1;34": color.Blue,
  51. "1;35": color.Magenta,
  52. "1;36": color.Cyan,
  53. "1;37": color.White
  54. }
  55. winattr = {"black" : 0, "darkgray" : 0+8,
  56. "darkred" : 4, "red" : 4+8,
  57. "darkgreen" : 2, "green" : 2+8,
  58. "darkyellow" : 6, "yellow" : 6+8,
  59. "darkblue" : 1, "blue" : 1+8,
  60. "darkmagenta" : 5, "magenta" : 5+8,
  61. "darkcyan" : 3, "cyan" : 3+8,
  62. "gray" : 7, "white" : 7+8}
  63. class Console(object):
  64. '''Console driver for Windows.
  65. '''
  66. def __init__(self, newbuffer=0):
  67. '''Initialize the Console object.
  68. newbuffer=1 will allocate a new buffer so the old content will be restored
  69. on exit.
  70. '''
  71. self.serial = 0
  72. self.attr = System.Console.ForegroundColor
  73. self.saveattr = winattr[str(System.Console.ForegroundColor).lower()]
  74. self.savebg = System.Console.BackgroundColor
  75. log('initial attr=%s' % self.attr)
  76. def _get(self):
  77. top = System.Console.WindowTop
  78. log("WindowTop:%s"%top)
  79. return top
  80. def _set(self, value):
  81. top = System.Console.WindowTop
  82. log("Set WindowTop:old:%s,new:%s"%(top, value))
  83. WindowTop = property(_get, _set)
  84. del _get, _set
  85. def __del__(self):
  86. '''Cleanup the console when finished.'''
  87. # I don't think this ever gets called
  88. pass
  89. def pos(self, x=None, y=None):
  90. '''Move or query the window cursor.'''
  91. if x is not None:
  92. System.Console.CursorLeft=x
  93. else:
  94. x = System.Console.CursorLeft
  95. if y is not None:
  96. System.Console.CursorTop=y
  97. else:
  98. y = System.Console.CursorTop
  99. return x, y
  100. def home(self):
  101. '''Move to home.'''
  102. self.pos(0, 0)
  103. # Map ANSI color escape sequences into Windows Console Attributes
  104. terminal_escape = re.compile('(\001?\033\\[[0-9;]*m\002?)')
  105. escape_parts = re.compile('\001?\033\\[([0-9;]*)m\002?')
  106. # This pattern should match all characters that change the cursor position differently
  107. # than a normal character.
  108. motion_char_re = re.compile('([\n\r\t\010\007])')
  109. def write_scrolling(self, text, attr=None):
  110. '''write text at current cursor position while watching for scrolling.
  111. If the window scrolls because you are at the bottom of the screen
  112. buffer, all positions that you are storing will be shifted by the
  113. scroll amount. For example, I remember the cursor position of the
  114. prompt so that I can redraw the line but if the window scrolls,
  115. the remembered position is off.
  116. This variant of write tries to keep track of the cursor position
  117. so that it will know when the screen buffer is scrolled. It
  118. returns the number of lines that the buffer scrolled.
  119. '''
  120. x, y = self.pos()
  121. w, h = self.size()
  122. scroll = 0 # the result
  123. # split the string into ordinary characters and funny characters
  124. chunks = self.motion_char_re.split(text)
  125. for chunk in chunks:
  126. n = self.write_color(chunk, attr)
  127. if len(chunk) == 1: # the funny characters will be alone
  128. if chunk[0] == '\n': # newline
  129. x = 0
  130. y += 1
  131. elif chunk[0] == '\r': # carriage return
  132. x = 0
  133. elif chunk[0] == '\t': # tab
  134. x = 8 * (int(x / 8) + 1)
  135. if x > w: # newline
  136. x -= w
  137. y += 1
  138. elif chunk[0] == '\007': # bell
  139. pass
  140. elif chunk[0] == '\010':
  141. x -= 1
  142. if x < 0:
  143. y -= 1 # backed up 1 line
  144. else: # ordinary character
  145. x += 1
  146. if x == w: # wrap
  147. x = 0
  148. y += 1
  149. if y == h: # scroll
  150. scroll += 1
  151. y = h - 1
  152. else: # chunk of ordinary characters
  153. x += n
  154. l = int(x / w) # lines we advanced
  155. x = x % w # new x value
  156. y += l
  157. if y >= h: # scroll
  158. scroll += y - h + 1
  159. y = h - 1
  160. return scroll
  161. trtable = {0 : color.Black, 4 : color.DarkRed, 2 : color.DarkGreen,
  162. 6 : color.DarkYellow, 1 : color.DarkBlue, 5 : color.DarkMagenta,
  163. 3 : color.DarkCyan, 7 : color.Gray, 8 : color.DarkGray,
  164. 4+8 : color.Red, 2+8 : color.Green, 6+8 : color.Yellow,
  165. 1+8 : color.Blue, 5+8 : color.Magenta,3+8 : color.Cyan,
  166. 7+8 : color.White}
  167. def write_color(self, text, attr=None):
  168. '''write text at current cursor position and interpret color escapes.
  169. return the number of characters written.
  170. '''
  171. log('write_color("%s", %s)' % (text, attr))
  172. chunks = self.terminal_escape.split(text)
  173. log('chunks=%s' % repr(chunks))
  174. bg = self.savebg
  175. n = 0 # count the characters we actually write, omitting the escapes
  176. if attr is None:#use attribute from initial console
  177. attr = self.attr
  178. try:
  179. fg = self.trtable[(0x000f&attr)]
  180. bg = self.trtable[(0x00f0&attr)>>4]
  181. except TypeError:
  182. fg = attr
  183. for chunk in chunks:
  184. m = self.escape_parts.match(chunk)
  185. if m:
  186. log(m.group(1))
  187. attr = ansicolor.get(m.group(1), self.attr)
  188. n += len(chunk)
  189. System.Console.ForegroundColor = fg
  190. System.Console.BackgroundColor = bg
  191. System.Console.Write(chunk)
  192. return n
  193. def write_plain(self, text, attr=None):
  194. '''write text at current cursor position.'''
  195. log('write("%s", %s)' %(text, attr))
  196. if attr is None:
  197. attr = self.attr
  198. n = c_int(0)
  199. self.SetConsoleTextAttribute(self.hout, attr)
  200. self.WriteConsoleA(self.hout, text, len(text), byref(n), None)
  201. return len(text)
  202. if "EMACS" in os.environ:
  203. def write_color(self, text, attr=None):
  204. junk = c_int(0)
  205. self.WriteFile(self.hout, text, len(text), byref(junk), None)
  206. return len(text)
  207. write_plain = write_color
  208. # make this class look like a file object
  209. def write(self, text):
  210. log('write("%s")' % text)
  211. return self.write_color(text)
  212. #write = write_scrolling
  213. def isatty(self):
  214. return True
  215. def flush(self):
  216. pass
  217. def page(self, attr=None, fill=' '):
  218. '''Fill the entire screen.'''
  219. System.Console.Clear()
  220. def text(self, x, y, text, attr=None):
  221. '''Write text at the given position.'''
  222. self.pos(x, y)
  223. self.write_color(text, attr)
  224. def clear_to_end_of_window(self):
  225. oldtop = self.WindowTop
  226. lastline = self.WindowTop+System.Console.WindowHeight
  227. pos = self.pos()
  228. w, h = self.size()
  229. length = w - pos[0] + min((lastline - pos[1] - 1), 5) * w - 1
  230. self.write_color(length * " ")
  231. self.pos(*pos)
  232. self.WindowTop = oldtop
  233. def rectangle(self, rect, attr=None, fill=' '):
  234. '''Fill Rectangle.'''
  235. oldtop = self.WindowTop
  236. oldpos = self.pos()
  237. #raise NotImplementedError
  238. x0, y0, x1, y1 = rect
  239. if attr is None:
  240. attr = self.attr
  241. if fill:
  242. rowfill = fill[:1] * abs(x1 - x0)
  243. else:
  244. rowfill = ' ' * abs(x1 - x0)
  245. for y in range(y0, y1):
  246. System.Console.SetCursorPosition(x0, y)
  247. self.write_color(rowfill, attr)
  248. self.pos(*oldpos)
  249. def scroll(self, rect, dx, dy, attr=None, fill=' '):
  250. '''Scroll a rectangle.'''
  251. raise NotImplementedError
  252. def scroll_window(self, lines):
  253. '''Scroll the window by the indicated number of lines.'''
  254. top = self.WindowTop + lines
  255. if top < 0:
  256. top = 0
  257. if top + System.Console.WindowHeight > System.Console.BufferHeight:
  258. top = System.Console.BufferHeight
  259. self.WindowTop = top
  260. def getkeypress(self):
  261. '''Return next key press event from the queue, ignoring others.'''
  262. ck = System.ConsoleKey
  263. while 1:
  264. e = System.Console.ReadKey(True)
  265. if e.Key == System.ConsoleKey.PageDown: #PageDown
  266. self.scroll_window(12)
  267. elif e.Key == System.ConsoleKey.PageUp:#PageUp
  268. self.scroll_window(-12)
  269. elif str(e.KeyChar) == "\000":#Drop deadkeys
  270. log("Deadkey: %s"%e)
  271. return event(self, e)
  272. else:
  273. return event(self, e)
  274. def title(self, txt=None):
  275. '''Set/get title.'''
  276. if txt:
  277. System.Console.Title = txt
  278. else:
  279. return System.Console.Title
  280. def size(self, width=None, height=None):
  281. '''Set/get window size.'''
  282. sc = System.Console
  283. if width is not None and height is not None:
  284. sc.BufferWidth, sc.BufferHeight = width,height
  285. else:
  286. return sc.BufferWidth, sc.BufferHeight
  287. if width is not None and height is not None:
  288. sc.WindowWidth, sc.WindowHeight = width,height
  289. else:
  290. return sc.WindowWidth - 1, sc.WindowHeight - 1
  291. def cursor(self, visible=True, size=None):
  292. '''Set cursor on or off.'''
  293. System.Console.CursorVisible = visible
  294. def bell(self):
  295. System.Console.Beep()
  296. def next_serial(self):
  297. '''Get next event serial number.'''
  298. self.serial += 1
  299. return self.serial
  300. class event(Event):
  301. '''Represent events from the console.'''
  302. def __init__(self, console, input):
  303. '''Initialize an event from the Windows input structure.'''
  304. self.type = '??'
  305. self.serial = console.next_serial()
  306. self.width = 0
  307. self.height = 0
  308. self.x = 0
  309. self.y = 0
  310. self.char = str(input.KeyChar)
  311. self.keycode = input.Key
  312. self.state = input.Modifiers
  313. log("%s,%s,%s"%(input.Modifiers, input.Key, input.KeyChar))
  314. self.type = "KeyRelease"
  315. self.keysym = make_keysym(self.keycode)
  316. self.keyinfo = make_KeyPress(self.char, self.state, self.keycode)
  317. def make_event_from_keydescr(keydescr):
  318. def input():
  319. return 1
  320. input.KeyChar = "a"
  321. input.Key = System.ConsoleKey.A
  322. input.Modifiers = System.ConsoleModifiers.Shift
  323. input.next_serial = input
  324. e = event(input,input)
  325. del input.next_serial
  326. keyinfo = make_KeyPress_from_keydescr(keydescr)
  327. e.keyinfo = keyinfo
  328. return e
  329. CTRL_C_EVENT=make_event_from_keydescr("Control-c")
  330. def install_readline(hook):
  331. def hook_wrap():
  332. try:
  333. res = hook()
  334. except KeyboardInterrupt as x: #this exception does not seem to be caught
  335. res = ""
  336. except EOFError:
  337. return None
  338. if res[-1:] == "\n":
  339. return res[:-1]
  340. else:
  341. return res
  342. class IronPythonWrapper(IronPythonConsole.IConsole):
  343. def ReadLine(self, autoIndentSize):
  344. return hook_wrap()
  345. def Write(self, text, style):
  346. System.Console.Write(text)
  347. def WriteLine(self, text, style):
  348. System.Console.WriteLine(text)
  349. IronPythonConsole.PythonCommandLine.MyConsole = IronPythonWrapper()
  350. if __name__ == '__main__':
  351. import time, sys
  352. c = Console(0)
  353. sys.stdout = c
  354. sys.stderr = c
  355. c.page()
  356. c.pos(5, 10)
  357. c.write('hi there')
  358. c.title("Testing console")
  359. # c.bell()
  360. print()
  361. print("size", c.size())
  362. print(' some printed output')
  363. for i in range(10):
  364. e = c.getkeypress()
  365. print(e.Key, chr(e.KeyChar), ord(e.KeyChar), e.Modifiers)
  366. del c
  367. System.Console.Clear()