示例#1
0
 def forward_search_history(self, e):  # (C-s)
     '''Search forward starting at the current line and moving down
     through the the history as necessary. This is an incremental
     search.'''
     log("fwd_search_history")
     self._init_incremental_search(self._history.forward_search_history, e)
     self.finalize()
示例#2
0
 def get_current_history_length(self):
     '''Return the number of lines currently in the history.
     (This is different from get_history_length(), which returns
     the maximum number of lines that will be written to a history file.)'''
     value = len(self.history)
     log("get_current_history_length:%d" % value)
     return value
示例#3
0
    def _init_incremental_search(self, searchfun, init_event):
        """Initialize search prompt
        """
        log("init_incremental_search")
        self.subsearch_query = ''
        self.subsearch_fun = searchfun
        self.subsearch_old_line = self.l_buffer.get_line_text()

        queue = self.process_keyevent_queue
        queue.append(self._process_incremental_search_keyevent)

        self.subsearch_oldprompt = self.prompt

        if (self.previous_func != self.reverse_search_history
                and self.previous_func != self.forward_search_history):
            self.subsearch_query = self.l_buffer[0:Point].get_line_text()

        if self.subsearch_fun == self.reverse_search_history:
            self.subsearch_prompt = "reverse-i-search%d`%s': "
        else:
            self.subsearch_prompt = "forward-i-search%d`%s': "

        self.prompt = self.subsearch_prompt % (self._history.history_cursor,
                                               "")

        if self.subsearch_query:
            self.line = self._process_incremental_search_keyevent(init_event)
        else:
            self.line = ""
示例#4
0
    def reverse_search_history(self, searchfor, startpos=None):
        if startpos is None:
            startpos = self.history_cursor
        origpos = startpos

        result = lineobj.ReadLineTextBuffer("")

        for idx, line in list(enumerate(self.history))[startpos:0:-1]:
            if searchfor in line:
                startpos = idx
                break

        # If we get a new search without change in search term it means
        # someone pushed ctrl-r and we should find the next match
        if self.last_search_for == searchfor and startpos > 0:
            startpos -= 1
            for idx, line in list(enumerate(self.history))[startpos:0:-1]:
                if searchfor in line:
                    startpos = idx
                    break

        if self.history:
            result = self.history[startpos].get_line_text()
        else:
            result = ""
        self.history_cursor = startpos
        self.last_search_for = searchfor
        log("reverse_search_history: old:%d new:%d result:%r" %
            (origpos, self.history_cursor, result))
        return result
示例#5
0
    def test_complete(self):
        import rlcompleter
        logger.sock_silent = False

        log("-" * 50)
        r = EmacsModeTest()
        completerobj = rlcompleter.Completer()

        def _nop(val, word):
            return word

        completerobj._callable_postfix = _nop
        r.completer = completerobj.complete
        r._bind_key("tab", r.complete)
        r.input('"exi(ksdjksjd)"')
        r.input('Control-a')
        r.input('Right')
        r.input('Right')
        r.input('Right')
        r.input('Tab')
        self.assert_line(r, "exit(ksdjksjd)", 4)

        r.input('Escape')
        r.input('"exi"')
        r.input('Control-a')
        r.input('Right')
        r.input('Right')
        r.input('Right')
        r.input('Tab')
        self.assert_line(r, "exit", 4)
示例#6
0
    def _process_non_incremental_search_keyevent(self, keyinfo):
        keytuple = keyinfo.tuple()
        log("SearchPromptMode %s %s" % (keyinfo, keytuple))
        history = self._history

        if keyinfo.keyname == 'backspace':
            self.non_inc_query = self.non_inc_query[:-1]
        elif keyinfo.keyname in ['return', 'escape']:
            if self.non_inc_query:
                if self.non_inc_direction == -1:
                    res = history.reverse_search_history(self.non_inc_query)
                else:
                    res = history.forward_search_history(self.non_inc_query)

            self._bell()
            self.prompt = self.non_inc_oldprompt
            self.process_keyevent_queue = self.process_keyevent_queue[:-1]
            self._history.history_cursor = len(self._history.history)
            if keyinfo.keyname == 'escape':
                self.l_buffer = self.non_inc_oldline
            else:
                self.l_buffer.set_line(res)
            return False
        elif keyinfo.keyname:
            pass
        elif keyinfo.control == False and keyinfo.meta == False:
            self.non_inc_query += keyinfo.char
        else:
            pass
        self.prompt = self.non_inc_oldprompt + ":" + self.non_inc_query
