@@ -282,6 +282,24 @@ BEGIN
282282 ' forks' => {
283283 ' override' => 0,
284284 ' default' => [0]},
285+
286+ # Allow gitweb scan project content tags described in ctags/
287+ # of project repository, and display the popular Web 2.0-ish
288+ # "tag cloud" near the project list. Note that this is something
289+ # COMPLETELY different from the normal Git tags.
290+
291+ # gitweb by itself can show existing tags, but it does not handle
292+ # tagging itself; you need an external application for that.
293+ # For an example script, check Girocco's cgi/tagproj.cgi.
294+ # You may want to install the HTML::TagCloud Perl module to get
295+ # a pretty tag cloud instead of just a list of tags.
296+
297+ # To enable system wide have in $GITWEB_CONFIG
298+ # $feature{'ctags'}{'default'} = ['path_to_tag_script'];
299+ # Project specific override is not supported.
300+ ' ctags' => {
301+ ' override' => 0,
302+ ' default' => [0]},
285303);
286304
287305sub gitweb_check_feature {
@@ -1762,6 +1780,67 @@ sub git_get_project_description {
17621780 return $descr ;
17631781}
17641782
1783+ sub git_get_project_ctags {
1784+ my $path = shift ;
1785+ my $ctags = {};
1786+
1787+ $git_dir = " $projectroot /$path " ;
1788+ foreach (<$git_dir /ctags/*>) {
1789+ open CT, $_ or next ;
1790+ my $val = <CT>;
1791+ chomp $val ;
1792+ close CT;
1793+ my $ctag = $_ ; $ctag =~ s # .*/## ;
1794+ $ctags -> {$ctag } = $val ;
1795+ }
1796+ $ctags ;
1797+ }
1798+
1799+ sub git_populate_project_tagcloud {
1800+ my $ctags = shift ;
1801+
1802+ # First, merge different-cased tags; tags vote on casing
1803+ my %ctags_lc ;
1804+ foreach (keys %$ctags ) {
1805+ $ctags_lc {lc $_ }-> {count } += $ctags -> {$_ };
1806+ if (not $ctags_lc {lc $_ }-> {topcount }
1807+ or $ctags_lc {lc $_ }-> {topcount } < $ctags -> {$_ }) {
1808+ $ctags_lc {lc $_ }-> {topcount } = $ctags -> {$_ };
1809+ $ctags_lc {lc $_ }-> {topname } = $_ ;
1810+ }
1811+ }
1812+
1813+ my $cloud ;
1814+ if (eval { require HTML::TagCloud; 1; }) {
1815+ $cloud = HTML::TagCloud-> new;
1816+ foreach (sort keys %ctags_lc ) {
1817+ # Pad the title with spaces so that the cloud looks
1818+ # less crammed.
1819+ my $title = $ctags_lc {$_ }-> {topname };
1820+ $title =~ s / / / g ;
1821+ $title =~ s / ^/ / g ;
1822+ $title =~ s / $/ / g ;
1823+ $cloud -> add($title , $home_link ." ?by_tag=" .$_ , $ctags_lc {$_ }-> {count });
1824+ }
1825+ } else {
1826+ $cloud = \%ctags_lc ;
1827+ }
1828+ $cloud ;
1829+ }
1830+
1831+ sub git_show_project_tagcloud {
1832+ my ($cloud , $count ) = @_ ;
1833+ print STDERR ref ($cloud )." ..\n " ;
1834+ if (ref $cloud eq ' HTML::TagCloud' ) {
1835+ return $cloud -> html_and_css($count );
1836+ } else {
1837+ my @tags = sort { $cloud -> {$a }-> {count } <=> $cloud -> {$b }-> {count } } keys %$cloud ;
1838+ return ' <p align="center">' . join (' , ' , map {
1839+ " <a href=\" $home_link ?by_tag=$_ \" >$cloud ->{$_ }->{topname}</a>"
1840+ } splice (@tags , 0, $count )) . ' </p>' ;
1841+ }
1842+ }
1843+
17651844sub git_get_project_url_list {
17661845 my $path = shift ;
17671846
@@ -3580,6 +3659,7 @@ sub fill_project_list_info {
35803659 my ($projlist , $check_forks ) = @_ ;
35813660 my @projects ;
35823661
3662+ my $show_ctags = gitweb_check_feature(' ctags' );
35833663 PROJECT:
35843664 foreach my $pr (@$projlist ) {
35853665 my (@activity ) = git_get_last_activity($pr -> {' path' });
@@ -3606,6 +3686,7 @@ sub fill_project_list_info {
36063686 $pr -> {' forks' } = 0;
36073687 }
36083688 }
3689+ $show_ctags and $pr -> {' ctags' } = git_get_project_ctags($pr -> {' path' });
36093690 push @projects , $pr ;
36103691 }
36113692
@@ -3652,6 +3733,18 @@ sub git_project_list_body {
36523733 $from = 0 unless defined $from ;
36533734 $to = $#projects if (!defined $to || $#projects < $to );
36543735
3736+ my $show_ctags = gitweb_check_feature(' ctags' );
3737+ if ($show_ctags ) {
3738+ my %ctags ;
3739+ foreach my $p (@projects ) {
3740+ foreach my $ct (keys %{$p -> {' ctags' }}) {
3741+ $ctags {$ct } += $p -> {' ctags' }-> {$ct };
3742+ }
3743+ }
3744+ my $cloud = git_populate_project_tagcloud(\%ctags );
3745+ print git_show_project_tagcloud($cloud , 64);
3746+ }
3747+
36553748 print " <table class=\" project_list\" >\n " ;
36563749 unless ($no_header ) {
36573750 print " <tr>\n " ;
@@ -3670,8 +3763,10 @@ sub git_project_list_body {
36703763 " </tr>\n " ;
36713764 }
36723765 my $alternate = 1;
3766+ my $tagfilter = $cgi -> param(' by_tag' );
36733767 for (my $i = $from ; $i <= $to ; $i ++) {
36743768 my $pr = $projects [$i ];
3769+ next if $tagfilter and $show_ctags and not grep { lc $_ eq lc $tagfilter } keys %{$pr -> {' ctags' }};
36753770 if ($alternate ) {
36763771 print " <tr class=\" dark\" >\n " ;
36773772 } else {
@@ -4093,6 +4188,20 @@ sub git_summary {
40934188 print " <tr class=\" metadata_url\" ><td>$url_tag </td><td>$git_url </td></tr>\n " ;
40944189 $url_tag = " " ;
40954190 }
4191+
4192+ # Tag cloud
4193+ my $show_ctags = (gitweb_check_feature(' ctags' ))[0];
4194+ if ($show_ctags ) {
4195+ my $ctags = git_get_project_ctags($project );
4196+ my $cloud = git_populate_project_tagcloud($ctags );
4197+ print " <tr id=\" metadata_ctags\" ><td>Content tags:<br />" ;
4198+ print " </td>\n <td>" unless %$ctags ;
4199+ print " <form action=\" $show_ctags \" method=\" post\" ><input type=\" hidden\" name=\" p\" value=\" $project \" />Add: <input type=\" text\" name=\" t\" size=\" 8\" /></form>" ;
4200+ print " </td>\n <td>" if %$ctags ;
4201+ print git_show_project_tagcloud($cloud , 48);
4202+ print " </td></tr>" ;
4203+ }
4204+
40964205 print " </table>\n " ;
40974206
40984207 if (-s " $projectroot /$project /README.html" ) {
0 commit comments