blob: 8fe9903a4bafe098dd71234e9efc8b8432aad276 [file] [log] [blame]
Guido van Rossumf09b7701994-07-06 21:17:21 +00001#! /ufs/guido/bin/sgi/tkpython
2
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 *
10from ManPage import ManPage
11
12MANDIR = '/usr/local/man/mann'
13
14def listmanpages(mandir = MANDIR):
15 files = os.listdir(mandir)
16 names = []
17 for file in files:
18 if file[-2:] == '.n':
19 names.append(file[:-2])
20 names.sort()
21 return names
22
23class SelectionBox:
24
25 def __init__(self, master=None):
26 self.choices = []
27
28 self.frame = Frame(master, {
29 Pack: {'expand': 1, 'fill': 'both'}})
30 self.master = self.frame.master
31 self.subframe = Frame(self.frame, {
32 Pack: {'expand': 0, 'fill': 'both'}})
33 self.listbox = Listbox(self.subframe,
34 {'relief': 'sunken', 'bd': 2,
35 'geometry': '20x6',
36 Pack: {'side': 'right',
37 'expand': 1, 'fill': 'both'}})
38 self.subsubframe = Frame(self.subframe, {
39 Pack: {'side': 'left', 'expand': 1, 'fill': 'both'}})
Guido van Rossum119749b1994-07-08 14:28:38 +000040 self.l1 = Button(self.subsubframe,
Guido van Rossumf09b7701994-07-06 21:17:21 +000041 {'text': 'Display manual page named:',
Guido van Rossum119749b1994-07-08 14:28:38 +000042 'command': self.entry_cb,
Guido van Rossumf09b7701994-07-06 21:17:21 +000043 Pack: {'side': 'top'}})
44 self.entry = Entry(self.subsubframe,
45 {'relief': 'sunken', 'bd': 2,
46 'width': 20,
47 Pack: {'side': 'top',
48 'expand': 0, 'fill': 'x'}})
Guido van Rossum119749b1994-07-08 14:28:38 +000049 self.l2frame = Frame(self.subsubframe, {
50 Pack: {'expand': 0, 'fill': 'none'}})
51 self.l2 = Button(self.l2frame,
52 {'text': 'Search regexp:',
53 'command': self.search_cb,
54 Pack: {'side': 'left'}})
55 self.casesense = Checkbutton(self.l2frame,
56 {'text': 'Case sensitive',
57 'variable': 'casesense',
58 'relief': 'flat',
59 Pack: {'side': 'left'}})
Guido van Rossumf09b7701994-07-06 21:17:21 +000060 self.search = Entry(self.subsubframe,
61 {'relief': 'sunken', 'bd': 2,
62 'width': 20,
63 Pack: {'side': 'top',
64 'expand': 0, 'fill': 'x'}})
65 self.title = Label(self.subsubframe,
66 {'text': '(none)',
67 Pack: {'side': 'bottom'}})
68 self.text = ManPage(self.frame,
69 {'relief': 'sunken', 'bd': 2,
70 'wrap': 'none', 'width': 72,
71 Pack: {'expand': 1, 'fill': 'both'}})
72
73 self.entry.bind('<Return>', self.entry_cb)
74 self.search.bind('<Return>', self.search_cb)
75 self.listbox.bind('<Double-1>', self.listbox_cb)
76
Guido van Rossum119749b1994-07-08 14:28:38 +000077 self.entry.bind('<Tab>', self.entry_tab)
78 self.search.bind('<Tab>', self.search_tab)
79 self.text.bind('<Tab>', self.text_tab)
Guido van Rossumf09b7701994-07-06 21:17:21 +000080
Guido van Rossum119749b1994-07-08 14:28:38 +000081 self.entry.focus_set()
Guido van Rossumf09b7701994-07-06 21:17:21 +000082
83 def addchoice(self, choice):
84 if choice not in self.choices:
85 self.choices.append(choice)
86 self.choices.sort()
87 self.update()
88
89 def addlist(self, list):
90 self.choices[len(self.choices):] = list
91 self.choices.sort()
92 self.update()
93
Guido van Rossum119749b1994-07-08 14:28:38 +000094 def entry_cb(self, *e):
95 self.update()
96
97 def listbox_cb(self, e):
98 selection = self.listbox.curselection()
99 if selection and len(selection) == 1:
100 name = self.listbox.get(selection[0])
101 self.show_page(name)
102
103 def search_cb(self, *e):
104 self.search_string(self.search.get())
105
106 def entry_tab(self, e):
107 self.search.focus_set()
108
109 def search_tab(self, e):
110 self.entry.focus_set()
111
112 def text_tab(self, e):
113 self.entry.focus_set()
114
Guido van Rossumf09b7701994-07-06 21:17:21 +0000115 def updatelist(self):
116 key = self.entry.get()
117 ok = filter(lambda name, key=key, n=len(key): name[:n]==key,
118 self.choices)
119 self.listbox.delete(0, AtEnd())
120 exactmatch = 0
121 for item in ok:
122 if item == key: exactmatch = 1
123 self.listbox.insert(AtEnd(), item)
124 if exactmatch:
125 return key
126 elif self.listbox.size() == 1:
127 return self.listbox.get(0)
Guido van Rossum119749b1994-07-08 14:28:38 +0000128 # Else return None, meaning not a unique selection
Guido van Rossumf09b7701994-07-06 21:17:21 +0000129
130 def update(self):
Guido van Rossum119749b1994-07-08 14:28:38 +0000131 name = self.updatelist()
132 if name:
133 self.show_page(name)
134 self.entry.delete(0, AtEnd())
135 self.updatelist()
Guido van Rossumf09b7701994-07-06 21:17:21 +0000136
137 def show_page(self, name):
Guido van Rossum119749b1994-07-08 14:28:38 +0000138 file = '%s/%s.n' % (MANDIR, name)
139 fp = os.popen('nroff -man %s | ul -i' % file, 'r')
140 self.text.kill()
141 self.title['text'] = name
Guido van Rossumf09b7701994-07-06 21:17:21 +0000142 self.text.parsefile(fp)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000143
144 def search_string(self, search):
145 if not search:
146 print 'Empty search string'
147 return
Guido van Rossum119749b1994-07-08 14:28:38 +0000148 if self.frame.tk.getvar('casesense') != '1':
149 map = regex.casefold
150 else:
151 map = None
Guido van Rossumf09b7701994-07-06 21:17:21 +0000152 try:
Guido van Rossum119749b1994-07-08 14:28:38 +0000153 if map:
154 prog = regex.compile(search, map)
155 else:
156 prog = regex.compile(search)
Guido van Rossumf09b7701994-07-06 21:17:21 +0000157 except regex.error, msg:
158 print 'Regex error:', msg
159 return
160 here = self.text.index(AtInsert())
161 lineno = string.atoi(here[:string.find(here, '.')])
162 end = self.text.index(AtEnd())
163 endlineno = string.atoi(end[:string.find(end, '.')])
164 wraplineno = lineno
165 while 1:
166 lineno = lineno + 1
167 if lineno > endlineno:
168 if wraplineno <= 0:
169 break
170 endlineno = wraplineno
171 lineno = 0
172 wraplineno = 0
173 line = self.text.get('%d.0 linestart' % lineno,
174 '%d.0 lineend' % lineno)
175 i = prog.search(line)
176 if i >= 0:
177 n = max(1, len(prog.group(0)))
178 try:
179 self.text.tag_remove('sel',
180 AtSelFirst(),
181 AtSelLast())
182 except TclError:
183 pass
184 self.text.tag_add('sel',
185 '%d.%d' % (lineno, i),
186 '%d.%d' % (lineno, i+n))
187 self.text.mark_set(AtInsert(),
188 '%d.%d' % (lineno, i))
189 self.text.yview_pickplace(AtInsert())
190 break
191
192def main():
193 root = Tk()
194 sb = SelectionBox(root)
195 sb.addlist(listmanpages())
196 if sys.argv[1:]:
197 sb.show_page(sys.argv[1])
198 root.minsize(1, 1)
199 root.mainloop()
200
201main()