示例#7
0
    def _readline_from_keyboard(self):
        c = self.console
        while True:
            self._update_line()
            event = c.getkeypress()
            if self.next_meta:
                self.next_meta = False
                control, meta, shift, code = event.keyinfo
                event.keyinfo = (control, True, shift, code)

            # Process exit keys. Only exit on empty line
            if event.keyinfo in self.exit_dispatch:
                if lineobj.EndOfLine(self.l_buffer) == 0:
                    raise EOFError

            dispatch_func = self.key_dispatch.get(
                event.keyinfo, self.self_insert)
            log("readline from keyboard:%s" % (event.keyinfo,))
            r = None
            if dispatch_func:
                r = dispatch_func(event)
                self.l_buffer.push_undo()

            self.previous_func = dispatch_func
            if r:
                self._update_line()
                break
示例#8
0
 def paste(self, e):
     """Paste windows clipboard.
     Assume single line strip other lines and end of line markers and trailing spaces"""  # (Control-v)
     if self.enable_win32_clipboard:
         txt = clipboard.get_clipboard_text_and_convert(False)
         txt = txt.split("\n")[0].strip("\r").strip("\n")
         log("paste: >%s<" % list(map(ord, txt)))
         self.insert_text(txt)
     self.finalize()
示例#9
0
 def write_plain(self, text, attr=None):
     '''write text at current cursor position.'''
     log('write("%s", %s)' % (text, attr))
     if attr is None:
         attr = self.attr
     n = c_int(0)
     self.SetConsoleTextAttribute(self.hout, attr)
     self.WriteConsoleA(self.hout, text, len(text), byref(n), None)
     return len(text)
示例#10
0
 def _bind_key(self, key, func):
     """setup the mapping from key to call the function."""
     if not callable(func):
         print("Trying to bind non method to keystroke:%s,%s" % (key, func))
         raise ReadlineError(
             "Trying to bind non method to keystroke:%s,%s,%s,%s" %
             (key, func, type(func), type(self._bind_key)))
     keyinfo = make_KeyPress_from_keydescr(key.lower()).tuple()
     log(">>>%s -> %s<<<" % (keyinfo, func.__name__))
     self.key_dispatch[keyinfo] = func
示例#11
0
    def __init__(self, newbuffer=0):
        '''Initialize the Console object.

        newbuffer=1 will allocate a new buffer so the old content will be restored
        on exit.
        '''
        self.serial = 0
        self.attr = System.Console.ForegroundColor
        self.saveattr = winattr[str(System.Console.ForegroundColor).lower()]
        self.savebg = System.Console.BackgroundColor
        log('initial attr=%s' % self.attr)
示例#12
0
 def write_color(self, text, attr=None):
     text = ensure_unicode(text)
     n, res = self.ansiwriter.write_color(text, attr)
     junk = DWORD(0)
     for attr, chunk in res:
         log("console.attr:%s" % (attr))
         log("console.chunk:%s" % (chunk))
         self.SetConsoleTextAttribute(self.hout, attr.winattr)
         for short_chunk in split_block(chunk):
             self.WriteConsoleW(self.hout, short_chunk, len(short_chunk),
                                byref(junk), None)
     return n
示例#13
0
 def write_plain(self, text, attr=None):
     '''write text at current cursor position.'''
     text = ensure_unicode(text)
     log('write("%s", %s)' % (text, attr))
     if attr is None:
         attr = self.attr
     junk = DWORD(0)
     self.SetConsoleTextAttribute(self.hout, attr)
     for short_chunk in split_block(chunk):
         self.WriteConsoleW(self.hout, ensure_unicode(short_chunk),
                            len(short_chunk), byref(junk), None)
     return len(text)
