blob: da827b8be16a149e19d86b08dac5b7ba1aadee30 [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001#! /usr/bin/env python
2
3# changes by dscherer@cmu.edu
4
5# the main() function has been replaced by a whole class, in order to
6# address the constraint that only one process can sit on the port
7# hard-coded into the loader.
8
9# It attempts to load the RPC protocol server and publish itself. If
10# that fails, it assumes that some other copy of IDLE is already running
11# on the port and attempts to contact it. It then uses the RPC mechanism
12# to ask that copy to do whatever it was instructed (via the command
13# line) to do. (Think netscape -remote). The handling of command line
14# arguments for remotes is still very incomplete.
15
16# default behavior (no command line options) is to NOT start the Python
17# Shell. If files are specified, they are opened, otherwise a single
18# blank editor window opens.
19
20# If any command line -options are specified, a shell does appear. This
21# is necessary to make the current semantics of the options make sense.
22
23import os
24import spawn
25import sys
26import string
27import getopt
28import re
29import protocol
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +000030import warnings
David Scherer7aced172000-08-15 01:13:23 +000031
32import linecache
33from code import InteractiveInterpreter
34
35from Tkinter import *
36import tkMessageBox
37
38from EditorWindow import EditorWindow, fixwordbreaks
39from FileList import FileList
40from ColorDelegator import ColorDelegator
41from UndoDelegator import UndoDelegator
42from OutputWindow import OutputWindow, OnDemandOutputWindow
43from IdleConf import idleconf
44import idlever
45
46# We need to patch linecache.checkcache, because we don't want it
47# to throw away our <pyshell#...> entries.
48# Rather than repeating its code here, we save those entries,
49# then call the original function, and then restore the saved entries.
50def linecache_checkcache(orig_checkcache=linecache.checkcache):
51 cache = linecache.cache
52 save = {}
53 for filename in cache.keys():
54 if filename[:1] + filename[-1:] == '<>':
55 save[filename] = cache[filename]
56 orig_checkcache()
57 cache.update(save)
58linecache.checkcache = linecache_checkcache
59
60
61# Note: <<newline-and-indent>> event is defined in AutoIndent.py
62
63#$ event <<plain-newline-and-indent>>
64#$ win <Control-j>
65#$ unix <Control-j>
66
67#$ event <<beginning-of-line>>
68#$ win <Control-a>
69#$ win <Home>
70#$ unix <Control-a>
71#$ unix <Home>
72
73#$ event <<history-next>>
74#$ win <Alt-n>
75#$ unix <Alt-n>
76
77#$ event <<history-previous>>
78#$ win <Alt-p>
79#$ unix <Alt-p>
80
81#$ event <<interrupt-execution>>
82#$ win <Control-c>
83#$ unix <Control-c>
84
85#$ event <<end-of-file>>
86#$ win <Control-d>
87#$ unix <Control-d>
88
89#$ event <<open-stack-viewer>>
90
91#$ event <<toggle-debugger>>
92
93
94class PyShellEditorWindow(EditorWindow):
95
96 # Regular text edit window when a shell is present
97 # XXX ought to merge with regular editor window
98
99 def __init__(self, *args):
100 apply(EditorWindow.__init__, (self,) + args)
101 self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
102 self.text.bind("<<open-python-shell>>", self.flist.open_shell)
103
104 rmenu_specs = [
105 ("Set breakpoint here", "<<set-breakpoint-here>>"),
106 ]
107
108 def set_breakpoint_here(self, event=None):
109 if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
110 self.text.bell()
111 return
112 self.flist.pyshell.interp.debugger.set_breakpoint_here(self)
113
114
115class PyShellFileList(FileList):
116
117 # File list when a shell is present
118
119 EditorWindow = PyShellEditorWindow
120
121 pyshell = None
122
123 def open_shell(self, event=None):
124 if self.pyshell:
125 self.pyshell.wakeup()
126 else:
127 self.pyshell = PyShell(self)
128 self.pyshell.begin()
129 return self.pyshell
130
131
132class ModifiedColorDelegator(ColorDelegator):
133
134 # Colorizer for the shell window itself
135
136 def recolorize_main(self):
137 self.tag_remove("TODO", "1.0", "iomark")
138 self.tag_add("SYNC", "1.0", "iomark")
139 ColorDelegator.recolorize_main(self)
140
141 tagdefs = ColorDelegator.tagdefs.copy()
142 cconf = idleconf.getsection('Colors')
143
144 tagdefs.update({
145 "stdin": cconf.getcolor("stdin"),
146 "stdout": cconf.getcolor("stdout"),
147 "stderr": cconf.getcolor("stderr"),
148 "console": cconf.getcolor("console"),
149 "ERROR": cconf.getcolor("ERROR"),
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000150 None: cconf.getcolor("normal"),
David Scherer7aced172000-08-15 01:13:23 +0000151 })
152
153
154class ModifiedUndoDelegator(UndoDelegator):
155
156 # Forbid insert/delete before the I/O mark
157
158 def insert(self, index, chars, tags=None):
159 try:
160 if self.delegate.compare(index, "<", "iomark"):
161 self.delegate.bell()
162 return
163 except TclError:
164 pass
165 UndoDelegator.insert(self, index, chars, tags)
166
167 def delete(self, index1, index2=None):
168 try:
169 if self.delegate.compare(index1, "<", "iomark"):
170 self.delegate.bell()
171 return
172 except TclError:
173 pass
174 UndoDelegator.delete(self, index1, index2)
175
176class ModifiedInterpreter(InteractiveInterpreter):
177
178 def __init__(self, tkconsole):
179 self.tkconsole = tkconsole
180 locals = sys.modules['__main__'].__dict__
181 InteractiveInterpreter.__init__(self, locals=locals)
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000182 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000183
184 gid = 0
185
186 def execsource(self, source):
187 # Like runsource() but assumes complete exec source
188 filename = self.stuffsource(source)
189 self.execfile(filename, source)
190
191 def execfile(self, filename, source=None):
192 # Execute an existing file
193 if source is None:
194 source = open(filename, "r").read()
195 try:
196 code = compile(source, filename, "exec")
197 except (OverflowError, SyntaxError):
198 self.tkconsole.resetoutput()
199 InteractiveInterpreter.showsyntaxerror(self, filename)
200 else:
201 self.runcode(code)
202
203 def runsource(self, source):
204 # Extend base class to stuff the source in the line cache first
205 filename = self.stuffsource(source)
206 self.more = 0
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000207 self.save_warnings_filters = warnings.filters[:]
208 warnings.filterwarnings(action="error", category=SyntaxWarning)
209 try:
210 return InteractiveInterpreter.runsource(self, source, filename)
211 finally:
212 if self.save_warnings_filters is not None:
213 warnings.filters[:] = self.save_warnings_filters
214 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000215
216 def stuffsource(self, source):
217 # Stuff source in the filename cache
218 filename = "<pyshell#%d>" % self.gid
219 self.gid = self.gid + 1
220 lines = string.split(source, "\n")
221 linecache.cache[filename] = len(source)+1, 0, lines, filename
222 return filename
223
224 def showsyntaxerror(self, filename=None):
225 # Extend base class to color the offending position
226 # (instead of printing it and pointing at it with a caret)
227 text = self.tkconsole.text
228 stuff = self.unpackerror()
229 if not stuff:
230 self.tkconsole.resetoutput()
231 InteractiveInterpreter.showsyntaxerror(self, filename)
232 return
233 msg, lineno, offset, line = stuff
234 if lineno == 1:
235 pos = "iomark + %d chars" % (offset-1)
236 else:
237 pos = "iomark linestart + %d lines + %d chars" % (lineno-1,
238 offset-1)
239 text.tag_add("ERROR", pos)
240 text.see(pos)
241 char = text.get(pos)
242 if char and char in string.letters + string.digits + "_":
243 text.tag_add("ERROR", pos + " wordstart", pos)
244 self.tkconsole.resetoutput()
245 self.write("SyntaxError: %s\n" % str(msg))
246
247 def unpackerror(self):
248 type, value, tb = sys.exc_info()
249 ok = type is SyntaxError
250 if ok:
251 try:
252 msg, (dummy_filename, lineno, offset, line) = value
253 except:
254 ok = 0
255 if ok:
256 return msg, lineno, offset, line
257 else:
258 return None
259
260 def showtraceback(self):
261 # Extend base class method to reset output properly
262 text = self.tkconsole.text
263 self.tkconsole.resetoutput()
264 self.checklinecache()
265 InteractiveInterpreter.showtraceback(self)
266
267 def checklinecache(self):
268 c = linecache.cache
269 for key in c.keys():
270 if key[:1] + key[-1:] != "<>":
271 del c[key]
272
273 debugger = None
274
275 def setdebugger(self, debugger):
276 self.debugger = debugger
277
278 def getdebugger(self):
279 return self.debugger
280
281 def runcode(self, code):
282 # Override base class method
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000283 if self.save_warnings_filters is not None:
284 warnings.filters[:] = self.save_warnings_filters
285 self.save_warnings_filters = None
David Scherer7aced172000-08-15 01:13:23 +0000286 debugger = self.debugger
287 try:
288 self.tkconsole.beginexecuting()
289 try:
290 if debugger:
291 debugger.run(code, self.locals)
292 else:
293 exec code in self.locals
294 except SystemExit:
295 if tkMessageBox.askyesno(
296 "Exit?",
297 "Do you want to exit altogether?",
298 default="yes",
299 master=self.tkconsole.text):
300 raise
301 else:
302 self.showtraceback()
303 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
304 self.tkconsole.open_stack_viewer()
305 except:
306 self.showtraceback()
307 if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
308 self.tkconsole.open_stack_viewer()
309
310 finally:
311 self.tkconsole.endexecuting()
312
313 def write(self, s):
314 # Override base class write
315 self.tkconsole.console.write(s)
316
317
318class PyShell(OutputWindow):
319
320 shell_title = "Python Shell"
321
322 # Override classes
323 ColorDelegator = ModifiedColorDelegator
324 UndoDelegator = ModifiedUndoDelegator
325
326 # Override menu bar specs
327 menu_specs = PyShellEditorWindow.menu_specs[:]
328 menu_specs.insert(len(menu_specs)-2, ("debug", "_Debug"))
329
330 # New classes
331 from IdleHistory import History
332
333 def __init__(self, flist=None):
334 self.interp = ModifiedInterpreter(self)
335 if flist is None:
336 root = Tk()
337 fixwordbreaks(root)
338 root.withdraw()
339 flist = PyShellFileList(root)
340
341 OutputWindow.__init__(self, flist, None, None)
342
343 import __builtin__
344 __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
345
346 self.auto = self.extensions["AutoIndent"] # Required extension
347 self.auto.config(usetabs=1, indentwidth=8, context_use_ps1=1)
348
349 text = self.text
350 text.configure(wrap="char")
351 text.bind("<<newline-and-indent>>", self.enter_callback)
352 text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
353 text.bind("<<interrupt-execution>>", self.cancel_callback)
354 text.bind("<<beginning-of-line>>", self.home_callback)
355 text.bind("<<end-of-file>>", self.eof_callback)
356 text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
357 text.bind("<<toggle-debugger>>", self.toggle_debugger)
358 text.bind("<<open-python-shell>>", self.flist.open_shell)
359 text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
360
361 self.save_stdout = sys.stdout
362 self.save_stderr = sys.stderr
363 self.save_stdin = sys.stdin
364 sys.stdout = PseudoFile(self, "stdout")
365 sys.stderr = PseudoFile(self, "stderr")
366 sys.stdin = self
367 self.console = PseudoFile(self, "console")
368
369 self.history = self.History(self.text)
370
371 reading = 0
372 executing = 0
373 canceled = 0
374 endoffile = 0
375
376 def toggle_debugger(self, event=None):
377 if self.executing:
378 tkMessageBox.showerror("Don't debug now",
379 "You can only toggle the debugger when idle",
380 master=self.text)
381 self.set_debugger_indicator()
382 return "break"
383 else:
384 db = self.interp.getdebugger()
385 if db:
386 self.close_debugger()
387 else:
388 self.open_debugger()
389
390 def set_debugger_indicator(self):
391 db = self.interp.getdebugger()
392 self.setvar("<<toggle-debugger>>", not not db)
393
394 def toggle_jit_stack_viewer( self, event=None):
395 pass # All we need is the variable
396
397 def close_debugger(self):
398 db = self.interp.getdebugger()
399 if db:
400 self.interp.setdebugger(None)
401 db.close()
402 self.resetoutput()
403 self.console.write("[DEBUG OFF]\n")
404 sys.ps1 = ">>> "
405 self.showprompt()
406 self.set_debugger_indicator()
407
408 def open_debugger(self):
409 import Debugger
410 self.interp.setdebugger(Debugger.Debugger(self))
411 sys.ps1 = "[DEBUG ON]\n>>> "
412 self.showprompt()
413 self.set_debugger_indicator()
414
415 def beginexecuting(self):
416 # Helper for ModifiedInterpreter
417 self.resetoutput()
418 self.executing = 1
419 ##self._cancel_check = self.cancel_check
420 ##sys.settrace(self._cancel_check)
421
422 def endexecuting(self):
423 # Helper for ModifiedInterpreter
424 ##sys.settrace(None)
425 ##self._cancel_check = None
426 self.executing = 0
427 self.canceled = 0
428
429 def close(self):
430 # Extend base class method
431 if self.executing:
432 # XXX Need to ask a question here
433 if not tkMessageBox.askokcancel(
434 "Kill?",
435 "The program is still running; do you want to kill it?",
436 default="ok",
437 master=self.text):
438 return "cancel"
439 self.canceled = 1
440 if self.reading:
441 self.top.quit()
442 return "cancel"
443 return PyShellEditorWindow.close(self)
444
445 def _close(self):
446 self.close_debugger()
447 # Restore std streams
448 sys.stdout = self.save_stdout
449 sys.stderr = self.save_stderr
450 sys.stdin = self.save_stdin
451 # Break cycles
452 self.interp = None
453 self.console = None
454 self.auto = None
455 self.flist.pyshell = None
456 self.history = None
457 OutputWindow._close(self) # Really EditorWindow._close
458
459 def ispythonsource(self, filename):
460 # Override this so EditorWindow never removes the colorizer
461 return 1
462
463 def short_title(self):
464 return self.shell_title
465
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000466 COPYRIGHT = \
467 'Type "copyright", "credits" or "license" for more information.'
468
David Scherer7aced172000-08-15 01:13:23 +0000469 def begin(self):
470 self.resetoutput()
471 self.write("Python %s on %s\n%s\nIDLE %s -- press F1 for help\n" %
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000472 (sys.version, sys.platform, self.COPYRIGHT,
David Scherer7aced172000-08-15 01:13:23 +0000473 idlever.IDLE_VERSION))
474 try:
475 sys.ps1
476 except AttributeError:
477 sys.ps1 = ">>> "
478 self.showprompt()
479 import Tkinter
480 Tkinter._default_root = None
481
482 def interact(self):
483 self.begin()
484 self.top.mainloop()
485
486 def readline(self):
487 save = self.reading
488 try:
489 self.reading = 1
490 self.top.mainloop()
491 finally:
492 self.reading = save
493 line = self.text.get("iomark", "end-1c")
494 self.resetoutput()
495 if self.canceled:
496 self.canceled = 0
497 raise KeyboardInterrupt
498 if self.endoffile:
499 self.endoffile = 0
500 return ""
501 return line
502
503 def isatty(self):
504 return 1
505
506 def cancel_callback(self, event):
507 try:
508 if self.text.compare("sel.first", "!=", "sel.last"):
509 return # Active selection -- always use default binding
510 except:
511 pass
512 if not (self.executing or self.reading):
513 self.resetoutput()
514 self.write("KeyboardInterrupt\n")
515 self.showprompt()
516 return "break"
517 self.endoffile = 0
518 self.canceled = 1
519 if self.reading:
520 self.top.quit()
521 return "break"
522
523 def eof_callback(self, event):
524 if self.executing and not self.reading:
525 return # Let the default binding (delete next char) take over
526 if not (self.text.compare("iomark", "==", "insert") and
527 self.text.compare("insert", "==", "end-1c")):
528 return # Let the default binding (delete next char) take over
529 if not self.executing:
530## if not tkMessageBox.askokcancel(
531## "Exit?",
532## "Are you sure you want to exit?",
533## default="ok", master=self.text):
534## return "break"
535 self.resetoutput()
536 self.close()
537 else:
538 self.canceled = 0
539 self.endoffile = 1
540 self.top.quit()
541 return "break"
542
543 def home_callback(self, event):
544 if event.state != 0 and event.keysym == "Home":
545 return # <Modifier-Home>; fall back to class binding
546 if self.text.compare("iomark", "<=", "insert") and \
547 self.text.compare("insert linestart", "<=", "iomark"):
548 self.text.mark_set("insert", "iomark")
549 self.text.tag_remove("sel", "1.0", "end")
550 self.text.see("insert")
551 return "break"
552
553 def linefeed_callback(self, event):
554 # Insert a linefeed without entering anything (still autoindented)
555 if self.reading:
556 self.text.insert("insert", "\n")
557 self.text.see("insert")
558 else:
559 self.auto.auto_indent(event)
560 return "break"
561
562 def enter_callback(self, event):
563 if self.executing and not self.reading:
564 return # Let the default binding (insert '\n') take over
565 # If some text is selected, recall the selection
566 # (but only if this before the I/O mark)
567 try:
568 sel = self.text.get("sel.first", "sel.last")
569 if sel:
570 if self.text.compare("sel.last", "<=", "iomark"):
571 self.recall(sel)
572 return "break"
573 except:
574 pass
575 # If we're strictly before the line containing iomark, recall
576 # the current line, less a leading prompt, less leading or
577 # trailing whitespace
578 if self.text.compare("insert", "<", "iomark linestart"):
579 # Check if there's a relevant stdin range -- if so, use it
580 prev = self.text.tag_prevrange("stdin", "insert")
581 if prev and self.text.compare("insert", "<", prev[1]):
582 self.recall(self.text.get(prev[0], prev[1]))
583 return "break"
584 next = self.text.tag_nextrange("stdin", "insert")
585 if next and self.text.compare("insert lineend", ">=", next[0]):
586 self.recall(self.text.get(next[0], next[1]))
587 return "break"
588 # No stdin mark -- just get the current line
589 self.recall(self.text.get("insert linestart", "insert lineend"))
590 return "break"
591 # If we're in the current input and there's only whitespace
592 # beyond the cursor, erase that whitespace first
593 s = self.text.get("insert", "end-1c")
594 if s and not string.strip(s):
595 self.text.delete("insert", "end-1c")
596 # If we're in the current input before its last line,
597 # insert a newline right at the insert point
598 if self.text.compare("insert", "<", "end-1c linestart"):
599 self.auto.auto_indent(event)
600 return "break"
601 # We're in the last line; append a newline and submit it
602 self.text.mark_set("insert", "end-1c")
603 if self.reading:
604 self.text.insert("insert", "\n")
605 self.text.see("insert")
606 else:
607 self.auto.auto_indent(event)
608 self.text.tag_add("stdin", "iomark", "end-1c")
609 self.text.update_idletasks()
610 if self.reading:
611 self.top.quit() # Break out of recursive mainloop() in raw_input()
612 else:
613 self.runit()
614 return "break"
615
616 def recall(self, s):
617 if self.history:
618 self.history.recall(s)
619
620 def runit(self):
621 line = self.text.get("iomark", "end-1c")
622 # Strip off last newline and surrounding whitespace.
623 # (To allow you to hit return twice to end a statement.)
624 i = len(line)
625 while i > 0 and line[i-1] in " \t":
626 i = i-1
627 if i > 0 and line[i-1] == "\n":
628 i = i-1
629 while i > 0 and line[i-1] in " \t":
630 i = i-1
631 line = line[:i]
632 more = self.interp.runsource(line)
633 if not more:
634 self.showprompt()
635
636 def cancel_check(self, frame, what, args,
637 dooneevent=tkinter.dooneevent,
638 dontwait=tkinter.DONT_WAIT):
639 # Hack -- use the debugger hooks to be able to handle events
640 # and interrupt execution at any time.
641 # This slows execution down quite a bit, so you may want to
642 # disable this (by not calling settrace() in runcode() above)
643 # for full-bore (uninterruptable) speed.
644 # XXX This should become a user option.
645 if self.canceled:
646 return
647 dooneevent(dontwait)
648 if self.canceled:
649 self.canceled = 0
650 raise KeyboardInterrupt
651 return self._cancel_check
652
653 def open_stack_viewer(self, event=None):
654 try:
655 sys.last_traceback
656 except:
657 tkMessageBox.showerror("No stack trace",
658 "There is no stack trace yet.\n"
659 "(sys.last_traceback is not defined)",
660 master=self.text)
661 return
662 from StackViewer import StackBrowser
663 sv = StackBrowser(self.root, self.flist)
664
665 def showprompt(self):
666 self.resetoutput()
667 try:
668 s = str(sys.ps1)
669 except:
670 s = ""
671 self.console.write(s)
672 self.text.mark_set("insert", "end-1c")
673
674 def resetoutput(self):
675 source = self.text.get("iomark", "end-1c")
676 if self.history:
677 self.history.history_store(source)
678 if self.text.get("end-2c") != "\n":
679 self.text.insert("end-1c", "\n")
680 self.text.mark_set("iomark", "end-1c")
681 sys.stdout.softspace = 0
682
683 def write(self, s, tags=()):
684 self.text.mark_gravity("iomark", "right")
685 OutputWindow.write(self, s, tags, "iomark")
686 self.text.mark_gravity("iomark", "left")
687 if self.canceled:
688 self.canceled = 0
689 raise KeyboardInterrupt
690
691class PseudoFile:
692
693 def __init__(self, shell, tags):
694 self.shell = shell
695 self.tags = tags
696
697 def write(self, s):
698 self.shell.write(s, self.tags)
699
700 def writelines(self, l):
701 map(self.write, l)
702
703 def flush(self):
704 pass
705
706 def isatty(self):
707 return 1
708
709usage_msg = """\
710usage: idle.py [-c command] [-d] [-e] [-s] [-t title] [arg] ...
711
712-c command run this command
713-d enable debugger
714-e edit mode; arguments are files to be edited
715-s run $IDLESTARTUP or $PYTHONSTARTUP before anything else
716-t title set title of shell window
717
718When neither -c nor -e is used, and there are arguments, and the first
719argument is not '-', the first argument is run as a script. Remaining
720arguments are arguments to the script or to the command run by -c.
721"""
722
723class usageError:
724 def __init__(self, string): self.string = string
725 def __repr__(self): return self.string
726
727class main:
728 def __init__(self):
729 try:
730 self.server = protocol.Server(connection_hook = self.address_ok)
731 protocol.publish( 'IDLE', self.connect )
732 self.main( sys.argv[1:] )
733 return
734 except protocol.connectionLost:
735 try:
736 client = protocol.Client()
737 IDLE = client.getobject('IDLE')
738 if IDLE:
739 try:
740 IDLE.remote( sys.argv[1:] )
741 except usageError, msg:
742 sys.stderr.write("Error: %s\n" % str(msg))
743 sys.stderr.write(usage_msg)
744 return
745 except protocol.connectionLost:
746 pass
747
748 # xxx Should scream via Tk()
749 print "Something already has our socket, but it won't open a window for me!"
750 print "Unable to proceed."
751
752 def idle(self):
753 spawn.kill_zombies()
754 self.server.rpc_loop()
755 root.after(25, self.idle)
756
757 # We permit connections from localhost only
758 def address_ok(self, addr):
759 return addr[0] == '127.0.0.1'
760
761 def connect(self, client, addr):
762 return self
763
764 def remote( self, argv ):
765 # xxx Should make this behavior match the behavior in main, or redo
766 # command line options entirely.
767
768 try:
769 opts, args = getopt.getopt(argv, "c:deist:")
770 except getopt.error, msg:
771 raise usageError(msg)
772
773 for filename in args:
774 flist.open(filename)
775 if not args:
776 flist.new()
777
778 def main( self, argv ):
779 cmd = None
780 edit = 0
781 noshell = 1
782
783 debug = 0
784 startup = 0
785
786 try:
787 opts, args = getopt.getopt(argv, "c:deist:")
788 except getopt.error, msg:
789 sys.stderr.write("Error: %s\n" % str(msg))
790 sys.stderr.write(usage_msg)
791 sys.exit(2)
792
793 for o, a in opts:
794 noshell = 0
795 if o == '-c':
796 cmd = a
797 if o == '-d':
798 debug = 1
799 if o == '-e':
800 edit = 1
801 if o == '-s':
802 startup = 1
803 if o == '-t':
804 PyShell.shell_title = a
805
806 if noshell: edit=1
807
David Scherer7aced172000-08-15 01:13:23 +0000808 for i in range(len(sys.path)):
809 sys.path[i] = os.path.abspath(sys.path[i])
810
811 pathx = []
812 if edit:
813 for filename in args:
814 pathx.append(os.path.dirname(filename))
815 elif args and args[0] != "-":
816 pathx.append(os.path.dirname(args[0]))
817 else:
818 pathx.append(os.curdir)
819 for dir in pathx:
820 dir = os.path.abspath(dir)
821 if not dir in sys.path:
822 sys.path.insert(0, dir)
823
824 global flist, root
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000825 root = Tk(className="Idle")
David Scherer7aced172000-08-15 01:13:23 +0000826 fixwordbreaks(root)
827 root.withdraw()
828 flist = PyShellFileList(root)
829
830 if edit:
831 for filename in args:
832 flist.open(filename)
833 if not args:
834 flist.new()
Kurt B. Kaiser94bd7742001-07-14 00:13:28 +0000835 else:
836 if cmd:
837 sys.argv = ["-c"] + args
838 else:
839 sys.argv = args or [""]
840
David Scherer7aced172000-08-15 01:13:23 +0000841 #dbg=OnDemandOutputWindow(flist)
842 #dbg.set_title('Internal IDLE Problem')
843 #sys.stdout = PseudoFile(dbg,['stdout'])
844 #sys.stderr = PseudoFile(dbg,['stderr'])
845
846 if noshell:
847 flist.pyshell = None
848 else:
849 shell = PyShell(flist)
850 interp = shell.interp
851 flist.pyshell = shell
852
853 if startup:
854 filename = os.environ.get("IDLESTARTUP") or \
855 os.environ.get("PYTHONSTARTUP")
856 if filename and os.path.isfile(filename):
857 interp.execfile(filename)
858
859 if debug:
860 shell.open_debugger()
861 if cmd:
862 interp.execsource(cmd)
863 elif not edit and args and args[0] != "-":
864 interp.execfile(args[0])
865
866 shell.begin()
867
868 self.idle()
869 root.mainloop()
870 root.destroy()
871
872
873if __name__ == "__main__":
874 main()