[interchange-cvs] interchange - jon modified eg/te

interchange-core@icdevgroup.org interchange-core@icdevgroup.org
Mon Nov 25 22:14:01 2002


User:      jon
Date:      2002-11-26 03:13:11 GMT
Modified:  eg       Tag: STABLE_4_8-branch te
Log:
Update to latest version of te.

Revision  Changes    Path
No                   revision



No                   revision



2.1.2.2   +97 -18    interchange/eg/te


rev 2.1.2.2, prev_rev 2.1.2.1
Index: te
===================================================================
RCS file: /var/cvs/interchange/eg/te,v
retrieving revision 2.1.2.1
retrieving revision 2.1.2.2
diff -u -u -r2.1.2.1 -r2.1.2.2
--- te	3 Oct 2001 19:33:49 -0000	2.1.2.1
+++ te	26 Nov 2002 03:13:11 -0000	2.1.2.2
@@ -4,8 +4,8 @@
 
 =head1 NAME
 
-te (table editor) - front-end for simplifying editing tab-delimited
-ASCII databases
+te (table editor) - front-end that simplifies editing tab-delimited
+ASCII tables
 
 =head1 SYNOPSIS
 
@@ -13,8 +13,9 @@
 
 =head1 DESCRIPTION
 
-This program makes it easier to edit tab-delimited ASCII databases,
-such as are used with Red Hat Interchange.
+This program makes it easier to edit tab-delimited ASCII tables, such
+as are used with Interchange (see icdevgroup.org), and can be exported
+from many popular spreadsheet and database applications.
 
 It converts tab-delimited ASCII files that have one record per line into
 temporary files with one field per line, each line beginning with the
@@ -55,6 +56,9 @@
 variables VISUAL or EDITOR to point to your favorite text editor. If
 neither of those is set, my favorite editor, B<vi>(1) is used.
 
+Options will also be read from environment variable TE_OPTIONS if it is
+set.
+
 =head1 LIMITATIONS
 
 There is currently no way to add or delete entire columns from the
@@ -62,11 +66,11 @@
 
 =head1 AUTHOR
 
-Jon Jensen <jon@redhat.com>
+Jon Jensen <jon@icdevgroup.org>
 
 =head1 COPYRIGHT
 
-Copyright (C) 2001 Red Hat, Inc., http://www.redhat.com/
+Copyright (C) 2001-2002 Red Hat, Inc.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -80,7 +84,7 @@
 
 =head1 VERSION
 
-$Id $
+$Id: te,v 2.1.2.2 2002/11/26 03:13:11 jon Exp $
 
 =head1 CHANGELOG
 
@@ -98,19 +102,73 @@
 
 2001-10-03. Added gvim support by forcing foreground option -f.
 
+2002-07-23. Remove line endings whether CR, LF, or CRLF, instead of
+using running Perl's platform-specific chomp. If preserving a trailing
+solitary CR in the last field of a line is important, you'll want to
+change this behavior.
+
+2002-08-30. Add option -s for starting value support (really only vi).
+
+	te -s os28004 <file>
+
+Jumps to first occurrence of "os28004" in <file>. Option -i ignores case
+in the search. (By Mike Heins.)
+
+2002-09-02. Add option -f to handle files without field names.
+
+2002-09-03. Add option -n to number rows in comments. Allow setting of
+persistent options in environment variable TE_OPTIONS.
+
 =cut
 
 use strict;
 use Digest::MD5;
 use File::Basename 'fileparse';
+use Text::ParseWords;
+
+use Getopt::Std;
+
+my ($prog) = fileparse($0);
 
-die "Usage: $0 tablefile1 [tablefile2 ...]\n" unless @ARGV;
+my $USAGE = <<EOF;
+Usage: $prog [-i] [-s startpoint] tablefile1 [tablefile2 ...]
 
