www: Drop search autocomplete, but make search itself a bit more useful

This commit is contained in:
Yorhel 2024-04-29 11:23:44 +02:00
parent fc9a19e7c4
commit 9a81147983
3 changed files with 31 additions and 252 deletions

View file

@ -2,7 +2,7 @@
use v5.26;
use warnings;
use TUWF ':html5_', ':xml';
use TUWF ':html5_', ':xml', 'uri_escape';
use POSIX 'ceil';
use List::Util 'uniq', 'min';
use SQL::Interp 'sql', 'sql_interp';
@ -206,14 +206,14 @@ sub framework_ {
html_ lang => 'en', sub {
head_ sub {
link_ rel => 'stylesheet', type => 'text/css', href => '/man.css?5';
link_ rel => 'stylesheet', type => 'text/css', href => '/man.css?6';
title_ $o{title}.' - manned.org';
};
body_ sub {
header_ sub {
a_ href => '/', 'Manned.org';
form_ action => '/browse/search', method => 'get', sub {
input_ type => 'text', name => 'q', id => 'q', tabindex => 1;
input_ type => 'text', name => 'q', id => 'q', placeholder => 'ncdu, btrfs.8, git-*', value => $o{q}, tabindex => 1;
input_ type => 'submit', value => 'Search';
}
};
@ -226,7 +226,7 @@ sub framework_ {
};
span_ 'all manual pages are copyrighted by their respective authors.';
};
script_ type => 'text/javascript', src => '/man.js', '';
script_ type => 'text/javascript', src => '/man.js?2', '';
}
};
@ -592,57 +592,46 @@ TUWF::get '/info/about' => sub {
};
# Very simple (and fast) prefix match.
sub search_man {
my($q, $limit) = @_;
my $sect = $q =~ s/^([0-9])\s+// || $q =~ s/\(([a-zA-Z0-9]+)\)$// ? $1 : '';
my $name = $q =~ s/^([a-zA-Z0-9,.:_-]+)// ? $1 : '';
return !$name ? [] : tuwf->dbAlli(
'SELECT name, section FROM mans WHERE', sql_and(
sql('lower(name) LIKE', \(escape_like(lc $name).'%')),
$sect ? sql('section ILIKE', \(escape_like(lc $sect).'%')) : (),
), 'ORDER BY name, section LIMIT', \$limit,
);
}
TUWF::get '/browse/search' => sub {
my $q = tuwf->reqGet('q')||'';
my $man = search_man $q, 150;
return tuwf->resRedirect("/$man->[0]{name}.$man->[0]{section}", 'temp') if @$man == 1;
framework_ title => 'Search results for '.$q, mainclass => 'searchres', sub {
h1_ 'Search results for '.$q;
# Package search would also be useful.
p_ 'Note: This is just a simple case-insensitive prefix match on the man names. In the future we\'ll have more powerful search functionality. Hopefully.';
if(@$man) {
my $name = $q;
my $sect = $name =~ s/^([0-9])\s+// || $name =~ s/\(([a-zA-Z0-9]+)\)$// || $name =~ s/\.([0-9][a-zA-Z0-9]*)$// ? $1 : '';
($name,$sect) = ($sect,'') if !length $name;
# Redirect if we have an exact match
my @sectsql = length $sect ? ('AND section =', \$sect) : ();
my $man = length $name && tuwf->dbRowi('SELECT name, section FROM mans WHERE name =', \$name, @sectsql);
return tuwf->resRedirect("/man/$man->{name}.$man->{section}", 'temp') if length $man->{name};
# Otherwise, do case-insensitive glob search
my $nameq = escape_like(lc $name) =~ tr/?*/_%/r;
my $lst = !length $nameq ? [] : tuwf->dbAlli('
SELECT name, section
FROM mans WHERE lower(name) LIKE', \$nameq, @sectsql, '
ORDER BY name, section
LIMIT 500');
framework_ title => 'Search results for '.$q, mainclass => 'searchres', q => $q, sub {
h1_ 'Search results for '.(length $sect ? "$name in section $sect" : $q);
if(@$lst) {
p_ 'Truncated to the first 500 results.' if @$lst >= 150;
ul_ sub {
li_ sub {
a_ href => "/$_->{name}.$_->{section}", $_->{name};
a_ href => "/man/$_->{name}.$_->{section}", $_->{name};
small_ " $_->{section}";
} for @$man;
} for @$lst;
}
} else {
p_ 'No results :-(';
p_ sub {
a_ href => '?q='.uri_escape($name), 'Try again in other sections?' if length $sect;
};
}
};
};
TUWF::get '/xml/search.xml' => sub {
my $q = tuwf->reqGet('q')||'';
my $man = search_man $q, 20;
tuwf->resHeader('Content-Type' => 'text/xml; charset=UTF-8');
xml;
tag 'results', sub {
tag 'item', id => "$_->{name}.$_->{section}", %$_, undef for @$man;
};
};
# Object to represent the various URLs to a man page.
#
# Parameters: