Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expand: don't slurp input file #344

Merged
merged 2 commits into from
Nov 24, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 62 additions & 61 deletions bin/expand
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,18 @@ License: perl

use strict;

use File::Basename qw(basename);

use constant EX_SUCCESS => 0;
use constant EX_FAILURE => 1;

my $Program = basename($0);

my %line_desc;
my $tabstop = 8;
my @tabstops;
my @files;

sub usage($;$)
{
print <<"EOF";
Usage:
expand [-h] [-tabstop] [-tab1, tab2, ...] [file ...]
EOF
print STDERR $_[1] if $_[1];
exit $_[0];
}

usage(0) if grep /^-h$/, @ARGV;

# at most one argument
if($ARGV[0] =~ /-(.*)/) {
@tabstops = split(/,/, $1);
Expand All @@ -52,17 +48,14 @@ if($ARGV[0] =~ /-(.*)/) {

@files = @ARGV;

my %line_desc;

# $tabstop is used only if multiple tab stops have not been defined
if(scalar @tabstops == 0) {
$tabstop = 8;
} elsif(scalar @tabstops == 1) {
$tabstop = $tabstops[0];
} else {
my $howfar = 1;
my %tabs;
map { $tabs{$_} = 1 } @tabstops;
my %tabs = map { $_ => 1 } @tabstops;
for (my $i = $tabstops[$#tabstops]-1; $i >= 0; $i--) {
# how far is the $i-th column from the next tab
$line_desc{$i} = $howfar;
Expand All @@ -71,48 +64,56 @@ if(scalar @tabstops == 0) {
}
}

sub do_expand(@)
{
my $incr;
for my $line(@_) {
my $curs = 0;
for my $c (split //, $line) {

if($c eq "\b") { # backspace
print "\b";
$curs-- if $curs;
} elsif($c eq "\t") {
if(scalar @tabstops > 0) {
if(defined($line_desc{$curs}) ){
$incr = $line_desc{$curs};
} else { # Jupiter, and beyond the infinite
$incr = 1;
}
} else {
$incr = $curs%$tabstop ? ($tabstop - $curs%$tabstop)
: $tabstop;
}
print " " x $incr;
$curs += $incr;
} else {
print $c;
$curs++;
}

}
for my $file (@files) {
my $in;
unless (open $in, '<', $file) {
warn "$Program: couldn't open '$file' for reading: $!'\n";
exit EX_FAILURE;
}

while (<$in>) {
expand_line($_);
}
close $in;
}
unless (@files) {
while (<>) {
expand_line($_);
}
}
exit EX_SUCCESS;

for my $file (@files) {

open IN, '<', $file or usage(1, "couldn't open '$file' for reading: $!'");
do_expand <IN>;
close IN;

sub usage {
warn "usage: $Program [-tabstop] [-tab1,tab2,...] [file ...]\n";
exit EX_FAILURE;
}
unless (@files) {
do_expand <STDIN>;

sub expand_line {
my $line = shift;
my $incr;
my $curs = 0;

for my $c (split //, $line) {
if($c eq "\b") { # backspace
print "\b";
$curs-- if $curs;
} elsif($c eq "\t") {
if(scalar @tabstops > 0) {
if(defined($line_desc{$curs})) {
$incr = $line_desc{$curs};
} else { # Jupiter, and beyond the infinite
$incr = 1;
}
} else {
$incr = $curs%$tabstop ? ($tabstop - $curs%$tabstop)
: $tabstop;
}
print ' ' x $incr;
$curs += $incr;
} else {
print $c;
$curs++;
}
}
}

__END__
Expand All @@ -123,7 +124,7 @@ expand - convert tabs to spaces

=head1 SYNOPSIS

expand [B<-h>] [B<-tabstop>] [B<-tab1, tab2, ...>] [B<file> ...]
expand [B<-tabstop>] [B<-tab1,tab2,...>] [B<file> ...]

=head1 DESCRIPTION

Expand All @@ -133,17 +134,17 @@ are preserved into the output and decrement the column count for tab
calculations. I<expand> is useful for pre-processing character files
(before sorting, looking at specific columns, etc.) that contain tabs.

If a single B<tabstop> argument is given, tabs are set B<tabstop> spaces
apart instead of the default 8. If multiple tabstops are given then
the tabs are set at those specific columns.

=head1 OPTIONS

=over 4

=item -h
=item -tabstop

Tabs are set B<tabstop> spaces apart instead of the default 8.

=item -tab1,tab2,...

Print a usage message and exit with a status code indicating success.
Tabs are set at the specific column numbers B<tab1>, B<tab2> and so on.

=back

Expand Down