Commits

Simon de Vlieger committed 4899f23 Merge

Merge

Comments (0)

Files changed (2)

 
         self.encoding = getpreferredencoding()
         self.interface = interface
+        self.buffer = list()
+
+    def __iter__(self):
+        return iter(self.readlines())
 
     def isatty(self):
         return True
 
-    def readline(self):
+    def readline(self, size=-1):
         """I can't think of any reason why anything other than readline would
         be useful in the context of an interactive interpreter so this is the
         only one I've done anything with. The others are just there in case
         someone does something weird to stop it from blowing up."""
 
+        if not size:
+            return ''
+        elif self.buffer:
+            buffer = self.buffer.pop(0)
+        else:
+            buffer = ''
+
         curses.raw(True)
-        buffer = ''
         try:
-            while True:
+            while not buffer.endswith('\n'):
                 key = self.interface.get_key()
                 if key in [curses.erasechar(), 'KEY_BACKSPACE']:
                     y, x = self.interface.scr.getyx()
                         self.interface.scr.delch(y, x - 1)
                         buffer = buffer[:-1]
                     continue
+                elif key == chr(4) and not buffer:
+                    # C-d
+                    return ''
                 elif (key != '\n' and
                     (len(key) > 1 or unicodedata.category(key) == 'Cc')):
                     continue
 # Include the \n in the buffer - raw_input() seems to deal with trailing
 # linebreaks and will break if it gets an empty string.
                 buffer += key
-                if key == '\n':
-                    break
         finally:
             curses.raw(False)
 
+        if size > 0:
+            rest = buffer[size:]
+            if rest:
+                self.buffer.append(rest)
+            buffer = buffer[:size]
+
         if py3:
             return buffer
         else:
             return buffer.encode(getpreferredencoding())
 
-    def read(self, x):
-        pass
+    def read(self, size=None):
+        if size == 0:
+            return ''
 
-    def readlines(self, x):
-        pass
+        data = list()
+        while size is None or size > 0:
+            line = self.readline(size or -1)
+            if not line:
+                break
+            if size is not None:
+                size -= len(line)
+            data.append(line)
+
+        return ''.join(data)
+
+    def readlines(self, size=-1):
+        return list(iter(self.readline, ''))
 
 OPTS = Struct()
 DO_RESIZE = False
         sys.stdin = FakeStdin(self)
         self.paste_mode = False
         self.last_key_press = time.time()
-        self.paste_time = float(OPTS.paste_time)
+        self.paste_time = OPTS.paste_time
         self.prev_block_finished = 0
         sys.path.insert(0, '.')
 
             else:
                 matches = self.completer.matches
 
+        if not e and self.argspec:
+            matches.extend(name + '=' for name in self.argspec[1][0]
+                           if name.startswith(cw))
+
         if e or not matches:
             self.matches = []
             self.matches_iter.update()
             if inp:
                 self.rl_hist.append(inp + '\n')
             stdout_position = len(self.stdout_hist)
-            more = self.push(inp) or self.paste_mode
+            more = self.push(inp)
             if not more:
                 self.prev_block_finished = stdout_position
                 self.s = ''
 
         n = 1
 
-        if x == 0:
-            y -= 1
-            x = gethw()[1]
-
         # Delete following lines if the current string is greater than the
         # screen width. Curses does not handle that on its own.
         width = self.scr.getmaxyx()[1]
-        for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 2):
+        for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 1):
             self.scr.move(y, 0)
             self.scr.clrtoeol()
 
         # It seems as if curses does not handle this on its own, which
         # makes me sad.
         width = self.scr.getmaxyx()[1]
-        for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 2):
+        for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 1):
             self.scr.move(y, 0)
             self.scr.clrtoeol()
 
         self.scr.redrawwin()
         self.scr.refresh()
 
-    def p_key(self):
+    def p_key(self, key):
         """Process a keypress"""
 
-        if self.c is None:
+        if key is None:
             return ''
 
-        if self.c == chr(8): # C-Backspace (on my computer anyway!)
+        if key == chr(8): # C-Backspace (on my computer anyway!)
             self.clrtobol()
-            self.c = '\n'
+            key = '\n'
             # Don't return; let it get handled
-        if self.c == chr(27):
+        if key == chr(27):
             return ''
 
-        if self.c in (chr(127), 'KEY_BACKSPACE'):
+        if key in (chr(127), 'KEY_BACKSPACE'):
             self.bs()
             self.complete()
             return ''
 
-        elif self.c == 'KEY_DC': # Del
+        elif key == 'KEY_DC': # Del
             self.delete()
             self.complete()
             # Redraw (as there might have been highlighted parens)
             self.print_line(self.s)
             return ''
 
-        elif self.c in key_dispatch[OPTS.undo_key]: # C-r
+        elif key in key_dispatch[OPTS.undo_key]: # C-r
             self.undo()
             return ''
 
-        elif self.c in ('KEY_UP', ) + key_dispatch[OPTS.up_one_line_key]: # Cursor Up/C-p
+        elif key in ('KEY_UP', ) + key_dispatch[OPTS.up_one_line_key]: # Cursor Up/C-p
             self.back()
             return ''
 
