Skip to content

Support for IPython 3.0 #119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
----------------
Expand Down
48 changes: 33 additions & 15 deletions ftplugin/python/vim_ipython.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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', '')
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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']
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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("\'","\\\'"))
Expand All @@ -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]))
Expand Down