##// END OF EJS Templates
merge from ileo-exp. Now requires trunk version of leo
Ville M. Vainio -
r1031:11c30a1d merge
parent child Browse files
Show More
@@ -9,15 +9,52 b' from IPython.hooks import CommandChainDispatcher'
9 import re
9 import re
10 import UserDict
10 import UserDict
11 from IPython.ipapi import TryNext
11 from IPython.ipapi import TryNext
12 import IPython.macro
12
13
13 ip = IPython.ipapi.get()
14 def init_ipython(ipy):
14 leo = ip.user_ns['leox']
15 """ This will be run by _ip.load('ipy_leo')
15 c,g = leo.c, leo.g
16
17 Leo still needs to run update_commander() after this.
18
19 """
20 global ip
21 ip = ipy
22 ip.set_hook('complete_command', mb_completer, str_key = '%mb')
23 ip.expose_magic('mb',mb_f)
24 ip.expose_magic('lee',lee_f)
25 ip.expose_magic('leoref',leoref_f)
26 expose_ileo_push(push_cl_node,100)
27 # this should be the LAST one that will be executed, and it will never raise TryNext
28 expose_ileo_push(push_ipython_script, 1000)
29 expose_ileo_push(push_plain_python, 100)
30 expose_ileo_push(push_ev_node, 100)
31 global wb
32 wb = LeoWorkbook()
33 ip.user_ns['wb'] = wb
34
35 show_welcome()
36
37
38 def update_commander(new_leox):
39 """ Set the Leo commander to use
40
41 This will be run every time Leo does ipython-launch; basically,
42 when the user switches the document he is focusing on, he should do
43 ipython-launch to tell ILeo what document the commands apply to.
44
45 """
46
47 global c,g
48 c,g = new_leox.c, new_leox.g
49 print "Set Leo Commander:",c.frame.getTitle()
16
50
17 # will probably be overwritten by user, but handy for experimentation early on
51 # will probably be overwritten by user, but handy for experimentation early on
18 ip.user_ns['c'] = c
52 ip.user_ns['c'] = c
19 ip.user_ns['g'] = g
53 ip.user_ns['g'] = g
54 ip.user_ns['_leo'] = new_leox
20
55
56 new_leox.push = push_position_from_leo
57 run_leo_startup_node()
21
58
22 from IPython.external.simplegeneric import generic
59 from IPython.external.simplegeneric import generic
23 import pprint
60 import pprint
@@ -35,14 +72,44 b' def format_for_leo(obj):'
35 def format_list(obj):
72 def format_list(obj):
36 return "\n".join(str(s) for s in obj)
73 return "\n".join(str(s) for s in obj)
37
74
75
38 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
76 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
39 def valid_attribute(s):
77 def valid_attribute(s):
40 return attribute_re.match(s)
78 return attribute_re.match(s)
41
79
80 _rootnode = None
81 def rootnode():
82 """ Get ileo root node (@ipy-root)
83
84 if node has become invalid or has not been set, return None
85
86 Note that the root is the *first* @ipy-root item found
87 """
88 global _rootnode
89 if _rootnode is None:
90 return None
91 if c.positionExists(_rootnode.p):
92 return _rootnode
93 _rootnode = None
94 return None
95
42 def all_cells():
96 def all_cells():
97 global _rootnode
43 d = {}
98 d = {}
44 for p in c.allNodes_iter():
99 r = rootnode()
100 if r is not None:
101 nodes = r.p.children_iter()
102 else:
103 nodes = c.allNodes_iter()
104
105 for p in nodes:
45 h = p.headString()
106 h = p.headString()
107 if h.strip() == '@ipy-root':
108 # update root node (found it for the first time)
109 _rootnode = LeoNode(p)
110 # the next recursive call will use the children of new root
111 return all_cells()
112
46 if h.startswith('@a '):
113 if h.startswith('@a '):
47 d[h.lstrip('@a ').strip()] = p.parent().copy()
114 d[h.lstrip('@a ').strip()] = p.parent().copy()
48 elif not valid_attribute(h):
115 elif not valid_attribute(h):
@@ -50,8 +117,6 b' def all_cells():'
50 d[h] = p.copy()
117 d[h] = p.copy()
51 return d
118 return d
52
119
53
54
55 def eval_node(n):
120 def eval_node(n):
56 body = n.b
121 body = n.b
57 if not body.startswith('@cl'):
122 if not body.startswith('@cl'):
@@ -92,6 +157,10 b' class LeoNode(object, UserDict.DictMixin):'
92
157
93 .ipush() - run push-to-ipython
158 .ipush() - run push-to-ipython
94
159
160 Minibuffer command access (tab completion works):
161
162 mb save-to-file
163
95 """
164 """
96 def __init__(self,p):
165 def __init__(self,p):
97 self.p = p.copy()
166 self.p = p.copy()
@@ -235,7 +304,7 b' class LeoWorkbook:'
235 cells = all_cells()
304 cells = all_cells()
236 p = cells.get(key, None)
305 p = cells.get(key, None)
237 if p is None:
306 if p is None:
238 p = add_var(key)
307 return add_var(key)
239
308
240 return LeoNode(p)
309 return LeoNode(p)
241
310
@@ -260,10 +329,6 b' class LeoWorkbook:'
260 yield node
329 yield node
261 return
330 return
262
331
263 ip.user_ns['wb'] = LeoWorkbook()
264
265
266
267 @IPython.generics.complete_object.when_type(LeoWorkbook)
332 @IPython.generics.complete_object.when_type(LeoWorkbook)
268 def workbook_complete(obj, prev):
333 def workbook_complete(obj, prev):
269 return all_cells().keys() + [s for s in prev if not s.startswith('_')]
334 return all_cells().keys() + [s for s in prev if not s.startswith('_')]
@@ -271,17 +336,23 b' def workbook_complete(obj, prev):'
271
336
272 def add_var(varname):
337 def add_var(varname):
273 c.beginUpdate()
338 c.beginUpdate()
339 r = rootnode()
274 try:
340 try:
341 if r is None:
275 p2 = g.findNodeAnywhere(c,varname)
342 p2 = g.findNodeAnywhere(c,varname)
343 else:
344 p2 = g.findNodeInChildren(c, r.p, varname)
276 if p2:
345 if p2:
277 return
346 return LeoNode(p2)
347
348 if r is not None:
349 p2 = r.p.insertAsLastChild()
350
351 else:
352 p2 = c.currentPosition().insertAfter()
278
353
279 rootpos = g.findNodeAnywhere(c,'@ipy-results')
280 if not rootpos:
281 rootpos = c.currentPosition()
282 p2 = rootpos.insertAsLastChild()
283 c.setHeadString(p2,varname)
354 c.setHeadString(p2,varname)
284 return p2
355 return LeoNode(p2)
285 finally:
356 finally:
286 c.endUpdate()
357 c.endUpdate()
287
358
@@ -302,8 +373,9 b' def push_ipython_script(node):'
302 script = node.script()
373 script = node.script()
303
374
304 script = g.splitLines(script + '\n')
375 script = g.splitLines(script + '\n')
305
376 ip.user_ns['_p'] = node
306 ip.runlines(script)
377 ip.runlines(script)
378 ip.user_ns.pop('_p',None)
307
379
308 has_output = False
380 has_output = False
309 for idx in range(hstart,len(ip.IP.input_hist)):
381 for idx in range(hstart,len(ip.IP.input_hist)):
@@ -322,8 +394,6 b' def push_ipython_script(node):'
322 finally:
394 finally:
323 c.endUpdate()
395 c.endUpdate()
324
396
325 # this should be the LAST one that will be executed, and it will never raise TryNext
326 expose_ileo_push(push_ipython_script, 1000)
327
397
328 def eval_body(body):
398 def eval_body(body):
329 try:
399 try:
@@ -345,12 +415,11 b' def push_plain_python(node):'
345 raise
415 raise
346 es('ipy plain: %s (%d LL)' % (node.h,lines))
416 es('ipy plain: %s (%d LL)' % (node.h,lines))
347
417
348 expose_ileo_push(push_plain_python, 100)
349
418
350 def push_cl_node(node):
419 def push_cl_node(node):
351 """ If node starts with @cl, eval it
420 """ If node starts with @cl, eval it
352
421
353 The result is put to root @ipy-results node
422 The result is put as last child of @ipy-results node, if it exists
354 """
423 """
355 if not node.b.startswith('@cl'):
424 if not node.b.startswith('@cl'):
356 raise TryNext
425 raise TryNext
@@ -362,24 +431,80 b' def push_cl_node(node):'
362 LeoNode(p2).v = val
431 LeoNode(p2).v = val
363 es(val)
432 es(val)
364
433
365 expose_ileo_push(push_cl_node,100)
434 def push_ev_node(node):
435 """ If headline starts with @ev, eval it and put result in body """
436 if not node.h.startswith('@ev '):
437 raise TryNext
438 expr = node.h.lstrip('@ev ')
439 es('ipy eval ' + expr)
440 res = ip.ev(expr)
441 node.v = res
442
366
443
367 def push_position_from_leo(p):
444 def push_position_from_leo(p):
368 push_from_leo(LeoNode(p))
445 push_from_leo(LeoNode(p))
369
446
370 ip.user_ns['leox'].push = push_position_from_leo
447 @generic
448 def edit_object_in_leo(obj, varname):
449 """ Make it @cl node so it can be pushed back directly by alt+I """
450 node = add_var(varname)
451 formatted = format_for_leo(obj)
452 if not formatted.startswith('@cl'):
453 formatted = '@cl\n' + formatted
454 node.b = formatted
455 node.go()
456
457 @edit_object_in_leo.when_type(IPython.macro.Macro)
458 def edit_macro(obj,varname):
459 bod = '_ip.defmacro("""\\\n' + obj.value + '""")'
460 node = add_var('Macro_' + varname)
461 node.b = bod
462 node.go()
463
464 def get_history(hstart = 0):
465 res = []
466 ohist = ip.IP.output_hist
467
468 for idx in range(hstart, len(ip.IP.input_hist)):
469 val = ohist.get(idx,None)
470 has_output = True
471 inp = ip.IP.input_hist_raw[idx]
472 if inp.strip():
473 res.append('In [%d]: %s' % (idx, inp))
474 if val:
475 res.append(pprint.pformat(val))
476 res.append('\n')
477 return ''.join(res)
371
478
372 def leo_f(self,s):
373 """ open file(s) in Leo
374
479
375 Takes an mglob pattern, e.g. '%leo *.cpp' or %leo 'rec:*.cpp'
480 def lee_f(self,s):
481 """ Open file(s)/objects in Leo
482
483 - %lee hist -> open full session history in leo
484 - Takes an object
485 - Takes an mglob pattern, e.g. '%lee *.cpp' or %leo 'rec:*.cpp'
376 """
486 """
377 import os
487 import os
378 from IPython.external import mglob
379
488
380 files = mglob.expand(s)
381 c.beginUpdate()
489 c.beginUpdate()
382 try:
490 try:
491 if s == 'hist':
492 wb.ipython_history.b = get_history()
493 wb.ipython_history.go()
494 return
495
496
497
498 # try editing the object directly
499 obj = ip.user_ns.get(s, None)
500 if obj is not None:
501 edit_object_in_leo(obj,s)
502 return
503
504 # if it's not object, it's a file name / mglob pattern
505 from IPython.external import mglob
506
507 files = (os.path.abspath(f) for f in mglob.expand(s))
383 for fname in files:
508 for fname in files:
384 p = g.findNodeAnywhere(c,'@auto ' + fname)
509 p = g.findNodeAnywhere(c,'@auto ' + fname)
385 if not p:
510 if not p:
@@ -389,16 +514,17 b' def leo_f(self,s):'
389 if os.path.isfile(fname):
514 if os.path.isfile(fname):
390 c.setBodyString(p,open(fname).read())
515 c.setBodyString(p,open(fname).read())
391 c.selectPosition(p)
516 c.selectPosition(p)
517 print "Editing file(s), press ctrl+shift+w in Leo to write @auto nodes"
392 finally:
518 finally:
393 c.endUpdate()
519 c.endUpdate()
394
520
395 ip.expose_magic('leo',leo_f)
521
396
522
397 def leoref_f(self,s):
523 def leoref_f(self,s):
398 """ Quick reference for ILeo """
524 """ Quick reference for ILeo """
399 import textwrap
525 import textwrap
400 print textwrap.dedent("""\
526 print textwrap.dedent("""\
401 %leo file - open file in leo
527 %leoe file/object - open file / object in leo
402 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
528 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
403 wb.foo.v = 12 - assign to body of node foo
529 wb.foo.v = 12 - assign to body of node foo
404 wb.foo.b - read or write the body of node foo
530 wb.foo.b - read or write the body of node foo
@@ -409,14 +535,15 b' def leoref_f(self,s):'
409
535
410 """
536 """
411 )
537 )
412 ip.expose_magic('leoref',leoref_f)
413
538
414 from ipy_leo import *
415
539
416 ip = IPython.ipapi.get()
417
540
418 def mb_f(self, arg):
541 def mb_f(self, arg):
419 """ Execute leo minibuffer commands """
542 """ Execute leo minibuffer commands
543
544 Example:
545 mb save-to-file
546 """
420 c.executeMinibufferCommand(arg)
547 c.executeMinibufferCommand(arg)
421
548
422 def mb_completer(self,event):
549 def mb_completer(self,event):
@@ -430,11 +557,6 b' def mb_completer(self,event):'
430 cmds.sort()
557 cmds.sort()
431 return cmds
558 return cmds
432
559
433 pass
434 ip.set_hook('complete_command', mb_completer, str_key = 'mb')
435 ip.expose_magic('mb',mb_f)
436
437
438 def show_welcome():
560 def show_welcome():
439 print "------------------"
561 print "------------------"
440 print "Welcome to Leo-enabled IPython session!"
562 print "Welcome to Leo-enabled IPython session!"
@@ -450,6 +572,4 b' def run_leo_startup_node():'
450 for n in LeoNode(p):
572 for n in LeoNode(p):
451 push_from_leo(n)
573 push_from_leo(n)
452
574
453 run_leo_startup_node()
454 show_welcome()
455
575
@@ -41,8 +41,9 b' Now launch a new IPython prompt and kill the process:'
41 (you don't need to specify PID for %kill if only one task is running)
41 (you don't need to specify PID for %kill if only one task is running)
42 """
42 """
43
43
44 from subprocess import Popen,PIPE
44 from subprocess import *
45 import os,shlex,sys,time
45 import os,shlex,sys,time
46 import threading,Queue
46
47
47 from IPython import genutils
48 from IPython import genutils
48
49
@@ -71,15 +72,70 b' def startjob(job):'
71 p.line = job
72 p.line = job
72 return p
73 return p
73
74
75 class AsyncJobQ(threading.Thread):
76 def __init__(self):
77 threading.Thread.__init__(self)
78 self.q = Queue.Queue()
79 self.output = []
80 self.stop = False
81 def run(self):
82 while 1:
83 cmd,cwd = self.q.get()
84 if self.stop:
85 self.output.append("** Discarding: '%s' - %s" % (cmd,cwd))
86 continue
87 self.output.append("** Task started: '%s' - %s" % (cmd,cwd))
88
89 p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd = cwd)
90 out = p.stdout.read()
91 self.output.append("** Task complete: '%s'\n" % cmd)
92 self.output.append(out)
93
94 def add(self,cmd):
95 self.q.put_nowait((cmd, os.getcwd()))
96
97 def dumpoutput(self):
98 while self.output:
99 item = self.output.pop(0)
100 print item
101
102 _jobq = None
103
104 def jobqueue_f(self, line):
105
106 global _jobq
107 if not _jobq:
108 print "Starting jobqueue - do '&some_long_lasting_system_command' to enqueue"
109 _jobq = AsyncJobQ()
110 _jobq.setDaemon(True)
111 _jobq.start()
112 ip.jobq = _jobq.add
113 return
114 if line.strip() == 'stop':
115 print "Stopping and clearing jobqueue, %jobqueue start to start again"
116 _jobq.stop = True
117 return
118 if line.strip() == 'start':
119 _jobq.stop = False
120 return
121
74 def jobctrl_prefilter_f(self,line):
122 def jobctrl_prefilter_f(self,line):
75 if line.startswith('&'):
123 if line.startswith('&'):
76 pre,fn,rest = self.split_user_input(line[1:])
124 pre,fn,rest = self.split_user_input(line[1:])
77
125
78 line = ip.IP.expand_aliases(fn,rest)
126 line = ip.IP.expand_aliases(fn,rest)
127 if not _jobq:
79 return '_ip.startjob(%s)' % genutils.make_quoted_expr(line)
128 return '_ip.startjob(%s)' % genutils.make_quoted_expr(line)
129 return '_ip.jobq(%s)' % genutils.make_quoted_expr(line)
80
130
81 raise IPython.ipapi.TryNext
131 raise IPython.ipapi.TryNext
82
132
133 def jobq_output_hook(self):
134 if not _jobq:
135 return
136 _jobq.dumpoutput()
137
138
83
139
84 def job_list(ip):
140 def job_list(ip):
85 keys = ip.db.keys('tasks/*')
141 keys = ip.db.keys('tasks/*')
@@ -91,8 +147,16 b' def magic_tasks(self,line):'
91
147
92 A 'task' is a process that has been started in IPython when 'jobctrl' extension is enabled.
148 A 'task' is a process that has been started in IPython when 'jobctrl' extension is enabled.
93 Tasks can be killed with %kill.
149 Tasks can be killed with %kill.
150
151 '%tasks clear' clears the task list (from stale tasks)
94 """
152 """
95 ip = self.getapi()
153 ip = self.getapi()
154 if line.strip() == 'clear':
155 for k in ip.db.keys('tasks/*'):
156 print "Clearing",ip.db[k]
157 del ip.db[k]
158 return
159
96 ents = job_list(ip)
160 ents = job_list(ip)
97 if not ents:
161 if not ents:
98 print "No tasks running"
162 print "No tasks running"
@@ -133,19 +197,32 b' else:'
133
197
134 def jobctrl_shellcmd(ip,cmd):
198 def jobctrl_shellcmd(ip,cmd):
135 """ os.system replacement that stores process info to db['tasks/t1234'] """
199 """ os.system replacement that stores process info to db['tasks/t1234'] """
200 cmd = cmd.strip()
136 cmdname = cmd.split(None,1)[0]
201 cmdname = cmd.split(None,1)[0]
137 if cmdname in shell_internal_commands:
202 if cmdname in shell_internal_commands:
138 use_shell = True
203 use_shell = True
139 else:
204 else:
140 use_shell = False
205 use_shell = False
141
206
207 jobentry = None
208 try:
209 try:
142 p = Popen(cmd,shell = use_shell)
210 p = Popen(cmd,shell = use_shell)
143 jobentry = 'tasks/t' + str(p.pid)
211 except WindowsError:
212 if use_shell:
213 # try with os.system
214 os.system(cmd)
215 return
216 else:
217 # have to go via shell, sucks
218 p = Popen(cmd,shell = True)
144
219
145 try:
220 jobentry = 'tasks/t' + str(p.pid)
146 ip.db[jobentry] = (p.pid,cmd,os.getcwd(),time.time())
221 ip.db[jobentry] = (p.pid,cmd,os.getcwd(),time.time())
147 p.communicate()
222 p.communicate()
223
148 finally:
224 finally:
225 if jobentry:
149 del ip.db[jobentry]
226 del ip.db[jobentry]
150
227
151
228
@@ -158,5 +235,6 b' def install():'
158 ip.set_hook('shell_hook', jobctrl_shellcmd)
235 ip.set_hook('shell_hook', jobctrl_shellcmd)
159 ip.expose_magic('kill',magic_kill)
236 ip.expose_magic('kill',magic_kill)
160 ip.expose_magic('tasks',magic_tasks)
237 ip.expose_magic('tasks',magic_tasks)
161
238 ip.expose_magic('jobqueue',jobqueue_f)
239 ip.set_hook('pre_prompt_hook', jobq_output_hook)
162 install()
240 install()
@@ -2670,6 +2670,7 b' Defaulting color scheme to \'NoColor\'"""'
2670 parameter_s = parameter_s.strip()
2670 parameter_s = parameter_s.strip()
2671 #bkms = self.shell.persist.get("bookmarks",{})
2671 #bkms = self.shell.persist.get("bookmarks",{})
2672
2672
2673 oldcwd = os.getcwd()
2673 numcd = re.match(r'(-)(\d+)$',parameter_s)
2674 numcd = re.match(r'(-)(\d+)$',parameter_s)
2674 # jump in directory history by number
2675 # jump in directory history by number
2675 if numcd:
2676 if numcd:
@@ -2719,6 +2720,7 b' Defaulting color scheme to \'NoColor\'"""'
2719 else:
2720 else:
2720 cwd = os.getcwd()
2721 cwd = os.getcwd()
2721 dhist = self.shell.user_ns['_dh']
2722 dhist = self.shell.user_ns['_dh']
2723 if oldcwd != cwd:
2722 dhist.append(cwd)
2724 dhist.append(cwd)
2723 self.db['dhist'] = compress_dhist(dhist)[-100:]
2725 self.db['dhist'] = compress_dhist(dhist)[-100:]
2724
2726
@@ -2728,6 +2730,8 b' Defaulting color scheme to \'NoColor\'"""'
2728 platutils.set_term_title("IPy ~")
2730 platutils.set_term_title("IPy ~")
2729 cwd = os.getcwd()
2731 cwd = os.getcwd()
2730 dhist = self.shell.user_ns['_dh']
2732 dhist = self.shell.user_ns['_dh']
2733
2734 if oldcwd != cwd:
2731 dhist.append(cwd)
2735 dhist.append(cwd)
2732 self.db['dhist'] = compress_dhist(dhist)[-100:]
2736 self.db['dhist'] = compress_dhist(dhist)[-100:]
2733 if not 'q' in opts and self.shell.user_ns['_dh']:
2737 if not 'q' in opts and self.shell.user_ns['_dh']:
@@ -56,7 +56,7 b' from pprint import PrettyPrinter'
56 __all__ = ['editor', 'fix_error_editor', 'result_display',
56 __all__ = ['editor', 'fix_error_editor', 'result_display',
57 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
57 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
58 'generate_prompt', 'generate_output_prompt','shell_hook',
58 'generate_prompt', 'generate_output_prompt','shell_hook',
59 'show_in_pager']
59 'show_in_pager','pre_prompt_hook']
60
60
61 pformat = PrettyPrinter().pformat
61 pformat = PrettyPrinter().pformat
62
62
@@ -227,8 +227,13 b' def show_in_pager(self,s):'
227 # raising TryNext here will use the default paging functionality
227 # raising TryNext here will use the default paging functionality
228 raise ipapi.TryNext
228 raise ipapi.TryNext
229
229
230 def pre_command_hook(self,cmd):
230 def pre_prompt_hook(self):
231 """" Executed before starting to execute a command """
231 """ Run before displaying the next prompt
232
233 Use this e.g. to display output from asynchronous operations (in order
234 to not mess up text entry)
235 """
236
232 return None
237 return None
233
238
234 def post_command_hook(self,cmd):
239 def post_command_hook(self,cmd):
@@ -6,7 +6,6 b' Requires Python 2.3 or newer.'
6
6
7 This file contains all the classes and helper functions specific to IPython.
7 This file contains all the classes and helper functions specific to IPython.
8
8
9 $Id: iplib.py 3005 2008-02-01 16:43:34Z vivainio $
10 """
9 """
11
10
12 #*****************************************************************************
11 #*****************************************************************************
@@ -377,7 +376,10 b' class InteractiveShell(object,Magic):'
377 # Get system encoding at startup time. Certain terminals (like Emacs
376 # Get system encoding at startup time. Certain terminals (like Emacs
378 # under Win32 have it set to None, and we need to have a known valid
377 # under Win32 have it set to None, and we need to have a known valid
379 # encoding to use in the raw_input() method
378 # encoding to use in the raw_input() method
379 try:
380 self.stdin_encoding = sys.stdin.encoding or 'ascii'
380 self.stdin_encoding = sys.stdin.encoding or 'ascii'
381 except AttributeError:
382 self.stdin_encoding = 'ascii'
381
383
382 # dict of things NOT to alias (keywords, builtins and some magics)
384 # dict of things NOT to alias (keywords, builtins and some magics)
383 no_alias = {}
385 no_alias = {}
@@ -1744,6 +1746,7 b' want to merge them back into the new files.""" % locals()'
1744 # exit_now is set by a call to %Exit or %Quit
1746 # exit_now is set by a call to %Exit or %Quit
1745
1747
1746 while not self.exit_now:
1748 while not self.exit_now:
1749 self.hooks.pre_prompt_hook()
1747 if more:
1750 if more:
1748 try:
1751 try:
1749 prompt = self.hooks.generate_prompt(True)
1752 prompt = self.hooks.generate_prompt(True)
General Comments 0
You need to be logged in to leave comments. Login now