+++ /dev/null
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use Unicode::GCString;
-use Text::CharWidth qw(mbswidth);
-use String::Print qw(printp);
-#use utf8;
-#################################################################################
-#
-# VERSION
-#
-#################################################################################
-my $VERSION = '0.0.1';
-# NB 16.01.18
-# - create script
-
-#################################################################################
-#
-# GLOBALS
-#
-#################################################################################
-my ($NAME) = $0 =~ m,([^/]+)$,;
-
-#################################################################################
-#
-# ARGS
-#
-#################################################################################
-my $VERBOSE = $main::VERBOSE = 1;
-my $DEBUG = $main::DEBUG = 0;
-
-my %Opt = (
- 'header' => 0,
- 'total' => 1,
- 'encode' => 1,
- 'sep' => "\t",
-);
-get_options(\%Opt);
-$main::_DATA_ = undef;
-
-#################################################################################
-#
-# BEGIN
-#
-#################################################################################
-#use Data::Dumper; print Dumper(\%Opt);
-use Encode;
-
-#
-# Calculate lengths
-#
-my @len = ();
-my @lines = ();
-
-use Encode;
-binmode STDOUT, ":utf8" if $Opt{encode};
-#binmode STDOUT, "raw:";
-#binmode STDOUT;
-sub realLength {
- my $str = shift;
- # NB 21.06.26 $str = Encode::encode_utf8($str) if $Opt{encode};
- # NB 21.06.26 $str = Encode::encode('UTF-8', $str) if $Opt{encode};
- $str = Encode::decode('UTF-8', $str);
- # NB 21.06.26 return mbswidth($str);
- # NB 21.06.26 my $gcs = Unicode::GCString->new($str);
- # NB 21.06.26 return $gcs->columns();
- return length($str);
-}
-
-sub pad_to_width {
- my ($string, $width) = @_;
- my $gcs = Unicode::GCString->new($string);
- my $visual_width = $gcs->columns(); # Gets the actual screen width[reference:9][reference:10]
- #$visual_width = length(Encode::encode_utf8($string));
- $visual_width = mbswidth($string);
- #return $string if $visual_width>$width;
- #$visual_width = 0 if $visual_width>$width;
- my $padding = " " x ($width - $visual_width);
- return $string . $padding; # For left-aligned text
-}
-
-sub pad_format {
- my $fmt = shift;
- for my $str (@_) {
- $fmt =~ /%-(\d+)s/;
- my $width = $1;
- my $new = pad_to_width($str,$width);
- $fmt =~ s/%-(\d+)s/$new/;
- }
- return $fmt;
-}
-
-while (<>) {
-
- my @F = $Opt{format} ? split(/\s*$Opt{sep}\s*/) : split(/$Opt{sep}/);
-
- for (my $i=0;$i<@F;$i++) {
- chomp($F[$i]);
- my $l;
- $len[$i] = $l if ( $l = realLength($F[$i]) ) >= ($len[$i] || 0);
- }
-
- push @lines, [@F];
-}
-
-exit unless @lines;
-
-#
-# Build format string
-#
-my $tot = @lines - ($Opt{header} ? 1 : 0);
-
-my $t = -1;
-
-my $format = "│ ".join(" │ ",map {$t += $_ + 3; "\%-".$_."s"} @len)." │".chr(10);
-my $sep_line_first = "┌".join("┬",map {("─"x($_+2))} @len)."┐".chr(10);
-my $sep_line = "├".join("┼",map {("─"x($_+2))} @len)."┤".chr(10);
-my $sep_line_last = "└".join("┴",map {("─"x($_+2))} @len)."┘".chr(10);
-if (1 and $Opt{encode}) {
- $format = Encode::decode("UTF-8",$format);
- $sep_line_first = Encode::decode("UTF-8",$sep_line_first);
- $sep_line = Encode::decode("UTF-8",$sep_line);
- $sep_line_last = Encode::decode("UTF-8",$sep_line_last);
-}
-# NB 21.06.26 utf8::decode($format);
-# NB 21.06.26 utf8::decode($sep_line_first);
-# NB 21.06.26 utf8::decode($sep_line);
-# NB 21.06.26 utf8::decode($sep_line_last);
-#die $format;
-
-#
-# Format / align
-#
-# a => 1
-# b => 222222
-if ($Opt{format}) {
- my $sep = " ".$Opt{sep}." ";
- my $i;
- $format = join($sep,
- map {
- $i++;
- $t += $_ + realLength($sep);
- $i == @len ? '%s' : "\%-".$_."s";
- } @len
- ).chr(10);
- $sep_line_first = "";
- $sep_line = "";
- $sep_line_last = "";
- $VERBOSE = 0;
- $Opt{total} = 0;
- $Opt{header} = 0;
-}
-
-#
-# Print
-#
-print $sep_line_first;
-my $i = 0;
-my $count;
-while (my $line = shift @lines)
-{
- # Add missing empty columns
- for (my $j=@$line; $j<@len; $j++ )
- {
- $line->[$j] = '';
- }
-
- @$line = map { utf8::decode($_); $_ } @$line;
- printf($format,@$line);
- # NB 21.06.26 printf pad_format($format,@$line);
- print $sep_line if $Opt{header} and !$i++;
-}
-
-print $sep_line_last;
-print "$tot Records\n" if $Opt{total};
-
-#################################################################################
-#
-# END
-#
-#################################################################################
-exit 0;
-
-#################################################################################
-#
-# Functions
-#
-#################################################################################
-sub help {
-#------------------------------------------------------------------------------
-# Print help and exit
-#------------------------------------------------------------------------------
-
- require 'Pod/Usage.pm' unless $INC{'Pod/Usage.pm'};
-
- # Substitutions
- sub pod_env {
- my $v = '';
- eval '$v = ref(\\'.$_[0].') eq "ARRAY" ? join(" ",'.$_[0].') : '.$_[0].'; return defined $v ? $v : qq|UNDEF|;';
- return $v;
- }
-
- $main::_DATA_ =~ s/([@\$][A-Z_a-z\{\}]+)/pod_env($1)/eg;
-
- my $in;
- open($in,'<',\$main::_DATA_);
-
- open(STDOUT,"|perl -pe 's/\.$$//g'".(($ENV{PAGER}||'') eq 'less' ? "|less -FRi" : ""));
- my $opts = {
- -input => $in,
- -ouput => \*STDOUT,
- -exitval => 'noexit',
- -sections => [qw(SYNOPSIS DESCRIPTION OPTIONS)],
- -verbose => ($Opt{'help'} ? 99 : 3),
- };
-
- Pod::Usage::pod2usage($opts);
- close $in;
- close STDOUT;
-
- exit 0;
-}
-
-#------------------------------------------------------------------------------
-# Print version and exit
-#------------------------------------------------------------------------------
-sub version { print "$NAME: version [$VERSION]\n"; exit 0; }
-
-#------------------------------------------------------------------------------
-# Get options from pod
-#------------------------------------------------------------------------------
-sub get_options {
-
- use Getopt::Long qw(:config no_ignore_case no_auto_abbrev);
-
- my @Opt;
-
- sub pod_opt {
- local $_;
- my $o = shift;
- $o =~ s/(=.|[\+\-\!]$)//;
- $o = join(", ",map{"-$_"} split(/[\|,:;]/,$o));
- return "$o";
- }
-
- while (<DATA>) {
- s/option\[([^\]]+)\]/push(@Opt,$1) and pod_opt($1)/eg;
- $main::_DATA_ .= $_;
- }
-
- GetOptions($_[0],@Opt) || exit -1;
-
- help() if $_[0]{'help'} or $_[0]{'man'};
- version() if $_[0]{'version'};
-
- $main::VERBOSE = $VERBOSE = $_[0]{'verbose'} if defined $_[0]{'verbose'};
- $main::DEBUG = $DEBUG = $_[0]{'debug'} if defined $_[0]{'debug'};
-
-}
-
-__DATA__
-
-=head1 NAME
-
-$NAME - Alternative to linux command column, format csv tab style rows
-
-=head1 SYNOPSIS
-
-Quick usage!
-
-=over
-
-=item $NAME --sep ',' --noheader FILE
-
-=item $NAME --help
-
-=back
-
-=head1 DESCRIPTION
-
-Description!
-
-=head1 OPTIONS
-
- -option[header|h!] Print or not header separotor after first row
- -option[sep|s=s] Separtor
- -option[encode|e!] Encode (default: $Opt{encode})
- -option[total|t!] Print number of total record (default: $Opt{total})
- -option[format|f!] Only format according to option --sep. Usefull for coding
- -option[verbose|v+] Verbose mode: increase the verbosity level.
- -option[debug+] Debug mode: increase the verbosity level.
- -option[version|V] Print version (default: $VERSION)
- -option[help|?] Print a brief help message and exits.
- -option[man] Print the manual page and exits.
-
-=cut
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (C) 2018 Nicolas Boisselier
-
-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 Free Software Foundation, either version 3 of the License, or (at your option) any later version.
-
-See <http://www.gnu.org/licenses/>.
-
-=head1 AUTHOR
-
-Nicolas Boisselier <nico@nbdom.net>
-
-=cut