mirror of
https://github.com/curl/curl.git
synced 2026-05-30 08:17:30 +03:00
docs: introduce "curldown" for libcurl man page format
curldown is this new file format for libcurl man pages. It is markdown inspired with differences: - Each file has a set of leading headers with meta-data - Supports a small subset of markdown - Uses .md file extensions for editors/IDE/GitHub to treat them nicely - Generates man pages very similar to the previous ones - Generates man pages that still convert nicely to HTML on the website - Detects and highlights mentions of curl symbols automatically (when their man page section is specified) tools: - cd2nroff: converts from curldown to nroff man page - nroff2cd: convert an (old) nroff man page to curldown - cdall: convert many nroff pages to curldown versions - cd2cd: verifies and updates a curldown to latest curldown This setup generates .3 versions of all the curldown versions at build time. CI: Since the documentation is now technically markdown in the eyes of many things, the CI runs many more tests and checks on this documentation, including proselint, link checkers and tests that make sure we capitalize the first letter after a period... Closes #12730
This commit is contained in:
parent
02f91d5b64
commit
eefcc1bda4
960 changed files with 41083 additions and 39724 deletions
|
|
@ -22,8 +22,8 @@
|
|||
#
|
||||
###########################################################################
|
||||
|
||||
EXTRA_DIST = updatemanpages.pl coverage.sh completion.pl firefox-db2pem.sh \
|
||||
checksrc.pl mk-ca-bundle.pl schemetable.c
|
||||
EXTRA_DIST = coverage.sh completion.pl firefox-db2pem.sh checksrc.pl \
|
||||
mk-ca-bundle.pl schemetable.c cd2nroff nroff2cd cdall cd2cd
|
||||
|
||||
ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@
|
||||
FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@
|
||||
|
|
|
|||
226
scripts/cd2cd
Executable file
226
scripts/cd2cd
Executable file
|
|
@ -0,0 +1,226 @@
|
|||
#!/usr/bin/env perl
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
=begin comment
|
||||
|
||||
This script updates a curldown file to current/better curldown.
|
||||
|
||||
Example: cd2cd [--in-place] <file.md> > <file.md>
|
||||
|
||||
--in-place: if used, it replaces the original file with the cleaned up
|
||||
version. When this is used, cd2cd accepts multiple files to work
|
||||
on and it ignores errors on single files.
|
||||
|
||||
=end comment
|
||||
=cut
|
||||
|
||||
my $cd2cd = "0.1"; # to keep check
|
||||
my $dir;
|
||||
my $extension;
|
||||
my $inplace = 0;
|
||||
|
||||
while(1) {
|
||||
if($ARGV[0] eq "--in-place") {
|
||||
shift @ARGV;
|
||||
$inplace = 1;
|
||||
}
|
||||
else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
use POSIX qw(strftime);
|
||||
my @ts;
|
||||
if (defined($ENV{SOURCE_DATE_EPOCH})) {
|
||||
@ts = localtime($ENV{SOURCE_DATE_EPOCH});
|
||||
} else {
|
||||
@ts = localtime;
|
||||
}
|
||||
my $date = strftime "%B %d %Y", @ts;
|
||||
|
||||
sub outseealso {
|
||||
my (@sa) = @_;
|
||||
my $comma = 0;
|
||||
my @o;
|
||||
push @o, ".SH SEE ALSO\n";
|
||||
for my $s (sort @sa) {
|
||||
push @o, sprintf "%s.BR $s", $comma ? ",\n": "";
|
||||
$comma = 1;
|
||||
}
|
||||
push @o, "\n";
|
||||
return @o;
|
||||
}
|
||||
|
||||
sub single {
|
||||
my @head;
|
||||
my @seealso;
|
||||
my ($f)=@_;
|
||||
my $title;
|
||||
my $section;
|
||||
my $source;
|
||||
my $start = 0;
|
||||
my $d;
|
||||
my $line = 0;
|
||||
open(F, "<:crlf", "$f") ||
|
||||
return 1;
|
||||
while(<F>) {
|
||||
$line++;
|
||||
$d = $_;
|
||||
if(!$start) {
|
||||
if(/^---/) {
|
||||
# header starts here
|
||||
$start = 1;
|
||||
push @head, $d;
|
||||
}
|
||||
next;
|
||||
}
|
||||
if(/^Title: *(.*)/i) {
|
||||
$title=$1;
|
||||
}
|
||||
elsif(/^Section: *(.*)/i) {
|
||||
$section=$1;
|
||||
}
|
||||
elsif(/^Source: *(.*)/i) {
|
||||
$source=$1;
|
||||
}
|
||||
elsif(/^See-also: +(.*)/i) {
|
||||
$salist = 0;
|
||||
push @seealso, $1;
|
||||
}
|
||||
elsif(/^See-also: */i) {
|
||||
if($seealso[0]) {
|
||||
print STDERR "$f:$line:1:ERROR: bad See-Also, needs list\n";
|
||||
return 2;
|
||||
}
|
||||
$salist = 1;
|
||||
}
|
||||
elsif(/^ +- (.*)/i) {
|
||||
# the only list we support is the see-also
|
||||
if($salist) {
|
||||
push @seealso, $1;
|
||||
}
|
||||
}
|
||||
# REUSE-IgnoreStart
|
||||
elsif(/^C: (.*)/i) {
|
||||
$copyright=$1;
|
||||
}
|
||||
elsif(/^SPDX-License-Identifier: (.*)/i) {
|
||||
$spdx=$1;
|
||||
}
|
||||
# REUSE-IgnoreEnd
|
||||
elsif(/^---/) {
|
||||
# end of the header section
|
||||
if(!$title) {
|
||||
print STDERR "ERROR: no 'Title:' in $f\n";
|
||||
return 1;
|
||||
}
|
||||
if(!$section) {
|
||||
print STDERR "ERROR: no 'Section:' in $f\n";
|
||||
return 2;
|
||||
}
|
||||
if(!$seealso[0]) {
|
||||
print STDERR "$f:$line:1:ERROR: no 'See-also:' present\n";
|
||||
return 2;
|
||||
}
|
||||
if(!$copyright) {
|
||||
print STDERR "$f:$line:1:ERROR: no 'C:' field present\n";
|
||||
return 2;
|
||||
}
|
||||
if(!$spdx) {
|
||||
print STDERR "$f:$line:1:ERROR: no 'SPDX-License-Identifier:' field present\n";
|
||||
return 2;
|
||||
}
|
||||
last;
|
||||
}
|
||||
else {
|
||||
chomp;
|
||||
print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
|
||||
}
|
||||
}
|
||||
|
||||
if(!$start) {
|
||||
print STDERR "$f:$line:1:ERROR: no header present\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
my @desc;
|
||||
|
||||
push @desc, sprintf <<HEAD
|
||||
---
|
||||
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
SPDX-License-Identifier: curl
|
||||
Title: $title
|
||||
Section: $section
|
||||
Source: $source
|
||||
HEAD
|
||||
;
|
||||
push @desc, "See-also:\n";
|
||||
for my $s (sort @seealso) {
|
||||
push @desc, " - $s\n" if($s);
|
||||
}
|
||||
push @desc, "---\n";
|
||||
|
||||
my $blankline = 0;
|
||||
while(<F>) {
|
||||
$d = $_;
|
||||
$line++;
|
||||
if($d =~ /^[ \t]*\n/) {
|
||||
$blankline++;
|
||||
}
|
||||
else {
|
||||
$blankline = 0;
|
||||
}
|
||||
# *italics* for curl symbol links get the asterisks removed
|
||||
$d =~ s/\*((lib|)curl[^ ]*\(3\))\*/$1/gi;
|
||||
|
||||
if(length($d) > 90) {
|
||||
print STDERR "$f:$line:1:WARN: excessive line length\n";
|
||||
}
|
||||
|
||||
push @desc, $d if($blankline < 2);
|
||||
}
|
||||
close(F);
|
||||
|
||||
if($inplace) {
|
||||
open(O, ">$f") || return 1;
|
||||
print O @desc;
|
||||
close(O);
|
||||
}
|
||||
else {
|
||||
print @desc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($inplace) {
|
||||
for my $a (@ARGV) {
|
||||
# this ignores errors
|
||||
single($a);
|
||||
}
|
||||
}
|
||||
else {
|
||||
exit single($ARGV[0]);
|
||||
}
|
||||
331
scripts/cd2nroff
Executable file
331
scripts/cd2nroff
Executable file
|
|
@ -0,0 +1,331 @@
|
|||
#!/usr/bin/env perl
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
=begin comment
|
||||
|
||||
Converts a curldown file to nroff (man page).
|
||||
|
||||
=end comment
|
||||
=cut
|
||||
|
||||
my $cd2nroff = "0.1"; # to keep check
|
||||
my $dir;
|
||||
my $extension;
|
||||
|
||||
while(1) {
|
||||
if($ARGV[0] eq "-d") {
|
||||
shift @ARGV;
|
||||
$dir = shift @ARGV;
|
||||
}
|
||||
elsif($ARGV[0] eq "-e") {
|
||||
shift @ARGV;
|
||||
$extension = shift @ARGV;
|
||||
}
|
||||
elsif($ARGV[0] eq "-h") {
|
||||
print <<HELP
|
||||
Usage: cd2nroff [options] [file.md]
|
||||
|
||||
-d <dir> Write the output to the file name from the meta-data in the
|
||||
specified directory, instead of writing to stdout
|
||||
-e <ext> If -d is used, this option can provide an added "extension", arbitrary
|
||||
text really, to append to the file name.
|
||||
-h This help text,
|
||||
-v Show version then exit
|
||||
HELP
|
||||
;
|
||||
exit 0;
|
||||
}
|
||||
elsif($ARGV[0] eq "-v") {
|
||||
print "cd2nroff version $cd2nroff\n";
|
||||
exit 0;
|
||||
}
|
||||
else {
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
use POSIX qw(strftime);
|
||||
my @ts;
|
||||
if (defined($ENV{SOURCE_DATE_EPOCH})) {
|
||||
@ts = localtime($ENV{SOURCE_DATE_EPOCH});
|
||||
} else {
|
||||
@ts = localtime;
|
||||
}
|
||||
my $date = strftime "%B %d %Y", @ts;
|
||||
|
||||
sub outseealso {
|
||||
my (@sa) = @_;
|
||||
my $comma = 0;
|
||||
my @o;
|
||||
push @o, ".SH SEE ALSO\n";
|
||||
for my $s (sort @sa) {
|
||||
push @o, sprintf "%s.BR $s", $comma ? ",\n": "";
|
||||
$comma = 1;
|
||||
}
|
||||
push @o, "\n";
|
||||
return @o;
|
||||
}
|
||||
|
||||
sub single {
|
||||
my @seealso;
|
||||
my ($f)=@_;
|
||||
my $title;
|
||||
my $section;
|
||||
my $source;
|
||||
my $start = 0;
|
||||
my $errors;
|
||||
my $fh;
|
||||
if($f) {
|
||||
open($fh, "<:crlf", "$f") || return 1;
|
||||
}
|
||||
else {
|
||||
$fh = STDIN;
|
||||
}
|
||||
while(<$fh>) {
|
||||
$line++;
|
||||
if(!$start) {
|
||||
if(/^---/) {
|
||||
# header starts here
|
||||
$start = 1;
|
||||
}
|
||||
next;
|
||||
}
|
||||
if(/^Title: *(.*)/i) {
|
||||
$title=$1;
|
||||
}
|
||||
elsif(/^Section: *(.*)/i) {
|
||||
$section=$1;
|
||||
}
|
||||
elsif(/^Source: *(.*)/i) {
|
||||
$source=$1;
|
||||
}
|
||||
elsif(/^See-also: +(.*)/i) {
|
||||
$salist = 0;
|
||||
push @seealso, $1;
|
||||
}
|
||||
elsif(/^See-also: */i) {
|
||||
if($seealso[0]) {
|
||||
print STDERR "$f:$line:1:ERROR: bad See-Also, needs list\n";
|
||||
return 2;
|
||||
}
|
||||
$salist = 1;
|
||||
}
|
||||
elsif(/^ +- (.*)/i) {
|
||||
# the only list we support is the see-also
|
||||
if($salist) {
|
||||
push @seealso, $1;
|
||||
}
|
||||
}
|
||||
# REUSE-IgnoreStart
|
||||
elsif(/^C: (.*)/i) {
|
||||
$copyright=$1;
|
||||
}
|
||||
elsif(/^SPDX-License-Identifier: (.*)/i) {
|
||||
$spdx=$1;
|
||||
}
|
||||
# REUSE-IgnoreEnd
|
||||
elsif(/^---/) {
|
||||
# end of the header section
|
||||
if(!$title) {
|
||||
print STDERR "ERROR: no 'Title:' in $f\n";
|
||||
return 1;
|
||||
}
|
||||
if(!$section) {
|
||||
print STDERR "ERROR: no 'Section:' in $f\n";
|
||||
return 2;
|
||||
}
|
||||
if(!$seealso[0]) {
|
||||
print STDERR "$f:$line:1:ERROR: no 'See-also:' present\n";
|
||||
return 2;
|
||||
}
|
||||
if(!$copyright) {
|
||||
print STDERR "$f:$line:1:ERROR: no 'C:' field present\n";
|
||||
return 2;
|
||||
}
|
||||
if(!$spdx) {
|
||||
print STDERR "$f:$line:1:ERROR: no 'SPDX-License-Identifier:' field present\n";
|
||||
return 2;
|
||||
}
|
||||
last;
|
||||
}
|
||||
else {
|
||||
chomp;
|
||||
print STDERR "WARN: unrecognized line in $f, ignoring:\n:'$_';"
|
||||
}
|
||||
}
|
||||
|
||||
if(!$start) {
|
||||
print STDERR "$f:$line:1:ERROR: no header present\n";
|
||||
return 2;
|
||||
}
|
||||
|
||||
my @desc;
|
||||
my $quote = 0;
|
||||
my $blankline = 0;
|
||||
my $header = 0;
|
||||
|
||||
# cut off the leading path from the file name, if any
|
||||
$f =~ s/^(.*[\\\/])//;
|
||||
|
||||
push @desc, ".\\\" generated by cd2nroff $cd2nroff from $f\n";
|
||||
push @desc, ".TH $title $section \"$date\" $source\n";
|
||||
while(<$fh>) {
|
||||
$line++;
|
||||
|
||||
$d = $_;
|
||||
|
||||
if($quote) {
|
||||
if($quote == 4) {
|
||||
# remove the indentation
|
||||
if($d =~ /^ (.*)/) {
|
||||
push @desc, "$1\n";
|
||||
next;
|
||||
}
|
||||
else {
|
||||
# end of quote
|
||||
$quote = 0;
|
||||
push @desc, ".fi\n";
|
||||
next;
|
||||
}
|
||||
}
|
||||
if(/^~~~/) {
|
||||
# end of quote
|
||||
$quote = 0;
|
||||
push @desc, ".fi\n";
|
||||
next;
|
||||
}
|
||||
# convert single backslahes to doubles
|
||||
$d =~ s/\\/\\\\/g;
|
||||
# lines starting with a period needs it escaped
|
||||
$d =~ s/^\./\\&./;
|
||||
push @desc, $d;
|
||||
next;
|
||||
}
|
||||
|
||||
# **bold**
|
||||
$d =~ s/\*\*(\S.*?)\*\*/\\fB$1\\fP/g;
|
||||
# *italics*
|
||||
$d =~ s/\*(\S.*?)\*/\\fI$1\\fP/g;
|
||||
|
||||
# mentions of curl symbols with man pages use italics by default
|
||||
$d =~ s/((lib|)curl([^ ]*\(3\)))/\\fI$1\\fP/gi;
|
||||
|
||||
# backticked becomes italics
|
||||
$d =~ s/\`(.*?)\`/\\fI$1\\fP/g;
|
||||
|
||||
if(/^## (.*)/) {
|
||||
my $word = $1;
|
||||
# if there are enclosing quotes, remove them first
|
||||
$word =~ s/[\"\'](.*)[\"\']\z/$1/;
|
||||
|
||||
# enclose in double quotes if there is a space present
|
||||
if($word =~ / /) {
|
||||
push @desc, ".IP \"$word\"\n";
|
||||
}
|
||||
else {
|
||||
push @desc, ".IP $word\n";
|
||||
}
|
||||
$header = 1;
|
||||
}
|
||||
elsif(/^# (.*)/) {
|
||||
my $word = $1;
|
||||
# if there are enclosing quotes, remove them first
|
||||
$word =~ s/[\"\'](.*)[\"\']\z/$1/;
|
||||
push @desc, ".SH $word\n";
|
||||
$header = 1;
|
||||
}
|
||||
elsif(/^~~~c/) {
|
||||
# start of a code section, not indented
|
||||
$quote = 1;
|
||||
push @desc, "\n" if($blankline && !$header);
|
||||
$header = 0;
|
||||
push @desc, ".nf\n";
|
||||
}
|
||||
elsif(/^~~~/) {
|
||||
# start of a quote section; not code, not indented
|
||||
$quote = 1;
|
||||
push @desc, "\n" if($blankline && !$header);
|
||||
$header = 0;
|
||||
push @desc, ".nf\n";
|
||||
}
|
||||
elsif(/^ (.*)/) {
|
||||
# quoted, indented by 4 space
|
||||
$quote = 4;
|
||||
push @desc, "\n" if($blankline && !$header);
|
||||
$header = 0;
|
||||
push @desc, ".nf\n$1\n";
|
||||
}
|
||||
elsif(/^[ \t]*\n/) {
|
||||
# count and ignore blank lines
|
||||
$blankline++;
|
||||
}
|
||||
else {
|
||||
# don't output newlines if this is the first content after a
|
||||
# header
|
||||
push @desc, "\n" if($blankline && !$header);
|
||||
$blankline = 0;
|
||||
$header = 0;
|
||||
|
||||
# remove single line HTML comments
|
||||
$d =~ s/<!--.*?-->//g;
|
||||
|
||||
# quote minuses in the output
|
||||
$d =~ s/([^\\])-/$1\\-/g;
|
||||
# replace single quotes
|
||||
$d =~ s/\'/\\(aq/g;
|
||||
# handle double quotes first on the line
|
||||
$d =~ s/^(\s*)\"/$1\\&\"/;
|
||||
|
||||
# lines starting with a period needs it escaped
|
||||
$d =~ s/^\./\\&./;
|
||||
|
||||
if($d =~ /^(.*) /) {
|
||||
printf STDERR "$f:$line:%d:ERROR: 2 spaces detected\n",
|
||||
length($1);
|
||||
$errors++;
|
||||
}
|
||||
if($d =~ /^[ \t]*\n/) {
|
||||
# replaced away all contents
|
||||
$blankline= 1;
|
||||
}
|
||||
else {
|
||||
push @desc, $d;
|
||||
}
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
push @desc, outseealso(@seealso);
|
||||
if($dir) {
|
||||
open(O, ">$dir/$title.$section$extension");
|
||||
print O @desc;
|
||||
close(O);
|
||||
}
|
||||
else {
|
||||
print @desc;
|
||||
}
|
||||
return $errors;
|
||||
}
|
||||
|
||||
exit single($ARGV[0]);
|
||||
44
scripts/cdall
Executable file
44
scripts/cdall
Executable file
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env perl
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
# provide all dir names to scan on the cmdline
|
||||
|
||||
sub convert {
|
||||
my ($dir)=@_;
|
||||
opendir(my $dh, $dir) || die "could not open $dir";
|
||||
my @cd = grep { /\.md\z/ && -f "$dir/$_" } readdir($dh);
|
||||
closedir $dh;
|
||||
|
||||
for my $cd (@cd) {
|
||||
my $nroff = "$cd";
|
||||
$nroff =~ s/\.md\z/.3/;
|
||||
print "$dir/$cd = $dir/$nroff\n";
|
||||
system("./scripts/cd2nroff -d $dir $dir/$cd");
|
||||
}
|
||||
}
|
||||
|
||||
for my $d (sort @ARGV) {
|
||||
convert($d);
|
||||
}
|
||||
193
scripts/nroff2cd
Executable file
193
scripts/nroff2cd
Executable file
|
|
@ -0,0 +1,193 @@
|
|||
#!/usr/bin/env perl
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
=begin comment
|
||||
|
||||
This script converts an nroff file to curldown
|
||||
|
||||
Example: cd2nroff [options] <file.md> > <file.3>
|
||||
|
||||
Note: when converting .nf sections, this tool does not know if the
|
||||
section is code or just regular quotes. It then assumes and uses ~~~c
|
||||
for code.
|
||||
|
||||
=end comment
|
||||
=cut
|
||||
|
||||
my $nroff2cd = "0.1"; # to keep check
|
||||
|
||||
sub single {
|
||||
my ($f)=@_;
|
||||
open(F, "<:crlf", "$f") ||
|
||||
return 1;
|
||||
my $line;
|
||||
my $title;
|
||||
my $section;
|
||||
my $source;
|
||||
my @seealso;
|
||||
my @desc;
|
||||
my $header; # non-zero when TH is passed
|
||||
my $quote = 0; # quote state
|
||||
while(<F>) {
|
||||
$line++;
|
||||
my $d = $_;
|
||||
if($_ =~ /^.\\\"/) {
|
||||
# a comment we can ignore
|
||||
next;
|
||||
}
|
||||
if(!$header) {
|
||||
if($d =~ /.so (.*)/) {
|
||||
# this is basically an include, so do that
|
||||
my $f = $1;
|
||||
# remove leading directory
|
||||
$f =~ s/(.*?\/)//;
|
||||
close(F);
|
||||
open(F, "<:crlf", "$f") || return 1;
|
||||
}
|
||||
if($d =~ /^\.TH ([^ ]*) (\d) \"(.*?)\" ([^ \n]*)/) {
|
||||
# header, this needs to be the first thing after leading comments
|
||||
$title = $1;
|
||||
$section = $2;
|
||||
# date is $3
|
||||
$source = $4;
|
||||
# if there are enclosing quotes around source, remove them
|
||||
$source =~ s/[\"\'](.*)[\"\']\z/$1/;
|
||||
$header = 1;
|
||||
|
||||
print <<HEAD
|
||||
---
|
||||
c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
SPDX-License-Identifier: curl
|
||||
Title: $title
|
||||
Section: $section
|
||||
Source: $source
|
||||
HEAD
|
||||
;
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
if($quote) {
|
||||
if($d =~ /^\.SH/) {
|
||||
#end of quote without an .fi
|
||||
$quote = 0;
|
||||
push @desc, "~~~\n";
|
||||
}
|
||||
elsif($d =~ /^\.fi/) {
|
||||
#end of quote
|
||||
$quote = 0;
|
||||
push @desc, "~~~\n";
|
||||
next;
|
||||
}
|
||||
else {
|
||||
# double-backslashes converted to single ones
|
||||
$d =~ s/\\\\/\\/g;
|
||||
push @desc, $d;
|
||||
next;
|
||||
}
|
||||
}
|
||||
if($d =~ /^\.SH (.*)/) {
|
||||
my $word = $1;
|
||||
# if there are enclosing quotes, remove them first
|
||||
$word =~ s/[\"\'](.*)[\"\']\z/$1/;
|
||||
if($word eq "SEE ALSO") {
|
||||
# we just slurp up this section
|
||||
next;
|
||||
}
|
||||
push @desc, "\n# $word\n\n";
|
||||
}
|
||||
elsif($d =~ /^\.(RS|RE)/) {
|
||||
# ignore these
|
||||
}
|
||||
elsif($d =~ /^\.IP (.*)/) {
|
||||
my $word = $1;
|
||||
# if there are enclosing quotes, remove them first
|
||||
$word =~ s/[\"\'](.*)[\"\']\z/$1/;
|
||||
push @desc, "\n## $word\n\n";
|
||||
}
|
||||
elsif($d =~ /^\.IP/) {
|
||||
# .IP with no text we just skip
|
||||
}
|
||||
elsif($d =~ /^\.BR (.*)/) {
|
||||
# only used for SEE ALSO
|
||||
my $word = $1;
|
||||
# remove trailing comma
|
||||
$word =~ s/,\z//;
|
||||
|
||||
for my $s (split(/,/, $word)) {
|
||||
# remove all double quotes
|
||||
$s =~ s/\"//g;
|
||||
# tream leading whitespace
|
||||
$s =~ s/^ +//g;
|
||||
push @seealso, $s;
|
||||
}
|
||||
}
|
||||
elsif($d =~ /^\.I (.*)/) {
|
||||
push @desc, "*$1*\n";
|
||||
}
|
||||
elsif($d =~ /^\.B (.*)/) {
|
||||
push @desc, "**$1**\n";
|
||||
}
|
||||
elsif($d =~ /^\.nf/) {
|
||||
push @desc, "~~~c\n";
|
||||
$quote = 1;
|
||||
}
|
||||
else {
|
||||
# embolden
|
||||
$d =~ s/\\fB(.*?)\\fP/**$1**/g;
|
||||
# links to "curl.*()" are left bare since cd2nroff handles them
|
||||
# specially
|
||||
$d =~ s/\\fI(curl.*?\(3\))\\fP/$1/ig;
|
||||
# emphasize
|
||||
$d =~ s/\\fI(.*?)\\fP/*$1*/g;
|
||||
# emphasize on a split line
|
||||
$d =~ s/\\fI/*/g;
|
||||
# bold on a split line
|
||||
$d =~ s/\\fB/**/g;
|
||||
# remove backslash amp
|
||||
$d =~ s/\\&//g;
|
||||
# remove backslashes
|
||||
$d =~ s/\\//g;
|
||||
# fix single quotes
|
||||
$d =~ s/\(aq/'/g;
|
||||
# fix double quotes
|
||||
$d =~ s/\(dq/\"/g;
|
||||
push @desc, $d;
|
||||
}
|
||||
}
|
||||
close(F);
|
||||
|
||||
print "See-also:\n";
|
||||
for my $s (sort @seealso) {
|
||||
print " - $s\n" if($s);
|
||||
}
|
||||
print "---\n";
|
||||
print @desc;
|
||||
|
||||
return !$header;
|
||||
}
|
||||
|
||||
exit single($ARGV[0]);
|
||||
|
||||
|
|
@ -1,357 +0,0 @@
|
|||
#!/usr/bin/env perl
|
||||
#***************************************************************************
|
||||
# _ _ ____ _
|
||||
# Project ___| | | | _ \| |
|
||||
# / __| | | | |_) | |
|
||||
# | (__| |_| | _ <| |___
|
||||
# \___|\___/|_| \_\_____|
|
||||
#
|
||||
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
#
|
||||
# This software is licensed as described in the file COPYING, which
|
||||
# you should have received as part of this distribution. The terms
|
||||
# are also available at https://curl.se/docs/copyright.html.
|
||||
#
|
||||
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
# copies of the Software, and permit persons to whom the Software is
|
||||
# furnished to do so, under the terms of the COPYING file.
|
||||
#
|
||||
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
# KIND, either express or implied.
|
||||
#
|
||||
# SPDX-License-Identifier: curl
|
||||
#
|
||||
###########################################################################
|
||||
|
||||
# Update man pages.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Tie::File;
|
||||
|
||||
# Data from the command line.
|
||||
|
||||
my $curlver = $ARGV[0];
|
||||
my $curldate = $ARGV[1];
|
||||
|
||||
# Directories and extensions.
|
||||
|
||||
my @dirlist = ("docs/", "docs/libcurl/", "docs/libcurl/opts/", "tests/");
|
||||
my @extlist = (".1", ".3");
|
||||
my @excludelist = ("mk-ca-bundle.1", "template.3");
|
||||
|
||||
# Subroutines
|
||||
|
||||
sub printargs{
|
||||
# Print arguments and exit.
|
||||
|
||||
print "usage: updatemanpages.pl <version> <date>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
sub getthline{
|
||||
# Process file looking for .TH section.
|
||||
|
||||
my $filename = shift;
|
||||
my $file_handle;
|
||||
my $file_line;
|
||||
|
||||
# Open the file.
|
||||
|
||||
open($file_handle, $filename);
|
||||
|
||||
# Look for the .TH section, process it into an array,
|
||||
# modify it and write to file.
|
||||
|
||||
tie(my @file_data, 'Tie::File', $filename);
|
||||
foreach my $file_data_line(@file_data) {
|
||||
if($file_data_line =~ /^.TH/) {
|
||||
$file_line = $file_data_line;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Close the file.
|
||||
|
||||
close($file_handle);
|
||||
return $file_line;
|
||||
}
|
||||
|
||||
sub extractth{
|
||||
# Extract .TH section as an array.
|
||||
|
||||
my $input = shift;
|
||||
|
||||
# Split the line into an array.
|
||||
|
||||
my @tharray;
|
||||
my $inputsize = length($input);
|
||||
my $inputcurrent = "";
|
||||
my $quotemode = 0;
|
||||
|
||||
for(my $inputseek = 0; $inputseek < $inputsize; $inputseek++) {
|
||||
|
||||
if(substr($input, $inputseek, 1) eq " " && $quotemode eq 0) {
|
||||
push(@tharray, $inputcurrent);
|
||||
$inputcurrent = "";
|
||||
next;
|
||||
}
|
||||
|
||||
$inputcurrent = $inputcurrent . substr($input, $inputseek, 1);
|
||||
|
||||
if(substr($input, $inputseek, 1) eq "\"") {
|
||||
if($quotemode eq 0) {
|
||||
$quotemode = 1;
|
||||
}
|
||||
else {
|
||||
$quotemode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($inputcurrent ne "") {
|
||||
push(@tharray, $inputcurrent);
|
||||
}
|
||||
|
||||
return @tharray;
|
||||
}
|
||||
|
||||
sub getdate{
|
||||
# Get the date from the .TH section.
|
||||
|
||||
my $filename = shift;
|
||||
my $thline;
|
||||
my @tharray;
|
||||
my $date = "";
|
||||
|
||||
$thline = getthline($filename);
|
||||
|
||||
# Return nothing if there is no .TH section found.
|
||||
|
||||
if(!$thline || $thline eq "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
@tharray = extractth($thline);
|
||||
|
||||
# Remove the quotes at the start and end.
|
||||
|
||||
$date = substr($tharray[3], 1, -1);
|
||||
return $date;
|
||||
}
|
||||
|
||||
sub processth{
|
||||
# Process .TH section.
|
||||
|
||||
my $input = shift;
|
||||
my $date = shift;
|
||||
|
||||
# Split the line into an array.
|
||||
|
||||
my @tharray = extractth($input);
|
||||
|
||||
# Alter the date.
|
||||
|
||||
my $itemdate = "\"";
|
||||
$itemdate .= $date;
|
||||
$itemdate .= "\"";
|
||||
$tharray[3] = $itemdate;
|
||||
|
||||
# Alter the item version.
|
||||
|
||||
my $itemver = $tharray[4];
|
||||
my $itemname = "";
|
||||
|
||||
for(my $itemnameseek = 1;
|
||||
$itemnameseek < length($itemver);
|
||||
$itemnameseek++) {
|
||||
if(substr($itemver, $itemnameseek, 1) eq " " ||
|
||||
substr($itemver, $itemnameseek, 1) eq "\"") {
|
||||
last;
|
||||
}
|
||||
$itemname .= substr($itemver, $itemnameseek, 1);
|
||||
}
|
||||
|
||||
$itemver = "\"";
|
||||
$itemver .= $itemname;
|
||||
$itemver .= " ";
|
||||
$itemver .= $curlver;
|
||||
$itemver .= "\"";
|
||||
|
||||
$tharray[4] = $itemver;
|
||||
|
||||
my $thoutput = "";
|
||||
|
||||
foreach my $thvalue (@tharray) {
|
||||
$thoutput .= $thvalue;
|
||||
$thoutput .= " ";
|
||||
}
|
||||
$thoutput =~ s/\s+$//;
|
||||
$thoutput .= "\n";
|
||||
|
||||
# Return updated string.
|
||||
|
||||
return $thoutput;
|
||||
}
|
||||
|
||||
sub processfile{
|
||||
# Process file looking for .TH section.
|
||||
|
||||
my $filename = shift;
|
||||
my $date = shift;
|
||||
my $file_handle;
|
||||
my $file_dist_handle;
|
||||
my $filename_dist;
|
||||
|
||||
# Open a handle for the original file and a second file handle
|
||||
# for the dist file.
|
||||
|
||||
$filename_dist = $filename . ".dist";
|
||||
|
||||
open($file_handle, $filename);
|
||||
open($file_dist_handle, ">" . $filename_dist);
|
||||
|
||||
# Look for the .TH section, process it into an array,
|
||||
# modify it and write to file.
|
||||
|
||||
tie(my @file_data, 'Tie::File', $filename);
|
||||
foreach my $file_data_line (@file_data) {
|
||||
if($file_data_line =~ /^.TH/) {
|
||||
my $file_dist_line = processth($file_data_line, $date);
|
||||
print $file_dist_handle $file_dist_line . "\n";
|
||||
}
|
||||
else {
|
||||
print $file_dist_handle $file_data_line . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Close the file.
|
||||
|
||||
close($file_handle);
|
||||
close($file_dist_handle);
|
||||
}
|
||||
|
||||
# Check that $curlver is set, otherwise print arguments and exit.
|
||||
|
||||
if(!$curlver) {
|
||||
printargs();
|
||||
}
|
||||
|
||||
# check to see that the git command works, it requires git 2.6 something
|
||||
my $gitcheck = `git log -1 --date="format:%B %d, %Y" $dirlist[0] 2>/dev/null`;
|
||||
if(length($gitcheck) < 1) {
|
||||
print "git version too old or $dirlist[0] is a bad argument\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# Look in each directory.
|
||||
|
||||
my $dir_handle;
|
||||
|
||||
foreach my $dirname (@dirlist) {
|
||||
foreach my $extname (@extlist) {
|
||||
# Go through the directory looking for files ending with
|
||||
# the current extension.
|
||||
|
||||
opendir($dir_handle, $dirname);
|
||||
my @filelist = grep(/.$extname$/i, readdir($dir_handle));
|
||||
|
||||
foreach my $file (@filelist) {
|
||||
# Skip if file is in exclude list.
|
||||
|
||||
if(grep(/^$file$/, @excludelist)) {
|
||||
next;
|
||||
}
|
||||
|
||||
# Load the file and get the date.
|
||||
|
||||
my $filedate;
|
||||
|
||||
# Check if dist version exists and load date from that
|
||||
# file if it does.
|
||||
|
||||
if(-e ($dirname . $file . ".dist")) {
|
||||
$filedate = getdate(($dirname . $file . ".dist"));
|
||||
}
|
||||
else {
|
||||
$filedate = getdate(($dirname . $file));
|
||||
}
|
||||
|
||||
# Skip if value is empty.
|
||||
|
||||
if(!$filedate || $filedate eq "") {
|
||||
next;
|
||||
}
|
||||
|
||||
# Check the man page in the git repository.
|
||||
|
||||
my $repodata = `LC_TIME=C git log -1 --date="format:%B %d, %Y" \\
|
||||
--since="$filedate" $dirname$file | grep ^Date:`;
|
||||
|
||||
# If there is output then update the man page
|
||||
# with the new date/version.
|
||||
|
||||
# Process the file if there is output.
|
||||
|
||||
if($repodata) {
|
||||
my $thisdate;
|
||||
if(!$curldate) {
|
||||
if($repodata =~ /^Date: +(.*)/) {
|
||||
$thisdate = $1;
|
||||
}
|
||||
else {
|
||||
print STDERR "Warning: " . ($dirname . $file) . ": found no " .
|
||||
"date\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$thisdate = $curldate;
|
||||
}
|
||||
processfile(($dirname . $file), $thisdate);
|
||||
print $dirname . $file . " page updated to $thisdate\n";
|
||||
}
|
||||
}
|
||||
closedir($dir_handle);
|
||||
}
|
||||
}
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 updatemanpages.pl
|
||||
|
||||
Updates the man pages with the version number and optional date. If the date
|
||||
isn't provided, the last modified date from git is used.
|
||||
|
||||
=head2 USAGE
|
||||
|
||||
updatemanpages.pl version [date]
|
||||
|
||||
=head3 version
|
||||
|
||||
Specifies version (required)
|
||||
|
||||
=head3 date
|
||||
|
||||
Specifies date (optional)
|
||||
|
||||
=head2 SETTINGS
|
||||
|
||||
=head3 @dirlist
|
||||
|
||||
Specifies the list of directories to look for files in.
|
||||
|
||||
=head3 @extlist
|
||||
|
||||
Specifies the list of files with extensions to process.
|
||||
|
||||
=head3 @excludelist
|
||||
|
||||
Specifies the list of files to not process.
|
||||
|
||||
=head2 NOTES
|
||||
|
||||
This script is used during maketgz.
|
||||
|
||||
=cut
|
||||
Loading…
Add table
Add a link
Reference in a new issue