From 9ab7103d9d6a37916429467c343209d3b53737f9 2015-01-19 23:44:23
From: Min RK <benjaminrk@gmail.com>
Date: 2015-01-19 23:44:23
Subject: [PATCH] handle unicode issues in `ipython console` completions

- readline.get_endidx gives byte offset, not character offset
- readline talks str, not unicode
---

diff --git a/IPython/terminal/console/completer.py b/IPython/terminal/console/completer.py
index fbc257b..018e438 100644
--- a/IPython/terminal/console/completer.py
+++ b/IPython/terminal/console/completer.py
@@ -11,6 +11,7 @@ except ImportError:
 
 from IPython.config import Configurable
 from IPython.core.completer import IPCompleter
+from IPython.utils.py3compat import str_to_unicode, cast_bytes, unicode_to_str
 from IPython.utils.traitlets import Float
 import IPython.utils.rlineimpl as readline
 
@@ -36,8 +37,17 @@ class ZMQCompleter(IPCompleter):
             self.readline.set_completer_delims('\r\n')
     
     def complete_request(self, text):
-        line = readline.get_line_buffer()
-        cursor_pos = readline.get_endidx()
+        line = str_to_unicode(readline.get_line_buffer())
+        byte_cursor_pos = readline.get_endidx()
+        
+        # get_endidx is a byte offset
+        # account for multi-byte characters to get correct cursor_pos
+        cursor_pos = byte_cursor_pos
+        i = 0
+        while i < cursor_pos:
+            bytelen = len(cast_bytes(line[i]))
+            cursor_pos -= (bytelen-1)
+            i += 1
         
         # send completion request to kernel
         # Give the kernel up to 5s to respond
@@ -54,6 +64,7 @@ class ZMQCompleter(IPCompleter):
             if content["cursor_end"] < cursor_pos:
                 extra = line[content["cursor_end"]: cursor_pos]
                 matches = [m + extra for m in matches]
+            matches = [ unicode_to_str(m) for m in matches ]
             return matches
         return []