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