]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Initial revision
authorGuido van Rossum <guido@python.org>
Wed, 6 Jul 1994 21:17:21 +0000 (21:17 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 6 Jul 1994 21:17:21 +0000 (21:17 +0000)
Demo/tkinter/guido/ManPage.py [new file with mode: 0755]
Demo/tkinter/guido/tkman.py [new file with mode: 0755]

diff --git a/Demo/tkinter/guido/ManPage.py b/Demo/tkinter/guido/ManPage.py
new file mode 100755 (executable)
index 0000000..993a3db
--- /dev/null
@@ -0,0 +1,149 @@
+# Widget to display a man page
+
+import regex
+from Tkinter import *
+from ScrolledText import ScrolledText
+
+# XXX These fonts may have to be changed to match your system
+BOLDFONT = '*-Courier-Bold-R-Normal-*-120-*'
+ITALICFONT = '*-Courier-Medium-O-Normal-*-120-*'
+
+# XXX Recognizing footers is system dependent
+# (This one works for IRIX 5.2 and Solaris 2.2)
+footerprog = regex.compile(
+       '^     Page [1-9][0-9]*[ \t]+\|^.*Last change:.*[1-9][0-9]*\n')
+emptyprog = regex.compile('^[ \t]*\n')
+ulprog = regex.compile('^[ \t]*[Xv!_][Xv!_ \t]*\n')
+
+# Basic Man Page class -- does not disable editing
+class EditableManPage(ScrolledText):
+
+       def __init__(self, master=None, cnf={}):
+               # Initialize base class
+               ScrolledText.__init__(self, master, cnf)
+
+               # Define tags for formatting styles
+               self.text.tag_config('bold', {'font': BOLDFONT})
+               self.text.tag_config('italic', {'font': ITALICFONT})
+               self.text.tag_config('underline', {'underline': 1})
+
+               # Create mapping from characters to tags
+               self.tagmap = {
+                       'X': 'bold',
+                       '_': 'underline',
+                       '!': 'italic',
+                       }
+
+       # Parse nroff output piped through ul -i and append it to the
+       # text widget
+       def parsefile(self, fp):
+               save_cursor = self.text['cursor']
+               self.text['cursor'] = 'watch'
+               self.text.update()
+               ok = 0
+               empty = 0
+               nextline = None
+               while 1:
+                       if nextline:
+                               line = nextline
+                               nextline = None
+                       else:
+                               line = fp.readline()
+                               if not line:
+                                       break
+                       if emptyprog.match(line) >= 0:
+                               empty = 1
+                               continue
+                       nextline = fp.readline()
+                       if nextline and ulprog.match(nextline) >= 0:
+                               propline = nextline
+                               nextline = None
+                       else:
+                               propline = ''
+                       if not ok:
+                               ok = 1
+                               empty = 0
+                               continue
+                       if footerprog.match(line) >= 0:
+                               ok = 0
+                               empty = 0
+                               continue
+                       if empty:
+                               self.insert_prop('\n')
+                               empty = 0
+                       p = ''
+                       j = 0
+                       for i in range(min(len(propline), len(line))):
+                               if propline[i] != p:
+                                       if j < i:
+                                               self.insert_prop(line[j:i], p)
+                                               j = i
+                                       p = propline[i]
+                       self.insert_prop(line[j:])
+               self.text['cursor'] = save_cursor
+
+       def insert_prop(self, str, prop = ' '):
+               here = self.text.index(AtInsert())
+               self.text.insert(AtInsert(), str)
+               for tag in self.tagmap.values():
+                       self.text.tag_remove(tag, here, AtInsert())
+               if self.tagmap.has_key(prop):
+                       self.text.tag_add(self.tagmap[prop], here, AtInsert())
+
+# Readonly Man Page class -- disables editing, otherwise the same
+class ReadonlyManPage(EditableManPage):
+
+       def __init__(self, master=None, cnf={}):
+               # Initialize base class
+               EditableManPage.__init__(self, master, cnf)
+
+               # Make the text readonly
+               self.text.bind('<Any-KeyPress>', self.modify_cb)
+               self.text.bind('<Return>', self.modify_cb)
+               self.text.bind('<BackSpace>', self.modify_cb)
+               self.text.bind('<Delete>', self.modify_cb)
+               self.text.bind('<Control-h>', self.modify_cb)
+               self.text.bind('<Control-d>', self.modify_cb)
+               self.text.bind('<Control-v>', self.modify_cb)
+
+       def modify_cb(self, e):
+               pass
+
+# Alias
+ManPage = ReadonlyManPage
+
+# Test program.
+# usage: ManPage [manpage]; or ManPage [-f] file
+# -f means that the file is nroff -man output run through ul -i
+def test():
+       import os
+       import sys
+       # XXX This directory may be different on your system
+       MANDIR = '/usr/local/man/mann'
+       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', 'bd': 2,
+                                Pack: {'expand': 1, 'fill': 'both'}})
+       if formatted:
+               fp = open(name, 'r')
+       else:
+               fp = os.popen('nroff -man %s | ul -i' % name, 'r')
+       manpage.parsefile(fp)
+       root.mainloop()
+
+# Run the test program when called as a script
+if __name__ == '__main__':
+       test()
diff --git a/Demo/tkinter/guido/tkman.py b/Demo/tkinter/guido/tkman.py
new file mode 100755 (executable)
index 0000000..c6610f8
--- /dev/null
@@ -0,0 +1,183 @@
+#! /ufs/guido/bin/sgi/tkpython
+
+# Tk man page browser -- currently only shows the Tcl/Tk man pages
+
+import sys
+import os
+import string
+import regex
+from Tkinter import *
+from ManPage import ManPage
+
+MANDIR = '/usr/local/man/mann'
+
+def listmanpages(mandir = MANDIR):
+       files = os.listdir(mandir)
+       names = []
+       for file in files:
+               if file[-2:] == '.n':
+                       names.append(file[:-2])
+       names.sort()
+       return names
+
+class SelectionBox:
+
+       def __init__(self, master=None):
+               self.choices = []
+
+               self.frame = Frame(master, {
+                       Pack: {'expand': 1, 'fill': 'both'}})
+               self.master = self.frame.master
+               self.subframe = Frame(self.frame, {
+                       Pack: {'expand': 0, 'fill': 'both'}})
+               self.listbox = Listbox(self.subframe,
+                                      {'relief': 'sunken', 'bd': 2,
+                                       'geometry': '20x6',
+                                       Pack: {'side': 'right',
+                                              'expand': 1, 'fill': 'both'}})
+               self.subsubframe = Frame(self.subframe, {
+                       Pack: {'side': 'left', 'expand': 1, 'fill': 'both'}})
+               self.l1 = Label(self.subsubframe,
+                               {'text': 'Display manual page named:',
+                                Pack: {'side': 'top'}})
+               self.entry = Entry(self.subsubframe,
+                                  {'relief': 'sunken', 'bd': 2,
+                                   'width': 20,
+                                   Pack: {'side': 'top',
+                                          'expand': 0, 'fill': 'x'}})
+               self.l2 = Label(self.subsubframe,
+                               {'text': 'Search (regexp, case insensitive):',
+                                Pack: {'side': 'top'}})
+               self.search = Entry(self.subsubframe,
+                                  {'relief': 'sunken', 'bd': 2,
+                                   'width': 20,
+                                   Pack: {'side': 'top',
+                                          'expand': 0, 'fill': 'x'}})
+               self.title = Label(self.subsubframe,
+                                  {'text': '(none)',
+                                   Pack: {'side': 'bottom'}})
+               self.text = ManPage(self.frame,
+                                        {'relief': 'sunken', 'bd': 2,
+                                         'wrap': 'none', 'width': 72,
+                                         Pack: {'expand': 1, 'fill': 'both'}})
+
+               self.entry.bind('<Return>', self.entry_cb)
+               self.search.bind('<Return>', self.search_cb)
+               self.listbox.bind('<Double-1>', self.listbox_cb)
+
+               self.entry.focus_set()
+
+               self.showing = None
+
+       def addchoice(self, choice):
+               if choice not in self.choices:
+                       self.choices.append(choice)
+                       self.choices.sort()
+               self.update()
+
+       def addlist(self, list):
+               self.choices[len(self.choices):] = list
+               self.choices.sort()
+               self.update()
+
+       def updatelist(self):
+               key = self.entry.get()
+               ok = filter(lambda name, key=key, n=len(key): name[:n]==key,
+                        self.choices)
+               self.listbox.delete(0, AtEnd())
+               exactmatch = 0
+               for item in ok:
+                       if item == key: exactmatch = 1
+                       self.listbox.insert(AtEnd(), item)
+               if exactmatch:
+                       return key
+               elif self.listbox.size() == 1:
+                       return self.listbox.get(0)
+
+       def entry_cb(self, e):
+               self.update()
+
+       def update(self):
+               self.show_page(self.updatelist())
+
+       def show_page(self, name):
+               if not name:
+                       return
+               if name == self.showing:
+                       print 'show_page: already showing'
+                       return
+               name = '%s/%s.n' % (MANDIR, name)
+               fp = os.popen('nroff -man %s | ul -i' % name, 'r')
+               self.text.delete('1.0', AtEnd())
+               frame_cursor = self.frame['cursor']
+               entry_cursor = self.entry['cursor']
+               self.entry['cursor'] = 'watch'
+               self.search['cursor'] = 'watch'
+               self.frame['cursor'] = 'watch'
+               self.text.parsefile(fp)
+               self.search['cursor'] = entry_cursor
+               self.entry['cursor'] = entry_cursor
+               self.frame['cursor'] = frame_cursor
+               self.entry.delete(0, AtEnd())
+               self.updatelist()
+
+       def listbox_cb(self, e):
+               selection = self.listbox.curselection()
+               if selection and len(selection) == 1:
+                       which = self.listbox.get(selection[0])
+                       self.show_page(which)
+
+       def search_cb(self, e):
+               self.search_string(self.search.get())
+
+       def search_string(self, search):
+               if not search:
+                       print 'Empty search string'
+                       return
+               try:
+                       prog = regex.compile(search, regex.casefold)
+               except regex.error, msg:
+                       print 'Regex error:', msg
+                       return
+               here = self.text.index(AtInsert())
+               lineno = string.atoi(here[:string.find(here, '.')])
+               end = self.text.index(AtEnd())
+               endlineno = string.atoi(end[:string.find(end, '.')])
+               wraplineno = lineno
+               while 1:
+                       lineno = lineno + 1
+                       if lineno > endlineno:
+                               if wraplineno <= 0:
+                                       break
+                               endlineno = wraplineno
+                               lineno = 0
+                               wraplineno = 0
+                       line = self.text.get('%d.0 linestart' % lineno,
+                                            '%d.0 lineend' % lineno)
+                       i = prog.search(line)
+                       if i >= 0:
+                               n = max(1, len(prog.group(0)))
+                               try:
+                                       self.text.tag_remove('sel',
+                                                            AtSelFirst(),
+                                                            AtSelLast())
+                               except TclError:
+                                       pass
+                               self.text.tag_add('sel',
+                                                 '%d.%d' % (lineno, i),
+                                                 '%d.%d' % (lineno, i+n))
+                               self.text.mark_set(AtInsert(),
+                                                  '%d.%d' % (lineno, i))
+                               self.text.yview_pickplace(AtInsert())
+                               break
+
+def main():
+       root = Tk()
+       sb = SelectionBox(root)
+       sb.addlist(listmanpages())
+       if sys.argv[1:]:
+               sb.show_page(sys.argv[1])
+       root.minsize(1, 1)
+       root.mainloop()
+
+main()