1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#!/usr/bin/perl
# Copyright (C) 2007-2022 Ole Tange, http://ole.tange.dk and Free
# Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <https://www.gnu.org/licenses/>
# or write to the Free Software Foundation, Inc., 51 Franklin St,
# Fifth Floor, Boston, MA 02110-1301 USA
#
# SPDX-FileCopyrightText: 2021-2022 Ole Tange, http://ole.tange.dk and Free Software and Foundation, Inc.
# SPDX-License-Identifier: GPL-3.0-or-later
# Convert .pod file containing:
#
# =item --option
#
# See also: --other-option
#
# to a graph.pdf with link between --option and --other-option
$pod=join("",<>);
# Remove stuff before OPTIONS
$pod=~s/^.*=head1 OPTIONS//s;
# Remove from EXAMPLES (which is next section) and till end
$pod=~s/=head1 EXAMPLES.*//s;
# Remove =over / =back pairs
$pod=~s/^.*?=over//s;
$pod=~s/=back\s*$//s;
$pod=~s/=over.*?=back//sg;
$in_text = 0;
$in_item = 0;
$in_see_also = 0;
for(split(/\n\n+/,$pod)) {
if(/^See also:\s+(\S.*)/s) {
# "See also" paragraph
$lex = "seealso";
$in_text = 0;
$in_item = 0;
$in_see_only = 1;
} elsif(/^=item\s+(B<[{]=.*?perl expression.*?=[}]>|[IB]<.*?>)(\s|$)/s) {
# "=item" paragraph
$lex = "item";
$in_text = 0;
$in_item = 1;
$in_see_only = 0;
} elsif(/\S/) {
# else it is just text
$lex = "text";
$in_text = 1;
$in_item = 0;
$in_see_only = 0;
}
if($lex eq "seealso") {
# We found "See also": output edge
if($lastlex eq "item") {
@saveditems = @items;
@items = ();
}
my $to = $1;
# Edge from = item/item/item
my $from = (join "/",
map {
s/I<(.*?)>/$1/g;
s/B<(.*?)>/$1/g;
$_ }
@saveditems[0]);
my @to;
while($to =~ s/(B<[{]=.*?perl expression.*?=[}]>|[BI]<.*?>)(\s|$)//) {
my $v = $1;
push @to, map {
s/I<(.*?)>/$1/g;
s/B<(.*?)>/$1/g;
$_;
} $v;
}
map {
if(not $seen{$from,$_}++
and
not $seen{$_,$from}++) {
push @nodelines, "\"$from\" -- \"$_\"\n"
}
} @to;
} elsif($lex eq "text") {
if($lastlex eq "item") {
@saveditems = @items;
@items = ();
}
} elsif($lex eq "item") {
push(@items,$1);
}
$lastlex=$lex;
}
sub header() {
return q[
graph test123 {
graph [splines=true; overlap=false;];
labelloc="t";
label="Related map for options for GNU Parallel\nFind the options you use and learn about the options related to it";fontsize=33;
"{}"[margin=0.3;]
"--sshlogin"[margin=0.3;]
"--pipe"[margin=0.3;]
":::"[margin=0.3;]
"-X"[margin=0.3;]
];
}
open(GRAPHVIZ,"|-","tee foo.dot |neato -Gepsilon=.000000001 -Tpdf") || die;
print GRAPHVIZ header(), (sort { rand()*3 -1 } @nodelines), "}";
close GRAPHVIZ;
|