diff --git a/README.rst b/README.rst index f4c8f3a..0e0dccc 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ vim-ipython A two-way integration between Vim and IPython. -IPython versions 0.11.x, 0.12.x, 0.13.x, 1.x and 2.x +IPython versions 0.11.x, 0.12.x, 0.13.x, 1.x, 2.x and 3.x * author: Paul Ivanov (http://pirsquared.org) * github: http://github.com/ivanov/vim-ipython @@ -293,6 +293,7 @@ pull request with your attribution. * @memeplex for fixing the identifier grabbing on e.g. non-PEP8 compliant code * @pydave for IPythonTerminate (sending SIGTERM using our hack) * @luispedro for IPythonNew +* @jjhelmus for IPython 3.x support. Similar Projects ---------------- diff --git a/ftplugin/python/vim_ipython.py b/ftplugin/python/vim_ipython.py index 202925c..075c1bf 100644 --- a/ftplugin/python/vim_ipython.py +++ b/ftplugin/python/vim_ipython.py @@ -39,7 +39,7 @@ def flush(self):pass def vim_variable(name, default=None): exists = int(vim.eval("exists('%s')" % name)) return vim.eval(name) if exists else default - + def vim_regex_escape(x): for old, new in (("[", "\\["), ("]", "\\]"), (":", "\\:"), (".", "\."), ("*", "\\*")): x = x.replace(old, new) @@ -122,7 +122,7 @@ def km_from_string(s=''): except ImportError: # < 0.12, no find_connection_file pass - + global km, kc, send s = s.replace('--existing', '') @@ -183,7 +183,7 @@ def km_from_string(s=''): klass = sc.__class__ klass._oinfo_orig = klass.object_info klass.object_info = lambda s,x,y: s._oinfo_orig(x) - + #XXX: backwards compatibility for IPython < 1.0 if not hasattr(kc, 'iopub_channel'): kc.iopub_channel = kc.sub_channel @@ -247,6 +247,16 @@ def get_doc_msg(msg_id): if not content['found']: return b + # IPython 3.0+ the documentation message is encoding by the kernel + if 'data' in content: + try: + text = content['data']['text/plain'] + for line in text.split('\n'): + b.append(strip_color_escapes(line).rstrip()) + return b + except KeyError: # no text/plain key + return b + for field in ['type_name','base_class','string_form','namespace', 'file','length','definition','source','docstring']: c = content.get(field,None) @@ -300,7 +310,10 @@ def get_doc_buffer(level=0): vim.command('setlocal syntax=python') def ipy_complete(base, current_line, pos): - msg_id = kc.shell_channel.complete(base, current_line, pos) + # pos is the location of the start of base, add the length + # to get the completion position + msg_id = kc.shell_channel.complete(base, current_line, + int(pos) + len(base) - 1) try: m = get_child_msg(msg_id) matches = m['content']['matches'] @@ -399,14 +412,17 @@ def update_subchannel_msgs(debug=False, force=False): # TODO: alllow for distinguishing between stdout and stderr (using # custom syntax markers in the vim-ipython buffer perhaps), or by # also echoing the message to the status bar - s = strip_color_escapes(m['content']['data']) - elif header == 'pyout': + try: + s = strip_color_escapes(m['content']['data']) + except KeyError: # changed in IPython 3.0.0 + s = strip_color_escapes(m['content']['text']) + elif header == 'pyout' or header == 'execute_result': s = status_prompt_out % {'line': m['content']['execution_count']} s += m['content']['data']['text/plain'] elif header == 'display_data': # TODO: handle other display data types (HMTL? images?) s += m['content']['data']['text/plain'] - elif header == 'pyin': + elif header == 'pyin' or header == 'execute_input': # TODO: the next line allows us to resend a line to ipython if # %doctest_mode is on. In the future, IPython will send the # execution_count on subchannel, so this will need to be updated @@ -418,13 +434,13 @@ def update_subchannel_msgs(debug=False, force=False): dots = '.' * len(prompt.rstrip()) dots += prompt[len(prompt.rstrip()):] s += m['content']['code'].rstrip().replace('\n', '\n' + dots) - elif header == 'pyerr': + elif header == 'pyerr' or header == 'error': c = m['content'] s = "\n".join(map(strip_color_escapes,c['traceback'])) s += c['ename'] + ":" + c['evalue'] if s.find('\n') == -1: - # somewhat ugly unicode workaround from + # somewhat ugly unicode workaround from # http://vim.1045645.n5.nabble.com/Limitations-of-vim-python-interface-with-respect-to-character-encodings-td1223881.html if isinstance(s,unicode): s=s.encode(vim_encoding) @@ -444,7 +460,7 @@ def update_subchannel_msgs(debug=False, force=False): if not startedin_vimipython: vim.command('normal! p') # go back to where you were return update_occured - + def get_child_msg(msg_id): # XXX: message handling should be split into its own process in the future while True: @@ -456,7 +472,7 @@ def get_child_msg(msg_id): #got a message, but not the one we were looking for echo('skipping a message on shell_channel','WarningMsg') return m - + def print_prompt(prompt,msg_id=None): """Print In[] or In[42] style messages""" global show_execution_count @@ -554,7 +570,6 @@ def set_pid(): global pid lines = '\n'.join(['import os', '_pid = os.getpid()']) msg_id = send(lines, silent=True, user_variables=['_pid']) - # wait to get message back from kernel try: child = get_child_msg(msg_id) @@ -565,6 +580,9 @@ def set_pid(): pid = int(child['content']['user_variables']['_pid']) except TypeError: # change in IPython 1.0.dev moved this out pid = int(child['content']['user_variables']['_pid']['data']['text/plain']) + except KeyError: # change in IPython 3.0+ + pid = int( + child['content']['user_expressions']['_pid']['data']['text/plain']) except KeyError: # change in IPython 1.0.dev moved this out echo("Could not get PID information, kernel not running Python?") return pid @@ -608,7 +626,7 @@ def dedent_run_this_line(): def dedent_run_these_lines(): run_these_lines(True) - + #def set_this_line(): # # not sure if there's a way to do this, since we have multiple clients # send("get_ipython().shell.set_next_input(\'%s\')" % vim.current.line.replace("\'","\\\'")) @@ -625,9 +643,9 @@ def toggle_reselect(): #def set_breakpoint(): # send("__IP.InteractiveTB.pdb.set_break('%s',%d)" % (vim.current.buffer.name, # vim.current.window.cursor[0])) -# print("set breakpoint in %s:%d"% (vim.current.buffer.name, +# print("set breakpoint in %s:%d"% (vim.current.buffer.name, # vim.current.window.cursor[0])) -# +# #def clear_breakpoint(): # send("__IP.InteractiveTB.pdb.clear_break('%s',%d)" % (vim.current.buffer.name, # vim.current.window.cursor[0]))