From e607b79fb14f2196f7ea46d2115f21c548972e78 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 27 Feb 2012 02:55:22 +0100 Subject: [PATCH] gitweb: Highlight matched part of shortened project description Previous commit make gitweb use esc_html_match_hl() to mark match in the _whole_ description of a project when searching projects. This commit makes gitweb highlight match in _shortened_ description, based on match in whole description, using esc_html_match_hl_chopped() subroutine. If match is in removed (chopped) part, even partially, then trailing "... " is highlighted. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 52 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 724f06f1f..01c13183c 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1742,20 +1742,61 @@ sub esc_html_hl_regions { return $out; } -# highlight match (if any), and escape HTML -sub esc_html_match_hl { +# return positions of beginning and end of each match +sub matchpos_list { my ($str, $regexp) = @_; - return esc_html($str) unless defined $regexp; + return unless (defined $str && defined $regexp); my @matches; while ($str =~ /$regexp/g) { push @matches, [$-[0], $+[0]]; } + return @matches; +} + +# highlight match (if any), and escape HTML +sub esc_html_match_hl { + my ($str, $regexp) = @_; + return esc_html($str) unless defined $regexp; + + my @matches = matchpos_list($str, $regexp); return esc_html($str) unless @matches; return esc_html_hl_regions($str, 'match', @matches); } + +# highlight match (if any) of shortened string, and escape HTML +sub esc_html_match_hl_chopped { + my ($str, $chopped, $regexp) = @_; + return esc_html_match_hl($str, $regexp) unless defined $chopped; + + my @matches = matchpos_list($str, $regexp); + return esc_html($chopped) unless @matches; + + # filter matches so that we mark chopped string + my $tail = "... "; # see chop_str + unless ($chopped =~ s/\Q$tail\E$//) { + $tail = ''; + } + my $chop_len = length($chopped); + my $tail_len = length($tail); + my @filtered; + + for my $m (@matches) { + if ($m->[0] > $chop_len) { + push @filtered, [ $chop_len, $chop_len + $tail_len ] if ($tail_len > 0); + last; + } elsif ($m->[1] > $chop_len) { + push @filtered, [ $m->[0], $chop_len + $tail_len ]; + last; + } + push @filtered, $m; + } + + return esc_html_hl_regions($chopped . $tail, 'match', @filtered); +} + ## ---------------------------------------------------------------------- ## functions returning short strings @@ -5405,9 +5446,10 @@ sub git_project_list_rows { "\n" . "" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"), -class => "list", - $search_regexp ? () : -title => $pr->{'descr_long'}}, + -title => $pr->{'descr_long'}}, $search_regexp - ? esc_html_match_hl($pr->{'descr_long'}, $search_regexp) + ? esc_html_match_hl_chopped($pr->{'descr_long'}, + $pr->{'descr'}, $search_regexp) : esc_html($pr->{'descr'})) . "\n" . "" . chop_and_escape_str($pr->{'owner'}, 15) . "\n"; -- 2.30.2