示例#14
0
 def input(self, keytext):
     if keytext[0:1] == '"' and keytext[-1:] == '"':
         lst_key = ['"%s"' % c for c in keytext[1:-1]]
     else:
         lst_key = [keytext]
     for key in lst_key:
         keyinfo, event = keytext_to_keyinfo_and_event(key)
         dispatch_func = self.key_dispatch.get(keyinfo.tuple(),
                                               self.self_insert)
         self.tested_commands[dispatch_func.__name__] = dispatch_func
         log("keydisp: %s %s" % (key, dispatch_func.__name__))
         dispatch_func(event)
         self.previous_func = dispatch_func
示例#15
0
 def getkeypress(self):
     '''Return next key press event from the queue, ignoring others.'''
     ck = System.ConsoleKey
     while True:
         e = System.Console.ReadKey(True)
         if e.Key == System.ConsoleKey.PageDown:  # PageDown
             self.scroll_window(12)
         elif e.Key == System.ConsoleKey.PageUp:  # PageUp
             self.scroll_window(-12)
         elif str(e.KeyChar) == "\000":  # Drop deadkeys
             log("Deadkey: %s" % e)
             return event(self, e)
         else:
             return event(self, e)
示例#16
0
    def __init__(self, newbuffer=0):
        '''Initialize the Console object.

        newbuffer=1 will allocate a new buffer so the old content will be restored
        on exit.
        '''
        # Do I need the following line? It causes a console to be created whenever
        # readline is imported into a pythonw application which seems wrong. Things
        # seem to work without it...
        # self.AllocConsole()

        if newbuffer:
            self.hout = self.CreateConsoleScreenBuffer(
                GENERIC_READ | GENERIC_WRITE, 0, None, 1, None)
            self.SetConsoleActiveScreenBuffer(self.hout)
        else:
            self.hout = self.GetStdHandle(STD_OUTPUT_HANDLE)

        self.hin = self.GetStdHandle(STD_INPUT_HANDLE)
        self.inmode = DWORD(0)
        self.GetConsoleMode(self.hin, byref(self.inmode))
        self.SetConsoleMode(self.hin, 0xf)
        info = CONSOLE_SCREEN_BUFFER_INFO()
        self.GetConsoleScreenBufferInfo(self.hout, byref(info))
        self.attr = info.wAttributes
        self.saveattr = info.wAttributes  # remember the initial colors
        self.defaultstate = AnsiState()
        self.defaultstate.winattr = info.wAttributes
        self.ansiwriter = AnsiWriter(self.defaultstate)

        background = self.attr & 0xf0
        for escape in self.escape_to_color:
            if self.escape_to_color[escape] is not None:
                self.escape_to_color[escape] |= background
        log('initial attr=%x' % self.attr)
        self.softspace = 0  # this is for using it as a file-like object
        self.serial = 0

        self.pythondll = ctypes.pythonapi
        self.inputHookPtr = c_void_p.from_address(
            addressof(self.pythondll.PyOS_InputHook)).value

        if sys.version_info[:2] > (3, 4):
            self.pythondll.PyMem_RawMalloc.restype = c_size_t
            self.pythondll.PyMem_Malloc.argtypes = [c_size_t]
            setattr(Console, 'PyMem_Malloc', self.pythondll.PyMem_RawMalloc)
        else:
            self.pythondll.PyMem_Malloc.restype = c_size_t
            self.pythondll.PyMem_Malloc.argtypes = [c_size_t]
            setattr(Console, 'PyMem_Malloc', self.pythondll.PyMem_Malloc)
示例#17
0
 def paste_mulitline_code(self, e):
     '''Paste windows clipboard'''
     reg = re.compile("\r?\n")
     if self.enable_win32_clipboard:
         txt = clipboard.get_clipboard_text_and_convert(False)
         t = reg.split(txt)
         t = [row for row in t if row.strip() != ""]  # remove empty lines
         if t != [""]:
             self.insert_text(t[0])
             self.add_history(self.l_buffer.copy())
             self.paste_line_buffer = t[1:]
             log("multi: %s" % self.paste_line_buffer)
             return True
         else:
             return False
