##// END OF EJS Templates
Work around bug in pprint.pformat. Closes gh-148
Fernando Perez -
Show More
@@ -1,288 +1,292 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Displayhook for IPython.
2 """Displayhook for IPython.
3
3
4 Authors:
4 Authors:
5
5
6 * Fernando Perez
6 * Fernando Perez
7 * Brian Granger
7 * Brian Granger
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2010 The IPython Development Team
11 # Copyright (C) 2008-2010 The IPython Development Team
12 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
12 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import __builtin__
22 import __builtin__
23 from pprint import PrettyPrinter
23 from pprint import PrettyPrinter
24 pformat = PrettyPrinter().pformat
24 pformat = PrettyPrinter().pformat
25
25
26 from IPython.config.configurable import Configurable
26 from IPython.config.configurable import Configurable
27 from IPython.core import prompts
27 from IPython.core import prompts
28 import IPython.utils.generics
28 import IPython.utils.generics
29 import IPython.utils.io
29 import IPython.utils.io
30 from IPython.utils.traitlets import Instance, Int
30 from IPython.utils.traitlets import Instance, Int
31 from IPython.utils.warn import warn
31 from IPython.utils.warn import warn
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Main displayhook class
34 # Main displayhook class
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37 # TODO: The DisplayHook class should be split into two classes, one that
37 # TODO: The DisplayHook class should be split into two classes, one that
38 # manages the prompts and their synchronization and another that just does the
38 # manages the prompts and their synchronization and another that just does the
39 # displayhook logic and calls into the prompt manager.
39 # displayhook logic and calls into the prompt manager.
40
40
41 # TODO: Move the various attributes (cache_size, colors, input_sep,
41 # TODO: Move the various attributes (cache_size, colors, input_sep,
42 # output_sep, output_sep2, ps1, ps2, ps_out, pad_left). Some of these are also
42 # output_sep, output_sep2, ps1, ps2, ps_out, pad_left). Some of these are also
43 # attributes of InteractiveShell. They should be on ONE object only and the
43 # attributes of InteractiveShell. They should be on ONE object only and the
44 # other objects should ask that one object for their values.
44 # other objects should ask that one object for their values.
45
45
46 class DisplayHook(Configurable):
46 class DisplayHook(Configurable):
47 """The custom IPython displayhook to replace sys.displayhook.
47 """The custom IPython displayhook to replace sys.displayhook.
48
48
49 This class does many things, but the basic idea is that it is a callable
49 This class does many things, but the basic idea is that it is a callable
50 that gets called anytime user code returns a value.
50 that gets called anytime user code returns a value.
51
51
52 Currently this class does more than just the displayhook logic and that
52 Currently this class does more than just the displayhook logic and that
53 extra logic should eventually be moved out of here.
53 extra logic should eventually be moved out of here.
54 """
54 """
55
55
56 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
56 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
57 # Each call to the In[] prompt raises it by 1, even the first.
57 # Each call to the In[] prompt raises it by 1, even the first.
58 prompt_count = Int(0)
58 prompt_count = Int(0)
59
59
60 def __init__(self, shell=None, cache_size=1000,
60 def __init__(self, shell=None, cache_size=1000,
61 colors='NoColor', input_sep='\n',
61 colors='NoColor', input_sep='\n',
62 output_sep='\n', output_sep2='',
62 output_sep='\n', output_sep2='',
63 ps1 = None, ps2 = None, ps_out = None, pad_left=True,
63 ps1 = None, ps2 = None, ps_out = None, pad_left=True,
64 config=None):
64 config=None):
65 super(DisplayHook, self).__init__(shell=shell, config=config)
65 super(DisplayHook, self).__init__(shell=shell, config=config)
66
66
67 cache_size_min = 3
67 cache_size_min = 3
68 if cache_size <= 0:
68 if cache_size <= 0:
69 self.do_full_cache = 0
69 self.do_full_cache = 0
70 cache_size = 0
70 cache_size = 0
71 elif cache_size < cache_size_min:
71 elif cache_size < cache_size_min:
72 self.do_full_cache = 0
72 self.do_full_cache = 0
73 cache_size = 0
73 cache_size = 0
74 warn('caching was disabled (min value for cache size is %s).' %
74 warn('caching was disabled (min value for cache size is %s).' %
75 cache_size_min,level=3)
75 cache_size_min,level=3)
76 else:
76 else:
77 self.do_full_cache = 1
77 self.do_full_cache = 1
78
78
79 self.cache_size = cache_size
79 self.cache_size = cache_size
80 self.input_sep = input_sep
80 self.input_sep = input_sep
81
81
82 # we need a reference to the user-level namespace
82 # we need a reference to the user-level namespace
83 self.shell = shell
83 self.shell = shell
84
84
85 # Set input prompt strings and colors
85 # Set input prompt strings and colors
86 if cache_size == 0:
86 if cache_size == 0:
87 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
87 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
88 or ps1.find(r'\N') > -1:
88 or ps1.find(r'\N') > -1:
89 ps1 = '>>> '
89 ps1 = '>>> '
90 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
90 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
91 or ps2.find(r'\N') > -1:
91 or ps2.find(r'\N') > -1:
92 ps2 = '... '
92 ps2 = '... '
93 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
93 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
94 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
94 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
95 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
95 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
96
96
97 self.color_table = prompts.PromptColors
97 self.color_table = prompts.PromptColors
98 self.prompt1 = prompts.Prompt1(self,sep=input_sep,prompt=self.ps1_str,
98 self.prompt1 = prompts.Prompt1(self,sep=input_sep,prompt=self.ps1_str,
99 pad_left=pad_left)
99 pad_left=pad_left)
100 self.prompt2 = prompts.Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
100 self.prompt2 = prompts.Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
101 self.prompt_out = prompts.PromptOut(self,sep='',prompt=self.ps_out_str,
101 self.prompt_out = prompts.PromptOut(self,sep='',prompt=self.ps_out_str,
102 pad_left=pad_left)
102 pad_left=pad_left)
103 self.set_colors(colors)
103 self.set_colors(colors)
104
104
105 # Store the last prompt string each time, we need it for aligning
105 # Store the last prompt string each time, we need it for aligning
106 # continuation and auto-rewrite prompts
106 # continuation and auto-rewrite prompts
107 self.last_prompt = ''
107 self.last_prompt = ''
108 self.output_sep = output_sep
108 self.output_sep = output_sep
109 self.output_sep2 = output_sep2
109 self.output_sep2 = output_sep2
110 self._,self.__,self.___ = '','',''
110 self._,self.__,self.___ = '','',''
111 self.pprint_types = map(type,[(),[],{}])
111 self.pprint_types = map(type,[(),[],{}])
112
112
113 # these are deliberately global:
113 # these are deliberately global:
114 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
114 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
115 self.shell.user_ns.update(to_user_ns)
115 self.shell.user_ns.update(to_user_ns)
116
116
117 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
117 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
118 if p_str is None:
118 if p_str is None:
119 if self.do_full_cache:
119 if self.do_full_cache:
120 return cache_def
120 return cache_def
121 else:
121 else:
122 return no_cache_def
122 return no_cache_def
123 else:
123 else:
124 return p_str
124 return p_str
125
125
126 def set_colors(self, colors):
126 def set_colors(self, colors):
127 """Set the active color scheme and configure colors for the three
127 """Set the active color scheme and configure colors for the three
128 prompt subsystems."""
128 prompt subsystems."""
129
129
130 # FIXME: This modifying of the global prompts.prompt_specials needs
130 # FIXME: This modifying of the global prompts.prompt_specials needs
131 # to be fixed. We need to refactor all of the prompts stuff to use
131 # to be fixed. We need to refactor all of the prompts stuff to use
132 # proper configuration and traits notifications.
132 # proper configuration and traits notifications.
133 if colors.lower()=='nocolor':
133 if colors.lower()=='nocolor':
134 prompts.prompt_specials = prompts.prompt_specials_nocolor
134 prompts.prompt_specials = prompts.prompt_specials_nocolor
135 else:
135 else:
136 prompts.prompt_specials = prompts.prompt_specials_color
136 prompts.prompt_specials = prompts.prompt_specials_color
137
137
138 self.color_table.set_active_scheme(colors)
138 self.color_table.set_active_scheme(colors)
139 self.prompt1.set_colors()
139 self.prompt1.set_colors()
140 self.prompt2.set_colors()
140 self.prompt2.set_colors()
141 self.prompt_out.set_colors()
141 self.prompt_out.set_colors()
142
142
143 #-------------------------------------------------------------------------
143 #-------------------------------------------------------------------------
144 # Methods used in __call__. Override these methods to modify the behavior
144 # Methods used in __call__. Override these methods to modify the behavior
145 # of the displayhook.
145 # of the displayhook.
146 #-------------------------------------------------------------------------
146 #-------------------------------------------------------------------------
147
147
148 def check_for_underscore(self):
148 def check_for_underscore(self):
149 """Check if the user has set the '_' variable by hand."""
149 """Check if the user has set the '_' variable by hand."""
150 # If something injected a '_' variable in __builtin__, delete
150 # If something injected a '_' variable in __builtin__, delete
151 # ipython's automatic one so we don't clobber that. gettext() in
151 # ipython's automatic one so we don't clobber that. gettext() in
152 # particular uses _, so we need to stay away from it.
152 # particular uses _, so we need to stay away from it.
153 if '_' in __builtin__.__dict__:
153 if '_' in __builtin__.__dict__:
154 try:
154 try:
155 del self.shell.user_ns['_']
155 del self.shell.user_ns['_']
156 except KeyError:
156 except KeyError:
157 pass
157 pass
158
158
159 def quiet(self):
159 def quiet(self):
160 """Should we silence the display hook because of ';'?"""
160 """Should we silence the display hook because of ';'?"""
161 # do not print output if input ends in ';'
161 # do not print output if input ends in ';'
162 try:
162 try:
163 if self.shell.input_hist[self.prompt_count].endswith(';\n'):
163 if self.shell.input_hist[self.prompt_count].endswith(';\n'):
164 return True
164 return True
165 except IndexError:
165 except IndexError:
166 # some uses of ipshellembed may fail here
166 # some uses of ipshellembed may fail here
167 pass
167 pass
168 return False
168 return False
169
169
170 def start_displayhook(self):
170 def start_displayhook(self):
171 """Start the displayhook, initializing resources."""
171 """Start the displayhook, initializing resources."""
172 pass
172 pass
173
173
174 def write_output_prompt(self):
174 def write_output_prompt(self):
175 """Write the output prompt."""
175 """Write the output prompt."""
176 # Use write, not print which adds an extra space.
176 # Use write, not print which adds an extra space.
177 IPython.utils.io.Term.cout.write(self.output_sep)
177 IPython.utils.io.Term.cout.write(self.output_sep)
178 outprompt = str(self.prompt_out)
178 outprompt = str(self.prompt_out)
179 if self.do_full_cache:
179 if self.do_full_cache:
180 IPython.utils.io.Term.cout.write(outprompt)
180 IPython.utils.io.Term.cout.write(outprompt)
181
181
182 # TODO: Make this method an extension point. The previous implementation
182 # TODO: Make this method an extension point. The previous implementation
183 # has both a result_display hook as well as a result_display generic
183 # has both a result_display hook as well as a result_display generic
184 # function to customize the repr on a per class basis. We need to rethink
184 # function to customize the repr on a per class basis. We need to rethink
185 # the hooks mechanism before doing this though.
185 # the hooks mechanism before doing this though.
186 def compute_result_repr(self, result):
186 def compute_result_repr(self, result):
187 """Compute and return the repr of the object to be displayed.
187 """Compute and return the repr of the object to be displayed.
188
188
189 This method only compute the string form of the repr and should NOT
189 This method only compute the string form of the repr and should NOT
190 actual print or write that to a stream. This method may also transform
190 actual print or write that to a stream. This method may also transform
191 the result itself, but the default implementation passes the original
191 the result itself, but the default implementation passes the original
192 through.
192 through.
193 """
193 """
194 try:
194 try:
195 if self.shell.pprint:
195 if self.shell.pprint:
196 result_repr = pformat(result)
196 try:
197 result_repr = pformat(result)
198 except:
199 # Work around possible bugs in pformat
200 result_repr = repr(result)
197 if '\n' in result_repr:
201 if '\n' in result_repr:
198 # So that multi-line strings line up with the left column of
202 # So that multi-line strings line up with the left column of
199 # the screen, instead of having the output prompt mess up
203 # the screen, instead of having the output prompt mess up
200 # their first line.
204 # their first line.
201 result_repr = '\n' + result_repr
205 result_repr = '\n' + result_repr
202 else:
206 else:
203 result_repr = repr(result)
207 result_repr = repr(result)
204 except TypeError:
208 except TypeError:
205 # This happens when result.__repr__ doesn't return a string,
209 # This happens when result.__repr__ doesn't return a string,
206 # such as when it returns None.
210 # such as when it returns None.
207 result_repr = '\n'
211 result_repr = '\n'
208 return result, result_repr
212 return result, result_repr
209
213
210 def write_result_repr(self, result_repr):
214 def write_result_repr(self, result_repr):
211 # We want to print because we want to always make sure we have a
215 # We want to print because we want to always make sure we have a
212 # newline, even if all the prompt separators are ''. This is the
216 # newline, even if all the prompt separators are ''. This is the
213 # standard IPython behavior.
217 # standard IPython behavior.
214 print >>IPython.utils.io.Term.cout, result_repr
218 print >>IPython.utils.io.Term.cout, result_repr
215
219
216 def update_user_ns(self, result):
220 def update_user_ns(self, result):
217 """Update user_ns with various things like _, __, _1, etc."""
221 """Update user_ns with various things like _, __, _1, etc."""
218
222
219 # Avoid recursive reference when displaying _oh/Out
223 # Avoid recursive reference when displaying _oh/Out
220 if result is not self.shell.user_ns['_oh']:
224 if result is not self.shell.user_ns['_oh']:
221 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
225 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
222 warn('Output cache limit (currently '+
226 warn('Output cache limit (currently '+
223 `self.cache_size`+' entries) hit.\n'
227 `self.cache_size`+' entries) hit.\n'
224 'Flushing cache and resetting history counter...\n'
228 'Flushing cache and resetting history counter...\n'
225 'The only history variables available will be _,__,___ and _1\n'
229 'The only history variables available will be _,__,___ and _1\n'
226 'with the current result.')
230 'with the current result.')
227
231
228 self.flush()
232 self.flush()
229 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
233 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
230 # we cause buggy behavior for things like gettext).
234 # we cause buggy behavior for things like gettext).
231 if '_' not in __builtin__.__dict__:
235 if '_' not in __builtin__.__dict__:
232 self.___ = self.__
236 self.___ = self.__
233 self.__ = self._
237 self.__ = self._
234 self._ = result
238 self._ = result
235 self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
239 self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
236
240
237 # hackish access to top-level namespace to create _1,_2... dynamically
241 # hackish access to top-level namespace to create _1,_2... dynamically
238 to_main = {}
242 to_main = {}
239 if self.do_full_cache:
243 if self.do_full_cache:
240 new_result = '_'+`self.prompt_count`
244 new_result = '_'+`self.prompt_count`
241 to_main[new_result] = result
245 to_main[new_result] = result
242 self.shell.user_ns.update(to_main)
246 self.shell.user_ns.update(to_main)
243 self.shell.user_ns['_oh'][self.prompt_count] = result
247 self.shell.user_ns['_oh'][self.prompt_count] = result
244
248
245 def log_output(self, result):
249 def log_output(self, result):
246 """Log the output."""
250 """Log the output."""
247 if self.shell.logger.log_output:
251 if self.shell.logger.log_output:
248 self.shell.logger.log_write(repr(result),'output')
252 self.shell.logger.log_write(repr(result),'output')
249
253
250 def finish_displayhook(self):
254 def finish_displayhook(self):
251 """Finish up all displayhook activities."""
255 """Finish up all displayhook activities."""
252 IPython.utils.io.Term.cout.write(self.output_sep2)
256 IPython.utils.io.Term.cout.write(self.output_sep2)
253 IPython.utils.io.Term.cout.flush()
257 IPython.utils.io.Term.cout.flush()
254
258
255 def __call__(self, result=None):
259 def __call__(self, result=None):
256 """Printing with history cache management.
260 """Printing with history cache management.
257
261
258 This is invoked everytime the interpreter needs to print, and is
262 This is invoked everytime the interpreter needs to print, and is
259 activated by setting the variable sys.displayhook to it.
263 activated by setting the variable sys.displayhook to it.
260 """
264 """
261 self.check_for_underscore()
265 self.check_for_underscore()
262 if result is not None and not self.quiet():
266 if result is not None and not self.quiet():
263 self.start_displayhook()
267 self.start_displayhook()
264 self.write_output_prompt()
268 self.write_output_prompt()
265 result, result_repr = self.compute_result_repr(result)
269 result, result_repr = self.compute_result_repr(result)
266 self.write_result_repr(result_repr)
270 self.write_result_repr(result_repr)
267 self.update_user_ns(result)
271 self.update_user_ns(result)
268 self.log_output(result)
272 self.log_output(result)
269 self.finish_displayhook()
273 self.finish_displayhook()
270
274
271 def flush(self):
275 def flush(self):
272 if not self.do_full_cache:
276 if not self.do_full_cache:
273 raise ValueError,"You shouldn't have reached the cache flush "\
277 raise ValueError,"You shouldn't have reached the cache flush "\
274 "if full caching is not enabled!"
278 "if full caching is not enabled!"
275 # delete auto-generated vars from global namespace
279 # delete auto-generated vars from global namespace
276
280
277 for n in range(1,self.prompt_count + 1):
281 for n in range(1,self.prompt_count + 1):
278 key = '_'+`n`
282 key = '_'+`n`
279 try:
283 try:
280 del self.shell.user_ns[key]
284 del self.shell.user_ns[key]
281 except: pass
285 except: pass
282 self.shell.user_ns['_oh'].clear()
286 self.shell.user_ns['_oh'].clear()
283
287
284 if '_' not in __builtin__.__dict__:
288 if '_' not in __builtin__.__dict__:
285 self.shell.user_ns.update({'_':None,'__':None, '___':None})
289 self.shell.user_ns.update({'_':None,'__':None, '___':None})
286 import gc
290 import gc
287 gc.collect() # xxx needed?
291 gc.collect() # xxx needed?
288
292
@@ -1,259 +1,263 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 need to put the
14 If you wish to define a new hook and activate it, you need to put the
15 necessary code into a python file which can be either imported or execfile()'d
15 necessary code into a python file which can be either imported or execfile()'d
16 from within your ipythonrc configuration.
16 from within your ipythonrc configuration.
17
17
18 For example, suppose that you have a module called 'myiphooks' in your
18 For example, suppose that you have a module called 'myiphooks' in your
19 PYTHONPATH, which contains the following definition:
19 PYTHONPATH, which contains the following definition:
20
20
21 import os
21 import os
22 from IPython.core import ipapi
22 from IPython.core import ipapi
23 ip = ipapi.get()
23 ip = ipapi.get()
24
24
25 def calljed(self,filename, linenum):
25 def calljed(self,filename, linenum):
26 "My editor hook calls the jed editor directly."
26 "My editor hook calls the jed editor directly."
27 print "Calling my own editor, jed ..."
27 print "Calling my own editor, jed ..."
28 if os.system('jed +%d %s' % (linenum,filename)) != 0:
28 if os.system('jed +%d %s' % (linenum,filename)) != 0:
29 raise TryNext()
29 raise TryNext()
30
30
31 ip.set_hook('editor', calljed)
31 ip.set_hook('editor', calljed)
32
32
33 You can then enable the functionality by doing 'import myiphooks'
33 You can then enable the functionality by doing 'import myiphooks'
34 somewhere in your configuration files or ipython command line.
34 somewhere in your configuration files or ipython command line.
35 """
35 """
36
36
37 #*****************************************************************************
37 #*****************************************************************************
38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
39 #
39 #
40 # Distributed under the terms of the BSD License. The full license is in
40 # Distributed under the terms of the BSD License. The full license is in
41 # the file COPYING, distributed as part of this software.
41 # the file COPYING, distributed as part of this software.
42 #*****************************************************************************
42 #*****************************************************************************
43
43
44 import os, bisect
44 import os, bisect
45 import sys
45 import sys
46
46
47 from IPython.core.error import TryNext
47 from IPython.core.error import TryNext
48 import IPython.utils.io
48 import IPython.utils.io
49
49
50 # List here all the default hooks. For now it's just the editor functions
50 # List here all the default hooks. For now it's just the editor functions
51 # but over time we'll move here all the public API for user-accessible things.
51 # but over time we'll move here all the public API for user-accessible things.
52
52
53 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor',
53 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor',
54 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
54 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
55 'generate_prompt', 'show_in_pager','pre_prompt_hook',
55 'generate_prompt', 'show_in_pager','pre_prompt_hook',
56 'pre_runcode_hook', 'clipboard_get']
56 'pre_runcode_hook', 'clipboard_get']
57
57
58 def editor(self,filename, linenum=None):
58 def editor(self,filename, linenum=None):
59 """Open the default editor at the given filename and linenumber.
59 """Open the default editor at the given filename and linenumber.
60
60
61 This is IPython's default editor hook, you can use it as an example to
61 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
62 write your own modified one. To set your own editor function as the
63 new editor hook, call ip.set_hook('editor',yourfunc)."""
63 new editor hook, call ip.set_hook('editor',yourfunc)."""
64
64
65 # IPython configures a default editor at startup by reading $EDITOR from
65 # IPython configures a default editor at startup by reading $EDITOR from
66 # the environment, and falling back on vi (unix) or notepad (win32).
66 # the environment, and falling back on vi (unix) or notepad (win32).
67 editor = self.editor
67 editor = self.editor
68
68
69 # marker for at which line to open the file (for existing objects)
69 # marker for at which line to open the file (for existing objects)
70 if linenum is None or editor=='notepad':
70 if linenum is None or editor=='notepad':
71 linemark = ''
71 linemark = ''
72 else:
72 else:
73 linemark = '+%d' % int(linenum)
73 linemark = '+%d' % int(linenum)
74
74
75 # Enclose in quotes if necessary and legal
75 # Enclose in quotes if necessary and legal
76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
77 editor = '"%s"' % editor
77 editor = '"%s"' % editor
78
78
79 # Call the actual editor
79 # Call the actual editor
80 if os.system('%s %s %s' % (editor,linemark,filename)) != 0:
80 if os.system('%s %s %s' % (editor,linemark,filename)) != 0:
81 raise TryNext()
81 raise TryNext()
82
82
83 import tempfile
83 import tempfile
84 def fix_error_editor(self,filename,linenum,column,msg):
84 def fix_error_editor(self,filename,linenum,column,msg):
85 """Open the editor at the given filename, linenumber, column and
85 """Open the editor at the given filename, linenumber, column and
86 show an error message. This is used for correcting syntax errors.
86 show an error message. This is used for correcting syntax errors.
87 The current implementation only has special support for the VIM editor,
87 The current implementation only has special support for the VIM editor,
88 and falls back on the 'editor' hook if VIM is not used.
88 and falls back on the 'editor' hook if VIM is not used.
89
89
90 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
90 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
91 """
91 """
92 def vim_quickfix_file():
92 def vim_quickfix_file():
93 t = tempfile.NamedTemporaryFile()
93 t = tempfile.NamedTemporaryFile()
94 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
94 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
95 t.flush()
95 t.flush()
96 return t
96 return t
97 if os.path.basename(self.editor) != 'vim':
97 if os.path.basename(self.editor) != 'vim':
98 self.hooks.editor(filename,linenum)
98 self.hooks.editor(filename,linenum)
99 return
99 return
100 t = vim_quickfix_file()
100 t = vim_quickfix_file()
101 try:
101 try:
102 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
102 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
103 raise TryNext()
103 raise TryNext()
104 finally:
104 finally:
105 t.close()
105 t.close()
106
106
107
107
108 def synchronize_with_editor(self, filename, linenum, column):
108 def synchronize_with_editor(self, filename, linenum, column):
109 pass
109 pass
110
110
111
111
112 class CommandChainDispatcher:
112 class CommandChainDispatcher:
113 """ Dispatch calls to a chain of commands until some func can handle it
113 """ Dispatch calls to a chain of commands until some func can handle it
114
114
115 Usage: instantiate, execute "add" to add commands (with optional
115 Usage: instantiate, execute "add" to add commands (with optional
116 priority), execute normally via f() calling mechanism.
116 priority), execute normally via f() calling mechanism.
117
117
118 """
118 """
119 def __init__(self,commands=None):
119 def __init__(self,commands=None):
120 if commands is None:
120 if commands is None:
121 self.chain = []
121 self.chain = []
122 else:
122 else:
123 self.chain = commands
123 self.chain = commands
124
124
125
125
126 def __call__(self,*args, **kw):
126 def __call__(self,*args, **kw):
127 """ Command chain is called just like normal func.
127 """ Command chain is called just like normal func.
128
128
129 This will call all funcs in chain with the same args as were given to this
129 This will call all funcs in chain with the same args as were given to this
130 function, and return the result of first func that didn't raise
130 function, and return the result of first func that didn't raise
131 TryNext """
131 TryNext """
132
132
133 for prio,cmd in self.chain:
133 for prio,cmd in self.chain:
134 #print "prio",prio,"cmd",cmd #dbg
134 #print "prio",prio,"cmd",cmd #dbg
135 try:
135 try:
136 return cmd(*args, **kw)
136 return cmd(*args, **kw)
137 except TryNext, exc:
137 except TryNext, exc:
138 if exc.args or exc.kwargs:
138 if exc.args or exc.kwargs:
139 args = exc.args
139 args = exc.args
140 kw = exc.kwargs
140 kw = exc.kwargs
141 # if no function will accept it, raise TryNext up to the caller
141 # if no function will accept it, raise TryNext up to the caller
142 raise TryNext
142 raise TryNext
143
143
144 def __str__(self):
144 def __str__(self):
145 return str(self.chain)
145 return str(self.chain)
146
146
147 def add(self, func, priority=0):
147 def add(self, func, priority=0):
148 """ Add a func to the cmd chain with given priority """
148 """ Add a func to the cmd chain with given priority """
149 bisect.insort(self.chain,(priority,func))
149 bisect.insort(self.chain,(priority,func))
150
150
151 def __iter__(self):
151 def __iter__(self):
152 """ Return all objects in chain.
152 """ Return all objects in chain.
153
153
154 Handy if the objects are not callable.
154 Handy if the objects are not callable.
155 """
155 """
156 return iter(self.chain)
156 return iter(self.chain)
157
157
158
158
159 def result_display(self,arg):
159 def result_display(self,arg):
160 """ Default display hook.
160 """ Default display hook.
161
161
162 Called for displaying the result to the user.
162 Called for displaying the result to the user.
163 """
163 """
164
164
165 if self.pprint:
165 if self.pprint:
166 out = pformat(arg)
166 try:
167 out = pformat(arg)
168 except:
169 # Work around possible bugs in pformat
170 out = repr(arg)
167 if '\n' in out:
171 if '\n' in out:
168 # So that multi-line strings line up with the left column of
172 # So that multi-line strings line up with the left column of
169 # the screen, instead of having the output prompt mess up
173 # the screen, instead of having the output prompt mess up
170 # their first line.
174 # their first line.
171 IPython.utils.io.Term.cout.write('\n')
175 IPython.utils.io.Term.cout.write('\n')
172 print >>IPython.utils.io.Term.cout, out
176 print >>IPython.utils.io.Term.cout, out
173 else:
177 else:
174 # By default, the interactive prompt uses repr() to display results,
178 # By default, the interactive prompt uses repr() to display results,
175 # so we should honor this. Users who'd rather use a different
179 # so we should honor this. Users who'd rather use a different
176 # mechanism can easily override this hook.
180 # mechanism can easily override this hook.
177 print >>IPython.utils.io.Term.cout, repr(arg)
181 print >>IPython.utils.io.Term.cout, repr(arg)
178 # the default display hook doesn't manipulate the value to put in history
182 # the default display hook doesn't manipulate the value to put in history
179 return None
183 return None
180
184
181
185
182 def input_prefilter(self,line):
186 def input_prefilter(self,line):
183 """ Default input prefilter
187 """ Default input prefilter
184
188
185 This returns the line as unchanged, so that the interpreter
189 This returns the line as unchanged, so that the interpreter
186 knows that nothing was done and proceeds with "classic" prefiltering
190 knows that nothing was done and proceeds with "classic" prefiltering
187 (%magics, !shell commands etc.).
191 (%magics, !shell commands etc.).
188
192
189 Note that leading whitespace is not passed to this hook. Prefilter
193 Note that leading whitespace is not passed to this hook. Prefilter
190 can't alter indentation.
194 can't alter indentation.
191
195
192 """
196 """
193 #print "attempt to rewrite",line #dbg
197 #print "attempt to rewrite",line #dbg
194 return line
198 return line
195
199
196
200
197 def shutdown_hook(self):
201 def shutdown_hook(self):
198 """ default shutdown hook
202 """ default shutdown hook
199
203
200 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
204 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
201 """
205 """
202
206
203 #print "default shutdown hook ok" # dbg
207 #print "default shutdown hook ok" # dbg
204 return
208 return
205
209
206
210
207 def late_startup_hook(self):
211 def late_startup_hook(self):
208 """ Executed after ipython has been constructed and configured
212 """ Executed after ipython has been constructed and configured
209
213
210 """
214 """
211 #print "default startup hook ok" # dbg
215 #print "default startup hook ok" # dbg
212
216
213
217
214 def generate_prompt(self, is_continuation):
218 def generate_prompt(self, is_continuation):
215 """ calculate and return a string with the prompt to display """
219 """ calculate and return a string with the prompt to display """
216 if is_continuation:
220 if is_continuation:
217 return str(self.displayhook.prompt2)
221 return str(self.displayhook.prompt2)
218 return str(self.displayhook.prompt1)
222 return str(self.displayhook.prompt1)
219
223
220
224
221 def show_in_pager(self,s):
225 def show_in_pager(self,s):
222 """ Run a string through pager """
226 """ Run a string through pager """
223 # raising TryNext here will use the default paging functionality
227 # raising TryNext here will use the default paging functionality
224 raise TryNext
228 raise TryNext
225
229
226
230
227 def pre_prompt_hook(self):
231 def pre_prompt_hook(self):
228 """ Run before displaying the next prompt
232 """ Run before displaying the next prompt
229
233
230 Use this e.g. to display output from asynchronous operations (in order
234 Use this e.g. to display output from asynchronous operations (in order
231 to not mess up text entry)
235 to not mess up text entry)
232 """
236 """
233
237
234 return None
238 return None
235
239
236
240
237 def pre_runcode_hook(self):
241 def pre_runcode_hook(self):
238 """ Executed before running the (prefiltered) code in IPython """
242 """ Executed before running the (prefiltered) code in IPython """
239 return None
243 return None
240
244
241
245
242 def clipboard_get(self):
246 def clipboard_get(self):
243 """ Get text from the clipboard.
247 """ Get text from the clipboard.
244 """
248 """
245 from IPython.lib.clipboard import (
249 from IPython.lib.clipboard import (
246 osx_clipboard_get, tkinter_clipboard_get,
250 osx_clipboard_get, tkinter_clipboard_get,
247 win32_clipboard_get
251 win32_clipboard_get
248 )
252 )
249 if sys.platform == 'win32':
253 if sys.platform == 'win32':
250 chain = [win32_clipboard_get, tkinter_clipboard_get]
254 chain = [win32_clipboard_get, tkinter_clipboard_get]
251 elif sys.platform == 'darwin':
255 elif sys.platform == 'darwin':
252 chain = [osx_clipboard_get, tkinter_clipboard_get]
256 chain = [osx_clipboard_get, tkinter_clipboard_get]
253 else:
257 else:
254 chain = [tkinter_clipboard_get]
258 chain = [tkinter_clipboard_get]
255 dispatcher = CommandChainDispatcher()
259 dispatcher = CommandChainDispatcher()
256 for func in chain:
260 for func in chain:
257 dispatcher.add(func)
261 dispatcher.add(func)
258 text = dispatcher()
262 text = dispatcher()
259 return text
263 return text
General Comments 0
You need to be logged in to leave comments. Login now