##// END OF EJS Templates
updated vim-ipython...
Paul Ivanov -
Show More
@@ -4,11 +4,10 b' vim-ipython'
4
4
5 A two-way integration between Vim and IPython 0.11+
5 A two-way integration between Vim and IPython 0.11+
6
6
7 author: Paul Ivanov (http://pirsquared.org)
7 * author: Paul Ivanov (http://pirsquared.org)
8
8 * github: http://github.com/ivanov/vim-ipython
9 github: http://github.com/ivanov/vim-ipython
9 * demos: http://pirsquared.org/vim-ipython/
10
10 * blogpost: http://pirsquared.org/blog/2011/07/28/vim-ipython/
11 demo: http://pirsquared.org/vim-ipython/
12
11
13 Using this plugin, you can send lines or whole files for IPython to
12 Using this plugin, you can send lines or whole files for IPython to
14 execute, and also get back object introspection and word completions in
13 execute, and also get back object introspection and word completions in
@@ -16,30 +15,46 b' Vim, like what you get with: ``object?<enter>`` and ``object.<tab>`` in'
16 IPython.
15 IPython.
17
16
18 The big change from previous versions of ``ipy.vim`` is that it no longer
17 The big change from previous versions of ``ipy.vim`` is that it no longer
19 requires the brittle ipy_vimserver.py instantiation, and since it uses
18 requires the old brittle ``ipy_vimserver.py`` instantiation, and since
20 just vim and python, it is platform independent (i.e. should work even
19 it uses just vim and python, it is platform independent (i.e. should work
21 on windows, unlike the previous \*nix only solution)
20 even on windows, unlike the previous \*nix only solution). The requirements
21 are IPython 0.11+ with zeromq capabilities, vim compiled with +python.
22
22
23 If you can launch ``ipython qtconsole`` or ``ipython kernel``, and
24 ``:echo has('python')`` returns 1 in vim, you should be good to go.
23
25
24 -----------------
26 -----------------
25 Quickstart Guide:
27 Quickstart Guide:
26 -----------------
28 -----------------
27 Start ``ipython qtconsole`` and copy the connection string.
29 Start ``ipython qtconsole`` [*]_ and copy the connection string.
28 Source ``ipy.vim`` file, which provides new IPython command::
30 Source ``ipy.vim`` file, which provides new IPython command::
29
31
30 :source ipy.vim
32 :source ipy.vim
31 (or copy it to ~/.vim/ftplugin/python to load automatically)
33 (or copy it to ~/.vim/ftplugin/python to load automatically)
32
34
33 :IPythonClipboard
35 :IPythonClipboard
34 (or :IPythonXSelection if you're using X11 without having to copy)
36 (or :IPythonXSelection if you're using X11 without having to copy)
35
37
36 The :IPython command allows you to put the full string, e.g.::
38 The :IPython command allows you to put the full connection string. For IPython
39 0.11, it would look like this::
37
40
38 :IPython --existing --shell=41882 --iopub=43286 --stdin=34987 --hb=36697
41 :IPython --existing --shell=41882 --iopub=43286 --stdin=34987 --hb=36697
39
42
43 and for IPython 0.12, like this::
44
45 :IPython --existing kernel-85997.json
46
40 The ``:IPythonClipboard`` command just uses the ``+`` register to get the
47 The ``:IPythonClipboard`` command just uses the ``+`` register to get the
41 connection string, whereas ``:IPythonXSelection`` uses the ``*`` register
48 connection string, whereas ``:IPythonXSelection`` uses the ``*`` register
42
49
50 .. [*] Though the demos above use ``qtconsole``, it is not required
51 for this workflow, it's just that it was the easiest way to show how to
52 make use of the new functionality in 0.11 release. In the current git
53 trunk of IPython, you can use ``ipython kernel`` to create a kernel and
54 get the connection string to use for any frontend (including vim-ipython).
55 If you are still using 0.11, you can launch a regular kernel using
56 ``python -c "from IPython.zmq.ipkernel import main; main()"``
57
43 ------------------------
58 ------------------------
44 Sending lines to IPython
59 Sending lines to IPython
45 ------------------------
60 ------------------------
@@ -50,10 +65,12 b' Now type out a line and send it to IPython using ``<Ctrl-S>`` from Command mode:'
50 You should see a notification message confirming the line was sent, along
65 You should see a notification message confirming the line was sent, along
51 with the input number for the line, like so ``In[1]: import os``.
66 with the input number for the line, like so ``In[1]: import os``.
52
67
53 ``<Ctrl-S>`` also works from insert mode, but doesn't show notification
68 ``<Ctrl-S>`` also works from insert mode, but doesn't show notification,
69 unless ``monitor_subchannel`` is set to ``True`` (see `vim-ipython 'shell'`_,
70 below)
54
71
55 It also works blockwise in Visual Mode. Strip the leading double quotes and
72 It also works blockwise in Visual Mode. Select and send these lines using
56 send these lines using ``<Ctrl-S>``::
73 ``<Ctrl-S>``::
57
74
58 import this,math # secret decoder ring
75 import this,math # secret decoder ring
59 a,b,c,d,e,f,g,h,i = range(1,10)
76 a,b,c,d,e,f,g,h,i = range(1,10)
@@ -65,7 +82,7 b' send these lines using ``<Ctrl-S>``::'
65 '%d'*len(code)%code == str(int(math.pi*1e5))
82 '%d'*len(code)%code == str(int(math.pi*1e5))
66
83
67 Then, go to the qtconsole and run this line::
84 Then, go to the qtconsole and run this line::
68
85
69 print secret_decoder(_i,_)
86 print secret_decoder(_i,_)
70
87
71 You can also send whole files to IPython's ``%run`` magic using ``<F5>``.
88 You can also send whole files to IPython's ``%run`` magic using ``<F5>``.
@@ -86,22 +103,87 b" IPython's tab-completion Functionality"
86 vim-ipython activates a 'completefunc' that queries IPython.
103 vim-ipython activates a 'completefunc' that queries IPython.
87 A completefunc is activated using ``Ctrl-X Ctrl-U`` in Insert Mode (vim
104 A completefunc is activated using ``Ctrl-X Ctrl-U`` in Insert Mode (vim
88 default). You can combine this functionality with SuperTab to get tab
105 default). You can combine this functionality with SuperTab to get tab
89 completion
106 completion.
90
107
91 ---------------
108 -------------------
92 Current issues:
109 vim-ipython 'shell'
93 ---------------
110 -------------------
94 For now, vim-ipython only connects to an ipython session in progress.
111 **NEW since IPython 0.11**!
112
113 By monitoring km.sub_channel, we can recreate what messages were sent to
114 IPython, and what IPython sends back in response.
115
116 ``monitor_subchannel`` is a parameter that sets whether this 'shell' should
117 updated on every sent command (default: True).
118
119 If at any later time you wish to bring this shell up, including if you've set
120 ``monitor_subchannel=False``, hit ``<leader>s``.
95
121
96 ipy.vim takes a while to load, I'll eventually move the python code to its
122 -------
97 own file and do a lazy import (only when the IPython command is called)
123 Options
124 -------
125 You can change these at the top of the ipy.vim::
98
126
99 The ipdb integration is not yet re-implemented.
127 reselect = False # reselect lines after sending from Visual mode
128 show_execution_count = True # wait to get numbers for In[43]: feedback?
129 monitor_subchannel = True # update vim-ipython 'shell' on every send?
130 run_flags= "-i" # flags to for IPython's run magic when using <F5>
100
131
101 Need to add more message handling for sub_channel messages from IPython
132 **Disabling default mappings**
102 (i.e. notification of changes which were not sent from vim).
133 In your own ``.vimrc``, if you don't like the mappings provided by default,
134 you can define a variable ``let g:ipy_perform_mappings=0`` which will prevent
135 vim-ipython from defining any of the default mappings.
103
136
104 ------
137 ---------------
105 Thanks
138 Current issues:
106 ------
139 ---------------
107 @MinRK for guiding me through the IPython kernel manager protocol.
140 - For now, vim-ipython only connects to an ipython session in progress.
141 - The ipdb integration is not yet re-implemented.
142 - If you're running inside ``screen``, read about the ``<CTRL-S>`` issue `here
143 <http://munkymorgy.blogspot.com/2008/07/screen-ctrl-s-bug.html>`_, and add
144 this line to your ``.bashrc`` to fix it::
145
146 stty stop undef # to unmap ctrl-s
147
148 - In vim, if you're getting ``ImportError: No module named
149 IPython.zmq.blockingkernelmanager`` but are able to import it in regular
150 python, **either**
151
152 1. your ``sys.path`` in vim differs from the ``sys.path`` in regular python.
153 Try running these two lines, and comparing their output files::
154
155 $ vim -c 'py import vim, sys; vim.current.buffer.append(sys.path)' -c ':wq vim_syspath'
156 $ python -c "import sys; f=file('python_syspath','w'); f.write('\n'.join(sys.path)); f.close()"
157
158 **or**
159
160 2. your vim is compiled against a different python than you are launching. See
161 if there's a difference between ::
162
163 $ vim -c ':py import os; print os.__file__' -c ':q'
164 $ python -c ':py import os; print os.__file__'
165
166 - For vim inside a terminal, using the arrow keys won't work inside a
167 documentation buffer, because the mapping for ``<Esc>`` overlaps with
168 ``^[OA`` and so on, and we use ``<Esc>`` as a quick way of closing the
169 documentation preview window. If you want go without this quick close
170 functionality and want to use the arrow keys instead, look for instructions
171 starting with "Known issue: to enable the use of arrow keys..." in the
172 ``get_doc_buffer`` function.
173
174 - @fholgado's update to ``minibufexpl.vim`` that is up on GitHub will always
175 put the cursor in the minibuf after sending a command when
176 ``monitor_subchannel`` is set. This is a bug in minibufexpl.vim and the workaround
177 is described in vim-ipython issue #7.
178
179 ----------------------------
180 Thanks and Bug Participation
181 ----------------------------
182 * @MinRK for guiding me through the IPython kernel manager protocol.
183 * @nakamuray and @tcheneau for reporting and providing a fix for when vim is compiled without a gui (#1)
184 * @unpingco for reporting Windows bugs (#3,#4)
185 * @simon-b for terminal vim arrow key issue (#5)
186 * @jorgesca and @kwgoodman for shell (#6)
187 * @zeekay for easily allowing custom mappings (#9)
188 * @minrk for support of connection_file-based IPython connection (#13)
189 * @jorgesca for reporting the lack of profile handling capability (#14)
@@ -17,10 +17,17 b''
17 "
17 "
18 " written by Paul Ivanov (http://pirsquared.org)
18 " written by Paul Ivanov (http://pirsquared.org)
19 python << EOF
19 python << EOF
20 import time
20 reselect = False # reselect lines after sending from Visual mode
21 show_execution_count = True # wait to get numbers for In[43]: feedback?
22 monitor_subchannel = True # update vim-ipython 'shell' on every send?
23 run_flags= "-i" # flags to for IPython's run magic when using <F5>
24
21 import vim
25 import vim
22 import sys
26 import sys
23
27
28 # get around unicode problems when interfacing with vim
29 vim_encoding=vim.eval('&encoding') or 'utf-8'
30
24 try:
31 try:
25 sys.stdout.flush
32 sys.stdout.flush
26 except AttributeError:
33 except AttributeError:
@@ -34,10 +41,6 b' except AttributeError:'
34 sys.stdout = WithFlush(sys.stdout)
41 sys.stdout = WithFlush(sys.stdout)
35 sys.stderr = WithFlush(sys.stderr)
42 sys.stderr = WithFlush(sys.stderr)
36
43
37 from IPython.zmq.blockingkernelmanager import BlockingKernelManager
38
39 from IPython.config.loader import KeyValueConfigLoader
40 from IPython.zmq.kernelapp import kernel_aliases
41
44
42
45
43 ip = '127.0.0.1'
46 ip = '127.0.0.1'
@@ -46,34 +49,62 b' try:'
46 except NameError:
49 except NameError:
47 km = None
50 km = None
48
51
49 def km_from_string(s):
52 def km_from_string(s=''):
50 """create kernel manager from IPKernelApp string
53 """create kernel manager from IPKernelApp string
51 such as '--shell=47378 --iopub=39859 --stdin=36778 --hb=52668'
54 such as '--shell=47378 --iopub=39859 --stdin=36778 --hb=52668' for IPython 0.11
55 or just 'kernel-12345.json' for IPython 0.12
52 """
56 """
53 global km,send
57 from os.path import join as pjoin
54 # vim interface currently only deals with existing kernels
58 from IPython.zmq.blockingkernelmanager import BlockingKernelManager, Empty
55 s = s.replace('--existing','')
59 from IPython.config.loader import KeyValueConfigLoader
56 loader = KeyValueConfigLoader(s.split(), aliases=kernel_aliases)
60 from IPython.zmq.kernelapp import kernel_aliases
57 cfg = loader.load_config()['KernelApp']
61 global km,send,Empty
58 try:
62
59 km = BlockingKernelManager(
63 s = s.replace('--existing', '')
60 shell_address=(ip, cfg['shell_port']),
64 if 'connection_file' in BlockingKernelManager.class_trait_names():
61 sub_address=(ip, cfg['iopub_port']),
65 from IPython.lib.kernel import find_connection_file
62 stdin_address=(ip, cfg['stdin_port']),
66 # 0.12 uses files instead of a collection of ports
63 hb_address=(ip, cfg['hb_port']))
67 # include default IPython search path
64 except KeyError,e:
68 # filefind also allows for absolute paths, in which case the search
65 echo(":IPython " +s + " failed", "Info")
69 # is ignored
66 echo("^-- failed --"+e.message.replace('_port','')+" not specified", "Error")
70 try:
67 return
71 # XXX: the following approach will be brittle, depending on what
72 # connection strings will end up looking like in the future, and
73 # whether or not they are allowed to have spaces. I'll have to sync
74 # up with the IPython team to address these issues -pi
75 if '--profile' in s:
76 k,p = s.split('--profile')
77 k = k.lstrip().rstrip() # kernel part of the string
78 p = p.lstrip().rstrip() # profile part of the string
79 fullpath = find_connection_file(k,p)
80 else:
81 fullpath = find_connection_file(s.lstrip().rstrip())
82 except IOError,e:
83 echo(":IPython " + s + " failed", "Info")
84 echo("^-- failed '" + s + "' not found", "Error")
85 return
86 km = BlockingKernelManager(connection_file = fullpath)
87 km.load_connection_file()
88 else:
89 if s == '':
90 echo(":IPython 0.11 requires the full connection string")
91 return
92 loader = KeyValueConfigLoader(s.split(), aliases=kernel_aliases)
93 cfg = loader.load_config()['KernelApp']
94 try:
95 km = BlockingKernelManager(
96 shell_address=(ip, cfg['shell_port']),
97 sub_address=(ip, cfg['iopub_port']),
98 stdin_address=(ip, cfg['stdin_port']),
99 hb_address=(ip, cfg['hb_port']))
100 except KeyError,e:
101 echo(":IPython " +s + " failed", "Info")
102 echo("^-- failed --"+e.message.replace('_port','')+" not specified", "Error")
103 return
68 km.start_channels()
104 km.start_channels()
69 send = km.shell_channel.execute
105 send = km.shell_channel.execute
70 return km
106 return km
71
107
72
73 reselect = False
74 show_id= True
75 run_flags= "-i"
76
77 def echo(arg,style="Question"):
108 def echo(arg,style="Question"):
78 try:
109 try:
79 vim.command("echohl %s" % style)
110 vim.command("echohl %s" % style)
@@ -88,12 +119,12 b' def disconnect():'
88 pass
119 pass
89
120
90 def get_doc(word):
121 def get_doc(word):
122 if km is None:
123 return ["Not connected to IPython, cannot query \"%s\"" %word]
91 msg_id = km.shell_channel.object_info(word)
124 msg_id = km.shell_channel.object_info(word)
92 time.sleep(.1)
93 doc = get_doc_msg(msg_id)
125 doc = get_doc_msg(msg_id)
94 #if len(doc):
126 # get around unicode problems when interfacing with vim
95 # echo(word, 'Special')
127 return [d.encode(vim_encoding) for d in doc]
96 return doc
97
128
98 import re
129 import re
99 # from http://serverfault.com/questions/71285/in-centos-4-4-how-can-i-strip-escape-sequences-from-a-text-file
130 # from http://serverfault.com/questions/71285/in-centos-4-4-how-can-i-strip-escape-sequences-from-a-text-file
@@ -102,25 +133,19 b' def strip_color_escapes(s):'
102 return strip.sub('',s)
133 return strip.sub('',s)
103
134
104 def get_doc_msg(msg_id):
135 def get_doc_msg(msg_id):
105 content = get_child_msgs(msg_id)[0]['content']
136 n = 13 # longest field name (empirically)
106 n = 13 # longest field name
107 ##XXX: debug (print the whole message)
108 b=[]
137 b=[]
138 try:
139 content = get_child_msg(msg_id)['content']
140 except Empty:
141 # timeout occurred
142 return ["no reply from IPython kernel"]
109
143
110 if not content['found']:
144 if not content['found']:
111 return b
145 return b
112
146
113 ## debugging the whole message
114 #for k in content:
115 # if isinstance(content[k],str) and content[k].find('\n')!=-1:
116 # b.append(k.ljust(n)+":")
117 # b.append(content[k].splitlines())
118 # else:
119 # b.append(k.ljust(n)+":"+str(content[k]))
120
121 for field in ['type_name','base_class','string_form','namespace',
147 for field in ['type_name','base_class','string_form','namespace',
122 'file','length','definition','source','docstring']:
148 'file','length','definition','source','docstring']:
123 # XXX: strip the 'definition' rich formatting
124 c = content.get(field,None)
149 c = content.get(field,None)
125 if c:
150 if c:
126 if field in ['definition']:
151 if field in ['definition']:
@@ -135,21 +160,27 b' def get_doc_msg(msg_id):'
135 return b
160 return b
136
161
137 def get_doc_buffer(level=0):
162 def get_doc_buffer(level=0):
138 word = vim.eval('expand("<cfile>")')
163 # empty string in case vim.eval return None
164 word = vim.eval('expand("<cfile>")') or ''
139 doc = get_doc(word)
165 doc = get_doc(word)
140 if len(doc) ==0:
166 if len(doc) ==0:
141 echo(word+" not found","Error")
167 echo(word+" not found","Error")
142 return
168 return
169 # close any currently open preview windows
143 vim.command('pcl')
170 vim.command('pcl')
171 # documentation buffer name is same as the query made to ipython
144 vim.command('new '+word)
172 vim.command('new '+word)
145 vim.command('setlocal pvw modifiable noro')
173 vim.command('setlocal pvw modifiable noro')
174 # doc window quick quit keys: 'q' and 'escape'
146 vim.command('map <buffer> q :q<CR>')
175 vim.command('map <buffer> q :q<CR>')
147 vim.command('map <buffer>  :q<CR>')
176 # Known issue: to enable the use of arrow keys inside the terminal when
148 #vim.command('pedit '+docbuf.name)
177 # viewing the documentation, comment out the next line
178 vim.command('map <buffer> <Esc> :q<CR>')
179 # and uncomment this line (which will work if you have a timoutlen set)
180 #vim.command('map <buffer> <Esc><Esc> :q<CR>')
149 b = vim.current.buffer
181 b = vim.current.buffer
150 #b.append(doc)
182 b[:] = None
151 b[:] = doc
183 b[:] = doc
152 #b.append(doc)
153 vim.command('setlocal nomodified bufhidden=wipe')
184 vim.command('setlocal nomodified bufhidden=wipe')
154 #vim.command('setlocal previewwindow nomodifiable nomodified ro')
185 #vim.command('setlocal previewwindow nomodifiable nomodified ro')
155 #vim.command('set previewheight=%d'%len(b))# go to previous window
186 #vim.command('set previewheight=%d'%len(b))# go to previous window
@@ -158,35 +189,153 b' def get_doc_buffer(level=0):'
158 #vim.command('pedit doc')
189 #vim.command('pedit doc')
159 #vim.command('normal ') # go to previous window
190 #vim.command('normal ') # go to previous window
160
191
161 def get_child_msgs(msg_id):
192 def update_subchannel_msgs(debug=False):
193 msgs = km.sub_channel.get_msgs()
194 if debug:
195 #try:
196 # vim.command("b debug_msgs")
197 #except vim.error:
198 # vim.command("new debug_msgs")
199 #finally:
200 db = vim.current.buffer
201 else:
202 db = []
203 b = vim.current.buffer
204 startedin_vimipython = vim.eval('@%')=='vim-ipython'
205 if not startedin_vimipython:
206 # switch to preview window
207 vim.command(
208 "try"
209 "|silent! wincmd P"
210 "|catch /^Vim\%((\a\+)\)\=:E441/"
211 "|silent pedit +set\ ma vim-ipython"
212 "|silent! wincmd P"
213 "|endtry")
214 # if the current window is called 'vim-ipython'
215 if vim.eval('@%')=='vim-ipython':
216 # set the preview window height to the current height
217 vim.command("set pvh=" + vim.eval('winheight(0)'))
218 else:
219 # close preview window, it was something other than 'vim-ipython'
220 vim.command("pcl")
221 vim.command("silent pedit +set\ ma vim-ipython")
222 vim.command("wincmd P") #switch to preview window
223 # subchannel window quick quit key 'q'
224 vim.command('map <buffer> q :q<CR>')
225 vim.command("set bufhidden=hide buftype=nofile ft=python")
226
227 #syntax highlighting for python prompt
228 # QtConsole In[] is blue, but I prefer the oldschool green
229 # since it makes the vim-ipython 'shell' look like the holidays!
230 #vim.command("hi Blue ctermfg=Blue guifg=Blue")
231 vim.command("hi Green ctermfg=Green guifg=Green")
232 vim.command("hi Red ctermfg=Red guifg=Red")
233 vim.command("syn keyword Green 'In\ []:'")
234 vim.command("syn match Green /^In \[[0-9]*\]\:/")
235 vim.command("syn match Red /^Out\[[0-9]*\]\:/")
236 b = vim.current.buffer
237 for m in msgs:
238 #db.append(str(m).splitlines())
239 s = ''
240 if 'msg_type' not in m['header']:
241 # debug information
242 #echo('skipping a message on sub_channel','WarningMsg')
243 #echo(str(m))
244 continue
245 elif m['header']['msg_type'] == 'status':
246 continue
247 elif m['header']['msg_type'] == 'stream':
248 s = strip_color_escapes(m['content']['data'])
249 elif m['header']['msg_type'] == 'pyout':
250 s = "Out[%d]: " % m['content']['execution_count']
251 s += m['content']['data']['text/plain']
252 elif m['header']['msg_type'] == 'pyin':
253 # TODO: the next line allows us to resend a line to ipython if
254 # %doctest_mode is on. In the future, IPython will send the
255 # execution_count on subchannel, so this will need to be updated
256 # once that happens
257 if 'execution_count' in m['content']:
258 s = "\nIn [%d]: "% m['content']['execution_count']
259 else:
260 s = "\nIn [00]: "
261 s += m['content']['code'].strip()
262 elif m['header']['msg_type'] == 'pyerr':
263 c = m['content']
264 s = "\n".join(map(strip_color_escapes,c['traceback']))
265 s += c['ename'] + ":" + c['evalue']
266 if s.find('\n') == -1:
267 # somewhat ugly unicode workaround from
268 # http://vim.1045645.n5.nabble.com/Limitations-of-vim-python-interface-with-respect-to-character-encodings-td1223881.html
269 if isinstance(s,unicode):
270 s=s.encode(vim_encoding)
271 b.append(s)
272 else:
273 try:
274 b.append(s.splitlines())
275 except:
276 b.append([l.encode(vim_encoding) for l in s.splitlines()])
277 # make a newline so we can just start typing there
278 if b[-1] != '':
279 b.append([''])
280 vim.command('normal G') # go to the end of the file
281 if not startedin_vimipython:
282 vim.command('normal p') # go back to where you were
283
284 def get_child_msg(msg_id):
162 # XXX: message handling should be split into its own process in the future
285 # XXX: message handling should be split into its own process in the future
163 msgs= km.shell_channel.get_msgs()
286 while True:
164 children = [m for m in msgs if m['parent_header']['msg_id'] == msg_id]
287 # get_msg will raise with Empty exception if no messages arrive in 1 second
165 return children
288 m= km.shell_channel.get_msg(timeout=1)
289 if m['parent_header']['msg_id'] == msg_id:
290 break
291 else:
292 #got a message, but not the one we were looking for
293 echo('skipping a message on shell_channel','WarningMsg')
294 return m
166
295
167
168
169 def run_this_file():
170 send('run %s %s' % (run_flags, vim.current.buffer.name,))
171 echo("In[]: run %s %s" % (run_flags, vim.current.buffer.name))
172
173 def print_prompt(prompt,msg_id=None):
296 def print_prompt(prompt,msg_id=None):
174 global show_id
297 """Print In[] or In[42] style messages"""
175 if show_id and msg_id:
298 global show_execution_count
176 time.sleep(.1) # wait to get message back from kernel
299 if show_execution_count and msg_id:
177 children = get_child_msgs(msg_id)
300 # wait to get message back from kernel
178 if len(children):
301 try:
179 count = children[0]['content']['execution_count']
302 child = get_child_msg(msg_id)
303 count = child['content']['execution_count']
180 echo("In[%d]: %s" %(count,prompt))
304 echo("In[%d]: %s" %(count,prompt))
181 else:
305 except Empty:
182 echo("In[]: %s (no reply from kernel)" % prompt)
306 echo("In[]: %s (no reply from IPython kernel)" % prompt)
183 else:
307 else:
184 echo("In[]: %s" % prompt)
308 echo("In[]: %s" % prompt)
185
309
310 def with_subchannel(f,*args):
311 "conditionally monitor subchannel"
312 def f_with_update(*args):
313 try:
314 f(*args)
315 if monitor_subchannel:
316 update_subchannel_msgs()
317 except AttributeError: #if km is None
318 echo("not connected to IPython", 'Error')
319 return f_with_update
320
321 @with_subchannel
322 def run_this_file():
323 msg_id = send('run %s %s' % (run_flags, repr(vim.current.buffer.name),))
324 print_prompt("In[]: run %s %s" % (run_flags, repr(vim.current.buffer.name)),msg_id)
325
326 @with_subchannel
186 def run_this_line():
327 def run_this_line():
187 msg_id = send(vim.current.line)
328 msg_id = send(vim.current.line)
188 print_prompt(vim.current.line, msg_id)
329 print_prompt(vim.current.line, msg_id)
189
330
331 @with_subchannel
332 def run_command(cmd):
333 msg_id = send(cmd)
334 print_prompt(cmd, msg_id)
335 if monitor_subchannel:
336 update_subchannel_msgs()
337
338 @with_subchannel
190 def run_these_lines():
339 def run_these_lines():
191 r = vim.current.range
340 r = vim.current.range
192 lines = "\n".join(vim.current.buffer[r.start:r.end+1])
341 lines = "\n".join(vim.current.buffer[r.start:r.end+1])
@@ -208,16 +357,19 b' def run_these_lines():'
208 def dedent_run_this_line():
357 def dedent_run_this_line():
209 vim.command("left")
358 vim.command("left")
210 run_this_line()
359 run_this_line()
211 vim.command("undo")
360 vim.command("silent undo")
212
361
213 def dedent_run_these_lines():
362 def dedent_run_these_lines():
214 vim.command("'<,'>left")
363 r = vim.current.range
364 shiftwidth = vim.eval('&shiftwidth')
365 count = int(vim.eval('indent(%d+1)/%s' % (r.start,shiftwidth)))
366 vim.command("'<,'>" + "<"*count)
215 run_these_lines()
367 run_these_lines()
216 vim.command("undo")
368 vim.command("silent undo")
217
369
218 #def set_this_line():
370 #def set_this_line():
219 # # not sure if there's a way to do this, since we have multiple clients
371 # # not sure if there's a way to do this, since we have multiple clients
220 # send("_ip.IP.rl_next_input= \'%s\'" % vim.current.line.replace("\'","\\\'"))
372 # send("get_ipython().shell.set_next_input(\'%s\')" % vim.current.line.replace("\'","\\\'"))
221 # #print "line \'%s\' set at ipython prompt"% vim.current.line
373 # #print "line \'%s\' set at ipython prompt"% vim.current.line
222 # echo("line \'%s\' set at ipython prompt"% vim.current.line,'Statement')
374 # echo("line \'%s\' set at ipython prompt"% vim.current.line,'Statement')
223
375
@@ -262,34 +414,45 b' fun! <SID>toggle_send_on_save()'
262 endif
414 endif
263 endfun
415 endfun
264
416
265 map <silent> <F5> :python run_this_file()<CR>
417 " Allow custom mappings
266 map <silent> <S-F5> :python run_this_line()<CR>
418 if !exists('g:ipy_perform_mappings')
267 map <silent> <F9> :python run_these_lines()<CR>
419 let g:ipy_perform_mappings = 1
268 map <leader>d :py get_doc_buffer()<CR>
420 endif
269 map <silent> <S-F9> :python toggle_reselect()<CR>
421 if g:ipy_perform_mappings != 0
270 "map <silent> <C-F6> :python send('%pdb')<CR>
422 map <silent> <F5> :python run_this_file()<CR>
271 "map <silent> <F6> :python set_breakpoint()<CR>
423 map <silent> <S-F5> :python run_this_line()<CR>
272 "map <silent> <s-F6> :python clear_breakpoint()<CR>
424 map <silent> <F9> :python run_these_lines()<CR>
273 "map <silent> <F7> :python run_this_file_pdb()<CR>
425 map <silent> <leader>d :py get_doc_buffer()<CR>
274 "map <silent> <s-F7> :python clear_all_breaks()<CR>
426 map <silent> <leader>s :py update_subchannel_msgs(); echo("vim-ipython shell updated",'Operator')<CR>
275 imap <C-F5> <C-O><F5>
427 map <silent> <S-F9> :python toggle_reselect()<CR>
276 imap <S-F5> <C-O><S-F5>
428 "map <silent> <C-F6> :python send('%pdb')<CR>
277 imap <silent> <F5> <C-O><F5>
429 "map <silent> <F6> :python set_breakpoint()<CR>
278 map <C-F5> :call <SID>toggle_send_on_save()<CR>
430 "map <silent> <s-F6> :python clear_breakpoint()<CR>
279
431 "map <silent> <F7> :python run_this_file_pdb()<CR>
280 "pi custom
432 "map <silent> <s-F7> :python clear_all_breaks()<CR>
281 map <silent> <C-Return> :python run_this_file()<CR>
433 imap <C-F5> <C-O><F5>
282 map <silent> <C-s> :python run_this_line()<CR>
434 imap <S-F5> <C-O><S-F5>
283 map <silent> <M-s> :python dedent_run_this_line()<CR>
435 imap <silent> <F5> <C-O><F5>
284 vmap <silent> <C-S> :python run_these_lines()<CR>
436 map <C-F5> :call <SID>toggle_send_on_save()<CR>
285 vmap <silent> <M-s> :python dedent_run_these_lines()<CR>
437 "" Example of how to quickly clear the current plot with a keystroke
286 "map <silent> <C-p> :python set_this_line()<CR>
438 map <silent> <F12> :python run_command("plt.clf()")<cr>
287 map <silent> <M-c> I#<ESC>
439 "" Example of how to quickly close all figures with a keystroke
288 vmap <silent> <M-c> I#<ESC>
440 map <silent> <F11> :python run_command("plt.close('all')")<cr>
289 map <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR>
441
290 vmap <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR>
442 "pi custom
291
443 map <silent> <C-Return> :python run_this_file()<CR>
292 command! -nargs=+ IPython :py km_from_string("<args>")
444 map <silent> <C-s> :python run_this_line()<CR>
445 imap <silent> <C-s> <C-O>:python run_this_line()<CR>
446 map <silent> <M-s> :python dedent_run_this_line()<CR>
447 vmap <silent> <C-S> :python run_these_lines()<CR>
448 vmap <silent> <M-s> :python dedent_run_these_lines()<CR>
449 map <silent> <M-c> I#<ESC>
450 vmap <silent> <M-c> I#<ESC>
451 map <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR>
452 vmap <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR>
453 endif
454
455 command! -nargs=* IPython :py km_from_string("<args>")
293 command! -nargs=0 IPythonClipboard :py km_from_string(vim.eval('@+'))
456 command! -nargs=0 IPythonClipboard :py km_from_string(vim.eval('@+'))
294 command! -nargs=0 IPythonXSelection :py km_from_string(vim.eval('@*'))
457 command! -nargs=0 IPythonXSelection :py km_from_string(vim.eval('@*'))
295
458
@@ -297,13 +460,14 b' function! IPythonBalloonExpr()'
297 python << endpython
460 python << endpython
298 word = vim.eval('v:beval_text')
461 word = vim.eval('v:beval_text')
299 reply = get_doc(word)
462 reply = get_doc(word)
300 #reply = reply[:40]
301 vim.command("let l:doc = %s"% reply)
463 vim.command("let l:doc = %s"% reply)
302 endpython
464 endpython
303 return l:doc
465 return l:doc
304 endfunction
466 endfunction
305 set bexpr=IPythonBalloonExpr()
467 if has('balloon_eval')
306 set ballooneval
468 set bexpr=IPythonBalloonExpr()
469 set ballooneval
470 endif
307
471
308 fun! CompleteIPython(findstart, base)
472 fun! CompleteIPython(findstart, base)
309 if a:findstart
473 if a:findstart
@@ -322,21 +486,35 b' fun! CompleteIPython(findstart, base)'
322 base = vim.eval("a:base")
486 base = vim.eval("a:base")
323 findstart = vim.eval("a:findstart")
487 findstart = vim.eval("a:findstart")
324 msg_id = km.shell_channel.complete(base, vim.current.line, vim.eval("col('.')"))
488 msg_id = km.shell_channel.complete(base, vim.current.line, vim.eval("col('.')"))
325 time.sleep(.1)
489 try:
326 m = get_child_msgs(msg_id)[0]
490 m = get_child_msg(msg_id)
327
491 matches = m['content']['matches']
328 matches = m['content']['matches']
492 matches.insert(0,base) # the "no completion" version
329 #end = len(base)
493 # we need to be careful with unicode, because we can have unicode
330 #completions = [m[end:]+findstart+base for m in matches]
494 # completions for filenames (for the %run magic, for example). So the next
331 matches.insert(0,base) # the "no completion" version
495 # line will fail on those:
332 completions = matches
496 #completions= [str(u) for u in matches]
333 vim.command("let l:completions = %s"% completions)
497 # because str() won't work for non-ascii characters
498 # and we also have problems with unicode in vim, hence the following:
499 completions = [s.encode(vim_encoding) for s in matches]
500 except Empty:
501 echo("no reply from IPython kernel")
502 completions=['']
503 ## Additionally, we have no good way of communicating lists to vim, so we have
504 ## to turn in into one long string, which can be problematic if e.g. the
505 ## completions contain quotes. The next line will not work if some filenames
506 ## contain quotes - but if that's the case, the user's just asking for
507 ## it, right?
508 #completions = '["'+ '", "'.join(completions)+'"]'
509 #vim.command("let completions = %s" % completions)
510 ## An alternative for the above, which will insert matches one at a time, so
511 ## if there's a problem with turning a match into a string, it'll just not
512 ## include the problematic match, instead of not including anything. There's a
513 ## bit more indirection here, but I think it's worth it
514 for c in completions:
515 vim.command('call add(res,"'+c+'")')
334 endpython
516 endpython
335 for m in l:completions
517 "call extend(res,completions)
336 "if m =~ '^' . a:base
337 call add(res, m)
338 "endif
339 endfor
340 return res
518 return res
341 endif
519 endif
342 endfun
520 endfun
General Comments 0
You need to be logged in to leave comments. Login now