-        elif self.c in ('KEY_DOWN', ) + key_dispatch[OPTS.down_one_line_key]: # Cursor Down/C-n
+        elif key in ('KEY_DOWN', ) + key_dispatch[OPTS.down_one_line_key]: # Cursor Down/C-n
             self.fwd()
             return ''
 
-        elif self.c == 'KEY_LEFT': # Cursor Left
+        elif key == 'KEY_LEFT': # Cursor Left
             self.mvc(1)
             # Redraw (as there might have been highlighted parens)
             self.print_line(self.s)
 
-        elif self.c == 'KEY_RIGHT': # Cursor Right
+        elif key == 'KEY_RIGHT': # Cursor Right
             self.mvc(-1)
             # Redraw (as there might have been highlighted parens)
             self.print_line(self.s)
 
-        elif self.c in ("KEY_HOME", '^A', chr(1)): # home or ^A
+        elif key in ("KEY_HOME", '^A', chr(1)): # home or ^A
             self.home()
             # Redraw (as there might have been highlighted parens)
             self.print_line(self.s)
 
-        elif self.c in ("KEY_END", '^E', chr(5)): # end or ^E
+        elif key in ("KEY_END", '^E', chr(5)): # end or ^E
             self.end()
             # Redraw (as there might have been highlighted parens)
             self.print_line(self.s)
 
-        elif self.c in key_dispatch[OPTS.cut_to_buffer_key]: # cut to buffer
+        elif key in key_dispatch[OPTS.cut_to_buffer_key]: # cut to buffer
             self.cut_to_buffer()
             return ''
 
-        elif self.c in key_dispatch[OPTS.yank_from_buffer_key]: # yank from buffer
+        elif key in key_dispatch[OPTS.yank_from_buffer_key]: # yank from buffer
             self.yank_from_buffer()
             return ''
 
-        elif self.c in key_dispatch[OPTS.clear_word_key]: 
+        elif key in key_dispatch[OPTS.clear_word_key]:
             self.bs_word()
             self.complete()
             return ''
 
-        elif self.c in key_dispatch[OPTS.clear_line_key]:
+        elif key in key_dispatch[OPTS.clear_line_key]:
             self.clrtobol()
             return ''
 
-        elif self.c in key_dispatch[OPTS.clear_screen_key]: 
+        elif key in key_dispatch[OPTS.clear_screen_key]:
             self.s_hist = [self.s_hist[-1]]
             self.highlighted_paren = None
             self.redraw()
             return ''
 
-        elif self.c in key_dispatch[OPTS.exit_key]: 
+        elif key in key_dispatch[OPTS.exit_key]:
             if not self.s:
                 self.do_exit = True
                 return None
             else:
                 return ''
 
-        elif self.c in key_dispatch[OPTS.save_key]:
+        elif key in key_dispatch[OPTS.save_key]:
             self.write2file()
             return ''
 
-        elif self.c in key_dispatch[OPTS.pastebin_key]:
+        elif key in key_dispatch[OPTS.pastebin_key]:
             self.pastebin()
             return ''
 
-        elif self.c in key_dispatch[OPTS.last_output_key]:
+        elif key in key_dispatch[OPTS.last_output_key]:
             page(self.stdout_hist[self.prev_block_finished:-4])
             return ''
 
-        elif self.c == '\n':
+        elif key == '\n':
             self.lf()
             return None
 
-        elif self.c == '\t':
+        elif key == '\t':
             return self.tab()
 
-        elif len(self.c) == 1 and not unicodedata.category(self.c) == 'Cc':
-            self.addstr(self.c)
+        elif len(key) == 1 and not unicodedata.category(key) == 'Cc':
+            self.addstr(key)
             self.print_line(self.s)
 
         else:
             return ''
 
