From 4055cc4f4b4e626b22c1baecd5b9b85aee886531 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Fri, 17 Mar 2017 11:04:47 +0000 Subject: [PATCH] [Minor] Update doxydown tool --- doc/doxydown/doxydown.pl | 380 ++++++++++++++++++++++++++++++--------- 1 file changed, 295 insertions(+), 85 deletions(-) diff --git a/doc/doxydown/doxydown.pl b/doc/doxydown/doxydown.pl index 530d95df9..1b543cf36 100755 --- a/doc/doxydown/doxydown.pl +++ b/doc/doxydown/doxydown.pl @@ -1,6 +1,6 @@ #!/usr/bin/env perl -$VERSION = "0.1"; +$VERSION = "0.1.4"; use strict; use warnings; @@ -19,21 +19,32 @@ my %languages = ( filter => qr/^(?:\s*\*+\s*)?(\s*\S.+)\s*$/, }, lua => { - start => qr/^\s*\--\[\[\[\s*$/, - end => qr/^\s*--\]\]\s*/, + start => qr/^\s*\--(?:\[\[+|-+)\s*$/, + end => qr/^\s*--(:?\]\]+|-+)\s*$/, + filter => qr/^(?:\s*--!?\s)?(\s*\S.+)\s*$/, + }, + sql => { + start => qr/^\s*\--(?:\[\[+|-+)\s*$/, + end => qr/^\s*--(:?\]\]+|-+)\s*$/, filter => qr/^(?:\s*--\s)?(\s*\S.+)\s*$/, }, + pl => { + start => qr/^\s*\##+\s*$/, + end => qr/^\s*##+\s*/, + filter => qr/^(?:\s*#+\s?)(\s*\S.+)\s*$/, + }, ); my $function_re = qr/^\s*\@(function|fn|method)\s*(\S.+)$/oi; +my $struct_re = qr/^\s*\@(table|struct)\s*(\S.+)$/oi; my $module_re = qr/^\s*\@(?:module|file)\s*(\S.+)$/oi; - my $language; +# /function print_module_markdown sub print_module_markdown { my ( $mname, $m ) = @_; - my $idline = $options{g} ? "" : " {#$m->{'id'}}"; + print <{'example'} ) { print <{'example_language'} $m->{'example'} @@ -55,29 +66,71 @@ EOD my $name = $f->{'name'}; my $id = $f->{'id'}; + if ($f->{'brief'}) { print "> [`$name`](#$id): ". $f->{'brief'} . "\n\n"; + } else { + print "> [`$name`](#$id)\n\n"; } - else { + } + + sub print_table { + my ($f) = @_; + + my $name = $f->{'name'}; + my $id = $f->{'id'}; + + if ($f->{'brief'}) { + print "> [`$name`](#$id): ". $f->{'brief'} . "\n\n"; + } else { print "> [`$name`](#$id)\n\n"; } } print "\n### Brief content:\n\n"; - if (scalar(@{ $m->{'functions'} }) > 0) { - print "**Functions**:\n\n"; - foreach ( @{ $m->{'functions'} } ) { - print_func($_); + + if ($m->{'functions'}) { + if (scalar(@{ $m->{'functions'} }) > 0) { + print "**Functions**:\n\n"; + + foreach ( @{ $m->{'functions'} } ) { + print_func($_); + } + } + } + + if ($m->{'methods'}) { + if (scalar(@{ $m->{'methods'} }) > 0) { + print "\n\n**Methods**:\n\n"; + + foreach ( @{ $m->{'methods'} } ) { + print_func($_); + } } } - if (scalar(@{ $m->{'methods'} }) > 0) { - print "\n\n**Methods**:\n\n"; - foreach (@{ $m->{'methods'} }) { - print_func($_); + + if ($m->{'tables'}) { + if (scalar(@{ $m->{'tables'} }) > 0) { + print "\n\n**Tables**:\n\n"; + + foreach ( @{ $m->{'tables'} } ) { + print_table($_); + } + } + } + + if ($m->{'structs'}) { + if (scalar(@{ $m->{'structs'} }) > 0) { + print "\n\n**Structs**:\n\n"; + + foreach ( @{ $m->{'structs'} } ) { + print_table($_); + } } } } +# /function print_function_markdown sub print_function_markdown { my ( $type, $fname, $f ) = @_; @@ -88,37 +141,75 @@ sub print_function_markdown { $f->{'data'} EOD print "\n**Parameters:**\n\n"; + if ( $f->{'params'} && scalar @{ $f->{'params'} } > 0 ) { foreach ( @{ $f->{'params'} } ) { if ( $_->{'type'} ) { print "- `$_->{'name'} \{$_->{'type'}\}`: $_->{'description'}\n"; - } - else { + } else { print "- `$_->{'name'}`: $_->{'description'}\n"; } } - } - else { + } else { print "No parameters\n"; } + print "\n**Returns:**\n\n"; - if ( $f->{'return'} && $f->{'return'}->{'description'} ) { - $_ = $f->{'return'}; - if ( $_->{'type'} ) { - print "- `\{$_->{'type'}\}`: $_->{'description'}\n"; - } - else { - print "- $_->{'description'}\n"; + + if ( $f->{'returns'} && scalar @{ $f->{'returns'} } > 0 ) { + foreach ( @{ $f->{'returns'} } ) { + if ( $_->{'type'} ) { + print "- `\{$_->{'type'}\}`: $_->{'description'}\n"; + } else { + print "- $_->{'description'}\n"; + } } - } - else { + } else { print "No return\n"; } + + if ( $f->{'example'} ) { + print <{'example_language'} +$f->{'example'} +~~~ +EOD + } +} + +# /function print_struct_markdown +sub print_struct_markdown { + my ( $type, $fname, $f ) = @_; + + my $idline = $options{g} ? "" : " {#$f->{'id'}}"; + print <{'data'} +EOD + print "\n**Elements:**\n\n"; + + if ( $f->{'params'} && scalar @{ $f->{'params'} } > 0 ) { + foreach ( @{ $f->{'params'} } ) { + if ( $_->{'type'} ) { + print + "- `$_->{'name'} \{$_->{'type'}\}`: $_->{'description'}\n"; + } else { + print "- `$_->{'name'}`: $_->{'description'}\n"; + } + } + } else { + print "No elements\n"; + } + if ( $f->{'example'} ) { print <{'example_language'} $f->{'example'} @@ -127,28 +218,62 @@ EOD } } +# /function print_markdown sub print_markdown { for my $m (@modules) { my $mname = $m->{name}; + print_module_markdown( $mname, $m ); - if (scalar(@{ $m->{'functions'} }) > 0) { - print - "\n## Functions\n\nThe module `$mname` defines the following functions.\n\n"; - foreach (@{ $m->{'functions'} }) { - print_function_markdown( "Function", $_->{'name'}, $_ ); - print "\nBack to [module description](#$m->{'id'}).\n\n"; + if ($m->{'functions'}) { + if ( scalar(@{ $m->{'functions'} }) > 0 ) { + print "\n## Functions\n\nThe module `$mname` defines the following functions.\n\n"; + + foreach ( @{ $m->{'functions'} } ) { + print_function_markdown( "Function", $_->{'name'}, $_ ); + + print "\nBack to [module description](#$m->{'id'}).\n\n"; + } } } - if (scalar(@{ $m->{'methods'} }) > 0) { - print - "\n## Methods\n\nThe module `$mname` defines the following methods.\n\n"; - foreach (@{ $m->{'methods'} }) { - print_function_markdown( "Method", $_->{'name'}, $_ ); - print "\nBack to [module description](#$m->{'id'}).\n\n"; + if ($m->{'methods'}) { + if ( scalar(@{ $m->{'methods'} }) > 0 ) { + print "\n## Methods\n\nThe module `$mname` defines the following methods.\n\n"; + + foreach ( @{ $m->{'methods'} } ) { + print_function_markdown( "Method", $_->{'name'}, $_ ); + + print "\nBack to [module description](#$m->{'id'}).\n\n"; + + } + } + } + + if ($m->{'tables'}) { + if ( scalar(@{ $m->{'tables'} }) > 0 ) { + print "\n## Tables\n\nThe module `$mname` defines the following tables.\n\n"; + foreach ( @{ $m->{'tables'} } ) { + print_struct_markdown( "Table", $_->{'name'}, $_ ); + + print "\nBack to [module description](#$m->{'id'}).\n\n"; + + } + } + } + + if ($m->{'stucts'}) { + if ( scalar(@{ $m->{'stucts'} }) > 0 ) { + print "\n## Stucts\n\nThe module `$mname` defines the following stucts.\n\n"; + + foreach ( @{ $m->{'stucts'} } ) { + print_stuct_markdown( "Stuct", $_->{'name'}, $_ ); + + print "\nBack to [module description](#$m->{'id'}).\n\n"; + + } } } @@ -156,43 +281,49 @@ sub print_markdown { } } +# /function make_id sub make_id { my ( $name, $prefix ) = @_; if ( !$prefix ) { $prefix = "f"; } + if ( !$options{g} ) { # Kramdown/pandoc version of ID's $name =~ /^(\S+).*$/; + return substr( substr( $prefix, 0, 1 ) . md5_hex($1), 0, 6 ); - } - else { + } else { my $input = lc $prefix . "-" . $name; my $id = join '-', split /\s+/, $input; + $id =~ s/[^\w_-]+//g; + return $id; } } +# /function substitute_data_keywords sub substitute_data_keywords { my ($line) = @_; if ( $line =~ /^.*\@see\s+(\S+)\s*.*$/ ) { my $name = $1; my $id = make_id($name); + return $line =~ s/\@see\s+\S+/[`$name`](#$id)/r; } return $line; } +# /function parse_function sub parse_function { my ( $func, @data ) = @_; my ( $type, $name ) = ( $func =~ $function_re ); - chomp $name; my $f = { @@ -204,52 +335,117 @@ sub parse_function { }; my $example = 0; - foreach (@data) { - if (/^\s*\@param\s*(?:\{([^}]+)\})?\s*(\S+)\s*(.+)?\s*$/) { - my $p = { name => $2, type => $1, description => $3 }; + foreach ( @data ) { + if ( /^\s*\@param\s*(?:\{([^}]+)\})?\s*(\S+)\s*(.+)?\s*$/ ) { + my $p = { + name => $2, + type => $1, + description => $3 + }; + push @{ $f->{'params'} }, $p; - } - elsif (/^\s*\@return\s*(?:\{([^}]+)\})?\s*(.+)?\s*$/) { - my $r = { type => $1, description => $2 }; - $f->{'return'} = $r; - } - elsif (/^\s*\@brief\s*(\S.+)$/) { + } elsif ( /^\s*\@return\s*(?:\{([^}]+)\})?\s*(.+)?\s*$/ ) { + my $r = { + type => $1, + description => $2 + }; + + push @{ $f->{'returns'} }, $r; + } elsif ( /^\s*\@brief\s*(\S.+)$/ ) { $f->{'brief'} = $1; } - elsif (/^\s*\@example\s*(\S)?\s*$/) { + elsif ( /^\s*\@example\s*(\S)?\s*$/ ) { $example = 1; - if ($1) { + if ( $1 ) { $f->{'example_language'} = $1; } - } - elsif ( $_ ne $func ) { - if ($example) { + } elsif ( $_ ne $func ) { + if ( $example ) { $f->{'example'} .= $_; - } - else { + } else { $f->{'data'} .= substitute_data_keywords($_); } } } + if ( $f->{'data'} ) { chomp $f->{'data'}; - } - elsif ($f->{'brief'}) { + } elsif ($f->{'brief'}) { chomp $f->{'brief'}; $f->{'data'} = $f->{'brief'}; } + if ( $f->{'example'} ) { chomp $f->{'example'}; } if ( $type eq "method" ) { push @{ $cur_module->{'methods'} }, $f; - } - else { + } elsif ( $type eq "function" || $type eq "fn") { push @{ $cur_module->{'functions'} }, $f; } } +# /function parse_struct +sub parse_struct { + my ( $func, @data ) = @_; + + my ( $type, $name ) = ( $func =~ $struct_re ); + chomp $name; + + my $f = { + name => $name, + data => '', + example => undef, + example_language => $example_language, + id => make_id( $name, $type ), + }; + my $example = 0; + + foreach ( @data ) { + if ( /^\s*\@param\s*(?:\{([^}]+)\})?\s*(\S+)\s*(.+)?\s*$/ ) { + my $p = { + name => $2, + type => $1, + description => $3 + }; + + push @{ $f->{'params'} }, $p; + } elsif ( /^\s*\@brief\s*(\S.+)$/ ) { + $f->{'brief'} = $1; + } elsif ( /^\s*\@example\s*(\S)?\s*$/ ) { + $example = 1; + if ( $1 ) { + $f->{'example_language'} = $1; + } + } elsif ( $_ ne $func ) { + if ( $example ) { + $f->{'example'} .= $_; + } else { + $f->{'data'} .= substitute_data_keywords($_); + } + } + } + + if ( $f->{'data'} ) { + chomp $f->{'data'}; + } elsif ($f->{'brief'}) { + chomp $f->{'brief'}; + $f->{'data'} = $f->{'brief'}; + } + + if ( $f->{'example'} ) { + chomp $f->{'example'}; + } + + if ( $type eq "table" ) { + push @{ $cur_module->{'tables'} }, $f; + } elsif ( $type eq "struct" ) { + push @{ $cur_module->{'structs'} }, $f; + } +} + +# /function parse_module sub parse_module { my ( $module, @data ) = @_; my ( $name ) = ( $module =~ $module_re ); @@ -265,47 +461,57 @@ sub parse_module { example_language => $example_language, id => make_id( $name, "module" ), }; + my $example = 0; - foreach (@data) { - if (/^\s*\@example\s*(\S)?\s*$/) { + foreach ( @data ) { + if ( /^\s*\@example\s*(\S)?\s*$/ ) { $example = 1; if ($1) { $f->{'example_language'} = $1; } - } - elsif (/^\s*\@brief\s*(\S.+)$/) { + } elsif ( /^\s*\@brief\s*(\S.+)$/ ) { $f->{'brief'} = $1; - } - elsif ( $_ ne $module ) { - if ($example) { + } elsif ( $_ ne $module ) { + if ( $example ) { $f->{'example'} .= $_; - } - else { + } else { $f->{'data'} .= substitute_data_keywords($_); } } } + if ( $f->{'data'} ) { chomp $f->{'data'}; - } - elsif ($f->{'brief'}) { + } elsif ( $f->{'brief'} ) { chomp $f->{'brief'}; + $f->{'data'} = $f->{'brief'}; } + if ( $f->{'example'} ) { chomp $f->{'example'}; } + $cur_module = $f; push @modules, $f; } +# /function parse_content sub parse_content { + # my @func = grep /$function_re/, @_; if ( scalar @func > 0 ) { parse_function( $func[0], @_ ); } + # + my @struct = grep /$struct_re/, @_; + if ( scalar @struct > 0 ) { + parse_struct( $struct[0], @_ ); + } + + # my @module = grep /$module_re/, @_; if ( scalar @module > 0 ) { parse_module( $module[0], @_ ); @@ -323,11 +529,13 @@ usage: $0 [-hg] [-l language] < input_source > markdown.md -l : sets input language (default: c) -g : use github flavoured markdown (default: kramdown/pandoc) EOF + exit; } $Getopt::Std::STANDARD_HELP_VERSION = 1; use Getopt::Std; + getopts( 'he:gl:', \%options ); HELP_MESSAGE() if $options{h}; @@ -339,6 +547,9 @@ if ( !$language ) { $language = $languages{c}; } +## TODO: select language based on file extention +## TODO: change calling structure to allow looping through directory + use constant { STATE_READ_SKIP => 0, STATE_READ_CONTENT => 1, @@ -349,34 +560,33 @@ use constant { my $state = STATE_READ_SKIP; my $content; -while (<>) { +while ( <> ) { if ( $state == STATE_READ_SKIP ) { if ( $_ =~ $language->{start} ) { $state = STATE_READ_CONTENT; + if (defined($1)) { chomp($content = $1); $content =~ tr/\r//d; $content .= "\n"; - } - else { + } else { $content = ""; } } - } - elsif ( $state == STATE_READ_CONTENT ) { + } elsif ( $state == STATE_READ_CONTENT ) { if ( $_ =~ $language->{end} ) { $state = STATE_READ_SKIP; + parse_content( split /^/, $content ); + $content = ""; - } - else { + } else { my ($line) = ( $_ =~ $language->{filter} ); - if ($line) { + if ( $line ) { $line =~ tr/\r//d; $content .= $line . "\n"; - } - else { + } else { # Preserve empty lines $content .= "\n"; } -- 2.39.5