~ubuntu-branches/ubuntu/lucid/pdl/lucid

« back to all changes in this revision

Viewing changes to Doc/Doc/Perldl.pm

  • Committer: Bazaar Package Importer
  • Author(s): Ben Gertzfield
  • Date: 2002-04-08 18:47:16 UTC
  • Revision ID: james.westby@ubuntu.com-20020408184716-0hf64dc96kin3htp
Tags: upstream-2.3.2
ImportĀ upstreamĀ versionĀ 2.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
=head1 NAME
 
2
 
 
3
PDL::Doc::Perldl - commands for accessing PDL doc database from 'perldl' shell
 
4
 
 
5
=head1 DESCRIPTION
 
6
 
 
7
This module provides a simple set of functions to
 
8
access the PDL documentation of database, for use
 
9
from the I<perldl> shell and the I<pdldoc> command-line
 
10
program.
 
11
 
 
12
Currently, multiple matches are not handled very well.
 
13
 
 
14
=head1 SYNOPSIS
 
15
 
 
16
 use PDL::Doc::Perldl; # Load all documenation functions
 
17
 
 
18
=head1 FUNCTIONS
 
19
 
 
20
=cut
 
21
 
 
22
package PDL::Doc::Perldl;
 
23
 
 
24
use Exporter;
 
25
use strict;
 
26
use vars qw(@ISA @EXPORT);
 
27
 
 
28
@ISA = qw(Exporter);
 
29
 
 
30
@EXPORT = qw( apropos aproposover usage help sig badinfo );
 
31
 
 
32
use PDL::Doc;
 
33
use IO::File;
 
34
use Pod::Text;
 
35
 
 
36
$PDL::onlinedoc = undef;
 
37
$PDL::onlinedoc = new PDL::Doc (FindStdFile());
 
38
 
 
39
use PDL::Config;
 
40
my $bvalflag = $PDL::Config{WITH_BADVAL} || 0;
 
41
 
 
42
# pod commands are stripped from the ref string before printing.
 
43
# How we do this depends on the version of Pod::Text installed.
 
44
#
 
45
# I'm guessing the difference in behaviour is between versions
 
46
# 1 and 2 of Pod::Text (it's certainly true for 
 
47
# version 1.0203 (perl5.005_03) and 2.03 (perl 5.6.0))
 
48
#
 
49
# version 1:
 
50
#  we use a private routine from Pod::Text
 
51
#  (prepare_for_output) in printmatch() in order
 
52
#  to strip away pod directives from the ref
 
53
#  string
 
54
#
 
55
# version 2: (Thanks to Tim Jenness)
 
56
#  create an object and use the interpol() method
 
57
#
 
58
 
 
59
# Find std file
 
60
 
 
61
sub FindStdFile {
 
62
  my ($d,$f);
 
63
  for $d (@INC) {
 
64
      $f = $d."/PDL/pdldoc.db";
 
65
      if (-f $f) {
 
66
         print "Found docs database $f\n" if $PDL::verbose;
 
67
         print "Type 'help' for online help\n" if $PDL::verbose;
 
68
         return $f;
 
69
      }
 
70
  }
 
71
  warn "Unable to find PDL/pdldoc.db in ".join(":",@INC)."\n";
 
72
}
 
73
 
 
74
# used to find out how wide the screen should be
 
75
# for printmatch() - really should check for a 
 
76
# sensible lower limit (for printmatch >~ 40
 
77
# would be my guess)
 
78
#
 
79
# taken from Pod::Text (v1.0203), then hacked to get it
 
80
# to work (at least on my solaris and linux
 
81
# machines)
 
82
#
 
