aboutsummaryrefslogtreecommitdiff
path: root/pydora/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'pydora/utils.py')
-rw-r--r--pydora/utils.py104
1 files changed, 90 insertions, 14 deletions
diff --git a/pydora/utils.py b/pydora/utils.py
index faa18e5..6c608a7 100644
--- a/pydora/utils.py
+++ b/pydora/utils.py
@@ -6,13 +6,14 @@ import getpass
6import subprocess 6import subprocess
7from pandora.py2compat import input 7from pandora.py2compat import input
8 8
9try:
10 import termios
11except ImportError:
12 # Windows does not have a termios module
13 termios = None
14 9
10class TerminalPlatformUnsupported(Exception):
11 """Platform-specific functionality is not supported
15 12
13 Raised by code that can not be used to interact with the terminal on this
14 platform.
15 """
16 pass
16 17
17 18
18class Colors(object): 19class Colors(object):
@@ -35,25 +36,100 @@ class Colors(object):
35 white = __wrap_with("37") 36 white = __wrap_with("37")
36 37
37 38
38class Screen(object): 39class PosixEchoControl(object):
40 """Posix Console Echo Control Driver
39 41
40 @staticmethod 42 Uses termios on POSIX compliant platforms to control console echo. Is not
41 def set_echo(enabled): 43 supported on Windows as termios is not available and will throw a
42 if not termios: 44 TerminalPlatformUnsupported exception if contructed on Windows.
43 return 45 """
46
47 def __init__(self):
48 try:
49 import termios
50 self.termios = termios
51 except ImportError:
52 raise TerminalPlatformUnsupported("POSIX not supported")
44 53
54 def set_echo(self, enabled):
45 handle = sys.stdin.fileno() 55 handle = sys.stdin.fileno()
46 if not os.isatty(handle): 56 if not os.isatty(handle):
47 return 57 return
48 58
49 attrs = termios.tcgetattr(handle) 59 attrs = self.termios.tcgetattr(handle)
60
61 if enabled:
62 attrs[3] |= self.termios.ECHO
63 else:
64 attrs[3] &= ~self.termios.ECHO
65
66 self.termios.tcsetattr(handle, self.termios.TCSANOW, attrs)
67
68
69class Win32EchoControl(object):
70 """Windows Console Echo Control Driver
71
72 This uses the console API from WinCon.h and ctypes to control console echo
73 on Windows clients. It is not possible to construct this class on
74 non-Windows systems, on those systems it will throw a
75 TerminalPlatformUnsupported exception.
76 """
77
78 STD_INPUT_HANDLE = -10
79 ENABLE_ECHO_INPUT = 0x4
80 DISABLE_ECHO_INPUT = ~ENABLE_ECHO_INPUT
81
82 def __init__(self):
83 import ctypes
84
85 if not hasattr(ctypes, "windll"):
86 raise TerminalPlatformUnsupported("Windows not supported")
87
88 from ctypes import wintypes
89
90 self.ctypes = ctypes
91 self.wintypes = wintypes
92 self.kernel32 = ctypes.windll.kernel32
93
94 def _GetStdHandle(self, handle):
95 return self.kernel32.GetStdHandle(handle)
96
97 def _GetConsoleMode(self, handle):
98 mode = self.wintypes.DWORD()
99 self.kernel32.GetConsoleMode(handle, self.ctypes.byref(mode))
100 return mode.value
101
102 def _SetConsoleMode(self, handle, value):
103 self.kernel32.SetConsoleMode(handle, value)
104
105 def set_echo(self, enabled):
106 stdin = self._GetStdHandle(self.STD_INPUT_HANDLE)
107 mode = self._GetConsoleMode(stdin)
50 108
51 if enabled: 109 if enabled:
52 attrs[3] |= termios.ECHO 110 self._SetConsoleMode(stdin, mode | self.ENABLE_ECHO_INPUT)
53 else: 111 else:
54 attrs[3] &= ~termios.ECHO 112 self._SetConsoleMode(stdin, mode & self.DISABLE_ECHO_INPUT)
113
114
115class Screen(object):
116
117 def __init__(self):
118 try:
119 self._echo_driver = PosixEchoControl()
120 except TerminalPlatformUnsupported:
121 pass
122
123 try:
124 self._echo_driver = Win32EchoControl()
125 except TerminalPlatformUnsupported:
126 pass
127
128 if not self._echo_driver:
129 raise TerminalPlatformUnsupported("No supported terminal driver")
55 130
56 termios.tcsetattr(handle, termios.TCSANOW, attrs) 131 def set_echo(self, enabled):
132 self._echo_driver.set_echo(enabled)
57 133
58 @staticmethod 134 @staticmethod
59 def clear(): 135 def clear():