-my $editor = $ENV{VISUAL} || $ENV{EDITOR} || 'vi';
+Edit tab-delimited file with easy field name delineation.
+
+Options:
+	-i       Ignores case on vim jump search.
+	-s TEXT  Jumps to first line where TEXT is. Only for vim.
+	-f       Do not look for field names on first line of file.
+	-n       Number rows in comments
+
+See 'man te' or 'perldoc $0' for more information.
+
+EOF
+
+unshift @ARGV, Text::ParseWords::shellwords($ENV{TE_OPTIONS})
+	if defined $ENV{TE_OPTIONS};
+
+use vars qw/$opt_i $opt_s $opt_f $opt_n/;
+getopts('is:fn') or die "$@\n$USAGE";
+
+die $USAGE unless @ARGV;
+
+my @ED = Text::ParseWords::shellwords($ENV{VISUAL} || $ENV{EDITOR} || 'vi');
+
+if ($opt_s) {
+	if ($opt_i) {
+		push @ED, '-c', 'set ic';
+		$opt_s = lc $opt_s;
+	}
+	$opt_s =~ s:/:\\/:g;
+	push @ED, '-c', qq{/$opt_s/};
+}
 
 # run gvim in foreground mode, since it otherwise immediately returns
 # control to us and we never get the user's changes
-$editor .= ' -f' if $editor =~ /\bgvim\b/ and $editor !~ /\s-f\b/;
+if($ED[0] =~ /\bgvim\b/) {
+	push @ED, '-f' unless grep $_ eq '-f', @ED;
+}
 
 for my $filename (@ARGV) {
 	my (@fieldnames, $fieldcount, @fields);
@@ -127,23 +185,33 @@
 		warn "Error 'opening' $filename for reading: $!\n";
 		next;
 	}
-	chomp ($_ = <IN>);
-	die "Error in '$filename' header: null field name found\n" if /\t\t/;
+
+	# get field names
+	$_ = <IN>;
+	s/\x0d?\x0a?$//;
 	$fieldcount = tr/\t/\t/ + 1;
+	if ($opt_f) {
+		@fieldnames = map { "field$_" } (1 .. $fieldcount);
+		seek IN, 0, 0;
+	}
+	else {
+		die "Error in '$filename' header: null field name found\n" if /\t\t/;
 	@fieldnames = split /\t/, $_, $fieldcount;
+	}
+
 	($name, $path) = fileparse($filename);
 
 	# I tried keeping the whole file in memory (for MD5's sake) instead of
 	# first writing to disk, but doing it this way turned out to be about 5
 	# times faster and used 1/10th the memory on large files. (My benchmark
-	# was a 12 MB products.txt database for Interchange.)
+	# was a 12 MB products.txt table for Interchange.)
 
 	$tmpfile = "$path.$name.tmp.$$";
 	open OUT, ">$tmpfile" or die "Error opening '$tmpfile' for writing: $!\n";
 	print STDERR "Prettifying $filename\n";
 	print OUT <<EOF;
 #
-# This is a temporary file, automatically generated from the database file:
+# This is a temporary file, automatically generated from the data file:
 #
 # $filename
 #
@@ -151,8 +219,10 @@
 # format and will replace the original file.
 #
 EOF
+	my $rowcount = 0;
 	while (<IN>) {
-		chomp;
+		s/\x0d?\x0a?$//;
+		++$rowcount, print OUT "# row $rowcount\n" if $opt_n;
 		@fields = split /\t/, $_, $fieldcount;
 		for (my $i = 0; $i < @fieldnames; $i++) {
 			print OUT $fieldnames[$i], ":",
@@ -186,8 +256,17 @@
 	binmode IN;
 	$digest1 = Digest::MD5->new->addfile(*IN)->digest;
 	close IN;
-	system (split(/ /, $editor), $tmpfile) == 0
-		or die "Error calling editor '$editor' with '$tmpfile': $!\n";
+	system (@ED, $tmpfile) == 0
+		or do {
+			@ED = ('gvim', '-f', 'some quotes " "', "some space");
+			for(@ED) {
+				next unless /\s/;
+				s/"/\\"/g;
+				$_ = qq["$_"];
+			}
+			my $editor = join " ", @ED;
+			die "Error calling editor '$editor' with '$tmpfile': $!\n";
+		};
 	open IN, "<$tmpfile" or die "Error opening '$tmpfile' for reading: $!\n";
 	binmode IN;
 	$digest2 = Digest::MD5->new->addfile(*IN)->digest;
@@ -200,7 +279,7 @@
 	print STDERR "Importing changes back into '$filename'\n";
 	$newfile = "$path.$name.new.$$";
 	open OUT, ">$newfile" or die "Error opening '$newfile' for writing: $!\n";
-	print OUT join("\t", @fieldnames), "\n";
+	print OUT join("\t", @fieldnames), "\n" unless $opt_f;
 	my $tabcounter = 0;
 	my $fieldpos = 0;
 	my $done;