示例#18
0
 def __init__(self, console, input):
     '''Initialize an event from the Windows input structure.'''
     self.type = '??'
     self.serial = console.next_serial()
     self.width = 0
     self.height = 0
     self.x = 0
     self.y = 0
     self.char = str(input.KeyChar)
     self.keycode = input.Key
     self.state = input.Modifiers
     log("%s,%s,%s" % (input.Modifiers, input.Key, input.KeyChar))
     self.type = "KeyRelease"
     self.keysym = make_keysym(self.keycode)
     self.keyinfo = make_KeyPress(self.char, self.state, self.keycode)
示例#19
0
 def getkeypress(self):
     '''Return next key press event from the queue, ignoring others.'''
     while True:
         e = self.get()
         if e.type == 'KeyPress' and e.keycode not in key_modifiers:
             log("console.getkeypress %s" % e)
             if e.keyinfo.keyname == 'next':
                 self.scroll_window(12)
             elif e.keyinfo.keyname == 'prior':
                 self.scroll_window(-12)
             else:
                 return e
         elif ((e.type == 'KeyRelease')
               and (e.keyinfo == KeyPress('S', False, True, False, 'S'))):
             log("getKeypress:%s,%s,%s" % (e.keyinfo, e.keycode, e.type))
             return e
示例#20
0
    def _process_incremental_search_keyevent(self, keyinfo):
        log("_process_incremental_search_keyevent")
        keytuple = keyinfo.tuple()
        #dispatch_func = self.key_dispatch.get(keytuple, default)
        revtuples = []
        fwdtuples = []
        for ktuple, func in self.key_dispatch.items():
            if func == self.reverse_search_history:
                revtuples.append(ktuple)
            elif func == self.forward_search_history:
                fwdtuples.append(ktuple)

        log("IncrementalSearchPromptMode %s %s" % (keyinfo, keytuple))
        if keyinfo.keyname == 'backspace':
            self.subsearch_query = self.subsearch_query[:-1]
            if len(self.subsearch_query) > 0:
                self.line = self.subsearch_fun(self.subsearch_query)
            else:
                self._bell()
                self.line = ""  # empty query means no search result
        elif keyinfo.keyname in ['return', 'escape']:
            self._bell()
            self.prompt = self.subsearch_oldprompt
            self.process_keyevent_queue = self.process_keyevent_queue[:-1]
            self._history.history_cursor = len(self._history.history)
            if keyinfo.keyname == 'escape':
                self.l_buffer.set_line(self.subsearch_old_line)
            return True
        elif keyinfo.keyname:
            pass
        elif keytuple in revtuples:
            self.subsearch_fun = self._history.reverse_search_history
            self.subsearch_prompt = "reverse-i-search%d`%s': "
            self.line = self.subsearch_fun(self.subsearch_query)
        elif keytuple in fwdtuples:
            self.subsearch_fun = self._history.forward_search_history
            self.subsearch_prompt = "forward-i-search%d`%s': "
            self.line = self.subsearch_fun(self.subsearch_query)
        elif keyinfo.control == False and keyinfo.meta == False:
            self.subsearch_query += keyinfo.char
            self.line = self.subsearch_fun(self.subsearch_query)
        else:
            pass
        self.prompt = self.subsearch_prompt % (self._history.history_cursor,
                                               self.subsearch_query)
        self.l_buffer.set_line(self.line)
示例#21
0
    def _init_digit_argument(self, keyinfo):
        """Initialize search prompt
        """
        c = self.console
        line = self.l_buffer.get_line_text()
        self._digit_argument_oldprompt = self.prompt
        queue = self.process_keyevent_queue
        queue = self.process_keyevent_queue
        queue.append(self._process_digit_argument_keyevent)

        if keyinfo.char == "-":
            self.argument = -1
        elif keyinfo.char in "0123456789":
            self.argument = int(keyinfo.char)
        log("<%s> %s" % (self.argument, type(self.argument)))
        self.prompt = "(arg: %s) " % self.argument
        log("arg-init %s %s" % (self.argument, keyinfo.char))
