@matheusbsbs / matheus-bagliano / commits / 592ea4173a
Fork 0

gitweb: Refactor syntax highlighting support

This refactoring (adding guess_file_syntax and run_highlighter subroutines) is meant to make it easier in the future to add support for other syntax highlighing solutions, or make it smarter by not re-running `git cat-file` second time. Instead of looping over list of regexps (keys of %highlight_type hash), make use of the fact that choosing syntax is based either on full basename (%highlight_basename), or on file extension (%highlight_ext). Add some basic test of syntax highlighting (with 'highlight' as prerequisite) to t/t9500-gitweb-standalone-no-errors.sh test. While at it make git_blob Perl style prettier. Signed-off-by: Jakub Narebski <jnareb@gmail.com> Acked-by: Petr Baudis <pasky@suse.cz> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jakub Narebski committed Apr 27, 2010 at 21:34 UTC 592ea4173af6b445042d74b989762fd41aecdf4c
2 files changed +92 -53
gitweb/gitweb.perl
+63 -53
@@ -227,36 +227,6 @@ our %avatar_size = (
227 # Leave it undefined (or set to 'undef') to turn off load checking.
228 our $maxload = 300;
229
230 -# syntax highlighting
231 -our %highlight_type = (
232 - # match by basename
233 - 'SConstruct' => 'py',
234 - 'Program' => 'py',
235 - 'Library' => 'py',
236 - 'Makefile' => 'make',
237 - # match by extension
238 - '\.py$' => 'py', # Python
239 - '\.c$' => 'c',
240 - '\.h$' => 'c',
241 - '\.cpp$' => 'cpp',
242 - '\.cxx$' => 'cpp',
243 - '\.rb$' => 'ruby',
244 - '\.java$' => 'java',
245 - '\.css$' => 'css',
246 - '\.php3?$' => 'php',
247 - '\.sh$' => 'sh', # Bash / shell script
248 - '\.pl$' => 'pl', # Perl
249 - '\.js$' => 'js', # JavaScript
250 - '\.tex$' => 'tex', # TeX and LaTeX
251 - '\.bib$' => 'bib', # BibTeX
252 - '\.x?html$' => 'xml',
253 - '\.xml$' => 'xml',
254 - '\.awk$' => 'awk',
255 - '\.bat$' => 'bat', # DOS Batch script
256 - '\.ini$' => 'ini',
257 - '\.spec$' => 'spec', # RPM Spec
258 -);
259 -
230 # You define site-wide feature defaults here; override them with
231 # $GITWEB_CONFIG as necessary.
232 our %feature = (
@@ -478,8 +448,8 @@ our %feature = (
448
449 # Syntax highlighting support. This is based on Daniel Svensson's
450 # and Sham Chukoury's work in gitweb-xmms2.git.
481 - # It requires the 'highlight' program, and therefore is disabled
482 - # by default.
451 + # It requires the 'highlight' program present in $PATH,
452 + # and therefore is disabled by default.
453
454 # To enable system wide have in $GITWEB_CONFIG
455 # $feature{'highlight'}{'default'} = [1];
@@ -3198,6 +3168,61 @@ sub blob_contenttype {
3168 return $type;
3169 }
3170
3171 +# guess file syntax for syntax highlighting; return undef if no highlighting
3172 +# the name of syntax can (in the future) depend on syntax highlighter used
3173 +sub guess_file_syntax {
3174 + my ($highlight, $mimetype, $file_name) = @_;
3175 + return undef unless ($highlight && defined $file_name);
3176 +
3177 + # configuration for 'highlight' (http://www.andre-simon.de/)
3178 + # match by basename
3179 + my %highlight_basename = (
3180 + #'Program' => 'py',
3181 + #'Library' => 'py',
3182 + 'SConstruct' => 'py', # SCons equivalent of Makefile
3183 + 'Makefile' => 'make',
3184 + );
3185 + # match by extension
3186 + my %highlight_ext = (
3187 + # main extensions, defining name of syntax;
3188 + # see files in /usr/share/highlight/langDefs/ directory
3189 + map { $_ => $_ }
3190 + qw(py c cpp rb java css php sh pl js tex bib xml awk bat ini spec tcl),
3191 + # alternate extensions, see /etc/highlight/filetypes.conf
3192 + 'h' => 'c',
3193 + map { $_ => 'cpp' } qw(cxx c++ cc),
3194 + map { $_ => 'php' } qw(php3 php4),
3195 + map { $_ => 'pl' } qw(perl pm), # perhaps also 'cgi'
3196 + 'mak' => 'make',
3197 + map { $_ => 'xml' } qw(xhtml html htm),
3198 + );
3199 +
3200 + my $basename = basename($file_name, '.in');
3201 + return $highlight_basename{$basename}
3202 + if exists $highlight_basename{$basename};
3203 +
3204 + $basename =~ /\.([^.]*)$/;
3205 + my $ext = $1 or return undef;
3206 + return $highlight_ext{$ext}
3207 + if exists $highlight_ext{$ext};
3208 +
3209 + return undef;
3210 +}
3211 +
3212 +# run highlighter and return FD of its output,
3213 +# or return original FD if no highlighting
3214 +sub run_highlighter {
3215 + my ($fd, $highlight, $syntax) = @_;
3216 + return $fd unless ($highlight && defined $syntax);
3217 +
3218 + close $fd
3219 + or die_error(404, "Reading blob failed");
3220 + open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ".
3221 + "highlight --xhtml --fragment --syntax $syntax |"
3222 + or die_error(500, "Couldn't open file or run syntax highlighter");
3223 + return $fd;
3224 +}
3225 +
3226 ## ======================================================================
3227 ## functions printing HTML: header, footer, error page
3228
@@ -5397,24 +5422,10 @@ sub git_blob {
5422 # we can have blame only for text/* mimetype
5423 $have_blame &&= ($mimetype =~ m!^text/!);
5424
5400 - my $have_highlight = gitweb_check_feature('highlight');
5401 - my $syntax;
5402 - if ($have_highlight && defined($file_name)) {
5403 - my $basename = basename($file_name, '.in');
5404 - foreach my $regexp (keys %highlight_type) {
5405 - if ($basename =~ /$regexp/) {
5406 - $syntax = $highlight_type{$regexp};
5407 - last;
5408 - }
5409 - }
5410 -
5411 - if ($syntax) {
5412 - close $fd;
5413 - open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ".
5414 - "highlight --xhtml --fragment -t 8 --syntax $syntax |"
5415 - or die_error(500, "Couldn't open file or run syntax highlighter");
5416 - }
5417 - }
5425 + my $highlight = gitweb_check_feature('highlight');
5426 + my $syntax = guess_file_syntax($highlight, $mimetype, $file_name);
5427 + $fd = run_highlighter($fd, $highlight, $syntax)
5428 + if $syntax;
5429
5430 git_header_html(undef, $expires);
5431 my $formats_nav = '';
@@ -5465,9 +5476,8 @@ sub git_blob {
5476 chomp $line;
5477 $nr++;
5478 $line = untabify($line);
5468 - printf "<div class=\"pre\"><a id=\"l%i\" href=\"" . href(-replay => 1)
5469 - . "#l%i\" class=\"linenr\">%4i</a> %s</div>\n",
5470 - $nr, $nr, $nr, $syntax ? $line : esc_html($line, -nbsp=>1);
5479 + printf qq!<div class="pre"><a id="l%i" href="%s#l%i" class="linenr">%4i</a> %s</div>\n!,
5480 + $nr, href(-replay => 1), $nr, $nr, $syntax ? $line : esc_html($line, -nbsp=>1);
5481 }
5482 }
5483 close $fd
t/t9500-gitweb-standalone-no-errors.sh
+29
@@ -647,4 +647,33 @@ test_expect_success \
647 gitweb_run "p=.git;a=summary"'
648 test_debug 'cat gitweb.log'
649
650 +# ----------------------------------------------------------------------
651 +# syntax highlighting
652 +
653 +cat >>gitweb_config.perl <<\EOF
654 +$feature{'highlight'}{'override'} = 1;
655 +EOF
656 +
657 +highlight --version >/dev/null 2>&1
658 +if [ $? -eq 127 ]; then
659 + say "Skipping syntax highlighting test, because 'highlight' was not found"
660 +else
661 + test_set_prereq HIGHLIGHT
662 +fi
663 +
664 +test_expect_success HIGHLIGHT \
665 + 'syntax highlighting (no highlight)' \
666 + 'git config gitweb.highlight yes &&
667 + gitweb_run "p=.git;a=blob;f=file"'
668 +test_debug 'cat gitweb.log'
669 +
670 +test_expect_success HIGHLIGHT \
671 + 'syntax highlighting (highlighted)' \
672 + 'git config gitweb.highlight yes &&
673 + echo "#!/usr/bin/sh" > test.sh &&
674 + git add test.sh &&
675 + git commit -m "Add test.sh" &&
676 + gitweb_run "p=.git;a=blob;f=test.sh"'
677 +test_debug 'cat gitweb.log'
678 +
679 test_done