Design Pattern Examples
Overview of object-oriented design patterns
flyweight_helpers.py
Go to the documentation of this file.
6
7import re
8import select
9import sys
10import time
11
12
13
14STD_INPUT_HANDLE = -10
15
16INVALID_HANDLE_VALUE = -1
17
18ENABLE_LINE_INPUT = 0x0002
19
20ENABLE_ECHO_INPUT = 0x0004
21
22
23ASCII_CTRL_Z = '\x1a'
24
25ASCII_ESC = '\x1b'
26
27
28# For Windows, try to import the Microsoft C Runtime (mscvrt) and ctypes to get
29# the kernel32 DLL. If neither is possible, the rest of the Windows-specific
30# code in this module does nothing.
31try:
32 import msvcrt # Only on Windows
33 import ctypes
34 kernel32 = ctypes.windll.kernel32
35 termios = None
36except:
37 # The Microsoft C Runtime does not exist, so assume Windows kernel32
38 # doesn't exist.
39 msvcrt = None
40 kernel32 = None
41 try:
42 import termios # Assume we are on Linux
43 except:
44 print(" Error! No termios or msvcrt. Cannot check for keys or get cursor position.")
45
46
47if kernel32:
48
49 #==================== Windows Functionality ===============================
50
59 def __init__(self):
60 self._inputMode = None
61 self._hStdIn = kernel32.GetStdHandle(STD_INPUT_HANDLE)
62 if self._hStdIn != INVALID_HANDLE_VALUE:
63 oldMode = ctypes.c_uint32(0)
64 if kernel32.GetConsoleMode(self._hStdIn, ctypes.byref(oldMode)):
65 self._inputMode = oldMode.value
66 else:
67 lastError = kernel32.GetLastError()
68 print("GetStdHandle(STD_INPUT_HANDLE) failed: code = {:x}".format(lastError))
69
70
72 if self._hStdIn != INVALID_HANDLE_VALUE:
73 newMode = self._inputMode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT)
74 if not kernel32.SetConsoleMode(self._hStdIn, newMode):
75 lastError = kernel32.GetLastError()
76 print("SetConsoleMode(hStdIn, newMode) failed: code = {:x}".format(lastError))
77
78
80 if self._hStdIn != INVALID_HANDLE_VALUE and self._inputMode is not None:
81 if not kernel32.SetConsoleMode(self._hStdIn, self._inputMode):
82 lastError = kernel32.GetLastError()
83 print("SetConsoleMode(hStdIn, inputMode) failed: code = {:x}".format(lastError))
84
85
87 def __enter__(self):
89
90
91 def __exit__(self, *args):
93
94 DisableInputEcho = DisableInputEcho_Windows
95 #==========================================================================
96
97elif termios:
98
99 #====================== Linux Functionality ===============================
100
101
110
111
112 def __init__(self):
113 self.old_settings = None
114
115
117 stdin_fd = sys.stdin.fileno()
118 self.old_settings = termios.tcgetattr(stdin_fd)
119 new_settings = termios.tcgetattr(stdin_fd);
120 new_settings[3] = new_settings[3] & ~termios.ICANON & ~termios.ECHO
121 termios.tcsetattr(stdin_fd, termios.TCSANOW, new_settings)
122
123
125 stdin_fd = sys.stdin.fileno()
126 if self.old_settings:
127 termios.tcsetattr(stdin_fd, termios.TCSANOW, self.old_settings)
128 self.old_settings = None
129
130
132 def __enter__(self):
133 self.disable_input_echo()
134
135
136 def __exit__(self, *args):
137 self.enable_input_echo()
138
139 DisableInputEcho = DisableInputEcho_Linux
140 #==========================================================================
141
142
143
144
153
154
160 def setcursorposition(self, column: int, row: int) -> None:
161 sys.stdout.write("{}[{};{}H".format(ASCII_ESC, row, column))
162 sys.stdout.flush()
163
164
169 def getcursorposition(self) -> tuple:
170 row = 0
171 column = 0
172 with DisableInputEcho():
173 # Send, via standard out, the ANSI string to request the current cursor
174 # position. The position will be returned in standard input.
175 sys.stdout.write("{}[6n".format(ASCII_ESC))
176 sys.stdout.flush()
177 # We are expecting in the input buffer the following characters (minus
178 # the spaces:
179 # ESC [ <r> ; <c> R
180 # Where <r> and <c> are 1 to n decimal digits specifying the row and
181 # column position, respectively.
182 # We know there are at least 6 characters waiting in the input queue
183 # so read them one at a time until we reach the end (signified by 'R').
184 #
185 # (Note: This could block if there is nothing in the standard input,
186 # which could happen if the "get cursor position" ANSI control sequence
187 # (or any ANSI control sequence) is not supported. Use Ctrl-Z on the
188 # keyboard to release the block.)
189 inputbuffer = []
190 while True:
191 c = sys.stdin.read(1)
192 inputbuffer.append(c)
193 if c == 'R' or c == ASCII_CTRL_Z:
194 break
195 buffer = ''.join(inputbuffer)
196 if len(buffer) > 2 and buffer[0] == ASCII_ESC and buffer[1] == '[':
197 elements = re.split(".\[([0-9]+);([0-9]+)R", buffer)
198 if len(elements) >= 3:
199 row = int(elements[1])
200 column = int(elements[2])
201 return (column, row)
202
203
204
205 def sleep(self, milliseconds : int) -> None:
206 time.sleep(milliseconds/1000.0)
207
208
212 def checkforkey(self) -> bool:
213 if msvcrt:
214 return msvcrt.kbhit()
215 else:
216 dr,dw,de = select.select([sys.stdin], [], [], 0)
217 if not dr == []:
218 return True
219 return False
220
221
222
229 def readkey(self) -> int:
230 return sys.stdin.read(1)
bool checkforkey(void)
Determine if a key has been pressed.
Definition: checkforkey.c:39
Class for temporarily disabling echoing of characters sent to standard in when run on Linux.
def disable_input_echo(self)
Disable echoing of anything sent to standard in.
def __enter__(self)
Entry function used in the with statement to initialize an instance of this class.
def enable_input_echo(self)
Enable echoing of everything sent to standard in.
def __exit__(self, *args)
Exit function automatically called when used in the with statement.
Class for temporarily disabling echoing of characters sent to standard when run on Windows.
def disable_input_echo(self)
Disable echoing of anything sent to standard in.
def __enter__(self)
Entry function used in the with statement to initialize an instance of this class.
def enable_input_echo(self)
Enable echoing of everything sent to standard in.
def __exit__(self, *args)
Exit function automatically called when used in the with statement.
Class containing a number of helper methods for use in the Flyweight Pattern example.
tuple getcursorposition(self)
Retrieve the current cursor position in the console window.
None setcursorposition(self, int column, int row)
Move the text cursor to the specified screen coordinates.
None sleep(self, int milliseconds)
Sleep for the specified number of milliseconds.
int readkey(void)
Read a key from the keyboard, blocking if no key is pressed. Use the checkforkey() function to see if...
Definition: readkey.c:14