CLI-LaTeX-Table

 view release on metacpan or  search on metacpan

scripts/latextable  view on Meta::CPAN

#!/usr/bin/perl -T
use v5.14 ; use strict ; use warnings ; # cpantersのレポートによると、5.14より前はNAだった。
use Getopt::Std ; getopts q['$/:=_#:0:13:9C:fjm:psw:x:H:] , \my%o ; # 5.
use utf8 ; # v5.6 ~ 
use Encode qw[ encode_utf8 decode_utf8 ] ; # v5.7 ~ 
use Term::ANSIColor qw [:constants ] ; $Term::ANSIColor::AUTORESET = 1 ; # v5.6 ~ 

$o{m} //= "1." ; # 表示拡大率  LaTeX displaying magnification efficient.
$o{x} //= "0mm" ; # 大きめのテーブルのセンタリングのために、左右を削り取る長さを指定する。
my $isep = $o{'/'} // "\t" ; # 入力の区切り文字
my $colspec = '' ; # LaTeXのtable環境の列指定  LaTeX table environment "column specifier"
my $rm = $o{0} if defined $o{0} ; # テーブルの値で除去対象となる値の正規表現
my %del ; # LaTeXで使わないコマンドの指定。
my @r3 = () ; #  3桁コンマ区切りにして右寄せにしたい列の指定。 Which columns are to be decimal being separated every 3 digits.

# 追加の水平線と垂直線
my $hdash = qq[\\hdashline[1pt/1pt]  % "\\hdashline[..]" requires "\\usepackcage{arydshln}"] ; 
my $HL = ! exists $o{'#'} ? '' : $o{'#'} =~ /1/ ? "\\hline" : $o{'#'} =~ m/\./ ? $hdash : '' ;
my $VL = ! exists $o{'#'} ? '' : $o{'#'} =~ /1/ ? '|' : $o{'#'} =~ /\./ ? ';{1pt/1pt}' : ' ' ;

my $angle = $o{9} ? 90 : 0 ; # 全体を回転する場合の指定  When -9 is specified, the entire table rotates in 90 degree.
my @out ; # $0の出力文字列  The output of this command is accumulated in this variable. 

my $otfFlag = 0 ; # usepackage{otf} が必要かどうかのフラグ
& main ( ) ; 
exit 0 ; 

sub plain2latex ( $ ) { 
	local $_ = $_[0] ;

	$otfFlag = 1 if m/\P{ascii}/ ; # <-- 全角ハイフンの時だけに表示する様にするのが、良いのかも知れない。
	my $hlen = $o{H} if defined $o{H} ;  # ハッシュ値のような16進数の文字列を長い場合に $hlen桁に縮めて .. を続ける。
    s/(?<=[0-9a-f]{$hlen})[0-9a-f]+/../gi if defined $o{H} ; # <-- - (?<= ) で正規表現の後読み

    # ドル$文字関連 The pre-processing of the character "$ dollar". The completion process will appear much later.
    s|\G(.*?)\$|$1=\$\$=|g ; # ドル文字の前処理。\Gは文字列の先頭、もしくは修飾子 g がついたパターンマッチングが終了した場所を記憶しておき、そこにマッチ

    # LaTeX中で 数式環境を利用するもの Utilization of math formula env. of LaTeX for some specific characters such as \~!<>.
    s/([\\\Q!~<>|"\E\x{FF0D}]+)/\$$1\$/g ; # 1. 数式環境に移行して、    ;  \Qと\Eの間はパターンメタ文字の無効化。 
    s/\\/\\backslash/g ;        # 2. そして、まず先にバックスラッシュに処理をして、後の処理が続く。
    s/~/\\sim/g;                # チルダ
    s/\x{FF0D}/\Q\!\!\frac{}{{{}\atop{H}}}\!\!\E/g if $o{'_'} ;   # 全角ハイフンはその下に、H を小さく書く ; \N{FULLWIDTH HYPHEN-MINUS}
    s/\ /\\scalebox{0.5}[0.5]{\$\\sqcup\$}/g if $o{'_'} ; # 半角スペースの強調  ; 
    s/\x{3000}/\\scalebox{1}[0.5]{\$\\sqcup\$}/g  if $o{'_'} ;  # 全角スペース  は、 -z 指定の場合、皿の形の線が置かれる。\N{IDEOGRAPHIC SPACE}

    # LaTeX中でバックスラッシュを伴うべき文字の処理 : Treatments on characters requiring backslash in LaTeX. 
    s/(?=[\Q_%#&{}\E])/\\/g ; # (?= ) で正規表現の先読み _%#&{}
    s/\^/\\^{}/g ; 

    # ドル文字の処理  The completion of dollar character.
    s/=\$\$=/\\\$/g ; # ドル文字の処理はここで終わり。

    # 半角カナの処理  Japanese Hankaku (half-width) Katakana letters.  (I tried to found them in the A1 - DF from JISX0201.)
    if ( $o{j} ) { 
        s/([。「」、・ヲァ-ッーア-ン゙゚]+)/\\scalebox{0.5}[1]{$1}/g  ; # 次の2行は範囲指定だとずれるので、一文字ずつ処理した。
        y/。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソ/。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソ/ ; 
        y/タチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚/タチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜/ ;
    }

    # 半角ハイフンで連続しているものの処理
    s/-(?=-)/-{}/g ;

    return $_ ;
}

sub main ( ) { 

    my $zflag = 0 ; # 全角空白の存在フラグ ; $ex{' '} のようにもっと柔軟にしたいかも
    my $maxF = 1 ; # フィールド数の最大値 ; 0 では無くて1とした訳は全て空行でも \begin{tabular}[l] とlが最低1個は必要なため
    my $tailF = $o{'$'} ? $o{w} : -1 ; 
    my $HS  = ' ' x 12 ; # 出力行の先頭のスペース。レイアウトをきれいにするため

    @r3 = split /,/, $o{3} , -1  if $o{3} ;    # オプション -3 についての処理
    do { splice @r3, $_ , 1 , $1 .. $2 if $r3[$_] =~ m/(\d+)\.\.(\d+)/ } for reverse 0 .. $#r3  ;
    grep { $_ -- } @r3 ; 

    binmode STDOUT, ":utf8" ;
    $SIG{ALRM} = sub { print STDERR CYAN "Please enter a tabular text in TSV format..\n" if -t } ;
    alarm 3 ;
    my $alF = 1 ; # alarm を立てたり下ろしたりしたことを表すフラグ
    while ( <> ) {
    	alarm 0 if $alF && $alF -- ; # <- if を使うことで sleep 0の3マイクロ秒くらい消費を 0.03マイクロ秒に縮まる
        chomp ; 
        do  { s/\s*$// ; if (/^$/) { $. -- ; next } } if $o{s} ; # -s 指定により末尾の空白文字を取り除く。
        $_ = decode_utf8 ( $_ ) ; # <- 括弧が外せるか確認
        $zflag = 1 if m/ / ; #全角空白 \x{3000} のチェック
        my @F = split /$isep/ , plain2latex ( $_ ) , $tailF ;   # <--- ここでコアとなる処理
        #$tailF //= @F ; # 1行目で設定することで、LaTeXコンパイル時に列数変動でエラーにならないようにする。
        splice @F , $o{w} if defined $o{w} ; # 列数の最大値が指定された場合の、切り取りの処理。
        $maxF = @F if @F > $maxF ;
        grep { s/$rm//} @F[ $o{1} // 0 .. $#F ] if defined $o{0} and $. > 1 || ! $o{'='} ; # -0の処理
        grep { s/(?<=\d)(?=(\d\d\d)+($|\D))/,/g } @F[ (grep{$_< scalar @F} @r3) ]  if $. > 1 || ! $o{'='} ; # 数値3桁区切りの処理
        grep { $_ = "\\rotatebox{90}{$_}"} @F if $o{q[']} and $. == 1 ; # 先頭行を回転したい場合。
        push @out,  $HS . (join ' & ' , @F  ) . "\\\\" , "\n" ;
        push @out,  $HS , "\\hline\n" if $o{'='} && $.== 1 ; # 1行目と2行目に横の罫線を入れる。
        push @out , $HS.$HL."\n" if $HL ne '' and ! ( $o{1} && $. == 1 ) ;
    } # while (<>)の終わり
    pop @out if $HS ne '' ; # -\# が指定されているときに、最後の 横罫線は取り消す。



( run in 1.127 second using v1.01-cache-2.11-cpan-df04353d9ac )