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