-
         return True
 
     def tab(self):
 
         if not self.paste_mode:
             for _ in range(indent_spaces // OPTS.tab_length):
-                self.c = '\t'
-                self.p_key()
+                self.p_key('\t')
 
         if indent and not self.paste_mode:
-            self.c = '\t'
-            self.p_key()
+            self.p_key('\t')
 
-        self.c = None
         self.cpos = 0
 
         while True:
-            self.c = self.get_key()
-            if self.p_key() is None:
+            key = self.get_key()
+            if self.p_key(key) is None:
                 return self.s
 
     def clear_current_line(self):

bpython/config.py

     """Simple class for instantiating objects we can add arbitrary attributes
     to and use for various arbitrary things."""
 
+def fill_config_with_default_values(config, default_values):
+    for section in default_values.iterkeys():
+        if not config.has_section(section):
+            config.add_section(section)
 
-
-class CP(ConfigParser):
-    def safeget(self, section, option, default):
-        """safet get method using default values"""
-        bools_t = ['true', 'yes', 'y', 'on']
-        bools_f = ['false', 'no', 'n', 'off']
-
-        try:
-            v = self.get(section, option)
-        except NoSectionError:
-            v = default
-        except NoOptionError:
-            v = default
-        if isinstance(v, bool):
-            return v
-        try:
-            if v.lower() in bools_t:
-                return True
-            if v.lower() in bools_f:
-                return False
-        except AttributeError:
-            pass
-        try:
-            return int(v)
-        except ValueError:
-            return v
+        for (opt, val) in default_values[section].iteritems():
+            if not config.has_option(section, opt):
+                config.set(section, opt, str(val))
 
 
 def loadini(struct, configfile):
         # eventually please.
         config_path = os.path.expanduser('~/.bpython.ini')
 
-    config = CP()
+    config = ConfigParser()
+    fill_config_with_default_values(config, {
+        'general': {
+            'arg_spec': True,
+            'auto_display_list': True,
+            'color_scheme': 'default',
+            'flush_output': True,
+            'hist_file': '~/.pythonhist',
+            'hist_length': 100,
+            'paste_time': 0.02,
+            'syntax': True,
+            'tab_length': 4
+        },
+        'keyboard': {
+            'clear_line': 'C-u',
+            'clear_screen': 'C-l',
+            'clear_word': 'C-w',
+            'cut_to_buffer': 'C-k',
+            'down_one_line': 'C-n',
+            'exit': 'C-d',
+            'last_output': 'F9',
+            'pastebin': 'F8',
+            'save': 'C-s',
+            'undo': 'C-r',
+            'up_one_line': 'C-p',
+            'yank_from_buffer': 'C-y'
+        }
+    })
     config.read(config_path)
 
-    struct.tab_length = config.safeget('general', 'tab_length', 4)
-    struct.auto_display_list = config.safeget('general', 'auto_display_list',
-                                              True)
-    struct.syntax = config.safeget('general', 'syntax', True)
-    struct.arg_spec = config.safeget('general', 'arg_spec', True)
-    struct.paste_time = config.safeget('general', 'paste_time', 0.02)
-    struct.hist_file = config.safeget('general', 'hist_file', '~/.pythonhist')
-    struct.hist_length = config.safeget('general', 'hist_length', 100)
-    struct.flush_output = config.safeget('general', 'flush_output', True)
-    struct.pastebin_key = config.safeget('keyboard', 'pastebin', 'F8')
-    struct.save_key = config.safeget('keyboard', 'save', 'C-s')
-    struct.undo_key = config.safeget('keyboard', 'undo', 'C-r')
-    struct.up_one_line_key = config.safeget('keyboard', 'up_one_line', 'C-p')
-    struct.down_one_line_key = config.safeget('keyboard', 'down_one_line', 'C-n')
-    struct.cut_to_buffer_key = config.safeget('keyboard', 'cut_to_buffer', 'C-k')
-    struct.yank_from_buffer_key = config.safeget('keybard', 'yank_from_buffer', 'C-y')
-    struct.clear_word_key = config.safeget('keyboard', 'clear_word', 'C-w')
-    struct.clear_line_key = config.safeget('keyboard', 'clear_line', 'C-u')
-    struct.clear_screen_key = config.safeget('keyboard', 'clear_screen', 'C-l')
-    struct.exit_key = config.safeget('keyboard', 'exit', 'C-d')
-    struct.last_output_key = config.safeget('keyboard', 'last_output', 'F9')
- 
-    color_scheme_name = config.safeget('general', 'color_scheme', 'default')
+    struct.tab_length = config.getint('general', 'tab_length')
+    struct.auto_display_list = config.getboolean('general',
+                                                 'auto_display_list')
+    struct.syntax = config.getboolean('general', 'syntax')
+    struct.arg_spec = config.getboolean('general', 'arg_spec')
+    struct.paste_time = config.getfloat('general', 'paste_time')
+    struct.hist_file = config.get('general', 'hist_file')
+    struct.hist_length = config.getint('general', 'hist_length')
+    struct.flush_output = config.getboolean('general', 'flush_output')
+    struct.pastebin_key = config.get('keyboard', 'pastebin')
+    struct.save_key = config.get('keyboard', 'save')
+    struct.undo_key = config.get('keyboard', 'undo')
+    struct.up_one_line_key = config.get('keyboard', 'up_one_line')
+    struct.down_one_line_key = config.get('keyboard', 'down_one_line')
+    struct.cut_to_buffer_key = config.get('keyboard', 'cut_to_buffer')
+    struct.yank_from_buffer_key = config.get('keyboard', 'yank_from_buffer')
+    struct.clear_word_key = config.get('keyboard', 'clear_word')
+    struct.clear_line_key = config.get('keyboard', 'clear_line')
+    struct.clear_screen_key = config.get('keyboard', 'clear_screen')
+    struct.exit_key = config.get('keyboard', 'exit')
+    struct.last_output_key = config.get('keyboard', 'last_output')
+
+    color_scheme_name = config.get('general', 'color_scheme')
 
     if color_scheme_name == 'default':
         struct.color_scheme = {
         key_dispatch[key]
 
 def load_theme(struct, path, inipath):
-    theme = CP()
+    theme = ConfigParser()
     try:
         f = open(path, 'r')
     except (IOError, OSError), e: