Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2fd5010

Browse files
committed
merge
2 parents 8e80ef7 + 49a22e1 commit 2fd5010

2 files changed

Lines changed: 108 additions & 34 deletions

File tree

README.rst

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ A two-way integration between Vim and IPython 0.11+
77
* author: Paul Ivanov (http://pirsquared.org)
88
* github: http://github.com/ivanov/vim-ipython
99
* demos: http://pirsquared.org/vim-ipython/
10-
* blogpost: http://pirsquared.org/blog/2011/07/28/vim-ipython/
10+
* blogpost: http://pirsquared.org/blog/vim-ipython.html
1111

1212
Using this plugin, you can send lines or whole files for IPython to
1313
execute, and also get back object introspection and word completions in
@@ -164,11 +164,41 @@ the line ``let g:ipy_completefunc = 'local'`` in one's vimrc will activate the
164164
IPython-based completion only for current buffer. Setting `g:ipy_completefunc`
165165
to anything other than `'local'` or `'global'` disables it altogether.
166166

167+
**NEW since IPython 0.13**
168+
169+
**Sending ? and ?? now works just like IPython**
170+
This is only supported for single lines that end with ? and ??, which works
171+
just the same as it does in IPython (The ?? variant will show the code, not
172+
just the docstring
173+
174+
**Sending arbitrary signal to IPython kernel**
175+
`:IPythonInterrupt` now supports sending of arbitrary signals. There's a
176+
convenience alias for sending SIGTERM via `:IPythonTerminate`, but you can
177+
also send any signal by just passing an argument to `:IPythonInterrupt`.
178+
Here's an example. First, send this code (or just run it in your kernel)::
179+
180+
import signal
181+
def greeting_user(signum, stack):
182+
import sys
183+
sys.stdout.flush()
184+
print "Hello, USER!"
185+
sys.stdout.flush()
186+
signal.signal(signal.SIGUSR1, greeting_user)
187+
188+
Now, proceed to connect up using vim-ipython and run `:IPythonInterrupt 10` -
189+
where 10 happens to be signal.SIGUSR1 in the POSIX world. This functionality,
190+
along with the sourcing of profile-dependent code on startup (
191+
``vi `ipython locate profile default`/startup/README`` ), brings the forgotten
192+
world of inter-process communication through signals to your favorite text
193+
editor and REPL combination.
194+
195+
167196
---------------
168-
Current issues:
197+
Known issues:
169198
---------------
170199
- For now, vim-ipython only connects to an ipython session in progress.
171-
- The ipdb integration is not yet re-implemented.
200+
- The ipdb integration is not yet re-implemented. Pending
201+
[IPython PR #3089](https://github.com/ipython/ipython/pull/3089)
172202
- If you're running inside ``screen``, read about the ``<CTRL-S>`` issue `here
173203
<http://munkymorgy.blogspot.com/2008/07/screen-ctrl-s-bug.html>`_, and add
174204
this line to your ``.bashrc`` to fix it::
@@ -210,6 +240,8 @@ Current issues:
210240
highlighting, but that syntax highlighting will be broken if a stack trace
211241
is returned which contains one half of a quote delimiter.
212242

243+
- vim-ipython is currently for Python2.X only.
244+
213245
----------------------------
214246
Thanks and Bug Participation
215247
----------------------------
@@ -242,6 +274,7 @@ pull request with your attribution.
242274
* @pielgrzym for setting completefunc locally to a buffer (#32)
243275
* @flacjacket for pointing out and providing fix for IPython API change
244276
* @memeplex for fixing the identifier grabbing on e.g. non-PEP8 compliant code
277+
* @pydave for IPythonTerminate (sending SIGTERM using our hack)
245278

246279
Similar Projects
247280
----------------

ftplugin/python/ipy.vim

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ status_blank_lines = int(vim_variable('g:ipy_status_blank_lines', '1'))
9393
ip = '127.0.0.1'
9494
try:
9595
km
96-
except NameError:
97-
km = None
98-
try:
96+
kc
9997
pid
10098
except NameError:
99+
km = None
100+
kc = None
101101
pid = None
102102

103103
def km_from_string(s=''):
@@ -110,23 +110,23 @@ def km_from_string(s=''):
110110
from Queue import Empty
111111
try:
112112
from IPython.kernel import (
113-
BlockingKernelManager,
113+
KernelManager,
114114
find_connection_file,
115115
)
116116
except ImportError:
117-
# < 0.14
118-
from IPython.zmq.blockingkernelmanager import BlockingKernelManager
117+
# IPython < 1.0
118+
from IPython.zmq.blockingkernelmanager import BlockingKernelManager as KernelManager
119119
from IPython.zmq.kernelapp import kernel_aliases
120120
try:
121121
from IPython.lib.kernel import find_connection_file
122122
except ImportError:
123123
# < 0.12, no find_connection_file
124124
pass
125125

126-
global km,send,Empty
126+
global km, kc, send, Empty
127127

128128
s = s.replace('--existing', '')
129-
if 'connection_file' in BlockingKernelManager.class_trait_names():
129+
if 'connection_file' in KernelManager.class_trait_names():
130130
# 0.12 uses files instead of a collection of ports
131131
# include default IPython search path
132132
# filefind also allows for absolute paths, in which case the search
@@ -147,7 +147,7 @@ def km_from_string(s=''):
147147
echo(":IPython " + s + " failed", "Info")
148148
echo("^-- failed '" + s + "' not found", "Error")
149149
return
150-
km = BlockingKernelManager(connection_file = fullpath)
150+
km = KernelManager(connection_file = fullpath)
151151
km.load_connection_file()
152152
else:
153153
if s == '':
@@ -156,7 +156,7 @@ def km_from_string(s=''):
156156
loader = KeyValueConfigLoader(s.split(), aliases=kernel_aliases)
157157
cfg = loader.load_config()['KernelApp']
158158
try:
159-
km = BlockingKernelManager(
159+
km = KernelManager(
160160
shell_address=(ip, cfg['shell_port']),
161161
sub_address=(ip, cfg['iopub_port']),
162162
stdin_address=(ip, cfg['stdin_port']),
@@ -165,12 +165,18 @@ def km_from_string(s=''):
165165
echo(":IPython " +s + " failed", "Info")
166166
echo("^-- failed --"+e.message.replace('_port','')+" not specified", "Error")
167167
return
168-
km.start_channels()
169-
send = km.shell_channel.execute
168+
169+
try:
170+
kc = km.client()
171+
except AttributeError:
172+
# 0.13
173+
kc = km
174+
kc.start_channels()
175+
send = kc.shell_channel.execute
170176

171177
#XXX: backwards compatability for IPython < 1.0
172-
if not hasattr(km, 'iopub_channel'):
173-
km.iopub_channel = km.sub_channel
178+
if not hasattr(kc, 'iopub_channel'):
179+
kc.iopub_channel = kc.sub_channel
174180

175181
# now that we're connect to an ipython kernel, activate completion
176182
# machinery, but do so only for the local buffer if the user added the
@@ -206,10 +212,10 @@ def disconnect():
206212
# XXX: make a prompt here if this km owns the kernel
207213
pass
208214

209-
def get_doc(word):
210-
if km is None:
215+
def get_doc(word, level=0):
216+
if kc is None:
211217
return ["Not connected to IPython, cannot query: %s" % word]
212-
msg_id = km.shell_channel.object_info(word)
218+
msg_id = kc.shell_channel.object_info(word, level)
213219
doc = get_doc_msg(msg_id)
214220
# get around unicode problems when interfacing with vim
215221
return [d.encode(vim_encoding) for d in doc]
@@ -253,7 +259,7 @@ def get_doc_buffer(level=0):
253259
vim.command("let &isk = '@,48-57,_,192-255,.'")
254260
word = vim.eval('expand("<cword>")') or ''
255261
vim.command("let &isk = isk_save") # restore iskeyword list
256-
doc = get_doc(word)
262+
doc = get_doc(word, level)
257263
if len(doc) ==0:
258264
echo(repr(word)+" not found","Error")
259265
return
@@ -277,8 +283,12 @@ def get_doc_buffer(level=0):
277283
#vim.command('pcl')
278284
#vim.command('pedit doc')
279285
#vim.command('normal ') # go to previous window
280-
# use the ReST formatting that ships with stock vim
281-
vim.command('setlocal syntax=rst')
286+
if level == 0:
287+
# use the ReST formatting that ships with stock vim
288+
vim.command('setlocal syntax=rst')
289+
else:
290+
# use Python syntax highlighting
291+
vim.command('setlocal syntax=python')
282292

283293
def vim_ipython_is_open():
284294
"""
@@ -296,9 +306,9 @@ def update_subchannel_msgs(debug=False, force=False):
296306
This function will do nothing if the vim-ipython shell is not visible,
297307
unless force=True argument is passed.
298308
"""
299-
if km is None or (not vim_ipython_is_open() and not force):
309+
if kc is None or (not vim_ipython_is_open() and not force):
300310
return False
301-
msgs = km.iopub_channel.get_msgs()
311+
msgs = kc.iopub_channel.get_msgs()
302312
if debug:
303313
#try:
304314
# vim.command("b debug_msgs")
@@ -369,6 +379,9 @@ def update_subchannel_msgs(debug=False, force=False):
369379
elif m['header']['msg_type'] == 'status':
370380
continue
371381
elif m['header']['msg_type'] == 'stream':
382+
# TODO: alllow for distinguishing between stdout and stderr (using
383+
# custom syntax markers in the vim-ipython buffer perhaps), or by
384+
# also echoing the message to the status bar
372385
s = strip_color_escapes(m['content']['data'])
373386
elif m['header']['msg_type'] == 'pyout':
374387
s = status_prompt_out % {'line': m['content']['execution_count']}
@@ -405,7 +418,8 @@ def update_subchannel_msgs(debug=False, force=False):
405418
if status_blank_lines:
406419
if b[-1] != '':
407420
b.append([''])
408-
vim.command('normal G') # go to the end of the file
421+
if update_occured or force:
422+
vim.command('normal G') # go to the end of the file
409423
if not startedin_vimipython:
410424
vim.command('normal p') # go back to where you were
411425
return update_occured
@@ -414,7 +428,7 @@ def get_child_msg(msg_id):
414428
# XXX: message handling should be split into its own process in the future
415429
while True:
416430
# get_msg will raise with Empty exception if no messages arrive in 1 second
417-
m= km.shell_channel.get_msg(timeout=1)
431+
m = kc.shell_channel.get_msg(timeout=1)
418432
if m['parent_header']['msg_id'] == msg_id:
419433
break
420434
else:
@@ -443,7 +457,7 @@ def with_subchannel(f,*args):
443457
f(*args)
444458
if monitor_subchannel:
445459
update_subchannel_msgs()
446-
except AttributeError: #if km is None
460+
except AttributeError: #if kc is None
447461
echo("not connected to IPython", 'Error')
448462
return f_with_update
449463

@@ -454,6 +468,24 @@ def run_this_file():
454468

455469
@with_subchannel
456470
def run_this_line():
471+
if vim.current.line.strip().endswith('?'):
472+
# intercept question mark queries -- move to the word just before the
473+
# question mark and call the get_doc_buffer on it
474+
w = vim.current.window
475+
original_pos = w.cursor
476+
new_pos = (original_pos[0], vim.current.line.index('?')-1)
477+
w.cursor = new_pos
478+
if vim.current.line.strip().endswith('??'):
479+
# double question mark should display source
480+
# XXX: it's not clear what level=2 is for, level=1 is sufficient
481+
# to get the code -- follow up with IPython team on this
482+
get_doc_buffer(1)
483+
else:
484+
get_doc_buffer()
485+
# leave insert mode, so we're in command mode
486+
vim.command('stopi')
487+
w.cursor = original_pos
488+
return
457489
msg_id = send(vim.current.line)
458490
print_prompt(vim.current.line, msg_id)
459491

@@ -486,7 +518,7 @@ def set_pid():
486518
"""
487519
Explicitly ask the ipython kernel for its pid
488520
"""
489-
global km, pid
521+
global pid
490522
lines = '\n'.join(['import os', '_pid = os.getpid()'])
491523
msg_id = send(lines, silent=True, user_variables=['_pid'])
492524

@@ -501,7 +533,12 @@ def set_pid():
501533
return pid
502534

503535

504-
def interrupt_kernel_hack():
536+
def terminate_kernel_hack():
537+
"Send SIGTERM to our the IPython kernel"
538+
import signal
539+
interrupt_kernel_hack(signal.SIGTERM)
540+
541+
def interrupt_kernel_hack(signal_to_send=None):
505542
"""
506543
Sends the interrupt signal to the remote kernel. This side steps the
507544
(non-functional) ipython interrupt mechanisms.
@@ -518,10 +555,13 @@ def interrupt_kernel_hack():
518555
if pid is None:
519556
echo("cannot get kernel PID, Ctrl-C will not be supported")
520557
return
558+
if not signal_to_send:
559+
signal_to_send = signal.SIGINT
560+
521561
echo("KeyboardInterrupt (sent to ipython: pid " +
522-
"%i with signal %i)" % (pid, signal.SIGINT),"Operator")
562+
"%i with signal %s)" % (pid, signal_to_send),"Operator")
523563
try:
524-
os.kill(pid, signal.SIGINT)
564+
os.kill(pid, int(signal_to_send))
525565
except OSError:
526566
echo("unable to kill pid %d" % pid)
527567
pid = None
@@ -654,7 +694,8 @@ endif
654694
command! -nargs=* IPython :py km_from_string("<args>")
655695
command! -nargs=0 IPythonClipboard :py km_from_string(vim.eval('@+'))
656696
command! -nargs=0 IPythonXSelection :py km_from_string(vim.eval('@*'))
657-
command! -nargs=0 IPythonInterrupt :py interrupt_kernel_hack()
697+
command! -nargs=* IPythonInterrupt :py interrupt_kernel_hack("<args>")
698+
command! -nargs=0 IPythonTerminate :py terminate_kernel_hack()
658699

659700
function! IPythonBalloonExpr()
660701
python << endpython
@@ -684,7 +725,7 @@ endpython
684725
python << endpython
685726
base = vim.eval("a:base")
686727
findstart = vim.eval("a:findstart")
687-
msg_id = km.shell_channel.complete(base, current_line, vim.eval("col('.')"))
728+
msg_id = kc.shell_channel.complete(base, current_line, vim.eval("col('.')"))
688729
try:
689730
m = get_child_msg(msg_id)
690731
matches = m['content']['matches']

0 commit comments

Comments
 (0)