diff options
author | Georg Brandl <georg@python.org> | 2010-11-26 08:59:40 (GMT) |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2010-11-26 08:59:40 (GMT) |
commit | f55aa80b372268902d27ad8ae3a45e465c6b9b19 (patch) | |
tree | c8dd7533c37a9d1e49350aadf5aa32c6672102bb /Demo/tkinter/guido/manpage.py | |
parent | d62ecbf0bae673af61fb87d8932cdb1ea80e8922 (diff) | |
download | cpython-f55aa80b372268902d27ad8ae3a45e465c6b9b19.zip cpython-f55aa80b372268902d27ad8ae3a45e465c6b9b19.tar.gz cpython-f55aa80b372268902d27ad8ae3a45e465c6b9b19.tar.bz2 |
Merged revisions 85820,85823,85825,85840,85843-85845,85849-85851,85855,85867,85875,85907-85908,85911,85914 via svnmerge from
svn+ssh://svn.python.org/python/branches/py3k
........
r85820 | georg.brandl | 2010-10-24 16:20:22 +0200 (So, 24 Okt 2010) | 1 line
Remove usage of exception indexing.
........
r85823 | georg.brandl | 2010-10-24 16:32:45 +0200 (So, 24 Okt 2010) | 1 line
Fix style.
........
r85825 | georg.brandl | 2010-10-24 17:16:02 +0200 (So, 24 Okt 2010) | 1 line
Add documentation about the default warnings filters.
........
r85840 | georg.brandl | 2010-10-25 19:50:20 +0200 (Mo, 25 Okt 2010) | 1 line
#3018: tkinter demo fixes for py3k.
........
r85843 | georg.brandl | 2010-10-26 08:59:23 +0200 (Di, 26 Okt 2010) | 1 line
Markup fix.
........
r85844 | georg.brandl | 2010-10-26 12:39:14 +0200 (Di, 26 Okt 2010) | 1 line
Work a bit more on tkinter demos.
........
r85845 | georg.brandl | 2010-10-26 12:42:16 +0200 (Di, 26 Okt 2010) | 1 line
faqwiz is removed.
........
r85849 | georg.brandl | 2010-10-26 21:31:06 +0200 (Di, 26 Okt 2010) | 1 line
#10200: typo.
........
r85850 | georg.brandl | 2010-10-26 21:58:11 +0200 (Di, 26 Okt 2010) | 1 line
#10200: typo.
........
r85851 | georg.brandl | 2010-10-26 22:12:37 +0200 (Di, 26 Okt 2010) | 1 line
Fix import.
........
r85855 | georg.brandl | 2010-10-27 09:21:54 +0200 (Mi, 27 Okt 2010) | 1 line
Encoding fix.
........
r85867 | georg.brandl | 2010-10-27 22:01:51 +0200 (Mi, 27 Okt 2010) | 1 line
Add David.
........
r85875 | georg.brandl | 2010-10-28 10:38:30 +0200 (Do, 28 Okt 2010) | 1 line
Fix bytes/str issues in get-remote-certificate.py.
........
r85907 | georg.brandl | 2010-10-29 06:54:13 +0200 (Fr, 29 Okt 2010) | 1 line
#10222: fix for overzealous AIX compiler.
........
r85908 | georg.brandl | 2010-10-29 07:22:17 +0200 (Fr, 29 Okt 2010) | 1 line
send_bytes obviously needs bytes...
........
r85911 | georg.brandl | 2010-10-29 07:36:28 +0200 (Fr, 29 Okt 2010) | 1 line
Fix markup error and update false positive entries from "make suspicious".
........
r85914 | georg.brandl | 2010-10-29 08:17:38 +0200 (Fr, 29 Okt 2010) | 1 line
(?:...) is a non-capturing, but still grouping construct.
........
Diffstat (limited to 'Demo/tkinter/guido/manpage.py')
-rw-r--r-- | Demo/tkinter/guido/manpage.py | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/Demo/tkinter/guido/manpage.py b/Demo/tkinter/guido/manpage.py new file mode 100644 index 0000000..750c675 --- /dev/null +++ b/Demo/tkinter/guido/manpage.py @@ -0,0 +1,215 @@ +# Widget to display a man page + +import os +import re +import sys + +from tkinter import * +from tkinter.font import Font +from tkinter.scrolledtext import ScrolledText + +# XXX Recognizing footers is system dependent +# (This one works for IRIX 5.2 and Solaris 2.2) +footerprog = re.compile( + '^ Page [1-9][0-9]*[ \t]+\|^.*Last change:.*[1-9][0-9]*\n') +emptyprog = re.compile('^[ \t]*\n') +ulprog = re.compile('^[ \t]*[Xv!_][Xv!_ \t]*\n') + + +class EditableManPage(ScrolledText): + """Basic Man Page class -- does not disable editing.""" + + def __init__(self, master=None, **cnf): + ScrolledText.__init__(self, master, **cnf) + + bold = Font(font=self['font']).copy() + bold.config(weight='bold') + italic = Font(font=self['font']).copy() + italic.config(slant='italic') + + # Define tags for formatting styles + self.tag_config('X', underline=1) + self.tag_config('!', font=bold) + self.tag_config('_', font=italic) + + # Set state to idle + self.fp = None + self.lineno = 0 + + def busy(self): + """Test whether we are busy parsing a file.""" + return self.fp != None + + def kill(self): + """Ensure we're not busy.""" + if self.busy(): + self._endparser() + + def asyncparsefile(self, fp): + """Parse a file, in the background.""" + self._startparser(fp) + self.tk.createfilehandler(fp, READABLE, + self._filehandler) + + parsefile = asyncparsefile # Alias + + def _filehandler(self, fp, mask): + """I/O handler used by background parsing.""" + nextline = self.fp.readline() + if not nextline: + self._endparser() + return + self._parseline(nextline) + + def syncparsefile(self, fp): + """Parse a file, now (cannot be aborted).""" + self._startparser(fp) + while True: + nextline = fp.readline() + if not nextline: + break + self._parseline(nextline) + self._endparser() + + def _startparser(self, fp): + """Initialize parsing from a particular file -- must not be busy.""" + if self.busy(): + raise RuntimeError('startparser: still busy') + fp.fileno() # Test for file-ness + self.fp = fp + self.lineno = 0 + self.ok = 0 + self.empty = 0 + self.buffer = None + savestate = self['state'] + self['state'] = NORMAL + self.delete('1.0', END) + self['state'] = savestate + + def _endparser(self): + """End parsing -- must be busy, need not be at EOF.""" + if not self.busy(): + raise RuntimeError('endparser: not busy') + if self.buffer: + self._parseline('') + try: + self.tk.deletefilehandler(self.fp) + except TclError: + pass + self.fp.close() + self.fp = None + del self.ok, self.empty, self.buffer + + def _parseline(self, nextline): + """Parse a single line.""" + if not self.buffer: + # Save this line -- we need one line read-ahead + self.buffer = nextline + return + if emptyprog.match(self.buffer): + # Buffered line was empty -- set a flag + self.empty = 1 + self.buffer = nextline + return + textline = self.buffer + if ulprog.match(nextline): + # Next line is properties for buffered line + propline = nextline + self.buffer = None + else: + # Next line is read-ahead + propline = None + self.buffer = nextline + if not self.ok: + # First non blank line after footer must be header + # -- skip that too + self.ok = 1 + self.empty = 0 + return + if footerprog.match(textline): + # Footer -- start skipping until next non-blank line + self.ok = 0 + self.empty = 0 + return + savestate = self['state'] + self['state'] = NORMAL + if TkVersion >= 4.0: + self.mark_set('insert', 'end-1c') + else: + self.mark_set('insert', END) + if self.empty: + # One or more previous lines were empty + # -- insert one blank line in the text + self._insert_prop('\n') + self.lineno = self.lineno + 1 + self.empty = 0 + if not propline: + # No properties + self._insert_prop(textline) + else: + # Search for properties + p = '' + j = 0 + for i in range(min(len(propline), len(textline))): + if propline[i] != p: + if j < i: + self._insert_prop(textline[j:i], p) + j = i + p = propline[i] + self._insert_prop(textline[j:]) + self.lineno = self.lineno + 1 + self['state'] = savestate + + def _insert_prop(self, str, prop = ' '): + """Insert a string at the end, with at most one property (tag).""" + here = self.index(AtInsert()) + self.insert(AtInsert(), str) + if TkVersion <= 4.0: + tags = self.tag_names(here) + for tag in tags: + self.tag_remove(tag, here, AtInsert()) + if prop != ' ': + self.tag_add(prop, here, AtInsert()) + + +class ReadonlyManPage(EditableManPage): + """Readonly Man Page class -- disables editing, otherwise the same.""" + + def __init__(self, master=None, **cnf): + cnf['state'] = DISABLED + EditableManPage.__init__(self, master, **cnf) + +# Alias +ManPage = ReadonlyManPage + +# usage: ManPage [manpage]; or ManPage [-f] file +# -f means that the file is nroff -man output run through ul -i +def main(): + # XXX This directory may be different on your system + MANDIR = '' + DEFAULTPAGE = 'Tcl' + formatted = 0 + if sys.argv[1:] and sys.argv[1] == '-f': + formatted = 1 + del sys.argv[1] + if sys.argv[1:]: + name = sys.argv[1] + else: + name = DEFAULTPAGE + if not formatted: + if name[-2:-1] != '.': + name = name + '.n' + name = os.path.join(MANDIR, name) + root = Tk() + root.minsize(1, 1) + manpage = ManPage(root, relief=SUNKEN, borderwidth=2) + manpage.pack(expand=1, fill=BOTH) + if formatted: + fp = open(name, 'r') + else: + fp = os.popen('nroff -man -c %s | ul -i' % name, 'r') + manpage.parsefile(fp) + root.mainloop() + +if __name__ == '__main__': + main() |