]> git.proxmox.com Git - pve-common.git/blame - src/PVE/PodParser.pm
schema_get_type_text: return format_description if available
[pve-common.git] / src / PVE / PodParser.pm
CommitLineData
e143e9d8
DM
1package PVE::PodParser;
2
3use strict;
c36f332e 4use warnings;
e143e9d8
DM
5use Pod::Parser;
6use base qw(Pod::Parser);
7
d415354b
DM
8my $currentYear = (localtime(time))[5] + 1900;
9
e143e9d8
DM
10my $stdinclude = {
11 pve_copyright => <<EODATA,
12\=head1 COPYRIGHT AND DISCLAIMER
13
d415354b 14Copyright (C) 2007-$currentYear Proxmox Server Solutions GmbH
e143e9d8
DM
15
16This program is free software: you can redistribute it and\/or modify
17it under the terms of the GNU Affero General Public License as
18published by the Free Software Foundation, either version 3 of the
19License, or (at your option) any later version.
20
21This program is distributed in the hope that it will be useful,
22but WITHOUT ANY WARRANTY; without even the implied warranty of
23MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24GNU Affero General Public License for more details.
25
26You should have received a copy of the GNU Affero General Public License
27along with this program. If not, see L<http://www.gnu.org/licenses/>.
28EODATA
29};
30
31sub command {
32 my ($self, $cmd, $text, $line_num, $pod_para) = @_;
33
34 if (($cmd eq 'include' && $text =~ m/^\s*(\S+)\s/)) {
35 my $incl = $1;
36 my $data = $stdinclude->{$incl} ? $stdinclude->{$incl} :
37 $self->{include}->{$incl};
38 chomp $data;
39 $self->textblock("$data\n\n", $line_num, $pod_para);
40 } else {
41 $self->textblock($pod_para->raw_text(), $line_num, $pod_para);
42 }
43}
44
45# helpers used to generate our manual pages
46
2421fba1
WB
47sub generate_typetext {
48 my ($schema) = @_;
49 my $typetext = '';
50 my (@optional, @required);
51 foreach my $key (sort keys %$schema) {
2ec53614 52 my $entry = $schema->{$key};
8506c60d 53 next if $entry->{alias};
2ec53614
WB
54 next if !$entry->{format_description} &&
55 !$entry->{typetext} &&
56 !$entry->{enum} &&
57 $entry->{type} ne 'boolean';
2421fba1
WB
58 if ($schema->{$key}->{optional}) {
59 push @optional, $key;
60 } else {
61 push @required, $key;
62 }
63 }
64 my ($pre, $post) = ('', '');
65 my $add = sub {
66 my ($key) = @_;
67 $typetext .= $pre;
68 my $entry = $schema->{$key};
303a9b34
WB
69 if (my $alias = $entry->{alias}) {
70 $key = $alias;
71 $entry = $schema->{$key};
72 }
2ec53614 73 if (!defined($entry->{typetext})) {
2421fba1 74 $typetext .= $entry->{default_key} ? "[$key=]" : "$key=";
2ec53614
WB
75 }
76 if (my $desc = $entry->{format_description}) {
2421fba1
WB
77 $typetext .= "<$desc>";
78 } elsif (my $text = $entry->{typetext}) {
79 $typetext .= $text;
2ec53614
WB
80 } elsif (my $enum = $entry->{enum}) {
81 $typetext .= '<' . join('|', @$enum) . '>';
82 } elsif ($entry->{type} eq 'boolean') {
83 $typetext .= '<1|0>';
2421fba1
WB
84 } else {
85 die "internal error: neither format_description nor typetext found";
86 }
87 $typetext .= $post;
88 };
89 foreach my $key (@required) {
90 &$add($key);
91 $pre = ', ';
92 }
93 $pre = $pre ? ' [,' : '[';
94 $post = ']';
95 foreach my $key (@optional) {
96 &$add($key);
97 $pre = ' [,';
98 }
99 return $typetext;
100}
101
e143e9d8
DM
102sub schema_get_type_text {
103 my ($phash) = @_;
104
105 if ($phash->{typetext}) {
106 return $phash->{typetext};
457c3fcb
DM
107 } elsif ($phash->{format_description}) {
108 return "<$phash->{format_description}>";
e143e9d8
DM
109 } elsif ($phash->{enum}) {
110 return "(" . join(' | ', sort @{$phash->{enum}}) . ")";
111 } elsif ($phash->{pattern}) {
112 return $phash->{pattern};
113 } elsif ($phash->{type} eq 'integer' || $phash->{type} eq 'number') {
114 if (defined($phash->{minimum}) && defined($phash->{maximum})) {
115 return "$phash->{type} ($phash->{minimum} - $phash->{maximum})";
116 } elsif (defined($phash->{minimum})) {
117 return "$phash->{type} ($phash->{minimum} - N)";
118 } elsif (defined($phash->{maximum})) {
119 return "$phash->{type} (-N - $phash->{maximum})";
120 }
990b6a1a 121 } elsif ($phash->{type} eq 'string') {
2421fba1
WB
122 if (my $format = $phash->{format}) {
123 $format = PVE::JSONSchema::get_format($format) if ref($format) ne 'HASH';
124 if (ref($format) eq 'HASH') {
125 return generate_typetext($format);
126 }
990b6a1a 127 }
e143e9d8
DM
128 }
129
130 my $type = $phash->{type} || 'string';
131
132 return $type;
133}
134
7b1e4b04
WB
135sub generate_property_text {
136 my ($schema) = @_;
137 my $data = '';
138 foreach my $key (sort keys %$schema) {
139 my $d = $schema->{$key};
5a917b42 140 next if $d->{alias};
7b1e4b04
WB
141 my $desc = $d->{description};
142 my $typetext = schema_get_type_text($d);
143 $desc = 'No description available' if !$desc;
144 $data .= "=item $key: $typetext\n\n$desc\n\n";
145 }
146 return $data;
147}
148
8ff24fe8 149# generate pod from JSON schema properties
e143e9d8
DM
150sub dump_properties {
151 my ($properties) = @_;
152
153 my $data = "=over 1\n\n";
154
155 my $idx_param = {}; # -vlan\d+ -scsi\d+
156
157 foreach my $key (sort keys %$properties) {
158 my $d = $properties->{$key};
159 my $base = $key;
160 if ($key =~ m/^([a-z]+)(\d+)$/) {
161 my $name = $1;
162 next if $idx_param->{$name};
163 $idx_param->{$name} = 1;
164 $base = "${name}[n]";
165 }
166
167 my $descr = $d->{description} || 'No description avalable.';
168 chomp $descr;
169
170 if (defined(my $dv = $d->{default})) {
171 my $multi = $descr =~ m/\n\n/; # multi paragraph ?
172 $descr .= $multi ? "\n\n" : " ";
173 $descr .= "Default value is '$dv'.";
174 }
175
176 my $typetext = schema_get_type_text($d);
177 $data .= "=item $base: $typetext\n\n";
178 $data .= "$descr\n\n";
7b1e4b04
WB
179
180 if ($d->{type} eq 'string') {
181 my $format = $d->{format};
182 if ($format && ref($format) eq 'HASH') {
183 $data .= "=over 1.1\n\n";
184 $data .= generate_property_text($format);
185 $data .= "=back\n\n";
186 }
187 }
e143e9d8
DM
188 }
189
190 $data .= "=back";
191
192 return $data;
193}
194
1951;