blob: cd604877e6e0248b48d8877870d8209919c5c8c5 [file] [log] [blame]
Guido van Rossumc27e0421995-09-07 19:47:46 +00001#! /home/guido/bin.sgi/python
Guido van Rossum4450bab1994-10-11 14:57:03 +00002#! /usr/local/bin/python
Guido van Rossumf09b7701994-07-06 21:17:21 +00003
4# Tk man page browser -- currently only shows the Tcl/Tk man pages
5
6import sys
7import os
8import string
9import regex
10from Tkinter import *
Guido van Rossumac97fd71994-10-06 15:50:49 +000011
12import addpack
Guido van Rossum4450bab1994-10-11 14:57:03 +000013addpack.addpack('/ufs/guido/src/python/Demo/guido/tkinter')
Guido van Rossumf09b7701994-07-06 21:17:21 +000014from ManPage import ManPage
15
Guido van Rossum36ea0e71994-07-11 13:15:05 +000016MANNDIR = '/usr/local/man/mann'
17MAN3DIR = '/usr/local/man/man3'
Guido van Rossumc27e0421995-09-07 19:47:46 +000018MANNDIR = '/depot/sundry/man/mann'
19MAN3DIR = '/depot/sundry/man/man3'
Guido van Rossumf09b7701994-07-06 21:17:21 +000020
Guido van Rossum36ea0e71994-07-11 13:15:05 +000021def listmanpages(mandir):
Guido van Rossumf09b7701994-07-06 21:17:21 +000022 files = os.listdir(mandir)
23 names = []
24 for file in files:
Guido van Rossum36ea0e71994-07-11 13:15:05 +000025 if file[-2:-1] == '.' and (file[-1] in 'ln123456789'):
Guido van Rossumf09b7701994-07-06 21:17:21 +000026 names.append(file[:-2])
27 names.sort()
28 return names
29
30class SelectionBox:
31
32 def __init__(self, master=None):
33 self.choices = []
34
35 self.frame = Frame(master, {
Guido van Rossum3e4f1821994-07-12 16:35:35 +000036 'name': 'frame',
Guido van Rossumf09b7701994-07-06 21:17:21 +000037 Pack: {'expand': 1, 'fill': 'both'}})
38 self.master = self.frame.master
39 self.subframe = Frame(self.frame, {
Guido van Rossum3e4f1821994-07-12 16:35:35 +000040 'name': 'subframe',
Guido van Rossumf09b7701994-07-06 21:17:21 +000041 Pack: {'expand': 0, 'fill': 'both'}})
Guido van Rossum36ea0e71994-07-11 13:15:05 +000042 self.leftsubframe = Frame(self.subframe, {
Guido van Rossum3e4f1821994-07-12 16:35:35 +000043 'name': 'leftsubframe',
Guido van Rossumf09b7701994-07-06 21:17:21 +000044 Pack: {'side': 'left', 'expand': 1, 'fill': 'both'}})
Guido van Rossum36ea0e71994-07-11 13:15:05 +000045 self.rightsubframe = Frame(self.subframe, {
Guido van Rossum3e4f1821994-07-12 16:35:35 +000046 'name': 'rightsubframe',
Guido van Rossum36ea0e71994-07-11 13:15:05 +000047 Pack: {'side': 'right', 'expand': 1, 'fill': 'both'}})
48 self.chaptervar = StringVar(master)
49 self.chapter = Menubutton(self.rightsubframe,
Guido van Rossum3e4f1821994-07-12 16:35:35 +000050 {'name': 'chapter',
51 'text': 'Directory',
Guido van Rossum36ea0e71994-07-11 13:15:05 +000052 'relief': 'raised', 'bd': 2,
53 Pack: {'side': 'top'}})
Guido van Rossum3e4f1821994-07-12 16:35:35 +000054 self.chaptermenu = Menu(self.chapter, {'name': 'chaptermenu'})
Guido van Rossum36ea0e71994-07-11 13:15:05 +000055 self.chaptermenu.add_radiobutton({'label': 'C functions',
56 'value': MAN3DIR,
57 'variable': self.chaptervar,
58 'command': self.newchapter})
59 self.chaptermenu.add_radiobutton({'label': 'Tcl/Tk functions',
60 'value': MANNDIR,
61 'variable': self.chaptervar,
62 'command': self.newchapter})
63 self.chapter['menu'] = self.chaptermenu
64 self.listbox = Listbox(self.rightsubframe,
Guido van Rossum3e4f1821994-07-12 16:35:35 +000065 {'name': 'listbox',
66 'relief': 'sunken', 'bd': 2,
Guido van Rossumc27e0421995-09-07 19:47:46 +000067 'width': 20, 'height': 5,
Guido van Rossum36ea0e71994-07-11 13:15:05 +000068 Pack: {'expand': 1, 'fill': 'both'}})
69 self.l1 = Button(self.leftsubframe,
Guido van Rossum3e4f1821994-07-12 16:35:35 +000070 {'name': 'l1',
71 'text': 'Display manual page named:',
Guido van Rossum119749b1994-07-08 14:28:38 +000072 'command': self.entry_cb,
Guido van Rossumf09b7701994-07-06 21:17:21 +000073 Pack: {'side': 'top'}})
Guido van Rossum36ea0e71994-07-11 13:15:05 +000074 self.entry = Entry(self.leftsubframe,
Guido van Rossum3e4f1821994-07-12 16:35:35 +000075 {'name': 'entry',
76 'relief': 'sunken', 'bd': 2,
Guido van Rossumf09b7701994-07-06 21:17:21 +000077 'width': 20,
78 Pack: {'side': 'top',
79 'expand': 0, 'fill': 'x'}})
Guido van Rossum3e4f1821994-07-12 16:35:35 +000080 self.l2frame = Frame(self.leftsubframe,
81 {'name': 'l2frame',
82 Pack: {'expand': 0, 'fill': 'none'}})
Guido van Rossum119749b1994-07-08 14:28:38 +000083 self.l2 = Button(self.l2frame,
Guido van Rossum3e4f1821994-07-12 16:35:35 +000084 {'name': 'l2',
85 'text': 'Search regexp:',
Guido van Rossum119749b1994-07-08 14:28:38 +000086 'command': self.search_cb,
87 Pack: {'side': 'left'}})
88 self.casesense = Checkbutton(self.l2frame,
Guido van Rossum3e4f1821994-07-12 16:35:35 +000089 {'name': 'casesense',
90 'text': 'Case sensitive',
Guido van Rossum119749b1994-07-08 14:28:38 +000091 'variable': 'casesense',
92 'relief': 'flat',
93 Pack: {'side': 'left'}})
Guido van Rossum36ea0e71994-07-11 13:15:05 +000094 self.search = Entry(self.leftsubframe,
Guido van Rossum3e4f1821994-07-12 16:35:35 +000095 {'name': 'search',
96 'relief': 'sunken', 'bd': 2,
Guido van Rossumf09b7701994-07-06 21:17:21 +000097 'width': 20,
98 Pack: {'side': 'top',
99 'expand': 0, 'fill': 'x'}})
Guido van Rossum36ea0e71994-07-11 13:15:05 +0000100 self.title = Label(self.leftsubframe,
Guido van Rossum3e4f1821994-07-12 16:35:35 +0000101 {'name': 'title',
102 'text': '(none)',
Guido van Rossumf09b7701994-07-06 21:17:21 +0000103 Pack: {'side': 'bottom'}})
104 self.text = ManPage(self.frame,
Guido van Rossum3e4f1821994-07-12 16:35:35 +0000105 {'name': 'text',
106 'relief': 'sunken', 'bd': 2,
Guido van Rossumf09b7701994-07-06 21:17:21 +0000107 'wrap': 'none', 'width': 72,
Guido van Rossumc27e0421995-09-07 19:47:46 +0000108 'selectbackground': 'pink',
Guido van Rossumf09b7701994-07-06 21:17:21 +0000109 Pack: {'expand': 1, 'fill': 'both'}})
110
111 self.entry.bind('<Return>', self.entry_cb)
112 self.search.bind('<Return>', self.search_cb)
113 self.listbox.bind('<Double-1>', self.listbox_cb)
114
Guido van Rossum119749b1994-07-08 14:28:38 +0000115 self.entry.bind('<Tab>', self.entry_tab)
116 self.search.bind('<Tab>', self.search_tab)
117 self.text.bind('<Tab>', self.text_tab)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000118
Guido van Rossum119749b1994-07-08 14:28:38 +0000119 self.entry.focus_set()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000120
Guido van Rossum36ea0e71994-07-11 13:15:05 +0000121 self.chaptervar.set(MANNDIR)
122 self.newchapter()
123
124 def newchapter(self):
125 mandir = self.chaptervar.get()
126 self.choices = []
127 self.addlist(listmanpages(mandir))
128
Guido van Rossumf09b7701994-07-06 21:17:21 +0000129 def addchoice(self, choice):
130 if choice not in self.choices:
131 self.choices.append(choice)
132 self.choices.sort()
133 self.update()
134
135 def addlist(self, list):
136 self.choices[len(self.choices):] = list
137 self.choices.sort()
138 self.update()
139
Guido van Rossum119749b1994-07-08 14:28:38 +0000140 def entry_cb(self, *e):
141 self.update()
142
143 def listbox_cb(self, e):
144 selection = self.listbox.curselection()
145 if selection and len(selection) == 1:
146 name = self.listbox.get(selection[0])
147 self.show_page(name)
148
149 def search_cb(self, *e):
150 self.search_string(self.search.get())
151
152 def entry_tab(self, e):
153 self.search.focus_set()
154
155 def search_tab(self, e):
156 self.entry.focus_set()
157
158 def text_tab(self, e):
159 self.entry.focus_set()
160
Guido van Rossumf09b7701994-07-06 21:17:21 +0000161 def updatelist(self):
162 key = self.entry.get()
163 ok = filter(lambda name, key=key, n=len(key): name[:n]==key,
164 self.choices)
Guido van Rossumc27e0421995-09-07 19:47:46 +0000165 if not ok:
166 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000167 self.listbox.delete(0, AtEnd())
168 exactmatch = 0
169 for item in ok:
170 if item == key: exactmatch = 1
171 self.listbox.insert(AtEnd(), item)
172 if exactmatch:
173 return key
Guido van Rossumc27e0421995-09-07 19:47:46 +0000174 n = self.listbox.size()
175 if n == 1:
Guido van Rossumf09b7701994-07-06 21:17:21 +0000176 return self.listbox.get(0)
Guido van Rossum119749b1994-07-08 14:28:38 +0000177 # Else return None, meaning not a unique selection
Guido van Rossumf09b7701994-07-06 21:17:21 +0000178
179 def update(self):
Guido van Rossum119749b1994-07-08 14:28:38 +0000180 name = self.updatelist()
181 if name:
182 self.show_page(name)
183 self.entry.delete(0, AtEnd())
184 self.updatelist()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000185
186 def show_page(self, name):
Guido van Rossum36ea0e71994-07-11 13:15:05 +0000187 file = '%s/%s.?' % (self.chaptervar.get(), name)
Guido van Rossum119749b1994-07-08 14:28:38 +0000188 fp = os.popen('nroff -man %s | ul -i' % file, 'r')
189 self.text.kill()
190 self.title['text'] = name
Guido van Rossumf09b7701994-07-06 21:17:21 +0000191 self.text.parsefile(fp)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000192
193 def search_string(self, search):
194 if not search:
Guido van Rossumc27e0421995-09-07 19:47:46 +0000195 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000196 print 'Empty search string'
197 return
Guido van Rossum119749b1994-07-08 14:28:38 +0000198 if self.frame.tk.getvar('casesense') != '1':
199 map = regex.casefold
200 else:
201 map = None
Guido van Rossumf09b7701994-07-06 21:17:21 +0000202 try:
Guido van Rossum119749b1994-07-08 14:28:38 +0000203 if map:
204 prog = regex.compile(search, map)
205 else:
206 prog = regex.compile(search)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000207 except regex.error, msg:
Guido van Rossumc27e0421995-09-07 19:47:46 +0000208 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000209 print 'Regex error:', msg
210 return
211 here = self.text.index(AtInsert())
212 lineno = string.atoi(here[:string.find(here, '.')])
213 end = self.text.index(AtEnd())
214 endlineno = string.atoi(end[:string.find(end, '.')])
215 wraplineno = lineno
Guido van Rossumc27e0421995-09-07 19:47:46 +0000216 found = 0
Guido van Rossumf09b7701994-07-06 21:17:21 +0000217 while 1:
218 lineno = lineno + 1
219 if lineno > endlineno:
220 if wraplineno <= 0:
221 break
222 endlineno = wraplineno
223 lineno = 0
224 wraplineno = 0
225 line = self.text.get('%d.0 linestart' % lineno,
226 '%d.0 lineend' % lineno)
227 i = prog.search(line)
228 if i >= 0:
Guido van Rossumc27e0421995-09-07 19:47:46 +0000229 found = 1
Guido van Rossumf09b7701994-07-06 21:17:21 +0000230 n = max(1, len(prog.group(0)))
231 try:
232 self.text.tag_remove('sel',
233 AtSelFirst(),
234 AtSelLast())
235 except TclError:
236 pass
237 self.text.tag_add('sel',
238 '%d.%d' % (lineno, i),
239 '%d.%d' % (lineno, i+n))
240 self.text.mark_set(AtInsert(),
241 '%d.%d' % (lineno, i))
242 self.text.yview_pickplace(AtInsert())
243 break
Guido van Rossumc27e0421995-09-07 19:47:46 +0000244 if not found:
245 self.frame.bell()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000246
247def main():
248 root = Tk()
249 sb = SelectionBox(root)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000250 if sys.argv[1:]:
251 sb.show_page(sys.argv[1])
252 root.minsize(1, 1)
253 root.mainloop()
254
255main()