makepp
view release on metacpan or search on metacpan
makeppgraph view on Meta::CPAN
}
sub SELF() { '' } # Impossible node name used for own attributes.
my $home = absolute_filename dereference file_info $ENV{HOME};
$datadir = absolute_filename dereference file_info $datadir;
package Mpp::Rewrite;
# Reduce any file (except dirs) to the containing directory.
sub dir() { defined and $_ ne '' and -d || s!/[^/]+$!! || s!^(\|\w+\|).*!$1! }
# Replace your home directory with '~'
sub home() { defined and s/^$home/~/ }
# Replace makepp dir with abbreviation |m|.
sub makepp() { defined and s!^$Mpp::datadir(?:/|$|(?=:))!|m|! }
# Replace basename including dir or optionally only part of dir with '*'
sub suf(;$) {
no warnings 'uninitialized';
if( !defined $_[0] ) {
s!.+ (\.[^/.]+) $!*$1!x;
} elsif( !$_[0] ) {
s!^ ([/~|]?) .+ (\.[^/.]+) $!$1*$2!x;
} elsif( $_[0] > 0 ) {
my $n_1 = $_[0] - 1;
s!^ (\|\w+\| | [/~]?[^/]*/ )? ((?:[^/]+/){0,$n_1}) .+ (\.[^/.]+) $!$1$2*$3!x;
} else {
my $n_1 = -1 - $_[0];
s! (?: ^\|\w+\| | ^/(?:[^/]+/)? | ^~[^/]*/ | [^|/]+/ )? (?:[^/]+/){0,$n_1} [^/]+ (\.[^/.]+) $!*$1!x;
}
}
# Replace common system dirs with abbreviation.
sub usr() {
no warnings 'uninitialized';
s!^/(?:(?=(.))(?:opt|usr)/(?:(?=(.))(?:local|X11R?[67]?)/)?)?(?=(.))(?:bin|etc|include|lib|share)(?:/|$)!|$1$2$3|!;
}
sub merge($$$$) {
return if !/([^\/]+)$_[2]$/;
my $basename = $1;
for( keys %{$_[0]} ) {
if( /(?:.*\/)?\Q$basename\E$_[3]$/ ) {
delete $_[0]{$_};
return ["$_$_[1]", $_];
}
}
}
# .o in any dir depending on a C or C++ source
sub c2o($) { merge $_[0], '>o', qr/\.o(?:bj)?/, qr/\.(?:c(|[xp+])\1|cc|CC?)/ }
# basename or .exe in any dir depending on same .o file
sub exe($) { merge $_[0], '*', qr/(?:\.exe)?/, qr/\.o/ }
# Same name in different directories, like headers published to a central include dir.
sub x2($) { merge $_[0], '*2', '', '' }
package Mpp;
# Styles which can be overridden.
our %head = ( dot => <<EOSdot, html => <<EOShtml, txt => '', udg => "[\n" );
// Generated by makeppgraph
digraph a {
rankdir=LR
outputorder=edgesfirst
node [shape=box style=filled fillcolor="#ffffffe0"]
edge [dir=back]
EOSdot
<html>
<meta name='generator' content='makeppgraph' />
<style>
a { border: 1px dotted #bbb; padding-left: 1ex; padding-right: 1ex; }
b { font-weight: normal; border: 1px solid; padding-left: 1ex; padding-right: 1ex; }
ul ul { border-left: 1px dotted #bbb; }
ul { margin: 0; padding-left: 1em; }
li { list-style: square; padding: 0; padding-top: 3px; }
li.fold { list-style: disc; }
li.fold > b { cursor: n-resize; }
li.unfold { list-style: circle; }
li.unfold > b { cursor: s-resize; }
.flash { background-color: yellow; }
/* Actually show and hide sublists */
li.fold ul { display: block; }
li.unfold ul { display: none; }
</style>
<script>
// Inspired by Stuart Langridge, www.kryogenix.org/code/browser/aqlists/
function foldify( ul ) {
if( !ul.childNodes || ul.childNodes.length == 0 ) return;
// Iterate LIs
for( var itemi = 0; itemi < ul.childNodes.length; itemi++ ) {
var item = ul.childNodes[itemi];
if( item.nodeName == "LI" ) {
// Iterate things in this LI
var b;
for( var sitemi = 0; sitemi < item.childNodes.length; sitemi++ ) {
var sitem = item.childNodes[sitemi];
switch( sitem.nodeName ) {
case "B": b = sitem; break;
case "UL": foldify(sitem);
item.className = 'fold';
b.title = 'click to (un)fold, double click to unfold all';
b.onclick = function() {
this.parentNode.className = (this.parentNode.className=='fold') ? 'unfold' : 'fold';
return false;
};
b.ondblclick = function() {
foldify( this.parentNode.parentNode.getElementsByTagName( "ul" )[0] );
return false;
};
}
}
( run in 1.190 second using v1.01-cache-2.11-cpan-13bb782fe5a )