/[wait]/trunk/script/smakewhatis
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/script/smakewhatis

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (hide annotations)
Fri Apr 28 15:41:10 2000 UTC (24 years, 1 month ago) by unknown
Original Path: branches/CPAN/script/smakewhatis
File size: 8984 byte(s)
This commit was manufactured by cvs2svn to create branch 'CPAN'.
1 ulpfr 10 #!/usr/bin/perl -w
2     ######################### -*- Mode: Cperl -*- #########################
3     ##
4     ## $Basename: smakewhatis $
5     ## $Revision: 1.8 $
6     ##
7     ## Author : Ulrich Pfeifer
8     ## Created On : Mon Sep 2 12:57:12 1996
9     ##
10     ## Last Modified By : Ulrich Pfeifer
11     ## Last Modified On : Sun Nov 22 18:44:34 1998
12     ##
13     ## Copyright (c) 1996-1997, Ulrich Pfeifer
14     ##
15     ##
16     ######################################################################
17    
18     use strict;
19    
20     use FileHandle;
21     use File::Path;
22     use DB_File;
23     use Getopt::Long;
24    
25     require WAIT::Database;
26     require WAIT::Config;
27     require WAIT::Parse::Nroff;
28     require WAIT::Document::Nroff;
29    
30    
31     my %OPT = (database => 'DB',
32     dir => $WAIT::Config->{WAIT_home} || '/tmp',
33     table => 'man',
34     clean => 0,
35     remove => 0,
36     );
37    
38     GetOptions(\%OPT,
39     'database=s',
40     'dir=s',
41     'table=s',
42     'clean!',
43     'remove',
44     ) || die "Usage: ...\n";
45    
46     if ($OPT{clean}) {
47     if (-d "$OPT{dir}/$OPT{database}") {
48     eval {
49     my $tmp = WAIT::Database->open(name => $OPT{database},
50     'directory' => $OPT{dir})
51     or die "Could not open table $OPT{table}: $@";
52     my $tbl = $tmp->table(name => $OPT{table});
53     $tbl->drop if $tbl;
54     $tmp->close;
55     rmtree("$OPT{dir}/$OPT{database}/$OPT{table}",1,1)
56     if -d "$OPT{dir}/$OPT{database}/$OPT{table}";
57     };
58     die $@ if $@;
59     } else {
60     die "Database $OPT{dir}/$OPT{database} doesn't exist,
61     nothing to clean, nothing done.\n";
62     }
63     exit;
64     }
65    
66     my $db = WAIT::Database->open(
67     name => $OPT{database},
68     'directory' => $OPT{dir},
69     )
70     ||
71     WAIT::Database->create(
72     name => $OPT{database},
73     'directory' => $OPT{dir},
74     );
75     unless ($db) {
76     require Carp;
77     Carp::croak("Could not open/create database '$OPT{dir}/$OPT{database}': $@");
78     }
79    
80    
81     # We need a class that allows the index to access each document.
82     # Remember, all documents in this collection are values of a single
83     # tied hash. An especially cool feature is that the tie may return the
84     # whole document as a single string or as an object or anything that
85     # fits into a scalar. WAIT::Document::Nroff illustrates how the tieing
86     # class can work. See WAIT::Table for a manpage (W:D:Nroff has none).
87    
88     my %D;
89     my $access = tie %D, 'WAIT::Document::Nroff', 'nroff -man';
90     die $@ unless defined $access;
91    
92     # While WAIT::Document::Nroff ignored the contents of the scalar it
93     # accessed, WAIT::Parse::Nroff knows how to understand it. So bear in
94     # mind:
95    
96     # access => Document
97     # layout => Parse
98    
99     # The access to a document is provided by a Document class just as
100     # the layout of a document is provided by a Parser class. Makes sense?
101    
102     my $layout= WAIT::Parse::Nroff->new;
103    
104     # The definition of filters is something that will be tought in the
105     # advanced techniques course. For now, just copy and paste the
106     # something from here and try out alternatives.
107     my $stem = [{
108     'prefix' => ['unroff', 'isotr', 'isolc'],
109     'intervall' => ['unroff', 'isotr', 'isolc'],
110     },'unroff', 'isolc', 'stop', 'isotr', 'split2', 'Stem'];
111     # unroff it as the first because nroff markup isn't very helpful for
112     # indexing, turn into lowercase, eliminate the stopwords before isotr
113     # because our stopwords contain ticks (isn't, i'm, wouldn't, etc.),
114     # replace line noise ith space, eliminate anything left with less than
115     # 2 letters, find the word's stem.
116     my $text = [{
117     'prefix' => ['unroff', 'isotr', 'isolc'],
118     'intervall' => ['unroff', 'isotr', 'isolc'],
119     },
120     'unroff', 'isolc', 'stop', 'isotr', 'split2'];
121     my $sound = ['unroff', 'isotr', 'isolc', 'split2', 'Soundex'],;
122    
123     my $tb;
124     eval { $tb = $db->table(name => $OPT{table}) };
125     $tb ||=
126     $db->create_table
127     (
128    
129     name => $OPT{table},
130     # mandatory argument like a tablename in a relational database
131    
132     access => $access,
133     # see above
134    
135     layout => $layout,
136     # see above
137    
138     attr => ['docid', 'headline', 'size'],
139     # the attr argument determines which attributes WAIT will store for
140     # us for later retrieval. A docid is a must, of course, so that we
141     # can retrieve the document later. The more attributes you name
142     # here, the bigger gets the database. For your first experiences it
143     # is highly recommended to have the two items C<docid> and
144     # C<headline> here, so that you can use sman for debugging as soon
145     # as you are through smakewhatis. In the sman program these two
146     # column names are hardcoded. You have the opportunity to create
147     # the two attributes for every record in the Layout/Parser class
148    
149     keyset => [['docid']],
150     # which keys are necessary to unambiguously identify a record and
151     # access it through $access?
152    
153     invindex =>
154     [
155     'name' => $stem,
156     'synopsis' => $stem,
157     'bugs' => $stem,
158     'description' => $stem,
159     'text' => $stem,
160     'environment' => $text,
161     'example' => $text, 'example' => $stem,
162     'author' => $sound, 'author' => $stem,
163     ]
164     # without this argument, WAIT will be able to run a pass through
165     # the indexer but it won't do anything useful. This argument is the
166     # heart of your indexing task and the place where you will start
167     # tuning once your indexes are working. For the impatent user, it's
168     # recommended to just have them all be text.
169    
170     );
171    
172     die unless $tb;
173    
174     my @DIRS;
175     if (@ARGV) {
176     @DIRS = @ARGV;
177     } else {
178     @DIRS = @{$WAIT::Config->{manpath}};
179     }
180    
181     my $mandir;
182     for $mandir (grep -d $_, @DIRS) {
183     opendir(DIR, $mandir) or warn "Could not open dir '$mandir': $!";
184     my @mdir = grep -d "$mandir/$_", grep /^man/, readdir(DIR);
185     closedir DIR;
186     my $section;
187     for $section (@mdir) {
188     my $file;
189     print STDERR "Scanning '$mandir/$section' ...\n";
190     opendir(DIR, "$mandir/$section")
191     or warn "Could not open dir '$mandir/section': $!";
192     my @files = grep -f "$mandir/$section/$_", grep $_ !~ /^\./, readdir(DIR);
193     closedir DIR;
194     for $file ( @files ) {
195     print STDERR "Indexing '$mandir/$section/$file' ... ";
196     &index("$mandir/$section/$file");
197     }
198     }
199     }
200    
201     # Do not forget to close the database after the extreme job you just finished.
202    
203     $db->close();
204     exit;
205    
206     # Now that you have created a database, lean back. To verify that it
207     # sort of worked and to understand what you actually did, I'd
208     # recommend to run sman through the debugger. Sman has options to
209     # choose databases and tables unrelated to its original task. You can
210     # run e.g.
211    
212     # perl -Sd sman -dir /usr/local/yourwaitdir -database yourdatabase -table yourtable
213    
214     # Step through the debugger to the place where a query object is
215     # created. Expect huge, self-referential datastrucures if you dump any
216     # of these object with the x command. It's quite instructive to watch
217     # the debugger print them for several minutes or hours.
218    
219     # Once you have established a working querying with sman, you will
220     # want to write your own sman.
221    
222     my $NO;
223     sub index {
224     my $did = shift;
225    
226     if ($tb->have('docid' => $did)) {
227     #die "$@" if $2 ne '';
228     if (!$OPT{remove}) {
229     print "duplicate\n";
230     return;
231     }
232     } elsif ($OPT{remove}) {
233     print "missing\n";
234     return;
235     }
236    
237     if (-s $did < 100) {
238     print "too small\n";
239     return;
240     }
241    
242     my $value = $D{$did};
243     unless (defined $value) {
244     print "unavailable\n";
245     }
246     printf STDERR "ok [%d]\n", ++$NO;
247    
248     my $record = $layout->split($value);
249     $record->{size} = length($value);
250     my $headline = $record->{name} || $did;
251     $headline =~ s/\s+/ /g; $headline =~ s/^\s+//;
252     printf "%s\n", substr($headline,0,80);
253     if ($OPT{remove}) {
254     $tb->delete('docid' => $did, headline => $headline, %{$record});
255     } else {
256     $tb->insert('docid' => $did, headline => $headline, %{$record});
257     }
258     }
259    
260    
261     __END__
262     ## ###################################################################
263     ## pod
264     ## ###################################################################
265    
266     =head1 NAME
267    
268     smakewhatis - generate a manual database for sman
269    
270     =head1 SYNOPSIS
271    
272     B<smakewhatis>
273     [B<-database> I<database name>]
274     [B<-dir> I<database directory>]
275     [B<-table> I<name>]
276     [B<-remove>]
277     [I<mandir> ...]
278    
279     =head1 DESCRIPTION
280    
281     B<Smakewhatis> generates/updates databases for B<sman>(1). If
282     I<mandir>s are specified, these are used. Otherwise the confiigured
283     default directories are indexed.
284    
285     =head2 OPTIONS
286    
287     =over 10
288    
289     =item B<-database> I<database name>
290    
291     Change the default database name to I<database name>.
292    
293     =item B<-dir> I<database directory>
294    
295     Change the default database directory to I<database directory>.
296    
297     =item B<-table> I<name>
298    
299     Use I<name> instead of C<man> as table name.
300    
301     =item B<-clean>
302    
303     Clean B<database> before indexing.
304    
305     =item B<-remove>
306    
307     Remove the selected directories from the database instead of
308     adding/updating. This works only for the manuals which are unchanged
309     since the indexing.
310    
311     =head1 SEE ALSO
312    
313     L<sman>.
314    
315     =head1 AUTHOR
316    
317     Ulrich Pfeifer E<lt>F<pfeifer@ls6.informatik.uni-dortmund.de>E<gt>

Properties

Name Value
cvs2svn:cvs-rev 1.1
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26