##// END OF EJS Templates
Add `wait` optional argument to `hooks.editor`...
Takafumi Arakaki -
Show More
@@ -1,228 +1,231 b''
1 1 """hooks for IPython.
2 2
3 3 In Python, it is possible to overwrite any method of any object if you really
4 4 want to. But IPython exposes a few 'hooks', methods which are _designed_ to
5 5 be overwritten by users for customization purposes. This module defines the
6 6 default versions of all such hooks, which get used by IPython if not
7 7 overridden by the user.
8 8
9 9 hooks are simple functions, but they should be declared with 'self' as their
10 10 first argument, because when activated they are registered into IPython as
11 11 instance methods. The self argument will be the IPython running instance
12 12 itself, so hooks have full access to the entire IPython object.
13 13
14 14 If you wish to define a new hook and activate it, you need to put the
15 15 necessary code into a python file which can be either imported or execfile()'d
16 16 from within your profile's ipython_config.py configuration.
17 17
18 18 For example, suppose that you have a module called 'myiphooks' in your
19 19 PYTHONPATH, which contains the following definition:
20 20
21 21 import os
22 22 from IPython.core import ipapi
23 23 ip = ipapi.get()
24 24
25 25 def calljed(self,filename, linenum):
26 26 "My editor hook calls the jed editor directly."
27 27 print "Calling my own editor, jed ..."
28 28 if os.system('jed +%d %s' % (linenum,filename)) != 0:
29 29 raise TryNext()
30 30
31 31 ip.set_hook('editor', calljed)
32 32
33 33 You can then enable the functionality by doing 'import myiphooks'
34 34 somewhere in your configuration files or ipython command line.
35 35 """
36 36
37 37 #*****************************************************************************
38 38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
39 39 #
40 40 # Distributed under the terms of the BSD License. The full license is in
41 41 # the file COPYING, distributed as part of this software.
42 42 #*****************************************************************************
43 43
44 44 import os, bisect
45 import subprocess
45 46 import sys
46 47
47 48 from IPython.core.error import TryNext
48 49
49 50 # List here all the default hooks. For now it's just the editor functions
50 51 # but over time we'll move here all the public API for user-accessible things.
51 52
52 53 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor',
53 54 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
54 55 'show_in_pager','pre_prompt_hook',
55 56 'pre_run_code_hook', 'clipboard_get']
56 57
57 def editor(self,filename, linenum=None):
58 def editor(self, filename, linenum=None, wait=True):
58 59 """Open the default editor at the given filename and linenumber.
59 60
60 61 This is IPython's default editor hook, you can use it as an example to
61 62 write your own modified one. To set your own editor function as the
62 63 new editor hook, call ip.set_hook('editor',yourfunc)."""
63 64
64 65 # IPython configures a default editor at startup by reading $EDITOR from
65 66 # the environment, and falling back on vi (unix) or notepad (win32).
66 67 editor = self.editor
67 68
68 69 # marker for at which line to open the file (for existing objects)
69 70 if linenum is None or editor=='notepad':
70 71 linemark = ''
71 72 else:
72 73 linemark = '+%d' % int(linenum)
73 74
74 75 # Enclose in quotes if necessary and legal
75 76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
76 77 editor = '"%s"' % editor
77 78
78 79 # Call the actual editor
79 if os.system('%s %s %s' % (editor,linemark,filename)) != 0:
80 proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename),
81 shell=True)
82 if wait and proc.wait() != 0:
80 83 raise TryNext()
81 84
82 85 import tempfile
83 86 def fix_error_editor(self,filename,linenum,column,msg):
84 87 """Open the editor at the given filename, linenumber, column and
85 88 show an error message. This is used for correcting syntax errors.
86 89 The current implementation only has special support for the VIM editor,
87 90 and falls back on the 'editor' hook if VIM is not used.
88 91
89 92 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
90 93 """
91 94 def vim_quickfix_file():
92 95 t = tempfile.NamedTemporaryFile()
93 96 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
94 97 t.flush()
95 98 return t
96 99 if os.path.basename(self.editor) != 'vim':
97 100 self.hooks.editor(filename,linenum)
98 101 return
99 102 t = vim_quickfix_file()
100 103 try:
101 104 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
102 105 raise TryNext()
103 106 finally:
104 107 t.close()
105 108
106 109
107 110 def synchronize_with_editor(self, filename, linenum, column):
108 111 pass
109 112
110 113
111 114 class CommandChainDispatcher:
112 115 """ Dispatch calls to a chain of commands until some func can handle it
113 116
114 117 Usage: instantiate, execute "add" to add commands (with optional
115 118 priority), execute normally via f() calling mechanism.
116 119
117 120 """
118 121 def __init__(self,commands=None):
119 122 if commands is None:
120 123 self.chain = []
121 124 else:
122 125 self.chain = commands
123 126
124 127
125 128 def __call__(self,*args, **kw):
126 129 """ Command chain is called just like normal func.
127 130
128 131 This will call all funcs in chain with the same args as were given to this
129 132 function, and return the result of first func that didn't raise
130 133 TryNext """
131 134
132 135 for prio,cmd in self.chain:
133 136 #print "prio",prio,"cmd",cmd #dbg
134 137 try:
135 138 return cmd(*args, **kw)
136 139 except TryNext, exc:
137 140 if exc.args or exc.kwargs:
138 141 args = exc.args
139 142 kw = exc.kwargs
140 143 # if no function will accept it, raise TryNext up to the caller
141 144 raise TryNext(*args, **kw)
142 145
143 146 def __str__(self):
144 147 return str(self.chain)
145 148
146 149 def add(self, func, priority=0):
147 150 """ Add a func to the cmd chain with given priority """
148 151 bisect.insort(self.chain,(priority,func))
149 152
150 153 def __iter__(self):
151 154 """ Return all objects in chain.
152 155
153 156 Handy if the objects are not callable.
154 157 """
155 158 return iter(self.chain)
156 159
157 160
158 161 def input_prefilter(self,line):
159 162 """ Default input prefilter
160 163
161 164 This returns the line as unchanged, so that the interpreter
162 165 knows that nothing was done and proceeds with "classic" prefiltering
163 166 (%magics, !shell commands etc.).
164 167
165 168 Note that leading whitespace is not passed to this hook. Prefilter
166 169 can't alter indentation.
167 170
168 171 """
169 172 #print "attempt to rewrite",line #dbg
170 173 return line
171 174
172 175
173 176 def shutdown_hook(self):
174 177 """ default shutdown hook
175 178
176 179 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
177 180 """
178 181
179 182 #print "default shutdown hook ok" # dbg
180 183 return
181 184
182 185
183 186 def late_startup_hook(self):
184 187 """ Executed after ipython has been constructed and configured
185 188
186 189 """
187 190 #print "default startup hook ok" # dbg
188 191
189 192
190 193 def show_in_pager(self,s):
191 194 """ Run a string through pager """
192 195 # raising TryNext here will use the default paging functionality
193 196 raise TryNext
194 197
195 198
196 199 def pre_prompt_hook(self):
197 200 """ Run before displaying the next prompt
198 201
199 202 Use this e.g. to display output from asynchronous operations (in order
200 203 to not mess up text entry)
201 204 """
202 205
203 206 return None
204 207
205 208
206 209 def pre_run_code_hook(self):
207 210 """ Executed before running the (prefiltered) code in IPython """
208 211 return None
209 212
210 213
211 214 def clipboard_get(self):
212 215 """ Get text from the clipboard.
213 216 """
214 217 from IPython.lib.clipboard import (
215 218 osx_clipboard_get, tkinter_clipboard_get,
216 219 win32_clipboard_get
217 220 )
218 221 if sys.platform == 'win32':
219 222 chain = [win32_clipboard_get, tkinter_clipboard_get]
220 223 elif sys.platform == 'darwin':
221 224 chain = [osx_clipboard_get, tkinter_clipboard_get]
222 225 else:
223 226 chain = [tkinter_clipboard_get]
224 227 dispatcher = CommandChainDispatcher()
225 228 for func in chain:
226 229 dispatcher.add(func)
227 230 text = dispatcher()
228 231 return text
General Comments 0
You need to be logged in to leave comments. Login now