]> Lady’s Gitweb - Gitweb/blobdiff - gitweb.perl
gitweb: Simplify fixed string search
[Gitweb] / gitweb.perl
index ff65d9a404f11c5771d6d149c54fc603b985c27c08e4ae7af17947f44ff91637..7a24642132f0003b920d657ebb8a71ae8478391742248f459a3180e3e06e826b 100755 (executable)
@@ -612,6 +612,8 @@ sub href(%) {
        );
        my %mapping = @mapping;
 
+       $params{'project'} = $project unless exists $params{'project'};
+
        if ($params{-replay}) {
                while (my ($name, $symbol) = each %mapping) {
                        if (!exists $params{$name}) {
@@ -621,8 +623,6 @@ sub href(%) {
                }
        }
 
-       $params{'project'} = $project unless exists $params{'project'};
-
        my ($use_pathinfo) = gitweb_check_feature('pathinfo');
        if ($use_pathinfo) {
                # use PATH_INFO for project name
@@ -849,32 +849,73 @@ sub project_in_list {
 ## ----------------------------------------------------------------------
 ## HTML aware string manipulation
 
+# Try to chop given string on a word boundary between position
+# $len and $len+$add_len. If there is no word boundary there,
+# chop at $len+$add_len. Do not chop if chopped part plus ellipsis
+# (marking chopped part) would be longer than given string.
 sub chop_str {
        my $str = shift;
        my $len = shift;
        my $add_len = shift || 10;
+       my $where = shift || 'right'; # 'left' | 'center' | 'right'
 
        # allow only $len chars, but don't cut a word if it would fit in $add_len
        # if it doesn't fit, cut it if it's still longer than the dots we would add
-       $str =~ m/^(.{0,$len}[^ \/\-_:\.@]{0,$add_len})(.*)/;
-       my $body = $1;
-       my $tail = $2;
-       if (length($tail) > 4) {
-               $tail = " ...";
-               $body =~ s/&[^;]*$//; # remove chopped character entities
+       # remove chopped character entities entirely
+
+       # when chopping in the middle, distribute $len into left and right part
+       # return early if chopping wouldn't make string shorter
+       if ($where eq 'center') {
+               return $str if ($len + 5 >= length($str)); # filler is length 5
+               $len = int($len/2);
+       } else {
+               return $str if ($len + 4 >= length($str)); # filler is length 4
+       }
+
+       # regexps: ending and beginning with word part up to $add_len
+       my $endre = qr/.{$len}\w{0,$add_len}/;
+       my $begre = qr/\w{0,$add_len}.{$len}/;
+
+       if ($where eq 'left') {
+               $str =~ m/^(.*?)($begre)$/;
+               my ($lead, $body) = ($1, $2);
+               if (length($lead) > 4) {
+                       $body =~ s/^[^;]*;// if ($lead =~ m/&[^;]*$/);
+                       $lead = " ...";
+               }
+               return "$lead$body";
+
+       } elsif ($where eq 'center') {
+               $str =~ m/^($endre)(.*)$/;
+               my ($left, $str)  = ($1, $2);
+               $str =~ m/^(.*?)($begre)$/;
+               my ($mid, $right) = ($1, $2);
+               if (length($mid) > 5) {
+                       $left  =~ s/&[^;]*$//;
+                       $right =~ s/^[^;]*;// if ($mid =~ m/&[^;]*$/);
+                       $mid = " ... ";
+               }
+               return "$left$mid$right";
+
+       } else {
+               $str =~ m/^($endre)(.*)$/;
+               my $body = $1;
+               my $tail = $2;
+               if (length($tail) > 4) {
+                       $body =~ s/&[^;]*$//;
+                       $tail = "... ";
+               }
+               return "$body$tail";
        }
-       return "$body$tail";
 }
 
 # takes the same arguments as chop_str, but also wraps a <span> around the
 # result with a title attribute if it does get chopped. Additionally, the
 # string is HTML-escaped.
 sub chop_and_escape_str {
-       my $str = shift;
-       my $len = shift;
-       my $add_len = shift || 10;
+       my ($str) = @_;
 
-       my $chopped = chop_str($str, $len, $add_len);
+       my $chopped = chop_str(@_);
        if ($chopped eq $str) {
                return esc_html($chopped);
        } else {
@@ -2039,7 +2080,7 @@ sub parse_commit {
 }
 
 sub parse_commits {
-       my ($commit_id, $maxcount, $skip, $arg, $filename) = @_;
+       my ($commit_id, $maxcount, $skip, $filename, @args) = @_;
        my @cos;
 
        $maxcount ||= 1;
@@ -2049,7 +2090,7 @@ sub parse_commits {
 
        open my $fd, "-|", git_cmd(), "rev-list",
                "--header",
-               ($arg ? ($arg) : ()),
+               @args,
                ("--max-count=" . $maxcount),
                ("--skip=" . $skip),
                @extra_options,
@@ -3785,18 +3826,24 @@ sub git_search_grep_body {
                print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
                      "<td><i>" . $author . "</i></td>\n" .
                      "<td>" .
-                     $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}), -class => "list subject"},
-                              chop_and_escape_str($co{'title'}, 50) . "<br/>");
+                     $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
+                              -class => "list subject"},
+                             chop_and_escape_str($co{'title'}, 50) . "<br/>");
                my $comment = $co{'comment'};
                foreach my $line (@$comment) {
                        if ($line =~ m/^(.*)($search_regexp)(.*)$/i) {
-                               my $lead = esc_html($1) || "";
-                               $lead = chop_str($lead, 30, 10);
-                               my $match = esc_html($2) || "";
-                               my $trail = esc_html($3) || "";
-                               $trail = chop_str($trail, 30, 10);
-                               my $text = "$lead<span class=\"match\">$match</span>$trail";
-                               print chop_str($text, 80, 5) . "<br/>\n";
+                               my ($lead, $match, $trail) = ($1, $2, $3);
+                               $match = chop_str($match, 70, 5, 'center');
+                               my $contextlen = int((80 - length($match))/2);
+                               $contextlen = 30 if ($contextlen > 30);
+                               $lead  = chop_str($lead,  $contextlen, 10, 'left');
+                               $trail = chop_str($trail, $contextlen, 10, 'right');
+
+                               $lead  = esc_html($lead);
+                               $match = esc_html($match);
+                               $trail = esc_html($trail);
+
+                               print "$lead<span class=\"match\">$match</span>$trail<br />";
                        }
                }
                print "</td>\n" .
@@ -5126,7 +5173,7 @@ sub git_history {
                $ftype = git_get_type($hash);
        }
 
-       my @commitlist = parse_commits($hash_base, 101, (100 * $page), "--full-history", $file_name);
+       my @commitlist = parse_commits($hash_base, 101, (100 * $page), $file_name, "--full-history");
 
        my $paging_nav = '';
        if ($page > 0) {
@@ -5208,14 +5255,16 @@ sub git_search {
                } elsif ($searchtype eq 'committer') {
                        $greptype = "--committer=";
                }
-               $greptype .= $search_regexp;
-               my @commitlist = parse_commits($hash, 101, (100 * $page), $greptype);
+               $greptype .= $searchtext;
+               my @commitlist = parse_commits($hash, 101, (100 * $page), undef,
+                                              $greptype, '--fixed-strings');
 
                my $paging_nav = '';
                if ($page > 0) {
                        $paging_nav .=
                                $cgi->a({-href => href(action=>"search", hash=>$hash,
-                                                      searchtext=>$searchtext, searchtype=>$searchtype)},
+                                                      searchtext=>$searchtext,
+                                                      searchtype=>$searchtype)},
                                        "first");
                        $paging_nav .= " &sdot; " .
                                $cgi->a({-href => href(-replay=>1, page=>$page-1),
@@ -5461,7 +5510,7 @@ sub git_feed {
 
        # log/feed of current (HEAD) branch, log of given branch, history of file/directory
        my $head = $hash || 'HEAD';
-       my @commitlist = parse_commits($head, 150, 0, undef, $file_name);
+       my @commitlist = parse_commits($head, 150, 0, $file_name);
 
        my %latest_commit;
        my %latest_date;
This page took 0.317087 seconds and 4 git commands to generate.