Unknown reporter writes
Trying to add my own custom field:
#!config
[prefixes]
sub = XYSUB
The html files will then have something like:
#!html
<head >
<title >Perl::Strip - reduce file size by stripping whitespace, comments, pod etc.</title >
<meta http-equiv="content-type" content="text/html; charset=utf-8" / >
<link rev="made" href="mailto:root@localhost" / >
<meta name="sub" content="document strip"/ >
</head >
When I run index I get the following in the log:
#!log
:5:../rcldb/rcldb.cpp:928:Db::add: no prefix for field [docsize], no indexing
:5:../rcldb/rcldb.cpp:933:Db::add: field [filename] pfx [XSFN] inc 1: [Strip.pm]
:5:../rcldb/rcldb.cpp:928:Db::add: no prefix for field [md5], no indexing
:5:../rcldb/rcldb.cpp:933:Db::add: field [sub] pfx [XYSUB] inc 1: [document strip]
:5:../rcldb/rcldb.cpp:933:Db::add: field [title] pfx [S] inc 1: [document strip Perl::Strip - reduce file size by stripping whitespace, comments, pod etc.]
Notice in the above my sub field information is getting included in the beginning of my title field. Not sure what I’m doing that is causing this but I would like for the title to only have the title information.
medoc writes
What version are you using ? I can’t seem to reproduce it directly. jf
medoc writes
Could you please also attach the exact HTML file you are using ? Having no luck in reproducing the problem.
mmcgillis writes
Recoll 1.18.1 + Xapian 1.2.7
Fedora 16 with recoll-1.18.1-1.fc16.i686
This works for me to reproducing:
#!html
<html >
<head >
<title >Perl::Strip - reduce file size by stripping whitespace, comments, pod etc.</title >
<meta http-equiv="content-type" content="text/html; charset=utf-8" / >
<link rev="made" href="mailto:root@localhost" / >
<meta name="sub" content="document strip"/ >
</head >
<body >
</body >
</html >
mmcgillis writes
Actually the above is not true. So maybe this has to do with some of the other stuff I’m doing. What I’m trying to do is process all perl files and generate two results for a single file one result is the raw code as text/plain the other result is the pod which would be text/html. The first issue I ran into is recoll is not very good at detecting perl files. recoll only looks at extensions and I need something that will look at the file to decide. So I created my own mimeconf
#!config
[index]
application/x-perl = execm rclperl
text/plain = execm rclperl
As indicated above that uses rclperl which currently is this:
#!python
#!/usr/bin/env python
# Perl file filter for Recoll
import re
import subprocess
import sys
sys.path.append("/usr/share/recoll/filters")
import rclexecm
class PerlExtractor:
def __init__(self, em):
self.currentindex = 0
self.em = em
def extractone(self, ipath):
#self.em.rclog("extractone: [%s]" % ipath)
iseof = rclexecm.RclExecM.noteof
p=subprocess.Popen(["file",self.filename],stdout=subprocess.PIPE)
x=p.stdout.read()
isPerl=(re.search("perl",x,re.IGNORECASE)!=None)
#self.em.rclog("isPerl: [%s]" % isPerl)
docdata = ""
if (ipath == "pod"):
self.em.setmimetype("text/html")
p=subprocess.Popen(["rclpod",self.filename],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
docdata=p.stdout.read()
iseof = rclexecm.RclExecM.eofnext
elif (isPerl):
self.em.setmimetype("text/x-perl")
# generate code content
f=open(self.filename,"r")
docdata= f.read()
f.close()
# check for pod
p=subprocess.Popen(["podchecker",self.filename],stderr=subprocess.PIPE)
x=p.stderr.read()
isPod=(re.search("does not contain any pod commands",x,re.IGNORECASE)==None)
#self.em.rclog("isPOD: [%s]" % isPod)
if (not isPod):
iseof = rclexecm.RclExecM.eofnext
else:
self.em.setmimetype("text/plain")
f=open(self.filename,"r")
docdata= f.read()
f.close()
iseof = rclexecm.RclExecM.eofnext
ok = True
self.currentindex = 0
return (ok, docdata, ipath, iseof)
###### File type handler api, used by rclexecm ---------- >
def openfile(self, params):
self.currentindex = -1
try:
self.filename = params["filename:"]
return True
except:
return False
def getipath(self, params):
ipath = params["ipath:"]
return self.extractone(ipath)
def getnext(self, params):
if self.currentindex == -1:
# Return "self" doc
return self.extractone("")
return self.extractone("pod")
# Main program: create protocol handler and extractor and run them
proto = rclexecm.RclExecM()
extract = PerlExtractor(proto)
rclexecm.main(proto, extract)
The basic idea of the above is if something is determined to actually be a perl file first generate the code using a empty ipath then if the perl code does have pod generate a html file for the pod using an ipath of "pod".
To actually generate the pod pice for the above I use this perl script:
#!perl
#!/usr/bin/perl
use lib("/home/matthew/tools/perl-strip/lib");
use Pod::Html;
use Perl::Strip;
pod2html("--cachedir=/tmp","--infile=$ARGV[0]","--outfile=/tmp/o");
open(FILE,$ARGV[0]);
my $code="";
while (<FILE >) {
$code.=$_;
}
close(FILE);
my $ps=Perl::Strip- >new();
my $striped=$ps- >strip($code);
my @sub=();
while ($striped=~/sub ([\w]+)/g) {
push(@sub,$1);
}
print "@sub\n";
open(INFILE,"</tmp/o");
open(OUTFILE," >/tmp/o2");
while (<INFILE >) {
if ($_ =~ /\<\/head\ >/) {
print OUTFILE '<meta name="sub" content="'.join(" ",@sub).'"/ >'."\n";
}
print OUTFILE $_;
}
close(INFILE);
close(OUTFILE);
system("cat /tmp/o2");
unlink("/tmp/pod2htmd.tmp");
unlink("/tmp/pod2htmi.tmp");
unlink("/tmp/o");
unlink("/tmp/o2");
So with all the above in place if I then process this file Strip.pm
#!perl
=head1 NAME
Perl::Strip - reduce file size by stripping whitespace, comments, pod etc.
=head1 SYNOPSIS
use Perl::Strip;
=head1 DESCRIPTION
This module transforms perl sources into a more compact format. It does
this by removing most whitespace, comments, pod, and by some other means.
The resulting code looks obfuscated, but perl (and the deparser) don't
have any problems with that. Depending on the source file you can expect
about 30-60% "compression".
The main target for this module is low-diskspace environments, such as
L<App::Staticperl >, boot floppy/CDs/flash environments and so on.
See also the commandline utility L<perlstrip >.
=head1 METHODS
The C<Perl::Strip > class is a subclsass of L<PPI::Transform >, and as such
inherits all of it's methods, even the ones not documented here.
=over 4
=cut
package Perl::Strip;
our $VERSION = '1.1';
our $CACHE_VERSION = 2;
use common::sense;
use PPI;
use base PPI::Transform::;
=item my $transform = new Perl::Strip key = > value...
Creates a new Perl::Strip transform object. It supports the following
parameters:
=over 4
=item optimise_size = > $bool
By default, this module optimises I<compressability >, not raw size. This
switch changes that (and makes it slower).
=item keep_nl = > $bool
By default, whitespace will either be stripped or replaced by a space. If
this option is enabled, then newlines will not be removed. This has the
advantage of keeping line number information intact (e.g. for backtraces),
but of course doesn't compress as well.
=item cache = > $path
Since this module can take a very long time (minutes for the larger files
in the perl distribution), it can utilise a cache directory. The directory
will be created if it doesn't exist, and can be deleted at any time.
=back
=cut
# PPI::Transform compatible
sub document {
my ($self, $doc) = @_;
$self- >{optimise_size} = 1; # more research is needed
# special stripping for unicore/ files
if (eval { $doc- >child (1)- >content =~ /^# .* (build by mktables|machine-generated .*mktables) / }) {
for my $heredoc (@{ $doc- >find (PPI::Token::HereDoc::) }) {
my $src = join "", $heredoc- >heredoc;
# special stripping for unicore swashes and properties
# much more could be done by going binary
for ($src) {
s/^(?:0*([0-9a-fA-F]+))?\t(?:0*([0-9a-fA-F]+))?\t(?:0*([0-9a-fA-F]+))?/$1\t$2\t$3/gm
if $self- >{optimise_size};
# s{
# ^([0-9a-fA-F]+)\t([0-9a-fA-F]*)\t
# }{
# # ww - smaller filesize, UU - compress better
# pack "C0UU",
# hex $1,
# length $2 ? (hex $2) - (hex $1) : 0
# }gemx;
s/#.*\n/\n/mg;
s/\s+\n/\n/mg;
}
# PPI seems to be mostly undocumented
$heredoc- >{_heredoc} = [split /$/, $src];
}
}
$doc- >prune (PPI::Token::Comment::);
$doc- >prune (PPI::Token::Pod::);
# prune END stuff
for (my $last = $doc- >last_element; $last; ) {
my $prev = $last- >previous_token;
if ($last- >isa (PPI::Token::Whitespace::)) {
$last- >delete;
} elsif ($last- >isa (PPI::Statement::End::)) {
$last- >delete;
last;
} elsif ($last- >isa (PPI::Token::Pod::)) {
$last- >delete;
} else {
last;
}
$last = $prev;
}
# prune some but not all insignificant whitespace
for my $ws (@{ $doc- >find (PPI::Token::Whitespace::) }) {
my $prev = $ws- >previous_token;
my $next = $ws- >next_token;
if (!$prev || !$next) {
$ws- >delete;
} else {
if (
$next- >isa (PPI::Token::Operator::) && $next- >{content} =~ /^(?:,|=|!|!=|==|= >)$/ # no ., because of digits. == float
or $prev- >isa (PPI::Token::Operator::) && $prev- >{content} =~ /^(?:,|=|\.|!|!=|==|= >)$/
or $prev- >isa (PPI::Token::Structure::)
or ($self- >{optimise_size} &&
($prev- >isa (PPI::Token::Word::)
&& (PPI::Token::Symbol:: eq ref $next
|| $next- >isa (PPI::Structure::Block::)
|| $next- >isa (PPI::Structure::List::)
|| $next- >isa (PPI::Structure::Condition::)))
)
) {
$ws- >delete;
} elsif ($prev- >isa (PPI::Token::Whitespace::)) {
$ws- >{content} = ' ';
$prev- >delete;
} else {
$ws- >{content} = ' ';
}
}
}
# prune whitespace around blocks, also ";" at end of blocks
if ($self- >{optimise_size}) {
# these usually decrease size, but decrease compressability more
for my $struct (PPI::Structure::Block::, PPI::Structure::Condition::, PPI::Structure::List::) {
for my $node (@{ $doc- >find ($struct) }) {
my $n1 = $node- >first_token;
# my $n2 = $n1- >previous_token;
my $n3 = $n1- >next_token;
$n1- >delete if $n1- >isa (PPI::Token::Whitespace::);
# $n2- >delete if $n2 && $n2- >isa (PPI::Token::Whitespace::); # unsafe! AE::timer $MAX_SIGNAL_LATENCY -($NOW - int$NOW)
$n3- >delete if $n3 && $n3- >isa (PPI::Token::Whitespace::);
my $n1 = $node- >last_token;
my $n2 = $n1- >next_token;
my $n3 = $n1- >previous_token;
$n1- >delete if $n1- >isa (PPI::Token::Whitespace::);
$n2- >delete if $n2 && $n2- >isa (PPI::Token::Whitespace::);
$n3- >{content} = "" # delete seems to trigger a bug inside PPI
if $n3 && ($n3- >isa (PPI::Token::Whitespace::)
|| ($n3- >isa (PPI::Token::Structure::) && $n3- >content eq ";"));
}
}
}
# foreach = > for
for my $node (@{ $doc- >find (PPI::Statement::Compound::) }) {
if (my $n = $node- >first_token) {
$n- >{content} = "for" if $n- >{content} eq "foreach" && $n- >isa (PPI::Token::Word::);
}
}
# reformat qw() lists which often have lots of whitespace
for my $node (@{ $doc- >find (PPI::Token::QuoteLike::Words::) }) {
if ($node- >{content} =~ /^qw(.)(.*)(.)$/s) {
my ($a, $qw, $b) = ($1, $2, $3);
$qw =~ s/^\s+//;
$qw =~ s/\s+$//;
$qw =~ s/\s+/ /g;
$node- >{content} = "qw$a$qw$b";
}
}
# prune return at end of sub-blocks
#TODO:
# PPI::Document
# PPI::Statement::Sub
# PPI::Token::Word 'sub'
# PPI::Token::Whitespace ' '
# PPI::Token::Word 'f'
# PPI::Structure::Block { ... }
# PPI::Statement
# PPI::Token::Word 'sub'
# PPI::Structure::Block { ... }
# PPI::Statement::Break
# PPI::Token::Word 'return'
# PPI::Token::Whitespace ' '
# PPI::Token::Number '5'
# PPI::Token::Structure ';'
# PPI::Statement::Compound
# PPI::Structure::Block { ... }
# PPI::Statement::Break
# PPI::Token::Word 'return'
# PPI::Token::Whitespace ' '
# PPI::Token::Number '8'
# PPI::Statement::Break
# PPI::Token::Word 'return'
# PPI::Token::Whitespace ' '
# PPI::Token::Number '7'
1
}
=item $perl = $transform- >strip ($perl)
Strips the perl source in C<$perl > and returns the stripped source.
=cut
sub strip {
my ($self, $src) = @_;
my $filter = sub {
my $ppi = new PPI::Document \$src
or return;
$self- >document ($ppi)
or return;
$src = $ppi- >serialize;
};
if (exists $self- >{cache} && (2048 <= length $src)) {
my $file = "$self- >{cache}/" . Digest::MD5::md5_hex "$CACHE_VERSION \n" . (!!$self- >{optimise_size}) . "\n\x00$src";
if (open my $fh, "<:perlio", $file) {
# zero size means unchanged
if (-s $fh) {
local $/;
$src = <$fh >
}
} else {
my $oldsrc = $src;
$filter- >();
mkdir $self- >{cache};
if (open my $fh, " >:perlio", "$file~") {
# write a zero-byte file if source is unchanged
if ($oldsrc eq $src or (syswrite $fh, $src) == length $src) {
close $fh;
rename "$file~", $file;
}
}
}
} else {
$filter- >();
}
$src
}
=back
=head1 SEE ALSO
L<App::Staticperl >, L<Perl::Squish >.
=head1 AUTHOR
Marc Lehmann <schmorp@schmorp.de >
http://home.schmorp.de/
=cut
1;
Then I get the results indicated.
mmcgillis writes
Sorry my fault the rclpod script still has some extra output. It is printing the sub information to stdout which is some how getting picked up in the title. I removed the print in this and problem solved:
#!perl
my @sub=();
while ($striped=~/sub ([\w]+)/g) {
push(@sub,$1);
}
print "@sub\n";
mmcgillis writes
Well with the above information this is the actual file that would produce the problem results:
#!html
document strip
<html >
<head >
<title >Perl::Strip - reduce file size by stripping whitespace, comments, pod etc.</title >
<meta http-equiv="content-type" content="text/html; charset=utf-8" / >
<link rev="made" href="mailto:root@localhost" / >
<meta name="sub" content="document strip"/ >
</head >
<body >
</body >
</html >
medoc writes
Ok, thanks, then this is an issue with the html parser. This text should probably not be discarded, but inserting it in the title does not seem right either… Apparently Firefox prepends it to the body, which is probably not standardized but the right approach. I’ll see if this is feasible with the parser used in Recoll.
I did not look at the scripts in much detail because I’m really not a Perl guy. Don’t hesitate to come back to me if there are things which don’t work as they could on the recoll side.
About the file type detection: for files without suffixes or with unknown suffixes, recoll will call "file -i" as a last resort. So, if "file" is better at recognizing perl files, you could try to remove any mistaken suffix from the mimemap file and let the "file" command do its thing. Unfortunately, there is no way to substract suffixes in the personal config, so you’ll have to modify the mimemap installed in /usr/share/recoll
mmcgillis writes
You can see in my rclperl I also use file because it will do a good job of detection perl but not if you restrict it to mime types. Meaning the file -i will still get things wrong but file when it uses magic to detect the type will properly identify perl files "man magic" for more details.
mmcgillis writes
Looks like file vs file -i issue is a bad magic config on some linux boxes. Not a recall issue.
medoc writes
HTML: do not concatenate text found before body tag with the title. Fixes issue #125
→ <<cset 5baf046df3f7 > >