@@ -282,6 +282,24 @@ BEGIN
282
282
' forks' => {
283
283
' override' => 0,
284
284
' 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]},
285
303
);
286
304
287
305
sub gitweb_check_feature {
@@ -1762,6 +1780,67 @@ sub git_get_project_description {
1762
1780
return $descr ;
1763
1781
}
1764
1782
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
+
1765
1844
sub git_get_project_url_list {
1766
1845
my $path = shift ;
1767
1846
@@ -3580,6 +3659,7 @@ sub fill_project_list_info {
3580
3659
my ($projlist , $check_forks ) = @_ ;
3581
3660
my @projects ;
3582
3661
3662
+ my $show_ctags = gitweb_check_feature(' ctags' );
3583
3663
PROJECT:
3584
3664
foreach my $pr (@$projlist ) {
3585
3665
my (@activity ) = git_get_last_activity($pr -> {' path' });
@@ -3606,6 +3686,7 @@ sub fill_project_list_info {
3606
3686
$pr -> {' forks' } = 0;
3607
3687
}
3608
3688
}
3689
+ $show_ctags and $pr -> {' ctags' } = git_get_project_ctags($pr -> {' path' });
3609
3690
push @projects , $pr ;
3610
3691
}
3611
3692
@@ -3652,6 +3733,18 @@ sub git_project_list_body {
3652
3733
$from = 0 unless defined $from ;
3653
3734
$to = $#projects if (!defined $to || $#projects < $to );
3654
3735
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
+
3655
3748
print " <table class=\" project_list\" >\n " ;
3656
3749
unless ($no_header ) {
3657
3750
print " <tr>\n " ;
@@ -3670,8 +3763,10 @@ sub git_project_list_body {
3670
3763
" </tr>\n " ;
3671
3764
}
3672
3765
my $alternate = 1;
3766
+ my $tagfilter = $cgi -> param(' by_tag' );
3673
3767
for (my $i = $from ; $i <= $to ; $i ++) {
3674
3768
my $pr = $projects [$i ];
3769
+ next if $tagfilter and $show_ctags and not grep { lc $_ eq lc $tagfilter } keys %{$pr -> {' ctags' }};
3675
3770
if ($alternate ) {
3676
3771
print " <tr class=\" dark\" >\n " ;
3677
3772
} else {
@@ -4093,6 +4188,20 @@ sub git_summary {
4093
4188
print " <tr class=\" metadata_url\" ><td>$url_tag </td><td>$git_url </td></tr>\n " ;
4094
4189
$url_tag = " " ;
4095
4190
}
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
+
4096
4205
print " </table>\n " ;
4097
4206
4098
4207
if (-s " $projectroot /$project /README.html" ) {
0 commit comments