示例#22
0
 def _get_completions(self):
     """Return a list of possible completions for the string ending at the point.
     Also set begidx and endidx in the process."""
     completions = []
     self.begidx = self.l_buffer.point
     self.endidx = self.l_buffer.point
     buf = self.l_buffer.line_buffer
     if self.completer:
         # get the string to complete
         while self.begidx > 0:
             self.begidx -= 1
             if buf[self.begidx] in self.completer_delims:
                 self.begidx += 1
                 break
         text = ensure_str(''.join(buf[self.begidx:self.endidx]))
         log('complete text="%s"' % ensure_unicode(text))
         i = 0
         while True:
             try:
                 r = self.completer(ensure_unicode(text), i)
             except IndexError:
                 break
             i += 1
             if r is None:
                 break
             elif r and r not in completions:
                 completions.append(r)
             else:
                 pass
         log('text completions=<%s>' %
             list(map(ensure_unicode, completions)))
     if (self.complete_filesystem == "on") and not completions:
         # get the filename to complete
         while self.begidx > 0:
             self.begidx -= 1
             if buf[self.begidx] in ' \t\n':
                 self.begidx += 1
                 break
         text = ensure_str(''.join(buf[self.begidx:self.endidx]))
         log('file complete text="%s"' % ensure_unicode(text))
         completions = list(
             map(ensure_unicode,
                 glob.glob(os.path.expanduser(text) + '*'.encode('ascii'))))
         if self.mark_directories == 'on':
             mc = []
             for f in completions:
                 if os.path.isdir(f):
                     mc.append(f + os.sep)
                 else:
                     mc.append(f)
             completions = mc
         log('fnames=<%s>' % list(map(ensure_unicode, completions)))
     return completions
示例#23
0
    def scroll_window(self, lines):
        '''Scroll the window by the indicated number of lines.'''
        info = CONSOLE_SCREEN_BUFFER_INFO()
        self.GetConsoleScreenBufferInfo(self.hout, byref(info))
        rect = info.srWindow
        log('sw: rtop=%d rbot=%d' % (rect.Top, rect.Bottom))
        top = rect.Top + lines
        bot = rect.Bottom + lines
        h = bot - top
        maxbot = info.dwSize.Y - 1
        if top < 0:
            top = 0
            bot = h
        if bot > maxbot:
            bot = maxbot
            top = bot - h

        nrect = SMALL_RECT()
        nrect.Top = top
        nrect.Bottom = bot
        nrect.Left = rect.Left
        nrect.Right = rect.Right
        log('sn: top=%d bot=%d' % (top, bot))
        r = self.SetConsoleWindowInfo(self.hout, True, byref(nrect))
        log('r=%d' % r)
示例#24
0
    def readline(self, prompt=''):
        '''Try to act like GNU readline.'''
        # handle startup_hook
        if self.first_prompt:
            self.first_prompt = False
            if self.startup_hook:
                try:
                    self.startup_hook()
                except BaseException:
                    print('startup hook failed')
                    traceback.print_exc()

        c = self.console
        self.l_buffer.reset_line()
        self.prompt = prompt
        self._print_prompt()

        if self.pre_input_hook:
            try:
                self.pre_input_hook()
            except BaseException:
                print('pre_input_hook failed')
                traceback.print_exc()
                self.pre_input_hook = None

        log("in readline: %s" % self.paste_line_buffer)
        if len(self.paste_line_buffer) > 0:
            self.l_buffer = lineobj.ReadlineTextBuffer(
                self.paste_line_buffer[0])
            self._update_line()
            self.paste_line_buffer = self.paste_line_buffer[1:]
            c.write('\r\n')
        else:
            self._readline_from_keyboard()
            c.write('\r\n')

        self.add_history(self.l_buffer.copy())

        log('returning(%s)' % self.l_buffer.get_line_text())
        return self.l_buffer.get_line_text() + '\n'