83
sub screen_width() {
 
84
    return $ENV{COLUMNS}
 
85
       || (($ENV{TERMCAP} =~ /co#(\d+)/) and $1)
 
86
       || ($^O ne 'MSWin32' and $^O ne 'dos' and 
 
87
           (`stty -a 2>/dev/null` =~ /columns\s*=?\s*(\d+)/) and $1)
 
88
       || 72;
 
89
}
 
90
 
 
91
# the $^W assignment stops Pod::Text::fill() from 
 
92
# generating "Use of uninitialised values" errors
 
93
#
 
94
sub printmatch {
 
95
    my @match = @_;
 
96
    if (@match) {
 
97
        foreach my $t ( format_ref( @_ ) ) { print $t; }
 
98
    } else {
 
99
        print "no match\n\n";
 
100
    }
 
101
} # sub: print_match()
 
102
 
 
103
# return a string containing a formated version of the Ref string
 
104
# for the given matches
 
105
#
 
106
sub format_ref {
 
107
    my @match = @_;
 
108
    my @text = ();
 
109
 
 
110
    # XXX this is NASTY
 
111
    my $width = screen_width()-17;
 
112
    if ( $Pod::Text::VERSION < 2 ) {
 
113
        $Pod::Text::indent = 0;
 
114
        $Pod::Text::SCREEN = $width;
 
115
        local $^W = 0;
 
116
        for my $m (@match) { 
 
117
            $_ = $m->[1]->{Ref} || "[No reference available]";
 
118
          Pod::Text::prepare_for_output(); # adds a '\n' to $_
 
119
            $_ = Pod::Text::fill $_; # try and get `nice' wrapping 
 
120
            s/\n*$//; # remove last new lines (so substitution doesn't append spaces at end of text)
 
121
            s/\n/\n                /g;
 
122
            my $name = $m->[0];
 
123
            if ( length($name) > 15 ) { 
 
124
                push @text, sprintf "%s ...\n                %s\n", $name, $_; 
 
125
            } else {
 
126
                push @text, sprintf "%-15s %s\n", $name, $_; 
 
127
            }
 
128
        }
 
129
    } else {
 
130
        my $parser = new Pod::Text( width => $width, indent => 0, sentence => 0 );
 
131
        
 
132
        for my $m (@match) { 
 
133
            my $ref = $m->[1]->{Ref} || "[No reference available]";
 
134
            $ref = $parser->interpolate( $ref );
 
135
            $ref = $parser->reformat( $ref );
 
136
            
 
137
            # remove last new lines (so substitution doesn't append spaces at end of text)
 
138
            $ref =~ s/\n*$//; 
 
139
            $ref =~ s/\n/\n                /g;
 
140
 
 
141
            my $name = $m->[0];
 
142
            if ( length($name) > 15 ) { 
 
143
                push @text, sprintf "%s ...\n                %s\n", $name, $ref; 
 
144
            } else {
 
145
                push @text, sprintf "%-15s %s\n", $name, $ref; 
 
146
            }
 
147
        }
 
148
    }
 
149
    return wantarray ? @text : $text[0];
 
150
 
 
151
} # sub: format_ref()
 
152
 
 
153
=head2 apropos
 
154
 
 
155
=for ref
 
156
 
 
157
Regex search PDL documentation database
 
158
 
 
159
=for usage
 
160
 
 
161
 apropos 'text'
 
162
 
 
163
=for example
 
164
 
 
165
 perldl> apropos 'pic'
 
166
 rpic            Read images in many formats with automatic format detection.
 
167
 rpiccan         Test which image formats can be read/written
 
168
 wmpeg           Write an image sequence ((x,y,n) piddle) as an MPEG animation.
 
169
 wpic            Write images in many formats with automatic format selection.
 
170
 wpiccan         Test which image formats can be read/written
 
171
 
 
172
To find all the manuals that come with PDL, try
 
173
 
 
174
  apropos 'manual:'
 
175
 
 
176
and to get quick info about PDL modules say
 
177
 
 
178
  apropos 'module:'
 
179
 
 
180
You get more detailed info about a PDL function/module/manual
 
181
with the C<help> function
 
182
 
 
183
=cut
 
184
 
 
185
sub aproposover {
 
186
    die "Usage: aproposover \$funcname\n" unless $#_>-1;
 
187
    die "no online doc database" unless defined $PDL::onlinedoc;
 
188
    my $func = shift;
 
189
    return $PDL::onlinedoc->search($func,['Name','Ref','Module'],1);
 
190
}
 
191
 
 
192
sub apropos  {
 
193
    die "Usage: apropos \$funcname\n" unless $#_>-1;
 
194
    die "no online doc database" unless defined $PDL::onlinedoc;
 
195
    my $func = shift;
 
196
    printmatch aproposover $func;
 
197
}
 
198
 
 
199
sub finddoc  {
 
200
    die 'Usage: doc $topic' unless $#_>-1;
 
201
    die "no online doc database" unless defined $PDL::onlinedoc;
 
202
    my $topic = shift;
 
203
 
 
204
    # See if it matches a PDL function name
 
205
    my @match = $PDL::onlinedoc->search("m/^(PDL::)?$topic\$/",['Name']);
 
206
 
 
207
    die "Unable to find PDL docs on $topic\n"
 
208
        if $#match == -1;
 
209
 
 
210
    # print out the matches
 
211
    # - do not like this solution when have multiple matches
 
212
    #   but looping through each match didn't seem right either
 
213
    my $m = shift @match;
 
214
    my $Ref = $m->[1]{Ref};
 
215
    if ( $Ref =~ /^(Module|Manual|Script): / ) {
 
216
        system("pod2text $m->[1]{File} | $PDL::Doc::pager");
 
217
    } else {
 
218
        my $out = IO::File->new( "| pod2text | $PDL::Doc::pager" );
 
219
        print $out "=head1 Module\n\n",$m->[1]{Module}, "\n\n";
 
220
        $PDL::onlinedoc->funcdocs($m->[0],$out);
 
221
    }
 
222
    if ( $#match > -1 ) {
 
223
        print "\nFound other matches for $topic:\n";
 
224
        foreach my $m ( @match ) {
 
225
            printf "  %-30s in %s\n", $m->[0], $m->[1]{Module};
 
226
        }
 
227
    }
 
228
}
 
229
 
 
230
=head2 usage
 
231
 
 
232
=for ref
 
233
 
 
234
Prints usage information for a PDL function
 
235
 
 
236
=for usage
 
237
 
 
238
 Usage: usage 'func'
 
239
 
 
240
=for example
 
241
 
 
242
   perldl> usage 'inner'
 
243
 
 
244
   inner           inner prodcuct over one dimension
 
245
                   (Module PDL::Primitive)
 
246
 
 
247
   Signature: inner(a(n); b(n); [o]c(); )
 
248
 
 
249
 
 
250
=cut
 
251
 
 
252
sub usage {
 
253
    die 'Usage: usage $funcname' unless $#_>-1;
 
254
    die "no online doc database" unless defined $PDL::onlinedoc;
 
255
    print usage_string(@_);
 
256
}
 
257
sub usage_string{
 
258
    my $func = shift;
 
259
    my $str = "";
 
260
    my @match = $PDL::onlinedoc->search("m/^(PDL::)?$func\$/",['Name']);
 
261
    unless (@match) { print "\n  no match\n" } 
 
262
    else {
 
263
        $str .= "\n" . format_ref( $match[0] );
 
264
        my ($name,$hash) = @{$match[0]};
 
265
        $str .= sprintf ( (' 'x16)."(Module %s)\n\n", $hash->{Module} );
 
266
        die "No usage info found for $func\n"
 
267
            if !defined $hash->{Example} && !defined $hash->{Sig} &&
 
268
                !defined $hash->{Usage};
 
269
        $str .= "  Signature: $name($hash->{Sig})\n\n" if defined $hash->{Sig};
 
270
        for (['Usage','Usage'],['Opt','Options'],['Example','Example']) {
 
271
            $str .= "  $_->[1]:\n\n".&allindent($hash->{$_->[0]},10)."\n\n"
 
272
                if defined $hash->{$_->[0]};
 
273
        }
 
274
    }
 
275
    return $str;
 
276
}
 
277
 
 
278
=head2 sig
 
279
 
 
280
=for ref
 
281
 
 
282
prints signature of PDL function
 
283
 
 
284
=for usage
 
285
 
 
286
 sig 'func'
 
287
 
 
288
The signature is the normal dimensionality of the
 
289
functions arguments. Calling with different dimensions
 
290
causes 'threading' - see C<PDL::PP> for more details.
 
291
 
 
292
=for example
 
293
 
 
294
  perldl> sig 'outer'
 
295
    Signature: outer(a(n); b(m); [o]c(n,m); )
 
296
 
 
297
 
 
298
=cut
 
299
 
 
300
sub sig {
 
301
        die "Usage: sig \$funcname\n" unless $#_>-1;
 
302
        die "no online doc database" unless defined $PDL::onlinedoc;
 
303
        my $func = shift;
 
304
        my @match = $PDL::onlinedoc->search("m/^(PDL::)?$func\$/",['Name']);
 
305
        unless (@match) { print "\n  no match\n" } else {
 
306
         my ($name,$hash) = @{$match[0]};
 
307
         die "No signature info found for $func\n"
 
308
            if !defined $hash->{Sig};
 
309
         print "  Signature: $name($hash->{Sig})\n" if defined $hash->{Sig};
 
310
        }
 
311
}
 
312
 
 
313
sub allindent {
 
314
        my ($txt,$n) = @_;
 
315
        my ($ntxt,$tspc) = ($txt,' 'x8);
 
316
        $ntxt =~ s/^\s*$//mg;
 
317
        $ntxt =~ s/\t/$tspc/g;
 
318
        my $minspc = length $txt;
 
319
        for (split '\n', $txt) { if (/^(\s*)/)
 
320
          { $minspc = length $1 if length $1 < $minspc } }
 
321
        $n -= $minspc;
 
322
        $tspc = ' 'x abs($n);
 
323
        $ntxt =~ s/^/$tspc/mg if $n > 0;
 
324
        return $ntxt;
 
325
}
 
326
 
 
327
 
 
328
=head2 help
 
329
 
 
330
=for ref
 
331
 
 
332
print documentation about a PDL function or module or show a PDL manual
 
333
 
 
334
In the case of multiple matches, the first command found is printed out,
 
335
and the remaining commands listed, along with the names of their modules.
 
336
 
 
337
=for usage
 
338
 
 
339
 Usage: help 'func'
 
340
 
 
341
=for example
 
342
 
 
343
 perldl> help 'PDL::Slices'   # show the docs in the PDL::Slices module
 
344
 perldl> help 'PDL::Intro'    # show the PDL::Intro manual
 
345
 perldl> help 'slice'         # show docs on the 'slice' function
 
346
 
 
347
=cut
 
348
 
 
349
sub help {
 
350
  if ($#_>-1) {
 
351
      require PDL::Dbg;
 
352
      my $topic = shift;
 
353
      if (PDL::Core::blessed($topic) && $topic->can('px')) {
 
354
          local $PDL::debug = 1;
 
355
          $topic->px('This variable is');
 
356
      } else {
 
357
          $topic = 'PDL::Doc::Perldl' if $topic =~ /^\s*help\s*$/i;
 
358
          if ($topic =~ /^\s*vars\s*$/i) {
 
359
              PDL->px((caller)[0]);
 
360
          } else {
 
361
              finddoc($topic);
 
362
          }
 
363
      }
 
364
  } else {
 
365
        print <<'EOH';
 
366
 
 
367
The following four commands support online help in the perldl shell:
 
368
 
 
369
  help            -- print this text
 
370
  help 'thing'    -- print the docs on 'thing' (can be function/module/manual)
 
371
  help $a         -- print information about $a (if it's a piddle)
 
372
  help vars       -- print information about all current piddles
 
373
  apropos 'word'  -- search for keywords/function names in the list of
 
374
                     documented PDL functions
 
375
  ?               -- alias for 'help'
 
376
  ??              -- alias for 'apropos'
 
377
  usage           -- print usage information for a given PDL function
 
378
  sig             -- print signature of PDL function
 
379
EOH
 
380
 
 
381
print "  badinfo         -- information on the support for bad values\n"
 
382
   if $bvalflag;
 
383
 
 
384
print <<'EOH';
 
385
 
 
386
  Quick start:
 
387
 
 
388
  apropos 'manual:' -- Find all the manual documents
 
389
  apropos 'module:' -- Quick summary of all PDL modules
 
390
  help 'help'       -- details about PDL help system
 
391
  help 'perldl'     -- help about this shell
 
392
 
 
393
EOH
 
394
  }
 
395
}
 
396
 
 
397
=head2 badinfo
 
398
 
 
399
=for ref
 
400
 
 
401
provides information on the bad-value support of a function
 
402
 
 
403
And has a horrible name.
 
404
 
 
405
=for usage
 
406
 
 
407
 badinfo 'func'
 
408
 
 
409
=cut
 
410
 
 
411
# need to get this to format the output - want a format_bad()
 
412
# subroutine that's like - but much simpler - than format_ref()
 
413
#
 
414
sub badinfo {
 
415
    my $func = shift;
 
416
    die "Usage: badinfo \$funcname\n" unless defined $func;
 
417
 
 
418
    die "PDL has not been compiled with support for bad values.\n" .
 
419
        "Recompile with WITH_BADVAL set to 1 in config file!.\n"
 
420
            unless $bvalflag;
 
421
 
 
422
    die "no online doc database" unless defined $PDL::onlinedoc;
 
423
 
 
424
    my @match = $PDL::onlinedoc->search("m/^(PDL::)?$func\$/",['Name']);
 
425
    if ( @match ) {
 
426
        my ($name,$hash) = @{$match[0]};
 
427
        my $info = $hash->{Bad};
 
428
 
 
429
        if ( defined $info ) {
 
430
            my $out = new IO::File "| pod2text | $PDL::Doc::pager";
 
431
            print $out "=head1 Bad value support for $name\n\n$info\n";
 
432
        } else {
 
433
            print "\n  No information on bad-value support found for $func\n";
 
434
        }
 
435
    } else {
 
436
        print "\n  no match\n";
 
437
    }
 
438
} # sub: badinfo()
 
439
 
 
440
1; # OK