home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_2352 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  42.6 KB  |  1,427 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import os
  5. import pyreadline.logger as logger
  6. from pyreadline.logger import log, log_sock
  7. import pyreadline.lineeditor.lineobj as lineobj
  8. import pyreadline.lineeditor.history as history
  9. import basemode
  10.  
  11. class ViMode(basemode.BaseMode):
  12.     mode = 'vi'
  13.     
  14.     def __init__(self, rlobj):
  15.         super(ViMode, self).__init__(rlobj)
  16.         self._ViMode__vi_insert_mode = None
  17.  
  18.     
  19.     def __repr__(self):
  20.         return '<ViMode>'
  21.  
  22.     
  23.     def _readline_from_keyboard(self):
  24.         c = self.console
  25.         while None:
  26.             event = c.getkeypress()
  27.             if self.next_meta:
  28.                 self.next_meta = False
  29.                 (control, meta, shift, code) = event.keyinfo
  30.                 event.keyinfo = (control, True, shift, code)
  31.             
  32.             if event.keyinfo in self.exit_dispatch:
  33.                 if lineobj.EndOfLine(self.l_buffer) == 0:
  34.                     raise EOFError
  35.                 lineobj.EndOfLine(self.l_buffer) == 0
  36.             
  37.             dispatch_func = self.key_dispatch.get(event.keyinfo.tuple(), self.vi_key)
  38.             log('readline from keyboard:%s->%s' % (event.keyinfo.tuple(), dispatch_func))
  39.             r = None
  40.             if dispatch_func:
  41.                 r = dispatch_func(event)
  42.                 self.l_buffer.push_undo()
  43.             
  44.             self.previous_func = dispatch_func
  45.             if r:
  46.                 self._update_line()
  47.                 break
  48.                 continue
  49.             continue
  50.             return None
  51.  
  52.     
  53.     def readline(self, prompt = ''):
  54.         if self.first_prompt:
  55.             self.first_prompt = False
  56.             if self.startup_hook:
  57.                 
  58.                 try:
  59.                     self.startup_hook()
  60.                 print 'startup hook failed'
  61.                 traceback.print_exc()
  62.  
  63.             
  64.         
  65.         c = self.console
  66.         self.l_buffer.reset_line()
  67.         self.prompt = prompt
  68.         self._print_prompt()
  69.         if self.pre_input_hook:
  70.             
  71.             try:
  72.                 self.pre_input_hook()
  73.             print 'pre_input_hook failed'
  74.             traceback.print_exc()
  75.             self.pre_input_hook = None
  76.  
  77.         
  78.         log('in readline: %s' % self.paste_line_buffer)
  79.         if len(self.paste_line_buffer) > 0:
  80.             self.l_buffer = lineobj.ReadlineTextBuffer(self.paste_line_buffer[0])
  81.             self._update_line()
  82.             self.paste_line_buffer = self.paste_line_buffer[1:]
  83.             c.write('\r\n')
  84.         else:
  85.             self._readline_from_keyboard()
  86.             c.write('\r\n')
  87.         self.add_history(self.l_buffer.copy())
  88.         log('returning(%s)' % self.l_buffer.get_line_text())
  89.         return self.l_buffer.get_line_text() + '\n'
  90.  
  91.     
  92.     def init_editing_mode(self, e):
  93.         self.show_all_if_ambiguous = 'on'
  94.         self.key_dispatch = { }
  95.         self._ViMode__vi_insert_mode = None
  96.         self._vi_command = None
  97.         self._vi_command_edit = None
  98.         self._vi_key_find_char = None
  99.         self._vi_key_find_direction = True
  100.         self._vi_yank_buffer = None
  101.         self._vi_multiplier1 = ''
  102.         self._vi_multiplier2 = ''
  103.         self._vi_undo_stack = []
  104.         self._vi_undo_cursor = -1
  105.         self._vi_current = None
  106.         self._vi_search_text = ''
  107.         self.vi_save_line()
  108.         self.vi_set_insert_mode(True)
  109.         for c in range(ord(' '), 127):
  110.             self._bind_key('%s' % chr(c), self.vi_key)
  111.         
  112.         self._bind_key('BackSpace', self.vi_backspace)
  113.         self._bind_key('Escape', self.vi_escape)
  114.         self._bind_key('Return', self.vi_accept_line)
  115.         self._bind_key('Left', self.backward_char)
  116.         self._bind_key('Right', self.forward_char)
  117.         self._bind_key('Home', self.beginning_of_line)
  118.         self._bind_key('End', self.end_of_line)
  119.         self._bind_key('Delete', self.delete_char)
  120.         self._bind_key('Control-d', self.vi_eof)
  121.         self._bind_key('Control-z', self.vi_eof)
  122.         self._bind_key('Control-r', self.vi_redo)
  123.         self._bind_key('Up', self.vi_arrow_up)
  124.         self._bind_key('Control-p', self.vi_up)
  125.         self._bind_key('Down', self.vi_arrow_down)
  126.         self._bind_key('Control-n', self.vi_down)
  127.         self._bind_key('Tab', self.vi_complete)
  128.  
  129.     
  130.     def vi_key(self, e):
  131.         if not self._vi_command:
  132.             self._vi_command = ViCommand(self)
  133.         elif self._vi_command.is_end:
  134.             if self._vi_command.is_edit:
  135.                 self._vi_command_edit = self._vi_command
  136.             
  137.             self._vi_command = ViCommand(self)
  138.         
  139.         self._vi_command.add_char(e.char)
  140.  
  141.     
  142.     def vi_error(self):
  143.         self._bell()
  144.  
  145.     
  146.     def vi_get_is_insert_mode(self):
  147.         return self._ViMode__vi_insert_mode
  148.  
  149.     vi_is_insert_mode = property(vi_get_is_insert_mode)
  150.     
  151.     def vi_escape(self, e):
  152.         if self.vi_is_insert_mode:
  153.             if self._vi_command:
  154.                 self._vi_command.add_char(e.char)
  155.             else:
  156.                 self._vi_command = ViCommand(self)
  157.             self.vi_set_insert_mode(False)
  158.             self.l_buffer.point = lineobj.PrevChar
  159.         elif self._vi_command and self._vi_command.is_replace_one:
  160.             self._vi_command.add_char(e.char)
  161.         else:
  162.             self.vi_error()
  163.  
  164.     
  165.     def vi_backspace(self, e):
  166.         if self._vi_command:
  167.             self._vi_command.add_char(e.char)
  168.         else:
  169.             self._vi_do_backspace(self._vi_command)
  170.  
  171.     
  172.     def _vi_do_backspace(self, vi_cmd):
  173.         if (self.vi_is_insert_mode or self._vi_command) and self._vi_command.is_search:
  174.             if self.l_buffer.point > 0:
  175.                 self.l_buffer.point -= 1
  176.                 if self.l_buffer.overwrite:
  177.                     
  178.                     try:
  179.                         prev = self._vi_undo_stack[self._vi_undo_cursor][1][self.l_buffer.point]
  180.                         self.l_buffer.line_buffer[self.l_buffer.point] = prev
  181.                     except IndexError:
  182.                         self.l_buffer
  183.                         self.l_buffer
  184.                         del self.l_buffer.line_buffer[self.l_buffer.point]
  185.                     except:
  186.                         self.l_buffer<EXCEPTION MATCH>IndexError
  187.                     
  188.  
  189.                 self.l_buffer<EXCEPTION MATCH>IndexError
  190.                 self.vi_save_line()
  191.                 del self.l_buffer.line_buffer[self.l_buffer.point]
  192.             
  193.         
  194.  
  195.     
  196.     def vi_accept_line(self, e):
  197.         if self._vi_command and self._vi_command.is_search:
  198.             self._vi_command.do_search()
  199.             return False
  200.         self._vi_command = None
  201.         self.vi_set_insert_mode(True)
  202.         self._vi_undo_stack = []
  203.         self._vi_undo_cursor = -1
  204.         self._vi_current = None
  205.         return self.accept_line(e)
  206.  
  207.     
  208.     def vi_eof(self, e):
  209.         raise EOFError
  210.  
  211.     
  212.     def vi_set_insert_mode(self, value):
  213.         if self._ViMode__vi_insert_mode == value:
  214.             return None
  215.         self._ViMode__vi_insert_mode = value
  216.         if value:
  217.             self.vi_save_line()
  218.             self.console.cursor(size = 25)
  219.         else:
  220.             self.console.cursor(size = 100)
  221.  
  222.     
  223.     def vi_undo_restart(self):
  224.         tpl_undo = (self.l_buffer.point, self.l_buffer.line_buffer[:])
  225.         self._vi_undo_stack = [
  226.             tpl_undo]
  227.         self._vi_undo_cursor = 0
  228.  
  229.     
  230.     def vi_save_line(self):
  231.         if self._vi_undo_stack and self._vi_undo_cursor >= 0:
  232.             del self._vi_undo_stack[self._vi_undo_cursor + 1:]
  233.         
  234.         tpl_undo = (self.l_buffer.point, self.l_buffer.line_buffer[:])
  235.         if not (self._vi_undo_stack) or self._vi_undo_stack[self._vi_undo_cursor][1] != tpl_undo[1]:
  236.             self._vi_undo_stack.append(tpl_undo)
  237.             self._vi_undo_cursor += 1
  238.         
  239.  
  240.     
  241.     def vi_undo_prepare(self):
  242.         if self._vi_undo_cursor == len(self._vi_undo_stack) - 1:
  243.             self.vi_save_line()
  244.         
  245.  
  246.     
  247.     def vi_undo(self, do_pop = True):
  248.         self.vi_undo_prepare()
  249.         if not (self._vi_undo_stack) or self._vi_undo_cursor <= 0:
  250.             self.vi_error()
  251.             return None
  252.         self._vi_undo_cursor -= 1
  253.         self.vi_undo_assign()
  254.  
  255.     
  256.     def vi_undo_all(self):
  257.         self.vi_undo_prepare()
  258.         if self._vi_undo_cursor > 0:
  259.             self._vi_undo_cursor = 0
  260.             self.vi_undo_assign()
  261.         else:
  262.             self.vi_error()
  263.  
  264.     
  265.     def vi_undo_assign(self):
  266.         tpl_undo = self._vi_undo_stack[self._vi_undo_cursor]
  267.         self.l_buffer.line_buffer = tpl_undo[1][:]
  268.         self.l_buffer.point = tpl_undo[0]
  269.  
  270.     
  271.     def vi_redo(self, e):
  272.         if self._vi_undo_cursor >= len(self._vi_undo_stack) - 1:
  273.             self.vi_error()
  274.             return None
  275.         self._vi_undo_cursor += 1
  276.         self.vi_undo_assign()
  277.  
  278.     
  279.     def vi_search(self, rng):
  280.         for i in rng:
  281.             line_history = self._history.history[i]
  282.             pos = line_history.get_line_text().find(self._vi_search_text)
  283.             if pos >= 0:
  284.                 self._history.history_cursor = i
  285.                 self.l_buffer.line_buffer = list(line_history.line_buffer)
  286.                 self.l_buffer.point = pos
  287.                 self.vi_undo_restart()
  288.                 return True
  289.         
  290.         self._bell()
  291.         return False
  292.  
  293.     
  294.     def vi_search_first(self):
  295.         text = ''.join(self.l_buffer.line_buffer[1:])
  296.         if text:
  297.             self._vi_search_text = text
  298.             position = len(self._history.history) - 1
  299.         elif self._vi_search_text:
  300.             position = self._history.history_cursor - 1
  301.         else:
  302.             self.vi_error()
  303.             self.vi_undo()
  304.             return None
  305.         if not text.vi_search(range(position, -1, -1)):
  306.             self.vi_undo()
  307.         
  308.  
  309.     
  310.     def vi_search_again_backward(self):
  311.         self.vi_search(range(self._history.history_cursor - 1, -1, -1))
  312.  
  313.     
  314.     def vi_search_again_forward(self):
  315.         self.vi_search(range(self._history.history_cursor + 1, len(self._history.history)))
  316.  
  317.     
  318.     def vi_up(self, e):
  319.         if self._history.history_cursor == len(self._history.history):
  320.             self._vi_current = self.l_buffer.line_buffer[:]
  321.         
  322.         self._history.previous_history(self.l_buffer)
  323.         if self.vi_is_insert_mode:
  324.             self.end_of_line(e)
  325.         else:
  326.             self.beginning_of_line(e)
  327.         self.vi_undo_restart()
  328.  
  329.     
  330.     def vi_down(self, e):
  331.         if self._history.history_cursor >= len(self._history.history):
  332.             self.vi_error()
  333.             return None
  334.         if self._history.history_cursor < len(self._history.history) - 1:
  335.             self._history.next_history(self.l_buffer)
  336.             if self.vi_is_insert_mode:
  337.                 self.end_of_line(e)
  338.             else:
  339.                 self.beginning_of_line(e)
  340.             self.vi_undo_restart()
  341.         elif self._vi_current is not None:
  342.             self._history.history_cursor = len(self._history.history)
  343.             self.l_buffer.line_buffer = self._vi_current
  344.             self.end_of_line(e)
  345.             self._vi_current = None
  346.         else:
  347.             self.vi_error()
  348.             return None
  349.         return None if not (self.vi_is_insert_mode) and self.l_buffer.point > 0 else self._history.history_cursor >= len(self._history.history)
  350.  
  351.     
  352.     def vi_arrow_up(self, e):
  353.         self.vi_set_insert_mode(True)
  354.         self.vi_up(e)
  355.         self.vi_save_line()
  356.  
  357.     
  358.     def vi_arrow_down(self, e):
  359.         self.vi_set_insert_mode(True)
  360.         self.vi_down(e)
  361.         self.vi_save_line()
  362.  
  363.     
  364.     def vi_complete(self, e):
  365.         text = self.l_buffer.get_line_text()
  366.         if text and not text.isspace():
  367.             return self.complete(e)
  368.         return self.vi_key(e)
  369.  
  370.  
  371. _VI_BEGIN = 'vi_begin'
  372. _VI_MULTI1 = 'vi_multi1'
  373. _VI_ACTION = 'vi_action'
  374. _VI_MULTI2 = 'vi_multi2'
  375. _VI_MOTION = 'vi_motion'
  376. _VI_MOTION_ARGUMENT = 'vi_motion_argument'
  377. _VI_REPLACE_ONE = 'vi_replace_one'
  378. _VI_TEXT = 'vi_text'
  379. _VI_SEARCH = 'vi_search'
  380. _VI_END = 'vi_end'
  381.  
  382. class ViCommand:
  383.     
  384.     def __init__(self, readline):
  385.         self.readline = readline
  386.         self.lst_char = []
  387.         self.state = _VI_BEGIN
  388.         self.action = self.movement
  389.         self.motion = None
  390.         self.motion_argument = None
  391.         self.text = None
  392.         self.pos_motion = None
  393.         self.is_edit = False
  394.         self.is_overwrite = False
  395.         self.is_error = False
  396.         self.is_star = False
  397.         self.delete_left = 0
  398.         self.delete_right = 0
  399.         self.readline._vi_multiplier1 = ''
  400.         self.readline._vi_multiplier2 = ''
  401.         self.set_override_multiplier(0)
  402.         self.skip_multipler = False
  403.         self.dct_fcn = {
  404.             ord('$'): self.key_dollar,
  405.             ord('^'): self.key_hat,
  406.             ord(';'): self.key_semicolon,
  407.             ord(','): self.key_comma,
  408.             ord('%'): self.key_percent,
  409.             ord('.'): self.key_dot,
  410.             ord('/'): self.key_slash,
  411.             ord('*'): self.key_star,
  412.             ord('|'): self.key_bar,
  413.             ord('~'): self.key_tilde,
  414.             8: self.key_backspace }
  415.  
  416.     
  417.     def add_char(self, char):
  418.         self.lst_char.append(char)
  419.         if self.state == _VI_BEGIN and self.readline.vi_is_insert_mode:
  420.             self.readline.vi_save_line()
  421.             self.state = _VI_TEXT
  422.         
  423.         if self.state == _VI_SEARCH:
  424.             if char == '\x08':
  425.                 self.key_backspace(char)
  426.             else:
  427.                 self.set_text(char)
  428.             return None
  429.         if self.state == _VI_TEXT:
  430.             if char == '\x1b':
  431.                 self.escape(char)
  432.             elif char == '\t':
  433.                 ts = self.readline.tabstop
  434.                 ws = ' ' * (ts - self.readline.l_buffer.point % ts)
  435.                 self.set_text(ws)
  436.             elif char == '\x08':
  437.                 self.key_backspace(char)
  438.             else:
  439.                 self.set_text(char)
  440.             return None
  441.         if self.state == _VI_MOTION_ARGUMENT:
  442.             self.set_motion_argument(char)
  443.             return None
  444.         if self.state == _VI_REPLACE_ONE:
  445.             self.replace_one(char)
  446.             return None
  447.         
  448.         try:
  449.             fcn_instance = self.dct_fcn[ord(char)]
  450.         except:
  451.             self.state == _VI_REPLACE_ONE
  452.             self.state == _VI_MOTION_ARGUMENT
  453.             self.state == _VI_TEXT
  454.             fcn_instance = getattr(self, 'key_%s' % char, None)
  455.  
  456.         if fcn_instance:
  457.             fcn_instance(char)
  458.             return None
  459.         if char.isdigit():
  460.             self.key_digit(char)
  461.             return None
  462.         self.error()
  463.  
  464.     
  465.     def set_text(self, text):
  466.         self.set_buffer(text)
  467.  
  468.     
  469.     def set_buffer(self, text):
  470.         for char in text:
  471.             if not self.char_isprint(char):
  472.                 continue
  473.             
  474.             if self.is_overwrite:
  475.                 if self.readline.l_buffer.point < len(self.readline.l_buffer.line_buffer):
  476.                     self.readline.l_buffer.line_buffer[self.readline.l_buffer.point] = char
  477.                 else:
  478.                     self.readline.l_buffer.line_buffer.append(char)
  479.             else:
  480.                 self.readline.l_buffer.line_buffer.insert(self.readline.l_buffer.point, char)
  481.             self.readline.l_buffer.point += 1
  482.         
  483.  
  484.     
  485.     def replace_one(self, char):
  486.         if char == '\x1b':
  487.             self.end()
  488.             return None
  489.         self.is_edit = True
  490.         self.readline.vi_save_line()
  491.         times = self.get_multiplier()
  492.         cursor = self.readline.l_buffer.point
  493.         self.readline.l_buffer.line_buffer[cursor:cursor + times] = char * times
  494.         self.end()
  495.  
  496.     
  497.     def char_isprint(self, char):
  498.         if ord(char) >= ord(' '):
  499.             pass
  500.         return ord(char) <= ord('~')
  501.  
  502.     
  503.     def key_dollar(self, char):
  504.         self.motion = self.motion_end_in_line
  505.         self.delete_right = 1
  506.         self.state = _VI_MOTION
  507.         self.apply()
  508.  
  509.     
  510.     def key_hat(self, char):
  511.         self.motion = self.motion_beginning_of_line
  512.         self.state = _VI_MOTION
  513.         self.apply()
  514.  
  515.     
  516.     def key_0(self, char):
  517.         if self.state in [
  518.             _VI_BEGIN,
  519.             _VI_ACTION]:
  520.             self.key_hat(char)
  521.         else:
  522.             self.key_digit(char)
  523.  
  524.     
  525.     def key_digit(self, char):
  526.         if self.state in [
  527.             _VI_BEGIN,
  528.             _VI_MULTI1]:
  529.             self.readline._vi_multiplier1 += char
  530.             self.readline._vi_multiplier2 = ''
  531.             self.state = _VI_MULTI1
  532.         elif self.state in [
  533.             _VI_ACTION,
  534.             _VI_MULTI2]:
  535.             self.readline._vi_multiplier2 += char
  536.             self.state = _VI_MULTI2
  537.         
  538.  
  539.     
  540.     def key_w(self, char):
  541.         if self.action == self.change:
  542.             self.key_e(char)
  543.             return None
  544.         self.motion = self.motion_word_short
  545.         self.state = _VI_MOTION
  546.         self.apply()
  547.  
  548.     
  549.     def key_W(self, char):
  550.         if self.action == self.change:
  551.             self.key_E(char)
  552.             return None
  553.         self.motion = self.motion_word_long
  554.         self.state = _VI_MOTION
  555.         self.apply()
  556.  
  557.     
  558.     def key_e(self, char):
  559.         self.motion = self.motion_end_short
  560.         self.state = _VI_MOTION
  561.         self.delete_right = 1
  562.         self.apply()
  563.  
  564.     
  565.     def key_E(self, char):
  566.         self.motion = self.motion_end_long
  567.         self.state = _VI_MOTION
  568.         self.delete_right = 1
  569.         self.apply()
  570.  
  571.     
  572.     def key_b(self, char):
  573.         self.motion = self.motion_back_short
  574.         self.state = _VI_MOTION
  575.         self.apply()
  576.  
  577.     
  578.     def key_B(self, char):
  579.         self.motion = self.motion_back_long
  580.         self.state = _VI_MOTION
  581.         self.apply()
  582.  
  583.     
  584.     def key_f(self, char):
  585.         self.readline._vi_key_find_direction = True
  586.         self.motion = self.motion_find_char_forward
  587.         self.delete_right = 1
  588.         self.state = _VI_MOTION_ARGUMENT
  589.  
  590.     
  591.     def key_F(self, char):
  592.         self.readline._vi_key_find_direction = False
  593.         self.motion = self.motion_find_char_backward
  594.         self.delete_left = 1
  595.         self.state = _VI_MOTION_ARGUMENT
  596.  
  597.     
  598.     def key_t(self, char):
  599.         self.motion = self.motion_to_char_forward
  600.         self.delete_right = 1
  601.         self.state = _VI_MOTION_ARGUMENT
  602.  
  603.     
  604.     def key_T(self, char):
  605.         self.motion = self.motion_to_char_backward
  606.         self.state = _VI_MOTION_ARGUMENT
  607.  
  608.     
  609.     def key_j(self, char):
  610.         self.readline.vi_down(ViEvent(char))
  611.         self.state = _VI_END
  612.  
  613.     
  614.     def key_k(self, char):
  615.         self.readline.vi_up(ViEvent(char))
  616.         self.state = _VI_END
  617.  
  618.     
  619.     def key_semicolon(self, char):
  620.         if self.readline._vi_key_find_char is None:
  621.             self.error()
  622.             return None
  623.         if self.readline._vi_key_find_direction:
  624.             self.motion = self.motion_find_char_forward
  625.         else:
  626.             self.motion = self.motion_find_char_backward
  627.         self.set_motion_argument(self.readline._vi_key_find_char)
  628.  
  629.     
  630.     def key_comma(self, char):
  631.         if self.readline._vi_key_find_char is None:
  632.             self.error()
  633.             return None
  634.         if self.readline._vi_key_find_direction:
  635.             self.motion = self.motion_find_char_backward
  636.         else:
  637.             self.motion = self.motion_find_char_forward
  638.         self.set_motion_argument(self.readline._vi_key_find_char)
  639.  
  640.     
  641.     def key_percent(self, char):
  642.         self.motion = self.motion_matching
  643.         self.delete_right = 1
  644.         self.state = _VI_MOTION
  645.         self.apply()
  646.  
  647.     
  648.     def key_dot(self, char):
  649.         vi_cmd_edit = self.readline._vi_command_edit
  650.         if not vi_cmd_edit:
  651.             return None
  652.         if vi_cmd_edit.is_star:
  653.             self.key_star(char)
  654.             return None
  655.         vi_cmd = ViCommand(self.readline)
  656.         if count >= 1:
  657.             vi_cmd.set_override_multiplier(count)
  658.             vi_cmd_edit.set_override_multiplier(count)
  659.         elif vi_cmd_edit.override_multiplier:
  660.             vi_cmd.set_override_multiplier(vi_cmd_edit.override_multiplier)
  661.         
  662.         for char in vi_cmd_edit.lst_char:
  663.             vi_cmd.add_char(char)
  664.         
  665.         if vi_cmd_edit.is_overwrite and self.readline.l_buffer.point > 0:
  666.             self.readline.l_buffer.point -= 1
  667.         
  668.         self.readline.vi_set_insert_mode(False)
  669.         self.end()
  670.  
  671.     
  672.     def key_slash(self, char):
  673.         self.readline.vi_save_line()
  674.         self.readline.l_buffer.line_buffer = [
  675.             '/']
  676.         self.readline.l_buffer.point = 1
  677.         self.state = _VI_SEARCH
  678.  
  679.     
  680.     def key_star(self, char):
  681.         self.is_star = True
  682.         self.is_edit = True
  683.         self.readline.vi_save_line()
  684.         completions = self.readline._get_completions()
  685.         if completions:
  686.             text = ' '.join(completions) + ' '
  687.             self.readline.l_buffer.line_buffer[self.readline.begidx:self.readline.endidx + 1] = list(text)
  688.             prefix_len = self.readline.endidx - self.readline.begidx
  689.             self.readline.l_buffer.point += len(text) - prefix_len
  690.             self.readline.vi_set_insert_mode(True)
  691.         else:
  692.             self.error()
  693.         self.state = _VI_TEXT
  694.  
  695.     
  696.     def key_bar(self, char):
  697.         self.motion = self.motion_column
  698.         self.state = _VI_MOTION
  699.         self.apply()
  700.  
  701.     
  702.     def key_tilde(self, char):
  703.         self.is_edit = True
  704.         self.readline.vi_save_line()
  705.         for i in range(self.get_multiplier()):
  706.             
  707.             try:
  708.                 c = self.readline.l_buffer.line_buffer[self.readline.l_buffer.point]
  709.                 if c.isupper():
  710.                     self.readline.l_buffer.line_buffer[self.readline.l_buffer.point] = c.lower()
  711.                 elif c.islower():
  712.                     self.readline.l_buffer.line_buffer[self.readline.l_buffer.point] = c.upper()
  713.                 
  714.                 self.readline.l_buffer.point += 1
  715.             continue
  716.             except IndexError:
  717.                 break
  718.                 continue
  719.             
  720.  
  721.         
  722.         self.end()
  723.  
  724.     
  725.     def key_h(self, char):
  726.         self.motion = self.motion_left
  727.         self.state = _VI_MOTION
  728.         self.apply()
  729.  
  730.     
  731.     def key_backspace(self, char):
  732.         if self.state in [
  733.             _VI_TEXT,
  734.             _VI_SEARCH]:
  735.             if self.text and len(self.text):
  736.                 self.text = self.text[:-1]
  737.                 
  738.                 try:
  739.                     self.lst_char.pop()
  740.                     self.lst_char.pop()
  741.                 except IndexError:
  742.                     pass
  743.                 except:
  744.                     None<EXCEPTION MATCH>IndexError
  745.                 
  746.  
  747.             None<EXCEPTION MATCH>IndexError
  748.         else:
  749.             self.key_h(char)
  750.         self.readline._vi_do_backspace(self)
  751.         if self.state == _VI_SEARCH and not (self.readline.l_buffer.line_buffer):
  752.             self.state = _VI_BEGIN
  753.         
  754.  
  755.     
  756.     def key_l(self, char):
  757.         self.motion = self.motion_right
  758.         self.state = _VI_MOTION
  759.         self.apply()
  760.  
  761.     
  762.     def key_i(self, char):
  763.         self.is_edit = True
  764.         self.state = _VI_TEXT
  765.         self.readline.vi_set_insert_mode(True)
  766.  
  767.     
  768.     def key_I(self, char):
  769.         self.is_edit = True
  770.         self.state = _VI_TEXT
  771.         self.readline.vi_set_insert_mode(True)
  772.         self.readline.l_buffer.point = 0
  773.  
  774.     
  775.     def key_a(self, char):
  776.         self.is_edit = True
  777.         self.state = _VI_TEXT
  778.         self.readline.vi_set_insert_mode(True)
  779.         if len(self.readline.l_buffer.line_buffer):
  780.             self.readline.l_buffer.point += 1
  781.         
  782.  
  783.     
  784.     def key_A(self, char):
  785.         self.is_edit = True
  786.         self.state = _VI_TEXT
  787.         self.readline.vi_set_insert_mode(True)
  788.         self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer)
  789.  
  790.     
  791.     def key_d(self, char):
  792.         self.is_edit = True
  793.         self.state = _VI_ACTION
  794.         self.action = self.delete
  795.  
  796.     
  797.     def key_D(self, char):
  798.         self.is_edit = True
  799.         self.state = _VI_ACTION
  800.         self.action = self.delete_end_of_line
  801.         self.apply()
  802.  
  803.     
  804.     def key_x(self, char):
  805.         self.is_edit = True
  806.         self.state = _VI_ACTION
  807.         self.action = self.delete_char
  808.         self.apply()
  809.  
  810.     
  811.     def key_X(self, char):
  812.         self.is_edit = True
  813.         self.state = _VI_ACTION
  814.         self.action = self.delete_prev_char
  815.         self.apply()
  816.  
  817.     
  818.     def key_s(self, char):
  819.         self.is_edit = True
  820.         i1 = self.readline.l_buffer.point
  821.         i2 = self.readline.l_buffer.point + self.get_multiplier()
  822.         self.skip_multipler = True
  823.         self.readline.vi_set_insert_mode(True)
  824.         del self.readline.l_buffer.line_buffer[i1:i2]
  825.         self.state = _VI_TEXT
  826.  
  827.     
  828.     def key_S(self, char):
  829.         self.is_edit = True
  830.         self.readline.vi_set_insert_mode(True)
  831.         self.readline.l_buffer.line_buffer = []
  832.         self.readline.l_buffer.point = 0
  833.         self.state = _VI_TEXT
  834.  
  835.     
  836.     def key_c(self, char):
  837.         self.is_edit = True
  838.         self.state = _VI_ACTION
  839.         self.action = self.change
  840.  
  841.     
  842.     def key_C(self, char):
  843.         self.is_edit = True
  844.         self.readline.vi_set_insert_mode(True)
  845.         del self.readline.l_buffer.line_buffer[self.readline.l_buffer.point:]
  846.         self.state = _VI_TEXT
  847.  
  848.     
  849.     def key_r(self, char):
  850.         self.state = _VI_REPLACE_ONE
  851.  
  852.     
  853.     def key_R(self, char):
  854.         self.is_edit = True
  855.         self.is_overwrite = True
  856.         self.readline.l_buffer.overwrite = True
  857.         self.readline.vi_set_insert_mode(True)
  858.         self.state = _VI_TEXT
  859.  
  860.     
  861.     def key_y(self, char):
  862.         self._state = _VI_ACTION
  863.         self.action = self.yank
  864.  
  865.     
  866.     def key_Y(self, char):
  867.         self.readline._vi_yank_buffer = self.readline.l_buffer.get_line_text()
  868.         self.end()
  869.  
  870.     
  871.     def key_p(self, char):
  872.         if not self.readline._vi_yank_buffer:
  873.             return None
  874.         self.is_edit = True
  875.         self.readline.vi_save_line()
  876.         self.readline.l_buffer.point += 1
  877.         self.readline.l_buffer.insert_text(self.readline._vi_yank_buffer * self.get_multiplier())
  878.         self.readline.l_buffer.point -= 1
  879.         self.state = _VI_END
  880.  
  881.     
  882.     def key_P(self, char):
  883.         if not self.readline._vi_yank_buffer:
  884.             return None
  885.         self.is_edit = True
  886.         self.readline.vi_save_line()
  887.         self.readline.l_buffer.insert_text(self.readline._vi_yank_buffer * self.get_multiplier())
  888.         self.readline.l_buffer.point -= 1
  889.         self.state = _VI_END
  890.  
  891.     
  892.     def key_u(self, char):
  893.         self.readline.vi_undo()
  894.         self.state = _VI_END
  895.  
  896.     
  897.     def key_U(self, char):
  898.         self.readline.vi_undo_all()
  899.         self.state = _VI_END
  900.  
  901.     
  902.     def key_v(self, char):
  903.         editor = ViExternalEditor(self.readline.l_buffer.line_buffer)
  904.         self.readline.l_buffer.line_buffer = list(editor.result)
  905.         self.readline.l_buffer.point = 0
  906.         self.is_edit = True
  907.         self.state = _VI_END
  908.  
  909.     
  910.     def error(self):
  911.         self.readline._bell()
  912.         self.is_error = True
  913.  
  914.     
  915.     def state_is_end(self):
  916.         return self.state == _VI_END
  917.  
  918.     is_end = property(state_is_end)
  919.     
  920.     def state_is_search(self):
  921.         return self.state == _VI_SEARCH
  922.  
  923.     is_search = property(state_is_search)
  924.     
  925.     def state_is_replace_one(self):
  926.         return self.state == _VI_REPLACE_ONE
  927.  
  928.     is_replace_one = property(state_is_replace_one)
  929.     
  930.     def do_search(self):
  931.         self.readline.vi_search_first()
  932.         self.state = _VI_END
  933.  
  934.     
  935.     def key_n(self, char):
  936.         self.readline.vi_search_again_backward()
  937.         self.state = _VI_END
  938.  
  939.     
  940.     def key_N(self, char):
  941.         self.readline.vi_search_again_forward()
  942.         self.state = _VI_END
  943.  
  944.     
  945.     def motion_beginning_of_line(self, line, index = 0, count = 1, **kw):
  946.         return 0
  947.  
  948.     
  949.     def motion_end_in_line(self, line, index = 0, count = 1, **kw):
  950.         return max(0, len(self.readline.l_buffer.line_buffer) - 1)
  951.  
  952.     
  953.     def motion_word_short(self, line, index = 0, count = 1, **kw):
  954.         return vi_pos_word_short(line, index, count)
  955.  
  956.     
  957.     def motion_word_long(self, line, index = 0, count = 1, **kw):
  958.         return vi_pos_word_long(line, index, count)
  959.  
  960.     
  961.     def motion_end_short(self, line, index = 0, count = 1, **kw):
  962.         return vi_pos_end_short(line, index, count)
  963.  
  964.     
  965.     def motion_end_long(self, line, index = 0, count = 1, **kw):
  966.         return vi_pos_end_long(line, index, count)
  967.  
  968.     
  969.     def motion_back_short(self, line, index = 0, count = 1, **kw):
  970.         return vi_pos_back_short(line, index, count)
  971.  
  972.     
  973.     def motion_back_long(self, line, index = 0, count = 1, **kw):
  974.         return vi_pos_back_long(line, index, count)
  975.  
  976.     
  977.     def motion_find_char_forward(self, line, index = 0, count = 1, char = None):
  978.         self.readline._vi_key_find_char = char
  979.         return vi_pos_find_char_forward(line, char, index, count)
  980.  
  981.     
  982.     def motion_find_char_backward(self, line, index = 0, count = 1, char = None):
  983.         self.readline._vi_key_find_char = char
  984.         return vi_pos_find_char_backward(line, char, index, count)
  985.  
  986.     
  987.     def motion_to_char_forward(self, line, index = 0, count = 1, char = None):
  988.         return vi_pos_to_char_forward(line, char, index, count)
  989.  
  990.     
  991.     def motion_to_char_backward(self, line, index = 0, count = 1, char = None):
  992.         return vi_pos_to_char_backward(line, char, index, count)
  993.  
  994.     
  995.     def motion_left(self, line, index = 0, count = 1, char = None):
  996.         return max(0, index - count)
  997.  
  998.     
  999.     def motion_right(self, line, index = 0, count = 1, char = None):
  1000.         return min(len(line), index + count)
  1001.  
  1002.     
  1003.     def motion_matching(self, line, index = 0, count = 1, char = None):
  1004.         return vi_pos_matching(line, index)
  1005.  
  1006.     
  1007.     def motion_column(self, line, index = 0, count = 1, char = None):
  1008.         return max(0, count - 1)
  1009.  
  1010.     
  1011.     def has_multiplier(self):
  1012.         if not self.override_multiplier and self.readline._vi_multiplier1:
  1013.             pass
  1014.         return self.readline._vi_multiplier2
  1015.  
  1016.     
  1017.     def get_multiplier(self):
  1018.         if self.override_multiplier:
  1019.             return int(self.override_multiplier)
  1020.         if self.readline._vi_multiplier1 == '':
  1021.             m1 = 1
  1022.         else:
  1023.             m1 = int(self.readline._vi_multiplier1)
  1024.         if self.readline._vi_multiplier2 == '':
  1025.             m2 = 1
  1026.         else:
  1027.             m2 = int(self.readline._vi_multiplier2)
  1028.         return m1 * m2
  1029.  
  1030.     
  1031.     def set_override_multiplier(self, count):
  1032.         self.override_multiplier = count
  1033.  
  1034.     
  1035.     def apply(self):
  1036.         if self.motion:
  1037.             self.pos_motion = self.motion(self.readline.l_buffer.line_buffer, self.readline.l_buffer.point, self.get_multiplier(), char = self.motion_argument)
  1038.             if self.pos_motion < 0:
  1039.                 self.error()
  1040.                 return None
  1041.         
  1042.         self.action()
  1043.         if self.state != _VI_TEXT:
  1044.             self.end()
  1045.         
  1046.  
  1047.     
  1048.     def movement(self):
  1049.         if self.pos_motion <= len(self.readline.l_buffer.line_buffer):
  1050.             self.readline.l_buffer.point = self.pos_motion
  1051.         else:
  1052.             self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer) - 1
  1053.  
  1054.     
  1055.     def yank(self):
  1056.         if self.pos_motion > self.readline.l_buffer.point:
  1057.             s = self.readline.l_buffer.line_buffer[self.readline.l_buffer.point:self.pos_motion + self.delete_right]
  1058.         else:
  1059.             index = max(0, self.pos_motion - self.delete_left)
  1060.             s = self.readline.l_buffer.line_buffer[index:self.readline.l_buffer.point + self.delete_right]
  1061.         self.readline._vi_yank_buffer = s
  1062.  
  1063.     
  1064.     def delete(self):
  1065.         self.readline.vi_save_line()
  1066.         self.yank()
  1067.         if self.pos_motion > self.readline.l_buffer.point:
  1068.             del self.readline.l_buffer.line_buffer[self.readline.l_buffer.point:self.pos_motion + self.delete_right]
  1069.             if self.readline.l_buffer.point > len(self.readline.l_buffer.line_buffer):
  1070.                 self.readline.l_buffer.point = len(self.readline.l_buffer.line_buffer)
  1071.             
  1072.         else:
  1073.             index = max(0, self.pos_motion - self.delete_left)
  1074.             del self.readline.l_buffer.line_buffer[index:self.readline.l_buffer.point + self.delete_right]
  1075.             self.readline.l_buffer.point = index
  1076.  
  1077.     
  1078.     def delete_end_of_line(self):
  1079.         self.readline.vi_save_line()
  1080.         line_text = self.readline.l_buffer.get_line_text()
  1081.         line_text = line_text[:self.readline.l_buffer.point]
  1082.         self.readline.l_buffer.set_line(line_text)
  1083.         if self.readline.l_buffer.point > 0:
  1084.             self.readline.l_buffer.point -= 1
  1085.         
  1086.  
  1087.     
  1088.     def delete_char(self):
  1089.         self.pos_motion = self.readline.l_buffer.point + self.get_multiplier()
  1090.         self.delete()
  1091.         end = max(0, len(self.readline.l_buffer) - 1)
  1092.         if self.readline.l_buffer.point > end:
  1093.             self.readline.l_buffer.point = end
  1094.         
  1095.  
  1096.     
  1097.     def delete_prev_char(self):
  1098.         self.pos_motion = self.readline.l_buffer.point - self.get_multiplier()
  1099.         self.delete()
  1100.  
  1101.     
  1102.     def change(self):
  1103.         self.readline.vi_set_insert_mode(True)
  1104.         self.delete()
  1105.         self.skip_multipler = True
  1106.         self.state = _VI_TEXT
  1107.  
  1108.     
  1109.     def escape(self, char):
  1110.         if self.state == _VI_TEXT:
  1111.             if not self.skip_multipler:
  1112.                 times = self.get_multiplier()
  1113.                 if times > 1 and self.text:
  1114.                     extra = self.text * (times - 1)
  1115.                     self.set_buffer(extra)
  1116.                 
  1117.             
  1118.         
  1119.         self.state = _VI_END
  1120.  
  1121.     
  1122.     def set_motion_argument(self, char):
  1123.         self.motion_argument = char
  1124.         self.apply()
  1125.  
  1126.     
  1127.     def end(self):
  1128.         self.state = _VI_END
  1129.         if self.readline.l_buffer.point >= len(self.readline.l_buffer.line_buffer):
  1130.             self.readline.l_buffer.point = max(0, len(self.readline.l_buffer.line_buffer) - 1)
  1131.         
  1132.  
  1133.  
  1134.  
  1135. class ViExternalEditor:
  1136.     
  1137.     def __init__(self, line):
  1138.         if type(line) is type([]):
  1139.             line = ''.join(line)
  1140.         
  1141.         file_tmp = self.get_tempfile()
  1142.         fp_tmp = self.file_open(file_tmp, 'w')
  1143.         fp_tmp.write(line)
  1144.         fp_tmp.close()
  1145.         self.run_editor(file_tmp)
  1146.         fp_tmp = self.file_open(file_tmp, 'r')
  1147.         self.result = fp_tmp.read()
  1148.         fp_tmp.close()
  1149.         self.file_remove(file_tmp)
  1150.  
  1151.     
  1152.     def get_tempfile(self):
  1153.         import tempfile
  1154.         return tempfile.mktemp(prefix = 'readline-', suffix = '.py')
  1155.  
  1156.     
  1157.     def file_open(self, filename, mode):
  1158.         return file(filename, mode)
  1159.  
  1160.     
  1161.     def file_remove(self, filename):
  1162.         os.remove(filename)
  1163.  
  1164.     
  1165.     def get_editor(self):
  1166.         
  1167.         try:
  1168.             return os.environ['EDITOR']
  1169.         except KeyError:
  1170.             return 'notepad'
  1171.  
  1172.  
  1173.     
  1174.     def run_editor(self, filename):
  1175.         cmd = '%s %s' % (self.get_editor(), filename)
  1176.         self.run_command(cmd)
  1177.  
  1178.     
  1179.     def run_command(self, command):
  1180.         os.system(command)
  1181.  
  1182.  
  1183.  
  1184. class ViEvent:
  1185.     
  1186.     def __init__(self, char):
  1187.         self.char = char
  1188.  
  1189.  
  1190.  
  1191. def vi_is_word(char):
  1192.     log('xx vi_is_word: type(%s), %s' % (type(char), char))
  1193.     if not char.isalpha() and char.isdigit():
  1194.         pass
  1195.     return char == '_'
  1196.  
  1197.  
  1198. def vi_is_space(char):
  1199.     return char.isspace()
  1200.  
  1201.  
  1202. def vi_is_word_or_space(char):
  1203.     if not vi_is_word(char):
  1204.         pass
  1205.     return vi_is_space(char)
  1206.  
  1207.  
  1208. def vi_pos_word_short(line, index = 0, count = 1):
  1209.     
  1210.     try:
  1211.         for i in range(count):
  1212.             in_word = vi_is_word(line[index])
  1213.             if not in_word:
  1214.                 while not vi_is_word(line[index]):
  1215.                     index += 1
  1216.             else:
  1217.                 while vi_is_word(line[index]):
  1218.                     index += 1
  1219.             while vi_is_space(line[index]):
  1220.                 index += 1
  1221.         
  1222.         return index
  1223.     except IndexError:
  1224.         return len(line)
  1225.  
  1226.  
  1227.  
  1228. def vi_pos_word_long(line, index = 0, count = 1):
  1229.     
  1230.     try:
  1231.         for i in range(count):
  1232.             in_space = vi_is_space(line[index])
  1233.             if not in_space:
  1234.                 while not vi_is_space(line[index]):
  1235.                     index += 1
  1236.             
  1237.             while vi_is_space(line[index]):
  1238.                 index += 1
  1239.         
  1240.         return index
  1241.     except IndexError:
  1242.         return len(line)
  1243.  
  1244.  
  1245.  
  1246. def vi_pos_end_short(line, index = 0, count = 1):
  1247.     
  1248.     try:
  1249.         for i in range(count):
  1250.             index += 1
  1251.             while vi_is_space(line[index]):
  1252.                 index += 1
  1253.             in_word = vi_is_word(line[index])
  1254.             if not in_word:
  1255.                 while not vi_is_word_or_space(line[index]):
  1256.                     index += 1
  1257.                 continue
  1258.             while vi_is_word(line[index]):
  1259.                 index += 1
  1260.         
  1261.         return index - 1
  1262.     except IndexError:
  1263.         return max(0, len(line) - 1)
  1264.  
  1265.  
  1266.  
  1267. def vi_pos_end_long(line, index = 0, count = 1):
  1268.     
  1269.     try:
  1270.         for i in range(count):
  1271.             index += 1
  1272.             while vi_is_space(line[index]):
  1273.                 index += 1
  1274.             while not vi_is_space(line[index]):
  1275.                 index += 1
  1276.         
  1277.         return index - 1
  1278.     except IndexError:
  1279.         return max(0, len(line) - 1)
  1280.  
  1281.  
  1282.  
  1283. class vi_list(list):
  1284.     
  1285.     def __getitem__(self, key):
  1286.         
  1287.         try:
  1288.             if int(key) < 0:
  1289.                 raise IndexError
  1290.             int(key) < 0
  1291.         except ValueError:
  1292.             pass
  1293.  
  1294.         return list.__getitem__(self, key)
  1295.  
  1296.  
  1297.  
  1298. def vi_pos_back_short(line, index = 0, count = 1):
  1299.     line = vi_list(line)
  1300.     
  1301.     try:
  1302.         for i in range(count):
  1303.             index -= 1
  1304.             while vi_is_space(line[index]):
  1305.                 index -= 1
  1306.             in_word = vi_is_word(line[index])
  1307.             if in_word:
  1308.                 while vi_is_word(line[index]):
  1309.                     index -= 1
  1310.                 continue
  1311.             while not vi_is_word_or_space(line[index]):
  1312.                 index -= 1
  1313.         
  1314.         return index + 1
  1315.     except IndexError:
  1316.         return 0
  1317.  
  1318.  
  1319.  
  1320. def vi_pos_back_long(line, index = 0, count = 1):
  1321.     line = vi_list(line)
  1322.     
  1323.     try:
  1324.         for i in range(count):
  1325.             index -= 1
  1326.             while vi_is_space(line[index]):
  1327.                 index -= 1
  1328.             while not vi_is_space(line[index]):
  1329.                 index -= 1
  1330.         
  1331.         return index + 1
  1332.     except IndexError:
  1333.         return 0
  1334.  
  1335.  
  1336.  
  1337. def vi_pos_find_char_forward(line, char, index = 0, count = 1):
  1338.     
  1339.     try:
  1340.         for i in range(count):
  1341.             index += 1
  1342.             while line[index] != char:
  1343.                 index += 1
  1344.         
  1345.         return index
  1346.     except IndexError:
  1347.         return -1
  1348.  
  1349.  
  1350.  
  1351. def vi_pos_find_char_backward(line, char, index = 0, count = 1):
  1352.     
  1353.     try:
  1354.         for i in range(count):
  1355.             index -= 1
  1356.             while index < 0:
  1357.                 return -1
  1358.                 if line[index] == char:
  1359.                     break
  1360.                 
  1361.             index -= 1
  1362.         
  1363.         return index
  1364.     except IndexError:
  1365.         return -1
  1366.  
  1367.  
  1368.  
  1369. def vi_pos_to_char_forward(line, char, index = 0, count = 1):
  1370.     index = vi_pos_find_char_forward(line, char, index, count)
  1371.     if index > 0:
  1372.         return index - 1
  1373.     return index
  1374.  
  1375.  
  1376. def vi_pos_to_char_backward(line, char, index = 0, count = 1):
  1377.     index = vi_pos_find_char_backward(line, char, index, count)
  1378.     if index >= 0:
  1379.         return index + 1
  1380.     return index
  1381.  
  1382. _vi_dct_matching = {
  1383.     '<': ('>', +1),
  1384.     '>': ('<', -1),
  1385.     '(': (')', +1),
  1386.     ')': ('(', -1),
  1387.     '[': (']', +1),
  1388.     ']': ('[', -1),
  1389.     '{': ('}', +1),
  1390.     '}': ('{', -1) }
  1391.  
  1392. def vi_pos_matching(line, index = 0):
  1393.     anchor = None
  1394.     target = None
  1395.     delta = 1
  1396.     count = 0
  1397.     
  1398.     try:
  1399.         while anchor is None:
  1400.             
  1401.             try:
  1402.                 (target, delta) = _vi_dct_matching[line[index]]
  1403.                 anchor = line[index]
  1404.                 count = 1
  1405.             except KeyError:
  1406.                 index += 1
  1407.                 continue
  1408.             except:
  1409.                 None<EXCEPTION MATCH>KeyError
  1410.             
  1411.  
  1412.             None<EXCEPTION MATCH>KeyError
  1413.             if index < 0:
  1414.                 return -1
  1415.             if line[index] == anchor:
  1416.                 count += 1
  1417.             elif line[index] == target:
  1418.                 count -= 1
  1419.                 if count == 0:
  1420.                     return index
  1421.             
  1422.         index += delta
  1423.     except IndexError:
  1424.         return -1
  1425.  
  1426.  
  1427.