#!/usr/bin/perl
my
$Program
= basename($0);
my
$MAX_WIDTH
= MAX;
my
@linedesc
;
@ARGV
= new_argv();
Getopt::Long::config(
'bundling'
);
GetOptions(
'w=i'
=> \
$MAX_WIDTH
,
) or usage();
if
(
$MAX_WIDTH
<= 0) {
warn
"$Program: width must be positive\n"
;
exit
EX_FAILURE;
}
my
$rc
= EX_SUCCESS;
foreach
my
$file
(
@ARGV
) {
if
(-d
$file
) {
warn
"$Program: '$file' is a directory\n"
;
$rc
= EX_FAILURE;
next
;
}
my
$fh
;
unless
(
open
$fh
,
'<'
,
$file
) {
warn
"$Program: failed to open '$file': $!\n"
;
$rc
= EX_FAILURE;
next
;
}
fmt_file(
$fh
);
unless
(
close
$fh
) {
warn
"$Program: failed to close '$file': $!\n"
;
$rc
= EX_FAILURE;
}
}
unless
(
@ARGV
) {
fmt_file(
*STDIN
);
}
while
(
@linedesc
) {
fmt_line()
}
exit
$rc
;
sub
usage {
warn
"usage: $Program [-w WIDTH] [file...]\n"
;
exit
EX_FAILURE;
}
sub
fmt_file {
my
$fh
=
shift
;
while
(<
$fh
>) {
chomp
;
fmt_line();
my
@line
= split_line(
$_
);
push
@linedesc
,
@line
;
}
}
sub
split_line {
my
$line
=
shift
;
my
$indent
= 0;
if
(
$line
=~ s/\A(\s+)//) {
$indent
=
length
$1;
}
my
@tok
;
while
(
length
$line
) {
if
(
$line
=~ s/\A(\S+)//) {
my
$t
= {};
$t
->{
'indent'
} =
$indent
;
$t
->{
'word'
} = $1;
$t
->{
'len'
} =
length
$1;
$t
->{
'suffix'
} = 1;
if
(
$line
=~ s/\A(\s+)//) {
$t
->{
'suffix'
} =
length
$1;
}
push
@tok
,
$t
;
}
}
my
$end
= {
'len'
=> 0 };
push
@tok
,
$end
;
return
@tok
;
}
sub
fmt_line {
return
unless
@linedesc
;
my
$max
=
int
(
$MAX_WIDTH
* 1.05);
my
$remain
=
$max
;
my
(
@out
,
$tok
);
my
$indent
;
while
(
@linedesc
) {
$tok
=
shift
@linedesc
;
if
(
$tok
->{
'len'
} == 0) {
next
unless
@linedesc
;
next
if
$linedesc
[0]->{
'len'
} != 0;
shift
@linedesc
;
$tok
->{
'len'
} = 1;
$tok
->{
'word'
} =
"\n"
;
$tok
->{
'suffix'
} = 0;
$tok
->{
'indent'
} = 0;
}
unless
(
defined
$indent
) {
$indent
=
$tok
->{
'indent'
};
$remain
-=
$indent
;
}
my
$len
=
$tok
->{
'len'
} +
$tok
->{
'suffix'
};
if
(
@out
) {
if
(
$remain
-
$len
< 0) {
unshift
@linedesc
,
$tok
;
last
;
}
if
(
$out
[-1]->{
'len'
} &&
$out
[-1]->{
'indent'
} !=
$tok
->{
'indent'
}){
unshift
@linedesc
,
$tok
;
last
;
}
}
$remain
-=
$len
;
push
@out
,
$tok
;
}
return
unless
@out
;
my
$s
=
' '
x
$out
[0]->{
'indent'
};
print
$s
;
$out
[-1]->{
'suffix'
} = 0;
foreach
$tok
(
@out
) {
$s
=
$tok
->{
'word'
};
$s
.=
' '
x
$tok
->{
'suffix'
};
print
$s
;
}
print
"\n"
;
return
;
}
sub
new_argv {
my
@new
;
my
$end
= 0;
foreach
my
$arg
(
@ARGV
) {
if
(
$arg
eq
'--'
||
$arg
!~ m/\A\-/) {
push
@new
,
$arg
;
$end
= 1;
next
;
}
if
(!
$end
&&
$arg
=~ m/\A\-([0-9]+)\Z/) {
push
@new
,
"-w$1"
;
}
else
{
push
@new
,
$arg
;
}
}
return
@new
;
}