diff options
author | Jakub Narebski <jnareb@gmail.com> | 2012-02-27 05:55:19 +0400 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2012-02-27 10:02:54 +0400 |
commit | 337da8d2b0b8a8a86f0aa969bba2756126d6c090 (patch) | |
tree | 9786b775df6528c0b809cbd71528c527a09e9e35 /gitweb/gitweb.perl | |
parent | 07b257f94035133376538c54620b43a14e28dcd3 (diff) |
gitweb: Introduce esc_html_match_hl and esc_html_hl_regions
The esc_html_match_hl() subroutine added in this commit will be used
to highlight *all* matches of given regexp, using 'match' class.
Ultimately it is to be used in all match highlighting, starting
with project search, which does not have it yet.
It uses the esc_html_hl_regions() subroutine, which is meant to
highlight in a given string a list of regions (given as a list of
[ beg, end ] pairs of positions in string), using HTML <span> element
with given class. It could probably be used in other places that
do highlighting of part of ready line, like highlighting of changes
in a diff (diff refinement highlighting).
Implementation and enhancement notes:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Currently esc_html_hl_regions() subroutine doesn't accept any
parameters, like esc_html() does. We might want for example to
pass nbsp=>1 to it.
It can easily be done with the following code:
my %opts = grep { ref($_) ne "ARRAY" } @sel;
@sel = grep { ref($_) eq "ARRAY" } @sel;
This allow adding parameters after or before regions, e.g.:
esc_html_hl_regions("foo bar", "mark", [ 0, 3 ], -nbsp => 1);
* esc_html_hl_regions() escapes like esc_html(); if we wanted to
highlight with esc_path(), we could pass subroutine reference
to now named esc_gen_hl_regions().
esc_html_hl_regions("foo bar", "mark", \&esc_path, [ 0, 3 ]);
Note that this way we can handle -nbsp=>1 case automatically,
e.g.
esc_html_hl_regions("foo bar", "mark",
sub { esc_html(@_, -nbsp=>1) },
[ 0, 3 ]);
* Alternate solution for highlighting region of a string would be to
use the idea that strings are to be HTML-escaped, and references to
scalars are HTML (like in the idea for generic committags).
This would require modifying gitweb code or esc_html to get list of
fragments, e.g.:
esc_html(\'<span class="mark">', 'foo', \'</span>', ' bar',
{ -nbsp => 1 });
or
esc_html([\'<span class="mark">', 'foo', \'</span>', ' bar'],
-nbsp=>1);
esc_html_match_hl() could be then simple wrapper around "match
formatter", e.g.
esc_html([ render_match_hl($str, $regexp) ], -nbsp=>1);
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'gitweb/gitweb.perl')
-rwxr-xr-x | gitweb/gitweb.perl | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 568b0775f2..f8c5b6a8b0 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1715,6 +1715,47 @@ sub chop_and_escape_str { } } +# Highlight selected fragments of string, using given CSS class, +# and escape HTML. It is assumed that fragments do not overlap. +# Regions are passed as list of pairs (array references). +# +# Example: esc_html_hl_regions("foobar", "mark", [ 0, 3 ]) returns +# '<span class="mark">foo</span>bar' +sub esc_html_hl_regions { + my ($str, $css_class, @sel) = @_; + return esc_html($str) unless @sel; + + my $out = ''; + my $pos = 0; + + for my $s (@sel) { + $out .= esc_html(substr($str, $pos, $s->[0] - $pos)) + if ($s->[0] - $pos > 0); + $out .= $cgi->span({-class => $css_class}, + esc_html(substr($str, $s->[0], $s->[1] - $s->[0]))); + + $pos = $s->[1]; + } + $out .= esc_html(substr($str, $pos)) + if ($pos < length($str)); + + return $out; +} + +# highlight match (if any), and escape HTML +sub esc_html_match_hl { + my ($str, $regexp) = @_; + return esc_html($str) unless defined $regexp; + + my @matches; + while ($str =~ /$regexp/g) { + push @matches, [$-[0], $+[0]]; + } + return esc_html($str) unless @matches; + + return esc_html_hl_regions($str, 'match', @matches); +} + ## ---------------------------------------------------------------------- ## functions returning short strings |