Changeset 554
- Timestamp:
- 06/15/08 05:17:39 (4 months ago)
- Files:
-
- cly/trunk/cly/interactive.py (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
cly/trunk/cly/interactive.py
r553 r554 17 17 Press ``?`` at any time to view contextual help. 18 18 """ 19 20 from __future__ import with_statement 19 21 20 22 import os … … 52 54 self.history_file = history_file 53 55 self.history_length = history_length 54 self._cli_inject_text = '' 55 self._completion_candidates = [] 56 57 def enter(self): 58 """Enter the input context.""" 56 59 57 60 def input(self): … … 59 62 raise NotImplementedError 60 63 61 def shutdown(self):62 """ Shutdown input driver."""64 def leave(self): 65 """Exit the input context.""" 63 66 64 67 @staticmethod 65 def choose():68 def usable(): 66 69 """Called to determine whether this driver is usable.""" 67 70 raise NotImplementedError 68 71 69 72 70 class Dum myInputDriver(InputDriver):73 class DumbInput(InputDriver): 71 74 """The horror.""" 75 76 def input(self): 77 return raw_input(self.prompt) 78 72 79 @staticmethod 73 def choose():80 def usable(): 74 81 print >> sys.stderr, \ 75 82 'WARNING: Most line editing features are unavailable.' 76 83 return True 77 84 78 def input(self): 79 return raw_input(self.prompt) 80 81 82 class BaseReadlineDriver(InputDriver): 85 86 class ReadlineDriver(InputDriver): 83 87 """Base class for readline variants.""" 88 84 89 def __init__(self, *args, **kwargs): 85 super(BaseReadlineDriver, self).__init__(*args, **kwargs) 90 super(ReadlineDriver, self).__init__(*args, **kwargs) 91 self._cli_inject_text = '' 92 self._completion_candidates = [] 93 94 def enter(self): 86 95 try: 87 96 readline.set_history_length(self.history_length) … … 95 104 readline.set_startup_hook(self._redraw_input) 96 105 97 self.rl_bind_help() 106 self._bind_help() 107 108 def input(self): 109 return raw_input(self.prompt) 110 111 def leave(self): 112 try: 113 readline.write_history_file(self.history_file) 114 except: 115 pass 98 116 99 117 @staticmethod 100 def choose():118 def usable(): 101 119 if readline: 102 120 print >> sys.stderr, \ … … 106 124 return readline 107 125 108 def shutdown(self): 109 try: 110 readline.write_history_file(self.history_file) 111 except: 112 pass 113 _interact = None 114 115 def input(self): 116 return raw_input(self.prompt) 117 118 def rl_bind_help(self): 126 def _bind_help(self): 119 127 pass 120 128 121 def rl_force_redisplay(self):129 def _force_redisplay(self): 122 130 raise NotImplementedError 123 131 124 def rl_get_cursor(self):132 def _get_cursor(self): 125 133 raise NotImplementedError 126 134 127 def rl_set_cursor(self, cursor):135 def _set_cursor(self, cursor): 128 136 raise NotImplementedError 129 137 130 cursor = property(lambda s: s. rl_get_cursor(), lambda s, c: s.rl_set_cursor(c))138 cursor = property(lambda s: s._get_cursor(), lambda s, c: s._set_cursor(c)) 131 139 132 140 # Internal methods … … 153 161 except Exception, e: 154 162 self._dump_traceback(e) 155 self. rl_force_redisplay()163 self._force_redisplay() 156 164 raise 157 165 … … 171 179 ', '.join(candidates)) 172 180 console.cerror(text) 173 self. rl_force_redisplay()181 self._force_redisplay() 174 182 return 175 183 help = context.help() 176 184 print 177 185 console.cprint('\n'.join(help.format())) 178 self. rl_force_redisplay()186 self._force_redisplay() 179 187 return 0 180 188 except Exception, e: 181 189 self._dump_traceback(e) 182 self. rl_force_redisplay()190 self._force_redisplay() 183 191 return 0 184 192 185 193 186 class PyReadlineDriver( BaseReadlineDriver):194 class PyReadlineDriver(ReadlineDriver): 187 195 """The IPython pure-Python pyreadline implementation.""" 196 188 197 @staticmethod 189 def choose():198 def usable(): 190 199 return pyreadline 191 200 192 def rl_bind_help(self):201 def _bind_help(self): 193 202 def _show_help_proxy(_, __): 194 203 self._show_help(None, None) … … 201 210 pyreadline.parse_and_bind('F1: cly-help') 202 211 203 def rl_force_redisplay(self):212 def _force_redisplay(self): 204 213 pyreadline.rl._print_prompt() 205 214 206 def rl_get_cursor(self):215 def _get_cursor(self): 207 216 return pyreadline.rl.l_buffer.point 208 217 209 def rl_set_cursor(self, cursor):218 def _set_cursor(self, cursor): 210 219 pyreadline.rl.l_buffer.point = cursor 211 220 212 221 213 class ExtendedReadlineDriver( BaseReadlineDriver):222 class ExtendedReadlineDriver(ReadlineDriver): 214 223 """Use CLY's built-in readline extensions.""" 215 224 216 225 @staticmethod 217 def choose():226 def usable(): 218 227 return _rlext 219 228 220 def rl_bind_help(self):229 def _bind_help(self): 221 230 _rlext.bind_key(ord('?'), self._show_help) 222 231 223 def rl_force_redisplay(self):232 def _force_redisplay(self): 224 233 _rlext.force_redisplay() 225 234 226 def rl_get_cursor(self):235 def _get_cursor(self): 227 236 return _rlext.cursor() 228 237 229 def rl_set_cursor(self, cursor):238 def _set_cursor(self, cursor): 230 239 _rlext.cursor(cursor) 231 240 … … 268 277 As for :meth:`loop`. 269 278 """ 279 280 # Available input drivers 281 INPUT_DRIVERS = [ExtendedReadlineDriver, PyReadlineDriver, ReadlineDriver, 282 DumbInput] 283 270 284 271 285 def __init__(self, grammar_or_parser, application='cly', prompt=None, … … 284 298 self.data = data 285 299 286 self.input_driver = input_driver(300 self.input_driver = self.best_input_driver( 287 301 parser, prompt, history_file, history_length 288 302 ) 289 303 290 def once(self , default_text=''):304 def once(self): 291 305 """Input one command from the user and return the result of the 292 306 executed command. 293 294 :param default_text:295 Text to insert into the input buffer prior to editing.296 307 """ 297 self._cli_inject_text = default_text298 299 308 while True: 300 309 command = '' 301 310 try: 302 command = self.input_driver.input() 303 except KeyboardInterrupt: 304 print 305 continue 306 except EOFError: 307 print 308 return None 311 self.input_driver.enter() 312 try: 313 command = self.input_driver.input() 314 except KeyboardInterrupt: 315 print 316 continue 317 except EOFError: 318 print 319 return None 320 finally: 321 self.input_driver.leave() 309 322 310 323 try: … … 329 342 Called with the Interact object before each line is displayed. 330 343 """ 331 try: 332 while True: 333 try: 334 if callback: 335 callback(self) 336 if not self.once(): 337 break 338 except Exception, e: 339 if inhibit_exceptions: 340 if with_backtrace: 341 import traceback 342 console.cerror(traceback.format_exc()) 343 else: 344 console.cerror('error: %s' % e) 344 while True: 345 try: 346 if callback: 347 callback(self) 348 if not self.once(): 349 break 350 except Exception, e: 351 if inhibit_exceptions: 352 if with_backtrace: 353 import traceback 354 console.cerror(traceback.format_exc()) 345 355 else: 346 raise347 finally:348 self.input_driver.shutdown()356 console.cerror('error: %s' % e) 357 else: 358 raise 349 359 350 360 def print_error(self, context, e): … … 388 398 389 399 390 # Available input drivers 391 DRIVERS = [ExtendedReadlineDriver, PyReadlineDriver, BaseReadlineDriver, 392 DummyInputDriver] 393 394 395 def input_driver(*args, **kwargs): 396 """Select the "best" available input driver.""" 397 for driver in DRIVERS: 398 if driver.choose(): 399 return driver(*args, **kwargs) 400 raise Error('No choose input driver found') 400 @classmethod 401 def best_input_driver(cls, *args, **kwargs): 402 """Select the "best" available input driver.""" 403 for driver in cls.INPUT_DRIVERS: 404 if driver.usable(): 405 return driver(*args, **kwargs) 406 raise Error('No usable input driver found') 401 407 402 408
