| 
									
										
										
										
											2010-03-11 22:53:45 +00:00
										 |  |  | #! /usr/bin/env python3 | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Tk man page browser -- currently only shows the Tcl/Tk man pages | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import string | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2009-01-04 18:53:28 +00:00
										 |  |  | from tkinter import * | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | from ManPage import ManPage | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  | MANNDIRLIST = ['/depot/sundry/man/mann','/usr/local/man/mann'] | 
					
						
							|  |  |  | MAN3DIRLIST = ['/depot/sundry/man/man3','/usr/local/man/man3'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | foundmanndir = 0 | 
					
						
							|  |  |  | for dir in MANNDIRLIST: | 
					
						
							|  |  |  |     if os.path.exists(dir): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         MANNDIR = dir | 
					
						
							|  |  |  |         foundmanndir = 1 | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | foundman3dir = 0 | 
					
						
							|  |  |  | for dir in MAN3DIRLIST: | 
					
						
							|  |  |  |     if os.path.exists(dir): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         MAN3DIR = dir | 
					
						
							|  |  |  |         foundman3dir =  1 | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if not foundmanndir or not foundman3dir: | 
					
						
							|  |  |  |     sys.stderr.write('\n') | 
					
						
							|  |  |  |     if not foundmanndir: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         msg = """\
 | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  | Failed to find mann directory. | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | Please add the correct entry to the MANNDIRLIST | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  | at the top of %s script.""" % \
 | 
					
						
							|  |  |  | sys.argv[0] | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         sys.stderr.write("%s\n\n" % msg) | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  |     if not foundman3dir: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         msg = """\
 | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  | Failed to find man3 directory. | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | Please add the correct entry to the MAN3DIRLIST | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  | at the top of %s script.""" % \
 | 
					
						
							|  |  |  | sys.argv[0] | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         sys.stderr.write("%s\n\n" % msg) | 
					
						
							| 
									
										
										
										
											1997-09-15 15:39:11 +00:00
										 |  |  |     sys.exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | del foundmanndir | 
					
						
							|  |  |  | del foundman3dir | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1994-07-11 13:15:05 +00:00
										 |  |  | def listmanpages(mandir): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     files = os.listdir(mandir) | 
					
						
							|  |  |  |     names = [] | 
					
						
							|  |  |  |     for file in files: | 
					
						
							|  |  |  |         if file[-2:-1] == '.' and  (file[-1] in 'ln123456789'): | 
					
						
							|  |  |  |             names.append(file[:-2]) | 
					
						
							|  |  |  |     names.sort() | 
					
						
							|  |  |  |     return names | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class SelectionBox: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def __init__(self, master=None): | 
					
						
							|  |  |  |         self.choices = [] | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         self.frame = Frame(master, name="frame") | 
					
						
							|  |  |  |         self.frame.pack(expand=1, fill=BOTH) | 
					
						
							|  |  |  |         self.master = self.frame.master | 
					
						
							|  |  |  |         self.subframe = Frame(self.frame, name="subframe") | 
					
						
							|  |  |  |         self.subframe.pack(expand=0, fill=BOTH) | 
					
						
							|  |  |  |         self.leftsubframe = Frame(self.subframe, name='leftsubframe') | 
					
						
							|  |  |  |         self.leftsubframe.pack(side=LEFT, expand=1, fill=BOTH) | 
					
						
							|  |  |  |         self.rightsubframe = Frame(self.subframe, name='rightsubframe') | 
					
						
							|  |  |  |         self.rightsubframe.pack(side=RIGHT, expand=1, fill=BOTH) | 
					
						
							|  |  |  |         self.chaptervar = StringVar(master) | 
					
						
							|  |  |  |         self.chapter = Menubutton(self.rightsubframe, name='chapter', | 
					
						
							|  |  |  |                                   text='Directory', relief=RAISED, | 
					
						
							|  |  |  |                                   borderwidth=2) | 
					
						
							|  |  |  |         self.chapter.pack(side=TOP) | 
					
						
							|  |  |  |         self.chaptermenu = Menu(self.chapter, name='chaptermenu') | 
					
						
							|  |  |  |         self.chaptermenu.add_radiobutton(label='C functions', | 
					
						
							|  |  |  |                                          value=MAN3DIR, | 
					
						
							|  |  |  |                                          variable=self.chaptervar, | 
					
						
							|  |  |  |                                          command=self.newchapter) | 
					
						
							|  |  |  |         self.chaptermenu.add_radiobutton(label='Tcl/Tk functions', | 
					
						
							|  |  |  |                                          value=MANNDIR, | 
					
						
							|  |  |  |                                          variable=self.chaptervar, | 
					
						
							|  |  |  |                                          command=self.newchapter) | 
					
						
							|  |  |  |         self.chapter['menu'] = self.chaptermenu | 
					
						
							|  |  |  |         self.listbox = Listbox(self.rightsubframe, name='listbox', | 
					
						
							|  |  |  |                                relief=SUNKEN, borderwidth=2, | 
					
						
							|  |  |  |                                width=20, height=5) | 
					
						
							|  |  |  |         self.listbox.pack(expand=1, fill=BOTH) | 
					
						
							|  |  |  |         self.l1 = Button(self.leftsubframe, name='l1', | 
					
						
							|  |  |  |                          text='Display manual page named:', | 
					
						
							|  |  |  |                          command=self.entry_cb) | 
					
						
							|  |  |  |         self.l1.pack(side=TOP) | 
					
						
							|  |  |  |         self.entry = Entry(self.leftsubframe, name='entry', | 
					
						
							|  |  |  |                             relief=SUNKEN, borderwidth=2, | 
					
						
							|  |  |  |                             width=20) | 
					
						
							|  |  |  |         self.entry.pack(expand=0, fill=X) | 
					
						
							|  |  |  |         self.l2frame = Frame(self.leftsubframe, name='l2frame') | 
					
						
							|  |  |  |         self.l2frame.pack(expand=0, fill=NONE) | 
					
						
							|  |  |  |         self.l2 = Button(self.l2frame, name='l2', | 
					
						
							|  |  |  |                          text='Search regexp:', | 
					
						
							|  |  |  |                          command=self.search_cb) | 
					
						
							|  |  |  |         self.l2.pack(side=LEFT) | 
					
						
							|  |  |  |         self.casevar = BooleanVar() | 
					
						
							|  |  |  |         self.casesense = Checkbutton(self.l2frame, name='casesense', | 
					
						
							|  |  |  |                                      text='Case sensitive', | 
					
						
							|  |  |  |                                      variable=self.casevar, | 
					
						
							|  |  |  |                                      relief=FLAT) | 
					
						
							|  |  |  |         self.casesense.pack(side=LEFT) | 
					
						
							|  |  |  |         self.search = Entry(self.leftsubframe, name='search', | 
					
						
							|  |  |  |                             relief=SUNKEN, borderwidth=2, | 
					
						
							|  |  |  |                             width=20) | 
					
						
							|  |  |  |         self.search.pack(expand=0, fill=X) | 
					
						
							|  |  |  |         self.title = Label(self.leftsubframe, name='title', | 
					
						
							|  |  |  |                            text='(none)') | 
					
						
							|  |  |  |         self.title.pack(side=BOTTOM) | 
					
						
							|  |  |  |         self.text = ManPage(self.frame, name='text', | 
					
						
							|  |  |  |                             relief=SUNKEN, borderwidth=2, | 
					
						
							|  |  |  |                             wrap=NONE, width=72, | 
					
						
							|  |  |  |                             selectbackground='pink') | 
					
						
							|  |  |  |         self.text.pack(expand=1, fill=BOTH) | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         self.entry.bind('<Return>', self.entry_cb) | 
					
						
							|  |  |  |         self.search.bind('<Return>', self.search_cb) | 
					
						
							|  |  |  |         self.listbox.bind('<Double-1>', self.listbox_cb) | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         self.entry.bind('<Tab>', self.entry_tab) | 
					
						
							|  |  |  |         self.search.bind('<Tab>', self.search_tab) | 
					
						
							|  |  |  |         self.text.bind('<Tab>', self.text_tab) | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         self.entry.focus_set() | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         self.chaptervar.set(MANNDIR) | 
					
						
							|  |  |  |         self.newchapter() | 
					
						
							| 
									
										
										
										
											1994-07-11 13:15:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def newchapter(self): | 
					
						
							|  |  |  |         mandir = self.chaptervar.get() | 
					
						
							|  |  |  |         self.choices = [] | 
					
						
							|  |  |  |         self.addlist(listmanpages(mandir)) | 
					
						
							| 
									
										
										
										
											1994-07-11 13:15:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def addchoice(self, choice): | 
					
						
							|  |  |  |         if choice not in self.choices: | 
					
						
							|  |  |  |             self.choices.append(choice) | 
					
						
							|  |  |  |             self.choices.sort() | 
					
						
							|  |  |  |         self.update() | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def addlist(self, list): | 
					
						
							|  |  |  |         self.choices[len(self.choices):] = list | 
					
						
							|  |  |  |         self.choices.sort() | 
					
						
							|  |  |  |         self.update() | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def entry_cb(self, *e): | 
					
						
							|  |  |  |         self.update() | 
					
						
							| 
									
										
										
										
											1994-07-08 14:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def listbox_cb(self, e): | 
					
						
							|  |  |  |         selection = self.listbox.curselection() | 
					
						
							|  |  |  |         if selection and len(selection) == 1: | 
					
						
							|  |  |  |             name = self.listbox.get(selection[0]) | 
					
						
							|  |  |  |             self.show_page(name) | 
					
						
							| 
									
										
										
										
											1994-07-08 14:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def search_cb(self, *e): | 
					
						
							|  |  |  |         self.search_string(self.search.get()) | 
					
						
							| 
									
										
										
										
											1994-07-08 14:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def entry_tab(self, e): | 
					
						
							|  |  |  |         self.search.focus_set() | 
					
						
							| 
									
										
										
										
											1994-07-08 14:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def search_tab(self, e): | 
					
						
							|  |  |  |         self.entry.focus_set() | 
					
						
							| 
									
										
										
										
											1994-07-08 14:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def text_tab(self, e): | 
					
						
							|  |  |  |         self.entry.focus_set() | 
					
						
							| 
									
										
										
										
											1994-07-08 14:28:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def updatelist(self): | 
					
						
							|  |  |  |         key = self.entry.get() | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |         ok = list(filter(lambda name, key=key, n=len(key): name[:n]==key, | 
					
						
							|  |  |  |                  self.choices)) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         if not ok: | 
					
						
							|  |  |  |             self.frame.bell() | 
					
						
							|  |  |  |         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 | 
					
						
							|  |  |  |         n = self.listbox.size() | 
					
						
							|  |  |  |         if n == 1: | 
					
						
							|  |  |  |             return self.listbox.get(0) | 
					
						
							|  |  |  |         # Else return None, meaning not a unique selection | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def update(self): | 
					
						
							|  |  |  |         name = self.updatelist() | 
					
						
							|  |  |  |         if name: | 
					
						
							|  |  |  |             self.show_page(name) | 
					
						
							|  |  |  |             self.entry.delete(0, AtEnd()) | 
					
						
							|  |  |  |             self.updatelist() | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def show_page(self, name): | 
					
						
							|  |  |  |         file = '%s/%s.?' % (self.chaptervar.get(), name) | 
					
						
							|  |  |  |         fp = os.popen('nroff -man %s | ul -i' % file, 'r') | 
					
						
							|  |  |  |         self.text.kill() | 
					
						
							|  |  |  |         self.title['text'] = name | 
					
						
							|  |  |  |         self.text.parsefile(fp) | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     def search_string(self, search): | 
					
						
							|  |  |  |         if not search: | 
					
						
							|  |  |  |             self.frame.bell() | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |             print('Empty search string') | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |             return | 
					
						
							|  |  |  |         if not self.casevar.get(): | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  |             map = re.IGNORECASE | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             map = None | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             if map: | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  |                 prog = re.compile(search, map) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2006-04-21 10:40:58 +00:00
										 |  |  |                 prog = re.compile(search) | 
					
						
							| 
									
										
										
										
											2007-01-10 16:19:56 +00:00
										 |  |  |         except re.error as msg: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |             self.frame.bell() | 
					
						
							| 
									
										
										
										
											2007-07-17 20:59:35 +00:00
										 |  |  |             print('Regex error:', msg) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |             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 | 
					
						
							|  |  |  |         found = 0 | 
					
						
							|  |  |  |         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: | 
					
						
							|  |  |  |                 found = 1 | 
					
						
							|  |  |  |                 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 | 
					
						
							|  |  |  |         if not found: | 
					
						
							|  |  |  |             self.frame.bell() | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     root = Tk() | 
					
						
							|  |  |  |     sb = SelectionBox(root) | 
					
						
							|  |  |  |     if sys.argv[1:]: | 
					
						
							|  |  |  |         sb.show_page(sys.argv[1]) | 
					
						
							|  |  |  |     root.minsize(1, 1) | 
					
						
							|  |  |  |     root.mainloop() | 
					
						
							| 
									
										
										
										
											1994-07-06 21:17:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | main() |