http://www.perlmonks.org?node_id=11166

The _sprintlist subroutine takes a list reference and returns a string where the list is nicely formatted. You can specify the tag for the first line, the indentation, the separator used, the line width, and even a prefix for every line. Play with the different options to see how they affect the output. For example, the following:
@list=('aaa'..'aax'); print _sprintlist(\@list,"Members:",undef,10,undef,60,"* ");
will produce:
* Members: aaa, aab, aac, aad, aae, aaf, aag, aah, aai, * aaj, aak, aal, aam, aan, aao, aap, aaq, aar, * aas, aat, aau, aav, aaw, aax
Any arguments given as "undef" (or not given) take on their default values.

The _sprintstr function takes a string instead of a list, and uses _sprintlist to print the string nicely formatted. Most of the arguments are the same.

I have also included a sample Help() function to print command summaries with their help strings. This assumes the hash %COMMANDS is indexed by command name, and each element is a hash ref with elements "Sum" and "Desc".

A named-argument interface is left as an exercise to the reader :-)

--ZZamboni

Updated: Added sample input and output for Help().

# Returns an indented string containing a list. Syntax is: # _sprintlist($listref[, $firstline[, $separator[, $indent # [, $break[, $linelen[, $lineprefix]]]]]) # All lines are indented by $indent spaces (default 0). # If $firstline is given, that string is inserted in the # indentation of the first line (it is truncated to $indent spaces # unless $break is true, in which case the list is pushed to the next # line). Normally the list elements are separated by commas and spaces # ", ". If $separator is given, that string is used as a separator. # Lines are wrapped to $linelen characters, unless it is specified as # some other value. A value of 0 for $linelen makes it not do line wra +pping. # If $lineprefix is given, it is printed at the beginning of each line +. sub _sprintlist { my $listref=shift or return; my @list=@$listref; my $fline=shift; my $separator=shift || ", "; my $indent=shift; $indent=0 unless defined($indent); my $space=" " x $indent; $fline||=$space; my $break=shift || 0; my $linelen=shift; $linelen=80 unless defined($linelen); my $lp=shift||""; $linelen-=length($lp); if (!$break || length($fline)<=$indent) { $fline=substr("$fline$space", 0, length($space)); } else { # length($fline)>$indent $fline="$fline\n$space"; } my $str=""; my $line=""; foreach (@list) { $line.=$separator if $line; if ($linelen && length($line)+length($_)+length($space)>=$linelen) + { $line=~s/\s*$//; $str.="$space$line\n"; $line=""; } $line.="$_"; } $str.="$space$line"; $str=~s/^$space/$fline/; $str=~s/^/$lp/mg if $lp; return $str; } # Gets a string, and returns it nicely formatted and word-wrapped. It # uses _sprintlist as a backend. Its syntax is the same as # _sprintlist, except that is gets a string instead of a list ref, and # that $separator is not used because we automatically break on white # space. # Syntax: _sprintstr($string[, $firstline[, $indent[, $break[, $linele +n # [, $lineprefix]]]]]); # See _sprintlist for the meaning of each parameter. sub _sprintstr { my ($str, $fl, $ind, $br, $len, $lp)=@_; $ind||=0; # Split string into \n-separated parts. my @strs=($str=~/([^\n]+\n?|[^\n]*\n)/g); # Now process each line separately my $s; my $result; foreach $s (@strs) { # Store end of lines at the end of the string my $eols=($s=~/(\n*)$/)[0]; # Split in words. my @words=(split(/\s+/, $s)); $result.=_sprintlist(\@words,$fl," ",$ind,$br,$len, $lp).$eols; # The $firstline is only needed at the beginning of the first stri +ng. $fl=undef; } return $result; }


And the sample Help() function:
# Sample %COMMANDS in the format assumed. %COMMANDS=( add => { Sum => 'add NAME to LIST', Desc => 'Add the name to the mailing list.' }, all => { Sum => 'all [-a|-l]', Desc => 'Print out all the aliases and mailing lists. '. 'With -a only prints aliases, with -l only prints ' +. 'lists.' }, delete => { Sum => 'delete LIST,...', Desc => 'Delete mailing lists. Also deleted owner-LIST a +nd '. 'LIST-owner if they exist.' }, list => { Sum => 'list [-1|-x|-s|-n] LIST|/regex/,...', Desc => 'List information about the given aliases. If list + '. 'name starts with "/" it is assumed to be a regula +r '. 'expression. '. '-1 lists members one per line, '. '-x lists members all on a single line. '. '-s lists in Unix alias format. '. '-n only shows list names.' }, ); # Usage message sub Help { print "The current commands are:\n"; my $cmd; foreach $cmd (sort keys %COMMANDS) { print _sprintstr($COMMANDS{$cmd}->{Desc}, $COMMANDS{$cmd}->{Sum},30,1)."\n"; } print "Use 'quit' or '^D' to quit.\n"; }
With the given definition of %COMMANDS, Help() produces:
The current commands are: add NAME to LIST Add the name to the mailing list. all [-a|-l] Print out all the aliases and mailing li +sts. With -a only prints aliases, with -l only pri +nts lists. delete LIST,... Delete mailing lists. Also deleted owner +-LIST and LIST-owner if they exist. list [-1|-x|-s|-n] LIST|/regex/,... List information about the given aliases +. If list name starts with "/" it is assumed to be + a regular expression. -1 lists members one + per line, -x lists members all on a single l +ine. -s lists in Unix alias format. -n only show +s list names. Use 'quit' or '^D' to quit.