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 |
|
|
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 |
|
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 |
|
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_ |
|
230 | def pre_prompt_hook(self): | |
231 |
""" |
|
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