home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!know!hri.com!snorkelwacker.mit.edu!paperboy.osf.org!meissner
- From: meissner@osf.org (Michael Meissner)
- Newsgroups: comp.lang.perl
- Subject: Re: Columnization
- Message-ID: <MEISSNER.92Sep13075954@curley.osf.org>
- Date: 13 Sep 92 11:59:58 GMT
- References: <1992Aug5.182712.14285@athena.mit.edu> <BtM68r.J0A@NCoast.ORG>
- <1360@minya.UUCP>
- Sender: news@osf.org (USENET News System)
- Organization: Open Software Foundation
- Lines: 168
- In-Reply-To: jc@minya.UUCP's message of 11 Sep 92 18:27:19 GMT
-
- In article <1360@minya.UUCP> jc@minya.UUCP (John Chambers) writes:
-
- | > | Consider the example from the manual page:
- | > | ls | paste - - - -
- | > | This is supposed to produce four-column output. It does put the names
- | > | four to a line, but in most directories, they will not be in columns.
- | > | There seems to be no options that will produce columnar output.
- | >
- | > pr -m -t -w# file1 file2 ...
- | >
- | > where # is the width (default 72). May be System V only.
- |
- | Several people have suggested something like this, but I don't see any
- | way that you can use pr to columnize the output of ls like the above
- | "ls | paste" command does (but correctly ;-). To do so, you would need
- | a filter that reads ls's output and writes it into N files, and then
- | feed these files to pr, and then remember to delete the intermediate
- | files. If you're going to write this filter, well, you might just as
- | well have it write a single file (stdout) instead and align the fields
- | itself. So pr doesn't help you at all. If you have to write a program
- | to chop up the data into multiple files, it's just as easy to write
- | your own program in C or perl to do the entire job.
-
- (I couldn't find the article the above article quotes, so hopefully it
- is solving the problem desired).
-
- While it doesn't allow you to specify exactly 4 column output, my
- columnization library will automatically pick as many columns as can
- fit on the line size. It would be used like:
-
- require 'columnize.pl'
- chop (@lines = <STDIN>);
- $, = '';
- $\ = '';
- print &columnize (4, 4, 72, 0, @lines);
-
- The initial arguments to columnize are:
-
- Arg 1: The number of leading spaces to print on each line.
- Arg 2: The number of spaces to leave between each column.
- Arg 3: The line width to use or 0, to use the current terminal's line size.
- Arg 4: The minimun column width to use
- Arg 5- Items to columnize.
-
- Note the line_size has the system call number for TIOCGWINSZ hard
- coded.
-
- #!/bin/sh
- # This is a shell archive (produced by shar 3.49)
- # To extract the files from this archive, save it to a file, remove
- # everything above the "!/bin/sh" line above, and type "sh file_name".
- #
- # made 09/13/1992 11:47 UTC by meissner@curley.osf.org
- # Source directory /usr/users/meissner/bin.perl
- #
- # existing files will NOT be overwritten unless -c is specified
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 2234 -rw-rw-r-- columnize.pl
- #
- # ============= columnize.pl ==============
- if test -f 'columnize.pl' -a X"$1" != X"-c"; then
- echo 'x - skipping columnize.pl (File already exists)'
- else
- echo 'x - extracting columnize.pl (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'columnize.pl' &&
- X#! /usr/local/bin/perl
- X
- X# External function to return a string array, such that when each
- X# element is printed, it is printed as a series of columns, each
- X# equally spaced.
- X#
- X# Arg 1: The number of leading spaces to print on each line.
- X# Arg 2: The number of spaces to leave between each column.
- X# Arg 3: The line width to use or 0, to use the current terminal's line size.
- X# Arg 4: The minimun column width to use
- X# Arg 5- Items to columnize.
- X
- Xsub columnize {
- X package columnize;
- X local ($leading_spaces) = shift (@_);
- X local ($num_spaces) = shift (@_);
- X local ($user_line_size) = shift (@_);
- X local ($max_length) = shift (@_);
- X local (@ret) = ();
- X local ($cur_col) = 1;
- X local ($initial) = ("\t" x ($leading_spaces / 8)) . (' ' x ($leading_spaces % 8));
- X local ($element);
- X local ($ncols);
- X
- X if ($#_ >= $[) {
- X foreach $element (@_) {
- X $max_length = length ($element) if (length ($element) > $max_length);
- X }
- X
- X $ncols = &main'line_length ($user_line_size) - 1 - $leading_spaces;
- X $ncols += ($num_spaces - 1) if ($num_spaces > 0);
- X $ncols /= ($max_length + $num_spaces);
- X $ncols = 1 if ($ncols <= 0);
- X
- X foreach $element (@_[ $[ .. $#_ - 1 ]) {
- X if (++$cur_col >= $ncols) {
- X $cur_col = 1;
- X push (@ret, "$initial$element\n");
- X $initial = ' ' x $leading_spaces;
- X
- X } else {
- X push (@ret, ($initial . $element . (' ' x ($max_length - length ($element)))));
- X $initial = ' ' x $num_spaces;
- X }
- X }
- X
- X push (@ret, "$initial$_[$#_]\n");
- X }
- X
- X return @ret;
- X}
- X
- X
- X# Internal function to get the line length.
- X
- Xsub line_length {
- X package columnize;
- X local ($user_line_size) = shift (@_);
- X
- X return $user_line_size if (defined ($user_line_size) && $user_line_size > 0);
- X
- X if (! defined ($line_length) || ! $line_length) {
- X
- X if (defined ($ENV{'COLUMNS'}) && $ENV{'COLUMNS'} > 0) {
- X $line_length = $ENV{'COLUMNS'} + 0;
- X
- X } else {
- X local ($winsize) = "\0\0\0\0\0\0\0\0";
- X local ($TIOCGWINSZ) = 0x40087468; # on OSF/1 at least
- X local (@winsize2);
- X
- X $line_length = 79;
- X if (-t STDIN && ioctl (STDIN, $TIOCGWINSZ, $winsize)) {
- X @winsize2 = unpack ('SSSS', $winsize);
- X
- X $line_length = $winsize2[1] if ($winsize2[1] > 0);
- X }
- X }
- X }
- X
- X return $line_length;
- X}
- X
- X
- X# Return 1, so require succeeds.
- X
- X1;
- SHAR_EOF
- chmod 0664 columnize.pl ||
- echo 'restore of columnize.pl failed'
- Wc_c="`wc -c < 'columnize.pl'`"
- test 2234 -eq "$Wc_c" ||
- echo 'columnize.pl: original size 2234, current size' "$Wc_c"
- fi
- exit 0
- --
- Michael Meissner email: meissner@osf.org phone: 617-621-8861
- Open Software Foundation, 11 Cambridge Center, Cambridge, MA, 02142
-
- You are in a twisty little passage of standards, all conflicting.
-