示例#25
0
    def write_color(self, text, attr=None):
        '''write text at current cursor position and interpret color escapes.

        return the number of characters written.
        '''
        log('write_color("%s", %s)' % (text, attr))
        chunks = self.terminal_escape.split(text)
        log('chunks=%s' % repr(chunks))
        bg = self.savebg
        n = 0  # count the characters we actually write, omitting the escapes
        if attr is None:  # use attribute from initial console
            attr = self.attr
        try:
            fg = self.trtable[(0x000f & attr)]
            bg = self.trtable[(0x00f0 & attr) >> 4]
        except TypeError:
            fg = attr

        for chunk in chunks:
            m = self.escape_parts.match(chunk)
            if m:
                log(m.group(1))
                attr = ansicolor.get(m.group(1), self.attr)
            n += len(chunk)
            System.Console.ForegroundColor = fg
            System.Console.BackgroundColor = bg
            System.Console.Write(chunk)
        return n
示例#26
0
    def process_keyevent(self, keyinfo):
        def nop(e):
            pass
        keytuple = keyinfo.tuple()

        # Process exit keys. Only exit on empty line
        if keytuple in self.exit_dispatch:
            if lineobj.EndOfLine(self.l_buffer) == 0:
                raise EOFError

        dispatch_func = self.key_dispatch.get(keytuple, self.vi_key)
        log("readline from keyboard:%s->%s" % (keytuple, dispatch_func))
        r = None
        if dispatch_func:
            r = dispatch_func(keyinfo)
            self.l_buffer.push_undo()

        self.previous_func = dispatch_func
        if r:
            self._update_line()
            return True
        return False
示例#27
0
        def debug_output(on, filename="pyreadline_debug_log.txt"):  # Not implemented yet
            if on in ["on", "on_nologfile"]:
                self.debug = True

            if on == "on":
                logger.start_file_log(filename)
                logger.start_socket_log()
                logger.log("STARTING LOG")
            elif on == "on_nologfile":
                logger.start_socket_log()
                logger.log("STARTING LOG")
            else:
                logger.log("STOPING LOG")
                logger.stop_file_log()
                logger.stop_socket_log()
示例#28
0
 def _process_digit_argument_keyevent(self, keyinfo):
     log("DigitArgumentMode.keyinfo %s" % keyinfo)
     keytuple = keyinfo.tuple()
     log("DigitArgumentMode.keytuple %s %s" % (keyinfo, keytuple))
     if keyinfo.keyname in ['return']:
         self.prompt = self._digit_argument_oldprompt
         self.process_keyevent_queue = self.process_keyevent_queue[:-1]
         return True
     elif keyinfo.keyname:
         pass
     elif (keyinfo.char in "0123456789" and keyinfo.control == False
           and keyinfo.meta == False):
         log("arg %s %s" % (self.argument, keyinfo.char))
         self.argument = self.argument * 10 + int(keyinfo.char)
     else:
         self.prompt = self._digit_argument_oldprompt
         raise LeaveModeTryNext
     self.prompt = "(arg: %s) " % self.argument
示例#29
0
    def _process_keyevent(self, keyinfo):
        """return True when line is final
        """
        # Process exit keys. Only exit on empty line
        log("_process_keyevent <%s>" % keyinfo)

        def nop(e):
            pass

        if self.next_meta:
            self.next_meta = False
            keyinfo.meta = True
        keytuple = keyinfo.tuple()

        if self._insert_verbatim:
            self.insert_text(keyinfo)
            self._insert_verbatim = False
            self.argument = 0
            return False

        if keytuple in self.exit_dispatch:
            pars = (self.l_buffer, lineobj.EndOfLine(self.l_buffer))
            log("exit_dispatch:<%s, %s>" % pars)
            if lineobj.EndOfLine(self.l_buffer) == 0:
                raise EOFError
        if keyinfo.keyname or keyinfo.control or keyinfo.meta:
            default = nop
        else:
            default = self.self_insert
        dispatch_func = self.key_dispatch.get(keytuple, default)

        log("readline from keyboard:<%s,%s>" % (keytuple, dispatch_func))

        r = None
        if dispatch_func:
            r = dispatch_func(keyinfo)
            self._keylog(dispatch_func, self.l_buffer)
            self.l_buffer.push_undo()

        self.previous_func = dispatch_func
        return r
示例#30
0
 def write(self, text):
     log('write("%s")' % text)
     return self.write_color(text)