blob: 34ca4a333840457ceab487c05126cdcea2c51d70 [file] [log] [blame]
Guido van Rossum4450bab1994-10-11 14:57:03 +00001#! /usr/local/bin/python
Guido van Rossumf09b7701994-07-06 21:17:21 +00002
3# Tk man page browser -- currently only shows the Tcl/Tk man pages
4
5import sys
6import os
7import string
8import regex
9from Tkinter import *
Guido van Rossumac97fd71994-10-06 15:50:49 +000010
11import addpack
Guido van Rossum4450bab1994-10-11 14:57:03 +000012addpack.addpack('/ufs/guido/src/python/Demo/guido/tkinter')
Guido van Rossumf09b7701994-07-06 21:17:21 +000013from ManPage import ManPage
14
Guido van Rossum36ea0e71994-07-11 13:15:05 +000015MANNDIR = '/usr/local/man/mann'
16MAN3DIR = '/usr/local/man/man3'
Guido van Rossumc27e0421995-09-07 19:47:46 +000017MANNDIR = '/depot/sundry/man/mann'
18MAN3DIR = '/depot/sundry/man/man3'
Guido van Rossumf09b7701994-07-06 21:17:21 +000019
Guido van Rossum36ea0e71994-07-11 13:15:05 +000020def listmanpages(mandir):
Guido van Rossumf09b7701994-07-06 21:17:21 +000021 files = os.listdir(mandir)
22 names = []
23 for file in files:
Guido van Rossum36ea0e71994-07-11 13:15:05 +000024 if file[-2:-1] == '.' and (file[-1] in 'ln123456789'):
Guido van Rossumf09b7701994-07-06 21:17:21 +000025 names.append(file[:-2])
26 names.sort()
27 return names
28
29class SelectionBox:
30
31 def __init__(self, master=None):
32 self.choices = []
33
Guido van Rossum89cb67b1996-07-30 18:57:18 +000034 self.frame = Frame(master, name="frame")
35 self.frame.pack(expand=1, fill=BOTH)
Guido van Rossumf09b7701994-07-06 21:17:21 +000036 self.master = self.frame.master
Guido van Rossum89cb67b1996-07-30 18:57:18 +000037 self.subframe = Frame(self.frame, name="subframe")
38 self.subframe.pack(expand=0, fill=BOTH)
39 self.leftsubframe = Frame(self.subframe, name='leftsubframe')
40 self.leftsubframe.pack(side=LEFT, expand=1, fill=BOTH)
41 self.rightsubframe = Frame(self.subframe, name='rightsubframe')
42 self.rightsubframe.pack(side=RIGHT, expand=1, fill=BOTH)
Guido van Rossum36ea0e71994-07-11 13:15:05 +000043 self.chaptervar = StringVar(master)
Guido van Rossum89cb67b1996-07-30 18:57:18 +000044 self.chapter = Menubutton(self.rightsubframe, name='chapter',
45 text='Directory', relief=RAISED,
46 borderwidth=2)
47 self.chapter.pack(side=TOP)
48 self.chaptermenu = Menu(self.chapter, name='chaptermenu')
49 self.chaptermenu.add_radiobutton(label='C functions',
50 value=MAN3DIR,
51 variable=self.chaptervar,
52 command=self.newchapter)
53 self.chaptermenu.add_radiobutton(label='Tcl/Tk functions',
54 value=MANNDIR,
55 variable=self.chaptervar,
56 command=self.newchapter)
Guido van Rossum36ea0e71994-07-11 13:15:05 +000057 self.chapter['menu'] = self.chaptermenu
Guido van Rossum89cb67b1996-07-30 18:57:18 +000058 self.listbox = Listbox(self.rightsubframe, name='listbox',
59 relief=SUNKEN, borderwidth=2,
60 width=20, height=5)
61 self.listbox.pack(expand=1, fill=BOTH)
62 self.l1 = Button(self.leftsubframe, name='l1',
63 text='Display manual page named:',
64 command=self.entry_cb)
65 self.l1.pack(side=TOP)
66 self.entry = Entry(self.leftsubframe, name='entry',
67 relief=SUNKEN, borderwidth=2,
68 width=20)
69 self.entry.pack(expand=0, fill=X)
70 self.l2frame = Frame(self.leftsubframe, name='l2frame')
71 self.l2frame.pack(expand=0, fill=NONE)
72 self.l2 = Button(self.l2frame, name='l2',
73 text='Search regexp:',
74 command=self.search_cb)
75 self.l2.pack(side=LEFT)
76 self.casevar = BooleanVar()
77 self.casesense = Checkbutton(self.l2frame, name='casesense',
78 text='Case sensitive',
79 variable=self.casevar,
80 relief=FLAT)
81 self.casesense.pack(side=LEFT)
82 self.search = Entry(self.leftsubframe, name='search',
83 relief=SUNKEN, borderwidth=2,
84 width=20)
85 self.search.pack(expand=0, fill=X)
86 self.title = Label(self.leftsubframe, name='title',
87 text='(none)')
88 self.title.pack(side=BOTTOM)
89 self.text = ManPage(self.frame, name='text',
90 relief=SUNKEN, borderwidth=2,
91 wrap=NONE, width=72,
92 selectbackground='pink')
93 self.text.pack(expand=1, fill=BOTH)
Guido van Rossumf09b7701994-07-06 21:17:21 +000094
95 self.entry.bind('<Return>', self.entry_cb)
96 self.search.bind('<Return>', self.search_cb)
97 self.listbox.bind('<Double-1>', self.listbox_cb)
98
Guido van Rossum119749b1994-07-08 14:28:38 +000099 self.entry.bind('<Tab>', self.entry_tab)
100 self.search.bind('<Tab>', self.search_tab)
101 self.text.bind('<Tab>', self.text_tab)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000102
Guido van Rossum119749b1994-07-08 14:28:38 +0000103 self.entry.focus_set()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000104
Guido van Rossum36ea0e71994-07-11 13:15:05 +0000105 self.chaptervar.set(MANNDIR)
106 self.newchapter()
107
108 def newchapter(self):
109 mandir = self.chaptervar.get()
110 self.choices = []
111 self.addlist(listmanpages(mandir))
112
Guido van Rossumf09b7701994-07-06 21:17:21 +0000113 def addchoice(self, choice):
114 if choice not in self.choices:
115 self.choices.append(choice)
116 self.choices.sort()
117 self.update()
118
119 def addlist(self, list):
120 self.choices[len(self.choices):] = list
121 self.choices.sort()
122 self.update()
123
Guido van Rossum119749b1994-07-08 14:28:38 +0000124 def entry_cb(self, *e):
125 self.update()
126
127 def listbox_cb(self, e):
128 selection = self.listbox.curselection()
129 if selection and len(selection) == 1:
130 name = self.listbox.get(selection[0])
131 self.show_page(name)
132
133 def search_cb(self, *e):
134 self.search_string(self.search.get())
135
136 def entry_tab(self, e):
137 self.search.focus_set()
138
139 def search_tab(self, e):
140 self.entry.focus_set()
141
142 def text_tab(self, e):
143 self.entry.focus_set()
144
Guido van Rossumf09b7701994-07-06 21:17:21 +0000145 def updatelist(self):
146 key = self.entry.get()
147 ok = filter(lambda name, key=key, n=len(key): name[:n]==key,
148 self.choices)
Guido van Rossumc27e0421995-09-07 19:47:46 +0000149 if not ok:
150 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000151 self.listbox.delete(0, AtEnd())
152 exactmatch = 0
153 for item in ok:
154 if item == key: exactmatch = 1
155 self.listbox.insert(AtEnd(), item)
156 if exactmatch:
157 return key
Guido van Rossumc27e0421995-09-07 19:47:46 +0000158 n = self.listbox.size()
159 if n == 1:
Guido van Rossumf09b7701994-07-06 21:17:21 +0000160 return self.listbox.get(0)
Guido van Rossum119749b1994-07-08 14:28:38 +0000161 # Else return None, meaning not a unique selection
Guido van Rossumf09b7701994-07-06 21:17:21 +0000162
163 def update(self):
Guido van Rossum119749b1994-07-08 14:28:38 +0000164 name = self.updatelist()
165 if name:
166 self.show_page(name)
167 self.entry.delete(0, AtEnd())
168 self.updatelist()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000169
170 def show_page(self, name):
Guido van Rossum36ea0e71994-07-11 13:15:05 +0000171 file = '%s/%s.?' % (self.chaptervar.get(), name)
Guido van Rossum119749b1994-07-08 14:28:38 +0000172 fp = os.popen('nroff -man %s | ul -i' % file, 'r')
173 self.text.kill()
174 self.title['text'] = name
Guido van Rossumf09b7701994-07-06 21:17:21 +0000175 self.text.parsefile(fp)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000176
177 def search_string(self, search):
178 if not search:
Guido van Rossumc27e0421995-09-07 19:47:46 +0000179 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000180 print 'Empty search string'
181 return
Guido van Rossum89cb67b1996-07-30 18:57:18 +0000182 if not self.casevar.get():
Guido van Rossum119749b1994-07-08 14:28:38 +0000183 map = regex.casefold
184 else:
185 map = None
Guido van Rossumf09b7701994-07-06 21:17:21 +0000186 try:
Guido van Rossum119749b1994-07-08 14:28:38 +0000187 if map:
188 prog = regex.compile(search, map)
189 else:
190 prog = regex.compile(search)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000191 except regex.error, msg:
Guido van Rossumc27e0421995-09-07 19:47:46 +0000192 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000193 print 'Regex error:', msg
194 return
195 here = self.text.index(AtInsert())
196 lineno = string.atoi(here[:string.find(here, '.')])
197 end = self.text.index(AtEnd())
198 endlineno = string.atoi(end[:string.find(end, '.')])
199 wraplineno = lineno
Guido van Rossumc27e0421995-09-07 19:47:46 +0000200 found = 0
Guido van Rossumf09b7701994-07-06 21:17:21 +0000201 while 1:
202 lineno = lineno + 1
203 if lineno > endlineno:
204 if wraplineno <= 0:
205 break
206 endlineno = wraplineno
207 lineno = 0
208 wraplineno = 0
209 line = self.text.get('%d.0 linestart' % lineno,
210 '%d.0 lineend' % lineno)
211 i = prog.search(line)
212 if i >= 0:
Guido van Rossumc27e0421995-09-07 19:47:46 +0000213 found = 1
Guido van Rossumf09b7701994-07-06 21:17:21 +0000214 n = max(1, len(prog.group(0)))
215 try:
216 self.text.tag_remove('sel',
217 AtSelFirst(),
218 AtSelLast())
219 except TclError:
220 pass
221 self.text.tag_add('sel',
222 '%d.%d' % (lineno, i),
223 '%d.%d' % (lineno, i+n))
224 self.text.mark_set(AtInsert(),
225 '%d.%d' % (lineno, i))
226 self.text.yview_pickplace(AtInsert())
227 break
Guido van Rossumc27e0421995-09-07 19:47:46 +0000228 if not found:
229 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000230
231def main():
232 root = Tk()
233 sb = SelectionBox(root)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000234 if sys.argv[1:]:
235 sb.show_page(sys.argv[1])
236 root.minsize(1, 1)
237 root.mainloop()
238
239main()