Show More
@@ -1,189 +1,253 | |||||
1 | ########### |
|
1 | ########### | |
2 | vim-ipython |
|
2 | vim-ipython | |
3 | ########### |
|
3 | ########### | |
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 | * github: http://github.com/ivanov/vim-ipython |
|
8 | * github: http://github.com/ivanov/vim-ipython | |
9 | * demos: http://pirsquared.org/vim-ipython/ |
|
9 | * demos: http://pirsquared.org/vim-ipython/ | |
10 | * blogpost: http://pirsquared.org/blog/2011/07/28/vim-ipython/ |
|
10 | * blogpost: http://pirsquared.org/blog/2011/07/28/vim-ipython/ | |
11 |
|
11 | |||
12 | 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 | |
13 | execute, and also get back object introspection and word completions in |
|
13 | execute, and also get back object introspection and word completions in | |
14 | Vim, like what you get with: ``object?<enter>`` and ``object.<tab>`` in |
|
14 | Vim, like what you get with: ``object?<enter>`` and ``object.<tab>`` in | |
15 | IPython. |
|
15 | IPython. | |
16 |
|
16 | |||
17 | 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 | |
18 | requires the old brittle ``ipy_vimserver.py`` instantiation, and since |
|
18 | requires the old brittle ``ipy_vimserver.py`` instantiation, and since | |
19 |
it uses just vim and python, it is platform independent (i.e. |
|
19 | it uses just vim and python, it is platform independent (i.e. works | |
20 | even on windows, unlike the previous \*nix only solution). The requirements |
|
20 | even on windows, unlike the previous \*nix only solution). The requirements | |
21 | are IPython 0.11+ with zeromq capabilities, vim compiled with +python. |
|
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 |
|
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. |
|
24 | ``:echo has('python')`` returns 1 in vim, you should be good to go. | |
25 |
|
25 | |||
26 | ----------------- |
|
26 | ----------------- | |
27 | Quickstart Guide: |
|
27 | Quickstart Guide: | |
28 | ----------------- |
|
28 | ----------------- | |
29 | Start ``ipython qtconsole`` [*]_ and copy the connection string. |
|
29 | Start ``ipython qtconsole`` [*]_ and copy the connection string. | |
30 | Source ``ipy.vim`` file, which provides new IPython command:: |
|
30 | Source ``ipy.vim`` file, which provides new IPython command:: | |
31 |
|
31 | |||
32 | :source ipy.vim |
|
32 | :source ipy.vim | |
33 | (or copy it to ~/.vim/ftplugin/python to load automatically) |
|
33 | (or copy it to ~/.vim/ftplugin/python to load automatically) | |
34 |
|
34 | |||
35 | :IPythonClipboard |
|
35 | :IPythonClipboard | |
36 | (or :IPythonXSelection if you're using X11 without having to copy) |
|
36 | (or :IPythonXSelection if you're using X11 without having to copy) | |
37 |
|
37 | |||
38 | The :IPython command allows you to put the full connection string. For IPython |
|
38 | The :IPython command allows you to put the full connection string. For IPython | |
39 | 0.11, it would look like this:: |
|
39 | 0.11, it would look like this:: | |
40 |
|
40 | |||
41 | :IPython --existing --shell=41882 --iopub=43286 --stdin=34987 --hb=36697 |
|
41 | :IPython --existing --shell=41882 --iopub=43286 --stdin=34987 --hb=36697 | |
42 |
|
42 | |||
43 | and for IPython 0.12, like this:: |
|
43 | and for IPython 0.12, like this:: | |
44 |
|
44 | |||
45 | :IPython --existing kernel-85997.json |
|
45 | :IPython --existing kernel-85997.json | |
46 |
|
46 | |||
47 | The ``:IPythonClipboard`` command just uses the ``+`` register to get the |
|
47 | The ``:IPythonClipboard`` command just uses the ``+`` register to get the | |
48 | connection string, whereas ``:IPythonXSelection`` uses the ``*`` register |
|
48 | connection string, whereas ``:IPythonXSelection`` uses the ``*`` register. | |
|
49 | ||||
|
50 | **NEW in IPython 0.12**! | |||
|
51 | Since IPython 0.12, you can simply use:: | |||
|
52 | ||||
|
53 | :IPython | |||
|
54 | ||||
|
55 | without arguments to connect to the most recent IPython session (this is the | |||
|
56 | same as passing just the ``--existing`` flag to ``ipython qtconsole`` and | |||
|
57 | ``ipython console``. | |||
49 |
|
58 | |||
50 | .. [*] Though the demos above use ``qtconsole``, it is not required |
|
59 | .. [*] 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 |
|
60 | 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. |
|
61 | make use of the new functionality in 0.11 release. Since IPython 0.12, you | |
53 |
|
|
62 | can use ``ipython kernel`` to create a kernel and get the connection | |
54 |
|
|
63 | string to use for any frontend (including vim-ipython), or use ``ipython | |
55 | If you are still using 0.11, you can launch a regular kernel using |
|
64 | console`` to create a kernel and immediately connect to it using a | |
56 | ``python -c "from IPython.zmq.ipkernel import main; main()"`` |
|
65 | terminal-based client. You can even connect to an active IPython Notebook | |
|
66 | kernel - just watch for the connection string that gets printed when you | |||
|
67 | open the notebook, or use the ``%connect_info`` magic to get the | |||
|
68 | connection string. If you are still using 0.11, you can launch a regular | |||
|
69 | kernel using ``python -c "from IPython.zmq.ipkernel import main; main()"`` | |||
57 |
|
70 | |||
58 | ------------------------ |
|
71 | ------------------------ | |
59 | Sending lines to IPython |
|
72 | Sending lines to IPython | |
60 | ------------------------ |
|
73 | ------------------------ | |
61 | Now type out a line and send it to IPython using ``<Ctrl-S>`` from Command mode:: |
|
74 | Now type out a line and send it to IPython using ``<Ctrl-S>`` from Command mode:: | |
62 |
|
75 | |||
63 | import os |
|
76 | import os | |
64 |
|
77 | |||
65 | You should see a notification message confirming the line was sent, along |
|
78 | You should see a notification message confirming the line was sent, along | |
66 | with the input number for the line, like so ``In[1]: import os``. |
|
79 | with the input number for the line, like so ``In[1]: import os``. | |
67 |
|
80 | |||
68 | ``<Ctrl-S>`` also works from insert mode, but doesn't show notification, |
|
81 | ``<Ctrl-S>`` also works from insert mode, but doesn't show notification, | |
69 | unless ``monitor_subchannel`` is set to ``True`` (see `vim-ipython 'shell'`_, |
|
82 | unless ``monitor_subchannel`` is set to ``True`` (see `vim-ipython 'shell'`_, | |
70 | below) |
|
83 | below) | |
71 |
|
84 | |||
72 | It also works blockwise in Visual Mode. Select and send these lines using |
|
85 | It also works blockwise in Visual Mode. Select and send these lines using | |
73 | ``<Ctrl-S>``:: |
|
86 | ``<Ctrl-S>``:: | |
74 |
|
87 | |||
75 | import this,math # secret decoder ring |
|
88 | import this,math # secret decoder ring | |
76 | a,b,c,d,e,f,g,h,i = range(1,10) |
|
89 | a,b,c,d,e,f,g,h,i = range(1,10) | |
77 | code =(c,a,d,a,e,i,) |
|
90 | code =(c,a,d,a,e,i,) | |
78 | msg = '...jrer nyy frag sebz Ivz.\nIvz+VClguba=%fyl '+this.s.split()[g] |
|
91 | msg = '...jrer nyy frag sebz Ivz.\nIvz+VClguba=%fyl '+this.s.split()[g] | |
79 | decode=lambda x:"\n"+"".join([this.d.get(c,c) for c in x])+"!" |
|
92 | decode=lambda x:"\n"+"".join([this.d.get(c,c) for c in x])+"!" | |
80 | format=lambda x:'These lines:\n '+'\n '.join([l for l in x.splitlines()]) |
|
93 | format=lambda x:'These lines:\n '+'\n '.join([l for l in x.splitlines()]) | |
81 | secret_decoder = lambda a,b: format(a)+decode(msg)%str(b)[:-1] |
|
94 | secret_decoder = lambda a,b: format(a)+decode(msg)%str(b)[:-1] | |
82 | '%d'*len(code)%code == str(int(math.pi*1e5)) |
|
95 | '%d'*len(code)%code == str(int(math.pi*1e5)) | |
83 |
|
96 | |||
84 | Then, go to the qtconsole and run this line:: |
|
97 | Then, go to the qtconsole and run this line:: | |
85 |
|
98 | |||
86 | print secret_decoder(_i,_) |
|
99 | print secret_decoder(_i,_) | |
87 |
|
100 | |||
88 | You can also send whole files to IPython's ``%run`` magic using ``<F5>``. |
|
101 | You can also send whole files to IPython's ``%run`` magic using ``<F5>``. | |
89 |
|
102 | |||
|
103 | **NEW in IPython 0.12**! | |||
|
104 | If you're trying to do run code fragments that have leading whitespace, use | |||
|
105 | ``<Alt-S>`` instead - it will dedent a single line, and remove the leading | |||
|
106 | whitespace of the first line from all lines in a visual mode selection. | |||
|
107 | ||||
90 | ------------------------------- |
|
108 | ------------------------------- | |
91 | IPython's object? Functionality |
|
109 | IPython's object? Functionality | |
92 | ------------------------------- |
|
110 | ------------------------------- | |
93 |
|
111 | |||
94 |
If you're using gvim, mouse-over a variable to see IPython's ? equivalent. |
|
112 | If you're using gvim, mouse-over a variable to see IPython's ``?`` equivalent. | |
95 | you're using vim from a terminal, or want to copy something from the |
|
113 | If you're using vim from a terminal, or want to copy something from the | |
96 | docstring, type ``<leader>d``. ``<leader>`` is usually ``\`` (the backslash |
|
114 | docstring, type ``<leader>d``. ``<leader>`` is usually ``\`` (the backslash | |
97 | key). This will open a quickpreview window, which can be closed by hitting |
|
115 | key). This will open a quickpreview window, which can be closed by hitting | |
98 | ``q`` or ``<escape>``. |
|
116 | ``q`` or ``<escape>``. | |
99 |
|
117 | |||
100 | -------------------------------------- |
|
118 | -------------------------------------- | |
101 | IPython's tab-completion Functionality |
|
119 | IPython's tab-completion Functionality | |
102 | -------------------------------------- |
|
120 | -------------------------------------- | |
103 | vim-ipython activates a 'completefunc' that queries IPython. |
|
121 | vim-ipython activates a 'completefunc' that queries IPython. | |
104 | A completefunc is activated using ``Ctrl-X Ctrl-U`` in Insert Mode (vim |
|
122 | A completefunc is activated using ``Ctrl-X Ctrl-U`` in Insert Mode (vim | |
105 | default). You can combine this functionality with SuperTab to get tab |
|
123 | default). You can combine this functionality with SuperTab to get tab | |
106 | completion. |
|
124 | completion. | |
107 |
|
125 | |||
108 | ------------------- |
|
126 | ------------------- | |
109 | vim-ipython 'shell' |
|
127 | vim-ipython 'shell' | |
110 | ------------------- |
|
128 | ------------------- | |
111 | **NEW since IPython 0.11**! |
|
|||
112 |
|
129 | |||
113 | By monitoring km.sub_channel, we can recreate what messages were sent to |
|
130 | By monitoring km.sub_channel, we can recreate what messages were sent to | |
114 | IPython, and what IPython sends back in response. |
|
131 | IPython, and what IPython sends back in response. | |
115 |
|
132 | |||
116 | ``monitor_subchannel`` is a parameter that sets whether this 'shell' should |
|
133 | ``monitor_subchannel`` is a parameter that sets whether this 'shell' should | |
117 | updated on every sent command (default: True). |
|
134 | updated on every sent command (default: True). | |
118 |
|
135 | |||
119 | If at any later time you wish to bring this shell up, including if you've set |
|
136 | If at any later time you wish to bring this shell up, including if you've set | |
120 | ``monitor_subchannel=False``, hit ``<leader>s``. |
|
137 | ``monitor_subchannel=False``, hit ``<leader>s``. | |
121 |
|
138 | |||
|
139 | **NEW since IPython 0.12** | |||
|
140 | For local kernels (kernels running on the same machine as vim), `Ctrl-C` in | |||
|
141 | the vim-ipython 'shell' sends an keyboard interrupt. (Note: this feature may | |||
|
142 | not work on Windows, please report the issue to ). | |||
|
143 | ||||
122 | ------- |
|
144 | ------- | |
123 | Options |
|
145 | Options | |
124 | ------- |
|
146 | ------- | |
125 | You can change these at the top of the ipy.vim:: |
|
147 | You can change these at the top of the ipy.vim:: | |
126 |
|
148 | |||
127 | reselect = False # reselect lines after sending from Visual mode |
|
149 | reselect = False # reselect lines after sending from Visual mode | |
128 | show_execution_count = True # wait to get numbers for In[43]: feedback? |
|
150 | show_execution_count = True # wait to get numbers for In[43]: feedback? | |
129 | monitor_subchannel = True # update vim-ipython 'shell' on every send? |
|
151 | monitor_subchannel = True # update vim-ipython 'shell' on every send? | |
130 | run_flags= "-i" # flags to for IPython's run magic when using <F5> |
|
152 | run_flags= "-i" # flags to for IPython's run magic when using <F5> | |
131 |
|
153 | |||
132 | **Disabling default mappings** |
|
154 | **Disabling default mappings** | |
133 | In your own ``.vimrc``, if you don't like the mappings provided by default, |
|
155 | 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 |
|
156 | you can define a variable ``let g:ipy_perform_mappings=0`` which will prevent | |
135 | vim-ipython from defining any of the default mappings. |
|
157 | vim-ipython from defining any of the default mappings. | |
136 |
|
158 | |||
|
159 | **NEW since IPython 0.12** | |||
|
160 | **Making completefunc local to a buffer, or disabling it** | |||
|
161 | By default, vim-ipython activates the custom completefunc globally. | |||
|
162 | Sometimes, having a completefunc breaks other plugins' completions. Putting | |||
|
163 | the line ``let g:ipy_completefunc = 'local'`` in one's vimrc will activate the | |||
|
164 | IPython-based completion only for current buffer. Setting `g:ipy_completefunc` | |||
|
165 | to anything other than `'local'` or `'global'` disables it altogether. | |||
|
166 | ||||
137 | --------------- |
|
167 | --------------- | |
138 | Current issues: |
|
168 | Current issues: | |
139 | --------------- |
|
169 | --------------- | |
140 | - For now, vim-ipython only connects to an ipython session in progress. |
|
170 | - For now, vim-ipython only connects to an ipython session in progress. | |
141 | - The ipdb integration is not yet re-implemented. |
|
171 | - The ipdb integration is not yet re-implemented. | |
142 | - If you're running inside ``screen``, read about the ``<CTRL-S>`` issue `here |
|
172 | - 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 |
|
173 | <http://munkymorgy.blogspot.com/2008/07/screen-ctrl-s-bug.html>`_, and add | |
144 | this line to your ``.bashrc`` to fix it:: |
|
174 | this line to your ``.bashrc`` to fix it:: | |
145 |
|
175 | |||
146 | stty stop undef # to unmap ctrl-s |
|
176 | stty stop undef # to unmap ctrl-s | |
147 |
|
177 | |||
148 | - In vim, if you're getting ``ImportError: No module named |
|
178 | - In vim, if you're getting ``ImportError: No module named | |
149 | IPython.zmq.blockingkernelmanager`` but are able to import it in regular |
|
179 | IPython.zmq.blockingkernelmanager`` but are able to import it in regular | |
150 | python, **either** |
|
180 | python, **either** | |
151 |
|
181 | |||
152 | 1. your ``sys.path`` in vim differs from the ``sys.path`` in regular python. |
|
182 | 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:: |
|
183 | Try running these two lines, and comparing their output files:: | |
154 |
|
184 | |||
155 | $ vim -c 'py import vim, sys; vim.current.buffer.append(sys.path)' -c ':wq vim_syspath' |
|
185 | $ 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()" |
|
186 | $ python -c "import sys; f=file('python_syspath','w'); f.write('\n'.join(sys.path)); f.close()" | |
157 |
|
187 | |||
158 | **or** |
|
188 | **or** | |
159 |
|
189 | |||
160 | 2. your vim is compiled against a different python than you are launching. See |
|
190 | 2. your vim is compiled against a different python than you are launching. See | |
161 | if there's a difference between :: |
|
191 | if there's a difference between :: | |
162 |
|
192 | |||
163 | $ vim -c ':py import os; print os.__file__' -c ':q' |
|
193 | $ vim -c ':py import os; print os.__file__' -c ':q' | |
164 |
$ python -c ' |
|
194 | $ python -c 'import os; print os.__file__' | |
165 |
|
195 | |||
166 | - For vim inside a terminal, using the arrow keys won't work inside a |
|
196 | - For vim inside a terminal, using the arrow keys won't work inside a | |
167 | documentation buffer, because the mapping for ``<Esc>`` overlaps with |
|
197 | 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 |
|
198 | ``^[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 |
|
199 | documentation preview window. If you want go without this quick close | |
170 | functionality and want to use the arrow keys instead, look for instructions |
|
200 | 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 |
|
201 | starting with "Known issue: to enable the use of arrow keys..." in the | |
172 | ``get_doc_buffer`` function. |
|
202 | ``get_doc_buffer`` function. | |
173 |
|
203 | |||
174 | - @fholgado's update to ``minibufexpl.vim`` that is up on GitHub will always |
|
204 | - @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 |
|
205 | 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 |
|
206 | ``monitor_subchannel`` is set. This is a bug in minibufexpl.vim and the workaround | |
177 | is described in vim-ipython issue #7. |
|
207 | is described in vim-ipython issue #7. | |
178 |
|
208 | |||
179 | ---------------------------- |
|
209 | ---------------------------- | |
180 | Thanks and Bug Participation |
|
210 | Thanks and Bug Participation | |
181 | ---------------------------- |
|
211 | ---------------------------- | |
182 | * @MinRK for guiding me through the IPython kernel manager protocol. |
|
212 | Here's a brief acknowledgment of the folks who have graciously pitched in. If | |
183 | * @nakamuray and @tcheneau for reporting and providing a fix for when vim is compiled without a gui (#1) |
|
213 | you've been missed, don't hesitate to contact me, or better yet, submit a | |
184 | * @unpingco for reporting Windows bugs (#3,#4) |
|
214 | pull request with your attribution. | |
|
215 | ||||
|
216 | * @minrk for guiding me through the IPython kernel manager protocol, and | |||
|
217 | support of connection_file-based IPython connection (#13) | |||
|
218 | * @nakamuray and @tcheneau for reporting and providing a fix for when vim is | |||
|
219 | compiled without a gui (#1) | |||
|
220 | * @unpingco for reporting Windows bugs (#3,#4), providing better multiline | |||
|
221 | dedenting (#15), and suggesting that a resized vim-ipython shell stays | |||
|
222 | resized (#16). | |||
185 | * @simon-b for terminal vim arrow key issue (#5) |
|
223 | * @simon-b for terminal vim arrow key issue (#5) | |
186 | * @jorgesca and @kwgoodman for shell (#6) |
|
224 | * @jorgesca and @kwgoodman for shell update problems (#6) | |
|
225 | * @xowlinx and @vladimiroff for Ctrl-S issues in Konsole (#8) | |||
187 | * @zeekay for easily allowing custom mappings (#9) |
|
226 | * @zeekay for easily allowing custom mappings (#9) | |
188 | * @minrk for support of connection_file-based IPython connection (#13) |
|
227 | * @jorgesca for reporting the lack of profile handling capability (#14), | |
189 | * @jorgesca for reporting the lack of profile handling capability (#14) |
|
228 | only open updating 'shell' if it is open (#29) | |
|
229 | * @enzbang for removing mapping that's not currently functional (#17) | |||
|
230 | * @ogrisel for fixing documentation typo (#19) | |||
|
231 | * @koepsell for gracefully exiting in case python is not available (#23) | |||
|
232 | * @mrterry for activating completefunc only after a connection is made (#25), | |||
|
233 | Ctrl-C implementation in vim-ipython 'shell' (#28) | |||
|
234 | * @nonameentername for completion on import statements (#26) | |||
|
235 | * @dstahlke for setting syntax of doc window to ReST | |||
|
236 | * @jtratner for docs with quotes (#30) | |||
|
237 | * @pielgrzym for setting completefunc locally to a buffer (#32) | |||
|
238 | ||||
|
239 | Similar Projects | |||
|
240 | ---------------- | |||
|
241 | * `vim-slime`_ - Grab some text and "send" it to a GNU Screen / tmux session | |||
|
242 | (Jonathan Palardy) | |||
|
243 | * `screen.vba`_ - Simulate a split shell, using GNU Screen / tmux, that you | |||
|
244 | can send commands to (Eric Van Dewoestine) | |||
|
245 | * conque_ - terminal emulator which uses a Vim buffer to display the program | |||
|
246 | output (Nico Raffo) | |||
|
247 | * `ipyqtmacvim`_ - plugin to send commands from MacVim to IPython Qt console | |||
|
248 | (Justin Kitzes) | |||
|
249 | ||||
|
250 | .. _vim-slime: https://github.com/jpalardy/vim-slime | |||
|
251 | .. _screen.vba: https://github.com/ervandew/screen | |||
|
252 | .. _conque: http://code.google.com/p/conque/ | |||
|
253 | .. _ipyqtmacvim: https://github.com/jkitzes/ipyqtmacvim/ |
@@ -1,521 +1,665 | |||||
1 | " Vim integration with IPython 0.11+ |
|
1 | " Vim integration with IPython 0.11+ | |
2 | " |
|
2 | " | |
3 |
" A two-way integration between Vim and IPython. |
|
3 | " A two-way integration between Vim and IPython. | |
4 | " |
|
4 | " | |
5 | " Using this plugin, you can send lines or whole files for IPython to execute, |
|
5 | " Using this plugin, you can send lines or whole files for IPython to execute, | |
6 | " and also get back object introspection and word completions in Vim, like |
|
6 | " and also get back object introspection and word completions in Vim, like | |
7 | " what you get with: object?<enter> object.<tab> in IPython |
|
7 | " what you get with: object?<enter> object.<tab> in IPython | |
8 | " |
|
8 | " | |
9 | " ----------------- |
|
9 | " ----------------- | |
10 | " Quickstart Guide: |
|
10 | " Quickstart Guide: | |
11 | " ----------------- |
|
11 | " ----------------- | |
12 | " Start ipython qtconsole and copy the connection string. |
|
12 | " Start ipython qtconsole and copy the connection string. | |
13 | " Source this file, which provides new IPython command |
|
13 | " Source this file, which provides new IPython command | |
14 |
" :source ipy.vim |
|
14 | " :source ipy.vim | |
15 |
" :IPythonClipboard |
|
15 | " :IPythonClipboard | |
16 | " (or :IPythonXSelection if you're using X11 without having to copy) |
|
16 | " (or :IPythonXSelection if you're using X11 without having to copy) | |
17 | " |
|
17 | " | |
18 | " written by Paul Ivanov (http://pirsquared.org) |
|
18 | " written by Paul Ivanov (http://pirsquared.org) | |
|
19 | " | |||
|
20 | if !has('python') | |||
|
21 | " exit if python is not available. | |||
|
22 | finish | |||
|
23 | endif | |||
|
24 | ||||
|
25 | " Allow custom mappings. | |||
|
26 | if !exists('g:ipy_perform_mappings') | |||
|
27 | let g:ipy_perform_mappings = 1 | |||
|
28 | endif | |||
|
29 | ||||
|
30 | " Register IPython completefunc | |||
|
31 | " 'global' -- for all of vim (default). | |||
|
32 | " 'local' -- only for the current buffer. | |||
|
33 | " otherwise -- don't register it at all. | |||
|
34 | " | |||
|
35 | " you can later set it using ':set completefunc=CompleteIPython', which will | |||
|
36 | " correspond to the 'global' behavior, or with ':setl ...' to get the 'local' | |||
|
37 | " behavior | |||
|
38 | if !exists('g:ipy_completefunc') | |||
|
39 | let g:ipy_completefunc = 'global' | |||
|
40 | endif | |||
|
41 | ||||
19 | python << EOF |
|
42 | python << EOF | |
20 | reselect = False # reselect lines after sending from Visual mode |
|
43 | reselect = False # reselect lines after sending from Visual mode | |
21 | show_execution_count = True # wait to get numbers for In[43]: feedback? |
|
44 | show_execution_count = True # wait to get numbers for In[43]: feedback? | |
22 | monitor_subchannel = True # update vim-ipython 'shell' on every send? |
|
45 | monitor_subchannel = True # update vim-ipython 'shell' on every send? | |
23 | run_flags= "-i" # flags to for IPython's run magic when using <F5> |
|
46 | run_flags= "-i" # flags to for IPython's run magic when using <F5> | |
|
47 | current_line = '' | |||
24 |
|
48 | |||
25 | import vim |
|
49 | import vim | |
26 | import sys |
|
50 | import sys | |
27 |
|
51 | |||
28 | # get around unicode problems when interfacing with vim |
|
52 | # get around unicode problems when interfacing with vim | |
29 | vim_encoding=vim.eval('&encoding') or 'utf-8' |
|
53 | vim_encoding=vim.eval('&encoding') or 'utf-8' | |
30 |
|
54 | |||
31 | try: |
|
55 | try: | |
32 | sys.stdout.flush |
|
56 | sys.stdout.flush | |
33 | except AttributeError: |
|
57 | except AttributeError: | |
34 | # IPython complains if stderr and stdout don't have flush |
|
58 | # IPython complains if stderr and stdout don't have flush | |
35 | # this is fixed in newer version of Vim |
|
59 | # this is fixed in newer version of Vim | |
36 | class WithFlush(object): |
|
60 | class WithFlush(object): | |
37 | def __init__(self,noflush): |
|
61 | def __init__(self,noflush): | |
38 | self.write=noflush.write |
|
62 | self.write=noflush.write | |
39 | self.writelines=noflush.writelines |
|
63 | self.writelines=noflush.writelines | |
40 | def flush(self):pass |
|
64 | def flush(self):pass | |
41 | sys.stdout = WithFlush(sys.stdout) |
|
65 | sys.stdout = WithFlush(sys.stdout) | |
42 | sys.stderr = WithFlush(sys.stderr) |
|
66 | sys.stderr = WithFlush(sys.stderr) | |
43 |
|
67 | |||
44 |
|
68 | |||
45 |
|
69 | |||
46 | ip = '127.0.0.1' |
|
70 | ip = '127.0.0.1' | |
47 | try: |
|
71 | try: | |
48 | km |
|
72 | km | |
49 | except NameError: |
|
73 | except NameError: | |
50 | km = None |
|
74 | km = None | |
|
75 | try: | |||
|
76 | pid | |||
|
77 | except NameError: | |||
|
78 | pid = None | |||
51 |
|
79 | |||
52 | def km_from_string(s=''): |
|
80 | def km_from_string(s=''): | |
53 | """create kernel manager from IPKernelApp string |
|
81 | """create kernel manager from IPKernelApp string | |
54 | such as '--shell=47378 --iopub=39859 --stdin=36778 --hb=52668' for IPython 0.11 |
|
82 | such as '--shell=47378 --iopub=39859 --stdin=36778 --hb=52668' for IPython 0.11 | |
55 | or just 'kernel-12345.json' for IPython 0.12 |
|
83 | or just 'kernel-12345.json' for IPython 0.12 | |
56 | """ |
|
84 | """ | |
57 | from os.path import join as pjoin |
|
85 | from os.path import join as pjoin | |
58 | from IPython.zmq.blockingkernelmanager import BlockingKernelManager, Empty |
|
86 | from IPython.zmq.blockingkernelmanager import BlockingKernelManager, Empty | |
59 | from IPython.config.loader import KeyValueConfigLoader |
|
87 | from IPython.config.loader import KeyValueConfigLoader | |
60 | from IPython.zmq.kernelapp import kernel_aliases |
|
88 | from IPython.zmq.kernelapp import kernel_aliases | |
61 | global km,send,Empty |
|
89 | global km,send,Empty | |
62 |
|
90 | |||
63 | s = s.replace('--existing', '') |
|
91 | s = s.replace('--existing', '') | |
64 | if 'connection_file' in BlockingKernelManager.class_trait_names(): |
|
92 | if 'connection_file' in BlockingKernelManager.class_trait_names(): | |
65 | from IPython.lib.kernel import find_connection_file |
|
93 | from IPython.lib.kernel import find_connection_file | |
66 | # 0.12 uses files instead of a collection of ports |
|
94 | # 0.12 uses files instead of a collection of ports | |
67 | # include default IPython search path |
|
95 | # include default IPython search path | |
68 | # filefind also allows for absolute paths, in which case the search |
|
96 | # filefind also allows for absolute paths, in which case the search | |
69 | # is ignored |
|
97 | # is ignored | |
70 | try: |
|
98 | try: | |
71 | # XXX: the following approach will be brittle, depending on what |
|
99 | # XXX: the following approach will be brittle, depending on what | |
72 | # connection strings will end up looking like in the future, and |
|
100 | # 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 |
|
101 | # 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 |
|
102 | # up with the IPython team to address these issues -pi | |
75 | if '--profile' in s: |
|
103 | if '--profile' in s: | |
76 | k,p = s.split('--profile') |
|
104 | k,p = s.split('--profile') | |
77 | k = k.lstrip().rstrip() # kernel part of the string |
|
105 | k = k.lstrip().rstrip() # kernel part of the string | |
78 | p = p.lstrip().rstrip() # profile part of the string |
|
106 | p = p.lstrip().rstrip() # profile part of the string | |
79 | fullpath = find_connection_file(k,p) |
|
107 | fullpath = find_connection_file(k,p) | |
80 | else: |
|
108 | else: | |
81 | fullpath = find_connection_file(s.lstrip().rstrip()) |
|
109 | fullpath = find_connection_file(s.lstrip().rstrip()) | |
82 | except IOError,e: |
|
110 | except IOError,e: | |
83 | echo(":IPython " + s + " failed", "Info") |
|
111 | echo(":IPython " + s + " failed", "Info") | |
84 | echo("^-- failed '" + s + "' not found", "Error") |
|
112 | echo("^-- failed '" + s + "' not found", "Error") | |
85 | return |
|
113 | return | |
86 | km = BlockingKernelManager(connection_file = fullpath) |
|
114 | km = BlockingKernelManager(connection_file = fullpath) | |
87 | km.load_connection_file() |
|
115 | km.load_connection_file() | |
88 | else: |
|
116 | else: | |
89 | if s == '': |
|
117 | if s == '': | |
90 | echo(":IPython 0.11 requires the full connection string") |
|
118 | echo(":IPython 0.11 requires the full connection string") | |
91 | return |
|
119 | return | |
92 | loader = KeyValueConfigLoader(s.split(), aliases=kernel_aliases) |
|
120 | loader = KeyValueConfigLoader(s.split(), aliases=kernel_aliases) | |
93 | cfg = loader.load_config()['KernelApp'] |
|
121 | cfg = loader.load_config()['KernelApp'] | |
94 | try: |
|
122 | try: | |
95 | km = BlockingKernelManager( |
|
123 | km = BlockingKernelManager( | |
96 | shell_address=(ip, cfg['shell_port']), |
|
124 | shell_address=(ip, cfg['shell_port']), | |
97 | sub_address=(ip, cfg['iopub_port']), |
|
125 | sub_address=(ip, cfg['iopub_port']), | |
98 | stdin_address=(ip, cfg['stdin_port']), |
|
126 | stdin_address=(ip, cfg['stdin_port']), | |
99 | hb_address=(ip, cfg['hb_port'])) |
|
127 | hb_address=(ip, cfg['hb_port'])) | |
100 | except KeyError,e: |
|
128 | except KeyError,e: | |
101 | echo(":IPython " +s + " failed", "Info") |
|
129 | echo(":IPython " +s + " failed", "Info") | |
102 | echo("^-- failed --"+e.message.replace('_port','')+" not specified", "Error") |
|
130 | echo("^-- failed --"+e.message.replace('_port','')+" not specified", "Error") | |
103 | return |
|
131 | return | |
104 | km.start_channels() |
|
132 | km.start_channels() | |
105 | send = km.shell_channel.execute |
|
133 | send = km.shell_channel.execute | |
|
134 | ||||
|
135 | # now that we're connect to an ipython kernel, activate completion | |||
|
136 | # machinery, but do so only for the local buffer if the user added the | |||
|
137 | # following line the vimrc: | |||
|
138 | # let g:ipy_completefunc = 'local' | |||
|
139 | vim.command(""" | |||
|
140 | if g:ipy_completefunc == 'global' | |||
|
141 | set completefunc=CompleteIPython | |||
|
142 | elseif g:ipy_completefunc == 'local' | |||
|
143 | setl completefunc=CompleteIPython | |||
|
144 | endif | |||
|
145 | """) | |||
|
146 | # also activate GUI doc balloons if in gvim | |||
|
147 | vim.command(""" | |||
|
148 | if has('balloon_eval') | |||
|
149 | set bexpr=IPythonBalloonExpr() | |||
|
150 | set ballooneval | |||
|
151 | endif | |||
|
152 | """) | |||
|
153 | set_pid() | |||
106 | return km |
|
154 | return km | |
107 |
|
155 | |||
108 | def echo(arg,style="Question"): |
|
156 | def echo(arg,style="Question"): | |
109 | try: |
|
157 | try: | |
110 | vim.command("echohl %s" % style) |
|
158 | vim.command("echohl %s" % style) | |
111 | vim.command("echom \"%s\"" % arg.replace('\"','\\\"')) |
|
159 | vim.command("echom \"%s\"" % arg.replace('\"','\\\"')) | |
112 | vim.command("echohl None") |
|
160 | vim.command("echohl None") | |
113 | except vim.error: |
|
161 | except vim.error: | |
114 | print "-- %s" % arg |
|
162 | print "-- %s" % arg | |
115 |
|
163 | |||
116 | def disconnect(): |
|
164 | def disconnect(): | |
117 | "disconnect kernel manager" |
|
165 | "disconnect kernel manager" | |
118 | # XXX: make a prompt here if this km owns the kernel |
|
166 | # XXX: make a prompt here if this km owns the kernel | |
119 | pass |
|
167 | pass | |
120 |
|
168 | |||
121 | def get_doc(word): |
|
169 | def get_doc(word): | |
122 | if km is None: |
|
170 | if km is None: | |
123 |
return ["Not connected to IPython, cannot query |
|
171 | return ["Not connected to IPython, cannot query: %s" % word] | |
124 | msg_id = km.shell_channel.object_info(word) |
|
172 | msg_id = km.shell_channel.object_info(word) | |
125 | doc = get_doc_msg(msg_id) |
|
173 | doc = get_doc_msg(msg_id) | |
126 | # get around unicode problems when interfacing with vim |
|
174 | # get around unicode problems when interfacing with vim | |
127 | return [d.encode(vim_encoding) for d in doc] |
|
175 | return [d.encode(vim_encoding) for d in doc] | |
128 |
|
176 | |||
129 | import re |
|
177 | import re | |
130 | # from http://serverfault.com/questions/71285/in-centos-4-4-how-can-i-strip-escape-sequences-from-a-text-file |
|
178 | # from http://serverfault.com/questions/71285/in-centos-4-4-how-can-i-strip-escape-sequences-from-a-text-file | |
131 | strip = re.compile('\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]') |
|
179 | strip = re.compile('\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]') | |
132 | def strip_color_escapes(s): |
|
180 | def strip_color_escapes(s): | |
133 | return strip.sub('',s) |
|
181 | return strip.sub('',s) | |
134 |
|
182 | |||
135 | def get_doc_msg(msg_id): |
|
183 | def get_doc_msg(msg_id): | |
136 | n = 13 # longest field name (empirically) |
|
184 | n = 13 # longest field name (empirically) | |
137 | b=[] |
|
185 | b=[] | |
138 | try: |
|
186 | try: | |
139 | content = get_child_msg(msg_id)['content'] |
|
187 | content = get_child_msg(msg_id)['content'] | |
140 | except Empty: |
|
188 | except Empty: | |
141 | # timeout occurred |
|
189 | # timeout occurred | |
142 | return ["no reply from IPython kernel"] |
|
190 | return ["no reply from IPython kernel"] | |
143 |
|
191 | |||
144 | if not content['found']: |
|
192 | if not content['found']: | |
145 | return b |
|
193 | return b | |
146 |
|
194 | |||
147 | for field in ['type_name','base_class','string_form','namespace', |
|
195 | for field in ['type_name','base_class','string_form','namespace', | |
148 | 'file','length','definition','source','docstring']: |
|
196 | 'file','length','definition','source','docstring']: | |
149 | c = content.get(field,None) |
|
197 | c = content.get(field,None) | |
150 | if c: |
|
198 | if c: | |
151 | if field in ['definition']: |
|
199 | if field in ['definition']: | |
152 | c = strip_color_escapes(c).rstrip() |
|
200 | c = strip_color_escapes(c).rstrip() | |
153 | s = field.replace('_',' ').title()+':' |
|
201 | s = field.replace('_',' ').title()+':' | |
154 | s = s.ljust(n) |
|
202 | s = s.ljust(n) | |
155 | if c.find('\n')==-1: |
|
203 | if c.find('\n')==-1: | |
156 | b.append(s+c) |
|
204 | b.append(s+c) | |
157 | else: |
|
205 | else: | |
158 | b.append(s) |
|
206 | b.append(s) | |
159 | b.extend(c.splitlines()) |
|
207 | b.extend(c.splitlines()) | |
160 | return b |
|
208 | return b | |
161 |
|
209 | |||
162 | def get_doc_buffer(level=0): |
|
210 | def get_doc_buffer(level=0): | |
163 | # empty string in case vim.eval return None |
|
211 | # empty string in case vim.eval return None | |
164 | word = vim.eval('expand("<cfile>")') or '' |
|
212 | word = vim.eval('expand("<cfile>")') or '' | |
165 | doc = get_doc(word) |
|
213 | doc = get_doc(word) | |
166 | if len(doc) ==0: |
|
214 | if len(doc) ==0: | |
167 | echo(word+" not found","Error") |
|
215 | echo(repr(word)+" not found","Error") | |
168 | return |
|
216 | return | |
169 | # close any currently open preview windows |
|
|||
170 | vim.command('pcl') |
|
|||
171 | # documentation buffer name is same as the query made to ipython |
|
217 | # documentation buffer name is same as the query made to ipython | |
172 | vim.command('new '+word) |
|
218 | vim.command('new '+word) | |
173 |
vim.command('setlocal |
|
219 | vim.command('setlocal modifiable noro') | |
174 | # doc window quick quit keys: 'q' and 'escape' |
|
220 | # doc window quick quit keys: 'q' and 'escape' | |
175 | vim.command('map <buffer> q :q<CR>') |
|
221 | vim.command('map <buffer> q :q<CR>') | |
176 | # Known issue: to enable the use of arrow keys inside the terminal when |
|
222 | # Known issue: to enable the use of arrow keys inside the terminal when | |
177 | # viewing the documentation, comment out the next line |
|
223 | # viewing the documentation, comment out the next line | |
178 | vim.command('map <buffer> <Esc> :q<CR>') |
|
224 | vim.command('map <buffer> <Esc> :q<CR>') | |
179 | # and uncomment this line (which will work if you have a timoutlen set) |
|
225 | # and uncomment this line (which will work if you have a timoutlen set) | |
180 | #vim.command('map <buffer> <Esc><Esc> :q<CR>') |
|
226 | #vim.command('map <buffer> <Esc><Esc> :q<CR>') | |
181 | b = vim.current.buffer |
|
227 | b = vim.current.buffer | |
182 | b[:] = None |
|
228 | b[:] = None | |
183 | b[:] = doc |
|
229 | b[:] = doc | |
184 | vim.command('setlocal nomodified bufhidden=wipe') |
|
230 | vim.command('setlocal nomodified bufhidden=wipe') | |
185 | #vim.command('setlocal previewwindow nomodifiable nomodified ro') |
|
231 | #vim.command('setlocal previewwindow nomodifiable nomodified ro') | |
186 | #vim.command('set previewheight=%d'%len(b))# go to previous window |
|
232 | #vim.command('set previewheight=%d'%len(b))# go to previous window | |
187 | vim.command('resize %d'%len(b)) |
|
233 | vim.command('resize %d'%len(b)) | |
188 | #vim.command('pcl') |
|
234 | #vim.command('pcl') | |
189 | #vim.command('pedit doc') |
|
235 | #vim.command('pedit doc') | |
190 | #vim.command('normal ') # go to previous window |
|
236 | #vim.command('normal ') # go to previous window | |
|
237 | # use the ReST formatting that ships with stock vim | |||
|
238 | vim.command('setlocal syntax=rst') | |||
|
239 | ||||
|
240 | def vim_ipython_is_open(): | |||
|
241 | """ | |||
|
242 | Helper function to let us know if the vim-ipython shell is currently | |||
|
243 | visible | |||
|
244 | """ | |||
|
245 | for w in vim.windows: | |||
|
246 | if w.buffer.name is not None and w.buffer.name.endswith("vim-ipython"): | |||
|
247 | return True | |||
|
248 | return False | |||
191 |
|
249 | |||
192 | def update_subchannel_msgs(debug=False): |
|
250 | def update_subchannel_msgs(debug=False, force=False): | |
|
251 | """ | |||
|
252 | Grab any pending messages and place them inside the vim-ipython shell. | |||
|
253 | This function will do nothing if the vim-ipython shell is not visible, | |||
|
254 | unless force=True argument is passed. | |||
|
255 | """ | |||
|
256 | if km is None or (not vim_ipython_is_open() and not force): | |||
|
257 | return False | |||
193 | msgs = km.sub_channel.get_msgs() |
|
258 | msgs = km.sub_channel.get_msgs() | |
194 | if debug: |
|
259 | if debug: | |
195 | #try: |
|
260 | #try: | |
196 | # vim.command("b debug_msgs") |
|
261 | # vim.command("b debug_msgs") | |
197 | #except vim.error: |
|
262 | #except vim.error: | |
198 | # vim.command("new debug_msgs") |
|
263 | # vim.command("new debug_msgs") | |
199 | #finally: |
|
264 | #finally: | |
200 | db = vim.current.buffer |
|
265 | db = vim.current.buffer | |
201 | else: |
|
266 | else: | |
202 | db = [] |
|
267 | db = [] | |
203 | b = vim.current.buffer |
|
268 | b = vim.current.buffer | |
204 | startedin_vimipython = vim.eval('@%')=='vim-ipython' |
|
269 | startedin_vimipython = vim.eval('@%')=='vim-ipython' | |
205 | if not startedin_vimipython: |
|
270 | if not startedin_vimipython: | |
206 | # switch to preview window |
|
271 | # switch to preview window | |
207 | vim.command( |
|
272 | vim.command( | |
208 | "try" |
|
273 | "try" | |
209 | "|silent! wincmd P" |
|
274 | "|silent! wincmd P" | |
210 | "|catch /^Vim\%((\a\+)\)\=:E441/" |
|
275 | "|catch /^Vim\%((\a\+)\)\=:E441/" | |
211 | "|silent pedit +set\ ma vim-ipython" |
|
276 | "|silent pedit +set\ ma vim-ipython" | |
212 | "|silent! wincmd P" |
|
277 | "|silent! wincmd P" | |
213 | "|endtry") |
|
278 | "|endtry") | |
214 | # if the current window is called 'vim-ipython' |
|
279 | # if the current window is called 'vim-ipython' | |
215 | if vim.eval('@%')=='vim-ipython': |
|
280 | if vim.eval('@%')=='vim-ipython': | |
216 | # set the preview window height to the current height |
|
281 | # set the preview window height to the current height | |
217 | vim.command("set pvh=" + vim.eval('winheight(0)')) |
|
282 | vim.command("set pvh=" + vim.eval('winheight(0)')) | |
218 | else: |
|
283 | else: | |
219 | # close preview window, it was something other than 'vim-ipython' |
|
284 | # close preview window, it was something other than 'vim-ipython' | |
220 | vim.command("pcl") |
|
285 | vim.command("pcl") | |
221 | vim.command("silent pedit +set\ ma vim-ipython") |
|
286 | vim.command("silent pedit +set\ ma vim-ipython") | |
222 | vim.command("wincmd P") #switch to preview window |
|
287 | vim.command("wincmd P") #switch to preview window | |
223 | # subchannel window quick quit key 'q' |
|
288 | # subchannel window quick quit key 'q' | |
224 | vim.command('map <buffer> q :q<CR>') |
|
289 | vim.command('map <buffer> q :q<CR>') | |
225 | vim.command("set bufhidden=hide buftype=nofile ft=python") |
|
290 | vim.command("set bufhidden=hide buftype=nofile ft=python") | |
|
291 | # make shift-enter and control-enter in insert mode behave same as in ipython notebook | |||
|
292 | # shift-enter send the current line, control-enter send the line | |||
|
293 | # but keeps it around for further editing. | |||
|
294 | vim.command("imap <buffer> <s-Enter> <esc>dd:python run_command('''<C-r>\"''')<CR>i") | |||
|
295 | # pkddA: paste, go up one line which is blank after run_command, | |||
|
296 | # delete it, and then back to insert mode | |||
|
297 | vim.command("imap <buffer> <c-Enter> <esc>dd:python run_command('''<C-r>\"''')<CR>pkddA") | |||
|
298 | # ctrl-C gets sent to the IPython process as a signal on POSIX | |||
|
299 | vim.command("map <buffer> :IPythonInterrupt<cr>") | |||
226 |
|
300 | |||
227 | #syntax highlighting for python prompt |
|
301 | #syntax highlighting for python prompt | |
228 | # QtConsole In[] is blue, but I prefer the oldschool green |
|
302 | # QtConsole In[] is blue, but I prefer the oldschool green | |
229 | # since it makes the vim-ipython 'shell' look like the holidays! |
|
303 | # since it makes the vim-ipython 'shell' look like the holidays! | |
230 | #vim.command("hi Blue ctermfg=Blue guifg=Blue") |
|
304 | #vim.command("hi Blue ctermfg=Blue guifg=Blue") | |
231 | vim.command("hi Green ctermfg=Green guifg=Green") |
|
305 | vim.command("hi Green ctermfg=Green guifg=Green") | |
232 | vim.command("hi Red ctermfg=Red guifg=Red") |
|
306 | vim.command("hi Red ctermfg=Red guifg=Red") | |
233 | vim.command("syn keyword Green 'In\ []:'") |
|
307 | vim.command("syn keyword Green 'In\ []:'") | |
234 | vim.command("syn match Green /^In \[[0-9]*\]\:/") |
|
308 | vim.command("syn match Green /^In \[[0-9]*\]\:/") | |
235 | vim.command("syn match Red /^Out\[[0-9]*\]\:/") |
|
309 | vim.command("syn match Red /^Out\[[0-9]*\]\:/") | |
236 | b = vim.current.buffer |
|
310 | b = vim.current.buffer | |
|
311 | update_occured = False | |||
237 | for m in msgs: |
|
312 | for m in msgs: | |
238 | #db.append(str(m).splitlines()) |
|
313 | #db.append(str(m).splitlines()) | |
239 | s = '' |
|
314 | s = '' | |
240 | if 'msg_type' not in m['header']: |
|
315 | if 'msg_type' not in m['header']: | |
241 | # debug information |
|
316 | # debug information | |
242 | #echo('skipping a message on sub_channel','WarningMsg') |
|
317 | #echo('skipping a message on sub_channel','WarningMsg') | |
243 | #echo(str(m)) |
|
318 | #echo(str(m)) | |
244 | continue |
|
319 | continue | |
245 | elif m['header']['msg_type'] == 'status': |
|
320 | elif m['header']['msg_type'] == 'status': | |
246 | continue |
|
321 | continue | |
247 | elif m['header']['msg_type'] == 'stream': |
|
322 | elif m['header']['msg_type'] == 'stream': | |
248 | s = strip_color_escapes(m['content']['data']) |
|
323 | s = strip_color_escapes(m['content']['data']) | |
249 | elif m['header']['msg_type'] == 'pyout': |
|
324 | elif m['header']['msg_type'] == 'pyout': | |
250 | s = "Out[%d]: " % m['content']['execution_count'] |
|
325 | s = "Out[%d]: " % m['content']['execution_count'] | |
251 | s += m['content']['data']['text/plain'] |
|
326 | s += m['content']['data']['text/plain'] | |
252 | elif m['header']['msg_type'] == 'pyin': |
|
327 | elif m['header']['msg_type'] == 'pyin': | |
253 | # TODO: the next line allows us to resend a line to ipython if |
|
328 | # 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 |
|
329 | # %doctest_mode is on. In the future, IPython will send the | |
255 | # execution_count on subchannel, so this will need to be updated |
|
330 | # execution_count on subchannel, so this will need to be updated | |
256 | # once that happens |
|
331 | # once that happens | |
257 | if 'execution_count' in m['content']: |
|
332 | if 'execution_count' in m['content']: | |
258 | s = "\nIn [%d]: "% m['content']['execution_count'] |
|
333 | s = "\nIn [%d]: "% m['content']['execution_count'] | |
259 | else: |
|
334 | else: | |
260 | s = "\nIn [00]: " |
|
335 | s = "\nIn [00]: " | |
261 | s += m['content']['code'].strip() |
|
336 | s += m['content']['code'].strip() | |
262 | elif m['header']['msg_type'] == 'pyerr': |
|
337 | elif m['header']['msg_type'] == 'pyerr': | |
263 | c = m['content'] |
|
338 | c = m['content'] | |
264 | s = "\n".join(map(strip_color_escapes,c['traceback'])) |
|
339 | s = "\n".join(map(strip_color_escapes,c['traceback'])) | |
265 | s += c['ename'] + ":" + c['evalue'] |
|
340 | s += c['ename'] + ":" + c['evalue'] | |
266 | if s.find('\n') == -1: |
|
341 | if s.find('\n') == -1: | |
267 | # somewhat ugly unicode workaround from |
|
342 | # somewhat ugly unicode workaround from | |
268 | # http://vim.1045645.n5.nabble.com/Limitations-of-vim-python-interface-with-respect-to-character-encodings-td1223881.html |
|
343 | # http://vim.1045645.n5.nabble.com/Limitations-of-vim-python-interface-with-respect-to-character-encodings-td1223881.html | |
269 | if isinstance(s,unicode): |
|
344 | if isinstance(s,unicode): | |
270 | s=s.encode(vim_encoding) |
|
345 | s=s.encode(vim_encoding) | |
271 | b.append(s) |
|
346 | b.append(s) | |
272 | else: |
|
347 | else: | |
273 | try: |
|
348 | try: | |
274 | b.append(s.splitlines()) |
|
349 | b.append(s.splitlines()) | |
275 | except: |
|
350 | except: | |
276 | b.append([l.encode(vim_encoding) for l in s.splitlines()]) |
|
351 | b.append([l.encode(vim_encoding) for l in s.splitlines()]) | |
|
352 | update_occured = True | |||
277 | # make a newline so we can just start typing there |
|
353 | # make a newline so we can just start typing there | |
278 | if b[-1] != '': |
|
354 | if b[-1] != '': | |
279 | b.append(['']) |
|
355 | b.append(['']) | |
280 | vim.command('normal G') # go to the end of the file |
|
356 | vim.command('normal G') # go to the end of the file | |
281 | if not startedin_vimipython: |
|
357 | if not startedin_vimipython: | |
282 | vim.command('normal p') # go back to where you were |
|
358 | vim.command('normal p') # go back to where you were | |
|
359 | return update_occured | |||
283 |
|
360 | |||
284 | def get_child_msg(msg_id): |
|
361 | def get_child_msg(msg_id): | |
285 | # XXX: message handling should be split into its own process in the future |
|
362 | # XXX: message handling should be split into its own process in the future | |
286 | while True: |
|
363 | while True: | |
287 | # get_msg will raise with Empty exception if no messages arrive in 1 second |
|
364 | # get_msg will raise with Empty exception if no messages arrive in 1 second | |
288 | m= km.shell_channel.get_msg(timeout=1) |
|
365 | m= km.shell_channel.get_msg(timeout=1) | |
289 | if m['parent_header']['msg_id'] == msg_id: |
|
366 | if m['parent_header']['msg_id'] == msg_id: | |
290 | break |
|
367 | break | |
291 | else: |
|
368 | else: | |
292 | #got a message, but not the one we were looking for |
|
369 | #got a message, but not the one we were looking for | |
293 | echo('skipping a message on shell_channel','WarningMsg') |
|
370 | echo('skipping a message on shell_channel','WarningMsg') | |
294 | return m |
|
371 | return m | |
295 |
|
372 | |||
296 | def print_prompt(prompt,msg_id=None): |
|
373 | def print_prompt(prompt,msg_id=None): | |
297 | """Print In[] or In[42] style messages""" |
|
374 | """Print In[] or In[42] style messages""" | |
298 | global show_execution_count |
|
375 | global show_execution_count | |
299 | if show_execution_count and msg_id: |
|
376 | if show_execution_count and msg_id: | |
300 | # wait to get message back from kernel |
|
377 | # wait to get message back from kernel | |
301 | try: |
|
378 | try: | |
302 | child = get_child_msg(msg_id) |
|
379 | child = get_child_msg(msg_id) | |
303 | count = child['content']['execution_count'] |
|
380 | count = child['content']['execution_count'] | |
304 | echo("In[%d]: %s" %(count,prompt)) |
|
381 | echo("In[%d]: %s" %(count,prompt)) | |
305 | except Empty: |
|
382 | except Empty: | |
306 | echo("In[]: %s (no reply from IPython kernel)" % prompt) |
|
383 | echo("In[]: %s (no reply from IPython kernel)" % prompt) | |
307 | else: |
|
384 | else: | |
308 | echo("In[]: %s" % prompt) |
|
385 | echo("In[]: %s" % prompt) | |
309 |
|
386 | |||
310 | def with_subchannel(f,*args): |
|
387 | def with_subchannel(f,*args): | |
311 | "conditionally monitor subchannel" |
|
388 | "conditionally monitor subchannel" | |
312 | def f_with_update(*args): |
|
389 | def f_with_update(*args): | |
313 | try: |
|
390 | try: | |
314 | f(*args) |
|
391 | f(*args) | |
315 | if monitor_subchannel: |
|
392 | if monitor_subchannel: | |
316 | update_subchannel_msgs() |
|
393 | update_subchannel_msgs() | |
317 | except AttributeError: #if km is None |
|
394 | except AttributeError: #if km is None | |
318 | echo("not connected to IPython", 'Error') |
|
395 | echo("not connected to IPython", 'Error') | |
319 | return f_with_update |
|
396 | return f_with_update | |
320 |
|
397 | |||
321 | @with_subchannel |
|
398 | @with_subchannel | |
322 | def run_this_file(): |
|
399 | def run_this_file(): | |
323 | msg_id = send('run %s %s' % (run_flags, repr(vim.current.buffer.name),)) |
|
400 | 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) |
|
401 | print_prompt("In[]: run %s %s" % (run_flags, repr(vim.current.buffer.name)),msg_id) | |
325 |
|
402 | |||
326 | @with_subchannel |
|
403 | @with_subchannel | |
327 | def run_this_line(): |
|
404 | def run_this_line(): | |
328 | msg_id = send(vim.current.line) |
|
405 | msg_id = send(vim.current.line) | |
329 | print_prompt(vim.current.line, msg_id) |
|
406 | print_prompt(vim.current.line, msg_id) | |
330 |
|
407 | |||
331 | @with_subchannel |
|
408 | @with_subchannel | |
332 | def run_command(cmd): |
|
409 | def run_command(cmd): | |
333 | msg_id = send(cmd) |
|
410 | msg_id = send(cmd) | |
334 | print_prompt(cmd, msg_id) |
|
411 | print_prompt(cmd, msg_id) | |
335 | if monitor_subchannel: |
|
|||
336 | update_subchannel_msgs() |
|
|||
337 |
|
412 | |||
338 | @with_subchannel |
|
413 | @with_subchannel | |
339 | def run_these_lines(): |
|
414 | def run_these_lines(): | |
340 | r = vim.current.range |
|
415 | r = vim.current.range | |
341 | lines = "\n".join(vim.current.buffer[r.start:r.end+1]) |
|
416 | lines = "\n".join(vim.current.buffer[r.start:r.end+1]) | |
342 | msg_id = send(lines) |
|
417 | msg_id = send(lines) | |
343 | #alternative way of doing this in more recent versions of ipython |
|
418 | #alternative way of doing this in more recent versions of ipython | |
344 | #but %paste only works on the local machine |
|
419 | #but %paste only works on the local machine | |
345 | #vim.command("\"*yy") |
|
420 | #vim.command("\"*yy") | |
346 | #send("'%paste')") |
|
421 | #send("'%paste')") | |
347 | #reselect the previously highlighted block |
|
422 | #reselect the previously highlighted block | |
348 | vim.command("normal gv") |
|
423 | vim.command("normal gv") | |
349 | if not reselect: |
|
424 | if not reselect: | |
350 | vim.command("normal ") |
|
425 | vim.command("normal ") | |
351 |
|
426 | |||
352 | #vim lines start with 1 |
|
427 | #vim lines start with 1 | |
353 | #print "lines %d-%d sent to ipython"% (r.start+1,r.end+1) |
|
428 | #print "lines %d-%d sent to ipython"% (r.start+1,r.end+1) | |
354 | prompt = "lines %d-%d "% (r.start+1,r.end+1) |
|
429 | prompt = "lines %d-%d "% (r.start+1,r.end+1) | |
355 | print_prompt(prompt,msg_id) |
|
430 | print_prompt(prompt,msg_id) | |
356 |
|
431 | |||
|
432 | ||||
|
433 | def set_pid(): | |||
|
434 | """ | |||
|
435 | Explicitly ask the ipython kernel for its pid | |||
|
436 | """ | |||
|
437 | global km, pid | |||
|
438 | lines = '\n'.join(['import os', '_pid = os.getpid()']) | |||
|
439 | msg_id = send(lines, silent=True, user_variables=['_pid']) | |||
|
440 | ||||
|
441 | # wait to get message back from kernel | |||
|
442 | try: | |||
|
443 | child = get_child_msg(msg_id) | |||
|
444 | except Empty: | |||
|
445 | echo("no reply from IPython kernel") | |||
|
446 | return | |||
|
447 | ||||
|
448 | pid = int(child['content']['user_variables']['_pid']) | |||
|
449 | return pid | |||
|
450 | ||||
|
451 | ||||
|
452 | def interrupt_kernel_hack(): | |||
|
453 | """ | |||
|
454 | Sends the interrupt signal to the remote kernel. This side steps the | |||
|
455 | (non-functional) ipython interrupt mechanisms. | |||
|
456 | Only works on posix. | |||
|
457 | """ | |||
|
458 | global pid | |||
|
459 | import signal | |||
|
460 | import os | |||
|
461 | if pid is None: | |||
|
462 | # Avoid errors if we couldn't get pid originally, | |||
|
463 | # by trying to obtain it now | |||
|
464 | pid = set_pid() | |||
|
465 | ||||
|
466 | if pid is None: | |||
|
467 | echo("cannot get kernel PID, Ctrl-C will not be supported") | |||
|
468 | return | |||
|
469 | echo("KeyboardInterrupt (sent to ipython: pid " + | |||
|
470 | "%i with signal %i)" % (pid, signal.SIGINT),"Operator") | |||
|
471 | try: | |||
|
472 | os.kill(pid, signal.SIGINT) | |||
|
473 | except OSError: | |||
|
474 | echo("unable to kill pid %d" % pid) | |||
|
475 | pid = None | |||
|
476 | ||||
357 | def dedent_run_this_line(): |
|
477 | def dedent_run_this_line(): | |
358 | vim.command("left") |
|
478 | vim.command("left") | |
359 | run_this_line() |
|
479 | run_this_line() | |
360 | vim.command("silent undo") |
|
480 | vim.command("silent undo") | |
361 |
|
481 | |||
362 | def dedent_run_these_lines(): |
|
482 | def dedent_run_these_lines(): | |
363 | r = vim.current.range |
|
483 | r = vim.current.range | |
364 | shiftwidth = vim.eval('&shiftwidth') |
|
484 | shiftwidth = vim.eval('&shiftwidth') | |
365 | count = int(vim.eval('indent(%d+1)/%s' % (r.start,shiftwidth))) |
|
485 | count = int(vim.eval('indent(%d+1)/%s' % (r.start,shiftwidth))) | |
366 | vim.command("'<,'>" + "<"*count) |
|
486 | vim.command("'<,'>" + "<"*count) | |
367 | run_these_lines() |
|
487 | run_these_lines() | |
368 | vim.command("silent undo") |
|
488 | vim.command("silent undo") | |
369 |
|
489 | |||
370 | #def set_this_line(): |
|
490 | #def set_this_line(): | |
371 | # # not sure if there's a way to do this, since we have multiple clients |
|
491 | # # not sure if there's a way to do this, since we have multiple clients | |
372 | # send("get_ipython().shell.set_next_input(\'%s\')" % vim.current.line.replace("\'","\\\'")) |
|
492 | # send("get_ipython().shell.set_next_input(\'%s\')" % vim.current.line.replace("\'","\\\'")) | |
373 | # #print "line \'%s\' set at ipython prompt"% vim.current.line |
|
493 | # #print "line \'%s\' set at ipython prompt"% vim.current.line | |
374 | # echo("line \'%s\' set at ipython prompt"% vim.current.line,'Statement') |
|
494 | # echo("line \'%s\' set at ipython prompt"% vim.current.line,'Statement') | |
375 |
|
495 | |||
376 |
|
496 | |||
377 | def toggle_reselect(): |
|
497 | def toggle_reselect(): | |
378 | global reselect |
|
498 | global reselect | |
379 | reselect=not reselect |
|
499 | reselect=not reselect | |
380 | print "F9 will%sreselect lines after sending to ipython"% (reselect and " " or " not ") |
|
500 | print "F9 will%sreselect lines after sending to ipython"% (reselect and " " or " not ") | |
381 |
|
501 | |||
382 | #def set_breakpoint(): |
|
502 | #def set_breakpoint(): | |
383 | # send("__IP.InteractiveTB.pdb.set_break('%s',%d)" % (vim.current.buffer.name, |
|
503 | # send("__IP.InteractiveTB.pdb.set_break('%s',%d)" % (vim.current.buffer.name, | |
384 | # vim.current.window.cursor[0])) |
|
504 | # vim.current.window.cursor[0])) | |
385 |
# print "set breakpoint in %s:%d"% (vim.current.buffer.name, |
|
505 | # print "set breakpoint in %s:%d"% (vim.current.buffer.name, | |
386 | # vim.current.window.cursor[0]) |
|
506 | # vim.current.window.cursor[0]) | |
387 | # |
|
507 | # | |
388 | #def clear_breakpoint(): |
|
508 | #def clear_breakpoint(): | |
389 | # send("__IP.InteractiveTB.pdb.clear_break('%s',%d)" % (vim.current.buffer.name, |
|
509 | # send("__IP.InteractiveTB.pdb.clear_break('%s',%d)" % (vim.current.buffer.name, | |
390 | # vim.current.window.cursor[0])) |
|
510 | # vim.current.window.cursor[0])) | |
391 | # print "clearing breakpoint in %s:%d" % (vim.current.buffer.name, |
|
511 | # print "clearing breakpoint in %s:%d" % (vim.current.buffer.name, | |
392 | # vim.current.window.cursor[0]) |
|
512 | # vim.current.window.cursor[0]) | |
393 | # |
|
513 | # | |
394 | #def clear_all_breakpoints(): |
|
514 | #def clear_all_breakpoints(): | |
395 | # send("__IP.InteractiveTB.pdb.clear_all_breaks()"); |
|
515 | # send("__IP.InteractiveTB.pdb.clear_all_breaks()"); | |
396 | # print "clearing all breakpoints" |
|
516 | # print "clearing all breakpoints" | |
397 | # |
|
517 | # | |
398 | #def run_this_file_pdb(): |
|
518 | #def run_this_file_pdb(): | |
399 | # send(' __IP.InteractiveTB.pdb.run(\'execfile("%s")\')' % (vim.current.buffer.name,)) |
|
519 | # send(' __IP.InteractiveTB.pdb.run(\'execfile("%s")\')' % (vim.current.buffer.name,)) | |
400 | # #send('run -d %s' % (vim.current.buffer.name,)) |
|
520 | # #send('run -d %s' % (vim.current.buffer.name,)) | |
401 | # echo("In[]: run -d %s (using pdb)" % vim.current.buffer.name) |
|
521 | # echo("In[]: run -d %s (using pdb)" % vim.current.buffer.name) | |
402 |
|
522 | |||
403 | EOF |
|
523 | EOF | |
404 |
|
524 | |||
405 | fun! <SID>toggle_send_on_save() |
|
525 | fun! <SID>toggle_send_on_save() | |
406 | if exists("s:ssos") && s:ssos == 0 |
|
526 | if exists("s:ssos") && s:ssos == 0 | |
407 | let s:ssos = 1 |
|
527 | let s:ssos = 1 | |
408 | au BufWritePost *.py :py run_this_file() |
|
528 | au BufWritePost *.py :py run_this_file() | |
409 | echo "Autosend On" |
|
529 | echo "Autosend On" | |
410 | else |
|
530 | else | |
411 | let s:ssos = 0 |
|
531 | let s:ssos = 0 | |
412 | au! BufWritePost *.py |
|
532 | au! BufWritePost *.py | |
413 | echo "Autosend Off" |
|
533 | echo "Autosend Off" | |
414 | endif |
|
534 | endif | |
415 | endfun |
|
535 | endfun | |
416 |
|
536 | |||
417 | " Allow custom mappings |
|
537 | " Update the vim-ipython shell when the cursor is not moving. | |
418 | if !exists('g:ipy_perform_mappings') |
|
538 | " You can change how quickly this happens after you stop moving the cursor by | |
419 | let g:ipy_perform_mappings = 1 |
|
539 | " setting 'updatetime' (in milliseconds). For example, to have this event | |
420 | endif |
|
540 | " trigger after 1 second: | |
|
541 | " | |||
|
542 | " :set updatetime 1000 | |||
|
543 | " | |||
|
544 | " NOTE: This will only be triggered once, after the first 'updatetime' | |||
|
545 | " milliseconds, *not* every 'updatetime' milliseconds. see :help CursorHold | |||
|
546 | " for more info. | |||
|
547 | " | |||
|
548 | " TODO: Make this easily configurable on the fly, so that an introspection | |||
|
549 | " buffer we may have opened up doesn't get closed just because of an idle | |||
|
550 | " event (i.e. user pressed \d and then left the buffer that popped up, but | |||
|
551 | " expects it to stay there). | |||
|
552 | au CursorHold *.*,vim-ipython :python if update_subchannel_msgs(): echo("vim-ipython shell updated (on idle)",'Operator') | |||
|
553 | ||||
|
554 | " XXX: broken - cursor hold update for insert mode moves the cursor one | |||
|
555 | " character to the left of the last character (update_subchannel_msgs must be | |||
|
556 | " doing this) | |||
|
557 | "au CursorHoldI *.* :python if update_subchannel_msgs(): echo("vim-ipython shell updated (on idle)",'Operator') | |||
|
558 | ||||
|
559 | " Same as above, but on regaining window focus (mostly for GUIs) | |||
|
560 | au FocusGained *.*,vim-ipython :python if update_subchannel_msgs(): echo("vim-ipython shell updated (on input focus)",'Operator') | |||
|
561 | ||||
|
562 | " Update vim-ipython buffer when we move the cursor there. A message is only | |||
|
563 | " displayed if vim-ipython buffer has been updated. | |||
|
564 | au BufEnter vim-ipython :python if update_subchannel_msgs(): echo("vim-ipython shell updated (on buffer enter)",'Operator') | |||
|
565 | ||||
421 | if g:ipy_perform_mappings != 0 |
|
566 | if g:ipy_perform_mappings != 0 | |
422 | map <silent> <F5> :python run_this_file()<CR> |
|
567 | map <silent> <F5> :python run_this_file()<CR> | |
423 | map <silent> <S-F5> :python run_this_line()<CR> |
|
568 | map <silent> <S-F5> :python run_this_line()<CR> | |
424 | map <silent> <F9> :python run_these_lines()<CR> |
|
569 | map <silent> <F9> :python run_these_lines()<CR> | |
425 | map <silent> <leader>d :py get_doc_buffer()<CR> |
|
570 | map <silent> <leader>d :py get_doc_buffer()<CR> | |
426 |
map <silent> <leader>s :py update_subchannel_msgs() |
|
571 | map <silent> <leader>s :py if update_subchannel_msgs(force=True): echo("vim-ipython shell updated",'Operator')<CR> | |
427 | map <silent> <S-F9> :python toggle_reselect()<CR> |
|
572 | map <silent> <S-F9> :python toggle_reselect()<CR> | |
428 | "map <silent> <C-F6> :python send('%pdb')<CR> |
|
573 | "map <silent> <C-F6> :python send('%pdb')<CR> | |
429 | "map <silent> <F6> :python set_breakpoint()<CR> |
|
574 | "map <silent> <F6> :python set_breakpoint()<CR> | |
430 | "map <silent> <s-F6> :python clear_breakpoint()<CR> |
|
575 | "map <silent> <s-F6> :python clear_breakpoint()<CR> | |
431 | "map <silent> <F7> :python run_this_file_pdb()<CR> |
|
576 | "map <silent> <F7> :python run_this_file_pdb()<CR> | |
432 | "map <silent> <s-F7> :python clear_all_breaks()<CR> |
|
577 | "map <silent> <s-F7> :python clear_all_breaks()<CR> | |
433 | imap <C-F5> <C-O><F5> |
|
578 | imap <C-F5> <C-O><F5> | |
434 | imap <S-F5> <C-O><S-F5> |
|
579 | imap <S-F5> <C-O><S-F5> | |
435 | imap <silent> <F5> <C-O><F5> |
|
580 | imap <silent> <F5> <C-O><F5> | |
436 | map <C-F5> :call <SID>toggle_send_on_save()<CR> |
|
581 | map <C-F5> :call <SID>toggle_send_on_save()<CR> | |
437 | "" Example of how to quickly clear the current plot with a keystroke |
|
582 | "" Example of how to quickly clear the current plot with a keystroke | |
438 | map <silent> <F12> :python run_command("plt.clf()")<cr> |
|
583 | "map <silent> <F12> :python run_command("plt.clf()")<cr> | |
439 | "" Example of how to quickly close all figures with a keystroke |
|
584 | "" Example of how to quickly close all figures with a keystroke | |
440 | map <silent> <F11> :python run_command("plt.close('all')")<cr> |
|
585 | "map <silent> <F11> :python run_command("plt.close('all')")<cr> | |
441 |
|
586 | |||
442 | "pi custom |
|
587 | "pi custom | |
443 | map <silent> <C-Return> :python run_this_file()<CR> |
|
588 | map <silent> <C-Return> :python run_this_file()<CR> | |
444 | map <silent> <C-s> :python run_this_line()<CR> |
|
589 | map <silent> <C-s> :python run_this_line()<CR> | |
445 | imap <silent> <C-s> <C-O>:python run_this_line()<CR> |
|
590 | imap <silent> <C-s> <C-O>:python run_this_line()<CR> | |
446 | map <silent> <M-s> :python dedent_run_this_line()<CR> |
|
591 | map <silent> <M-s> :python dedent_run_this_line()<CR> | |
447 | vmap <silent> <C-S> :python run_these_lines()<CR> |
|
592 | vmap <silent> <C-S> :python run_these_lines()<CR> | |
448 | vmap <silent> <M-s> :python dedent_run_these_lines()<CR> |
|
593 | vmap <silent> <M-s> :python dedent_run_these_lines()<CR> | |
449 | map <silent> <M-c> I#<ESC> |
|
594 | map <silent> <M-c> I#<ESC> | |
450 | vmap <silent> <M-c> I#<ESC> |
|
595 | vmap <silent> <M-c> I#<ESC> | |
451 | map <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR> |
|
596 | map <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR> | |
452 | vmap <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR> |
|
597 | vmap <silent> <M-C> :s/^\([ \t]*\)#/\1/<CR> | |
453 | endif |
|
598 | endif | |
454 |
|
599 | |||
455 | command! -nargs=* IPython :py km_from_string("<args>") |
|
600 | command! -nargs=* IPython :py km_from_string("<args>") | |
456 | command! -nargs=0 IPythonClipboard :py km_from_string(vim.eval('@+')) |
|
601 | command! -nargs=0 IPythonClipboard :py km_from_string(vim.eval('@+')) | |
457 | command! -nargs=0 IPythonXSelection :py km_from_string(vim.eval('@*')) |
|
602 | command! -nargs=0 IPythonXSelection :py km_from_string(vim.eval('@*')) | |
|
603 | command! -nargs=0 IPythonInterrupt :py interrupt_kernel_hack() | |||
458 |
|
604 | |||
459 | function! IPythonBalloonExpr() |
|
605 | function! IPythonBalloonExpr() | |
460 | python << endpython |
|
606 | python << endpython | |
461 | word = vim.eval('v:beval_text') |
|
607 | word = vim.eval('v:beval_text') | |
462 | reply = get_doc(word) |
|
608 | reply = get_doc(word) | |
463 | vim.command("let l:doc = %s"% reply) |
|
609 | vim.command("let l:doc = %s"% reply) | |
464 | endpython |
|
610 | endpython | |
465 | return l:doc |
|
611 | return l:doc | |
466 | endfunction |
|
612 | endfunction | |
467 | if has('balloon_eval') |
|
|||
468 | set bexpr=IPythonBalloonExpr() |
|
|||
469 | set ballooneval |
|
|||
470 | endif |
|
|||
471 |
|
613 | |||
472 | fun! CompleteIPython(findstart, base) |
|
614 | fun! CompleteIPython(findstart, base) | |
473 |
|
|
615 | if a:findstart | |
474 |
|
|
616 | " locate the start of the word | |
475 |
|
|
617 | let line = getline('.') | |
476 |
|
|
618 | let start = col('.') - 1 | |
477 |
|
|
619 | while start > 0 && line[start-1] =~ '\k\|\.' "keyword | |
478 |
|
|
620 | let start -= 1 | |
479 |
|
|
621 | endwhile | |
480 | echo start |
|
622 | echo start | |
|
623 | python << endpython | |||
|
624 | current_line = vim.current.line | |||
|
625 | endpython | |||
481 |
|
|
626 | return start | |
482 |
|
|
627 | else | |
483 |
|
|
628 | " find months matching with "a:base" | |
484 |
|
|
629 | let res = [] | |
485 | python << endpython |
|
630 | python << endpython | |
486 | base = vim.eval("a:base") |
|
631 | base = vim.eval("a:base") | |
487 | findstart = vim.eval("a:findstart") |
|
632 | findstart = vim.eval("a:findstart") | |
488 |
msg_id = km.shell_channel.complete(base, |
|
633 | msg_id = km.shell_channel.complete(base, current_line, vim.eval("col('.')")) | |
489 | try: |
|
634 | try: | |
490 | m = get_child_msg(msg_id) |
|
635 | m = get_child_msg(msg_id) | |
491 | matches = m['content']['matches'] |
|
636 | matches = m['content']['matches'] | |
492 | matches.insert(0,base) # the "no completion" version |
|
637 | matches.insert(0,base) # the "no completion" version | |
493 | # we need to be careful with unicode, because we can have unicode |
|
638 | # we need to be careful with unicode, because we can have unicode | |
494 | # completions for filenames (for the %run magic, for example). So the next |
|
639 | # completions for filenames (for the %run magic, for example). So the next | |
495 | # line will fail on those: |
|
640 | # line will fail on those: | |
496 | #completions= [str(u) for u in matches] |
|
641 | #completions= [str(u) for u in matches] | |
497 | # because str() won't work for non-ascii characters |
|
642 | # because str() won't work for non-ascii characters | |
498 | # and we also have problems with unicode in vim, hence the following: |
|
643 | # and we also have problems with unicode in vim, hence the following: | |
499 | completions = [s.encode(vim_encoding) for s in matches] |
|
644 | completions = [s.encode(vim_encoding) for s in matches] | |
500 | except Empty: |
|
645 | except Empty: | |
501 | echo("no reply from IPython kernel") |
|
646 | echo("no reply from IPython kernel") | |
502 | completions=[''] |
|
647 | completions=[''] | |
503 | ## Additionally, we have no good way of communicating lists to vim, so we have |
|
648 | ## 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 |
|
649 | ## 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 |
|
650 | ## 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 |
|
651 | ## contain quotes - but if that's the case, the user's just asking for | |
507 | ## it, right? |
|
652 | ## it, right? | |
508 | #completions = '["'+ '", "'.join(completions)+'"]' |
|
653 | #completions = '["'+ '", "'.join(completions)+'"]' | |
509 | #vim.command("let completions = %s" % completions) |
|
654 | #vim.command("let completions = %s" % completions) | |
510 | ## An alternative for the above, which will insert matches one at a time, so |
|
655 | ## 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 |
|
656 | ## 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 |
|
657 | ## include the problematic match, instead of not including anything. There's a | |
513 | ## bit more indirection here, but I think it's worth it |
|
658 | ## bit more indirection here, but I think it's worth it | |
514 | for c in completions: |
|
659 | for c in completions: | |
515 | vim.command('call add(res,"'+c+'")') |
|
660 | vim.command('call add(res,"'+c+'")') | |
516 | endpython |
|
661 | endpython | |
517 | "call extend(res,completions) |
|
662 | "call extend(res,completions) | |
518 |
|
|
663 | return res | |
519 |
|
|
664 | endif | |
520 |
|
|
665 | endfun | |
521 | set completefunc=CompleteIPython |
|
General Comments 0
You need to be logged in to leave comments.
Login now