#!/usr/bin/perl 
use v5.14 ; use strict ; use warnings ; # cpantersのレポートによると、5.14より前はNAだった。
use Getopt::Std ; getopts q['/:=_3:9c:fjs: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{s} //= "1." ; # 表示拡大率  LaTeX displaying magnification efficient.

my $isep = $o{'/'} // "\t" ; # 入力の区切り文字
my $colspec = '' ; # LaTeXのtable環境の列指定  LaTeX table environment "column specifier"
my @r3 = () ; #  3桁コンマ区切りにして右寄せにしたい列の指定。 Which columns are to be decimal being separated every 3 digits.
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. 

& main ( ) ; 
exit 0 ; 


sub plain2latex ( $ ) { 

    s/(?<=[0-9a-f]{15})[0-9a-f]{49}/../g if $o{H} ; # <-- - 16進数64桁の処理 ; (?<= ) で正規表現の後読み

    # ドル$文字関連 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 ;   # 全角ハイフンはその下に、H を小さく書く ; \N{FULLWIDTH HYPHEN-MINUS}

    s/\ /\\scalebox{0.5}[0.5]{\$\\sqcup\$}/g if $o{'_'} ; # 半角スペースの強調 if $o{z} ; 
    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/ﾀﾁﾂﾃﾄﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎﾏﾐﾑﾒﾓﾔﾕﾖﾗﾘﾙﾚﾛﾜﾝﾞﾟ/タチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゛゜/ ;
    }

    return $_ ;
}

sub main ( ) { 

    my $zflag = 0 ; 
    

    # オプション -3 についての処理
    @r3 = split /,/, $o{3} , -1  if $o{3} ;

    for ( reverse 0 .. $#r3 ) {         
        splice @r3, $_ , 1 , $1 .. $2 if $r3[$_] =~ m/(\d+)\.\.(\d+)/
    }
    grep { $_ -- } @r3 ; 


    binmode STDOUT, ":utf8" ;
    while ( <> ) {
        chomp ; 
        $_ = decode_utf8 ($_) ;
        $zflag = 1 if m/　/ ; #全角空白 \x{3000} のチェック
        my @F = split /$isep/ , plain2latex ( $_ )  , -1 ; 
        splice @F , $o{c} if defined $o{c} ; # 切り取り
        s/(?<=\d)(?=(\d\d\d)+($|\D))/,/g for @F[ @r3 ] ; # 数値3桁区切りの処理

        grep { $_ = "\\rotatebox{90}{$_}"} @F if $o{q[']} and $. == 1 ; # 先頭行を回転したい場合。
        push @out, tableStart ( scalar @F ) if $. == 1 ;  
        push @out,  ' ' x 12 , (join ' & ' , @F  ) , "\\\\", "\n" ;
        push @out,  ' ' x 12 , "\\hline\n" if $o{'='} && $.== 1 ; # 1行目と2行目に横の罫線を入れる。
    }
    push @out, tableEnding( ) ; 
    print @out ; 

    print STDERR CYAN "Full-width space included. Using the option '-_' is advisable.\n" if $zflag && ! $o{z} ;

}

sub tableStart ( $ ) { 
    my @tmp  = ('l') x ( $o{c} // $_[0] ) ;  # 列指定
    $tmp [$_] = 'r' for @r3 ; 
    $colspec = "| " . ( join '' , @tmp ) . "| " ;
    return << "END" 
\\begin{table}
    \\center
    \\rotatebox{$angle}{
    \\scalebox{$o{s}}{
        \\begin{tabular}{$colspec}
            \\hline
END
}

sub tableEnding ( ) {
    return << "END"
            \\hline
        \\end{tabular} 
    }}
    \\caption{}%
    \\label{tbl:}%
\\end{table}
END
}

## ヘルプの扱い
sub VERSION_MESSAGE {}
sub HELP_MESSAGE {
    use FindBin qw[ $Script $Bin ] ;
    sub EnvJ ( ) { $ENV{LANG} =~ m/^ja_JP/ ? 1 : 0 } ; # # ja_JP.UTF-8 
    sub en( ) { grep ( /^en(g(i(sh?)?)?)?/i , @ARGV ) ? 1 : 0 } # English という文字列を先頭から2文字以上を含むか 
    sub ja( ) { grep ( /^jp$|^ja(p(a(n?)?)?)?/i , @ARGV ) ? 1 : 0 } # jp または japan という文字列を先頭から2文字以上を含むか 
    sub opt( ) { grep (/^opt(i(o(ns?)?)?)?$/i, @ARGV ) ? 1 : 0 } # options という文字列を先頭から3文字以上含むから
    sub noPOD ( ) { grep (/^no-?pod\b/i, @ARGV) ? 1 : 0 } # POD を使わないと言う指定がされているかどうか
    my $jd = "JapaneseManual" ;
    my $flagE = ! ja && ( en || ! EnvJ ) ; # 英語にするかどうかのフラグ

    exec "perldoc $0" if $flagE &&  ! opt && ! noPOD   ; 
    $ARGV[1] //= '' ;
    open my $FH , '<' , $0 ;
    while(<$FH>){
        s/\Q'=script='\E/$Script/gi ;
        s/\Q'=bin='\E/$Bin/gi ;
        if ( s/^=head1\b\s*// .. s/^=cut\b\s*// ) { 
            if ( s/^=begin\s+$jd\b\s*// .. s/^=end\s+$jd\b\s*// xor $flagE ) {
                print $_ if ! opt || m/^\s+\-/  ; 
            }
        } 
        #print $_ if /^=head1/ .. /^=cut\b/ and opt ? m/^\s+\-/ : 1 and ( EnvJ && ! en xor s/^=begin $jd\b// .. s/^=end $jd\b// ) ;
    }
    close $FH ;
    exit 0 ;

}


=encoding utf8
=pod
=head1

   Program Name : '=SCRIPT='    ('=Bin=')

   Usage Example : 
     '=SCRIPT=' -_ -c 12 -3 4..8  # Assuming 12 columns and treat some column in numbers and emphasize spaces.

    Give the tab separated table from STDIN, then it yields a LaTeX table code from "\begin{table})..".
    Labor-saving to create LaTeX tables from the copy/paste from Excel and SQL outputs, etc.

    Main functions : 
     NOT ONLY performing the tedious work in typing LaTeX codes such as 
    (1) transforming tab characters into ampersands (&) characters for table environments,
    (2) adding the "\hline" on the beginning and the ending inside the tabular environments,
     BUT ALSO
    (3) grouping every 3 digits by comma on numbers >= 1000 and aligning toward right in a column,
    (4) properly modifying various signs \~!<>_%#&$ fitting into LaTeX (with -j, Japanese half-width as well),
    (5) emphasizing the space chacters both usual half-size space and full-width space, 
    (6) by with -z, emphasizing the fullsize hyphen to indicate that it differs from prolonged sound sign.

 Options :     
    -/ REGEX : Specifying the input delimter. Default is tab character. You can specify as -/ ,  for pseudo-CSV.
    -=   : To indicate that the first line in STDIN is the header, to yield "\hline" btw. 1st and 2nd lines.
    -c N : To explicitly indicate that the table has N columns. (Else, automatically determined by 1st line)
    -j   : For Japanese half-width character. The LaTeX output utilize \scalebox{0.5}[1]{...}
    -s N : N is the displaying magnifying factor. Often used for large-size table to reduce the physical size.
    -_   : To emphasize the space character. Both for half-width \x{20} and full-width \x{3000}.

    -3 n[..n][,n[..n]][,n[..n]].. ;  Specify number columns. The leftest columns is numbered 1. 
    -9  : Rotate the entire table 90 degree unclockwise, using "\rotatebox{90}".
    -\'  : Rotate each cell of the 1st line unclockwise. Often used that column names are long string. 
    -H :  (Just for the author's usage. 64digit hexagonal codes from SHA2 is shrinked into 15 digits.)


    --help : Print this online help manual of this command "'=SCRIPT='". Similar to "perldoc `which [-t] '=SCRIPT='` ".
    --help opt ..or..  --help options : Only shows the option helps. It is easy to read when you are in very necessary.
    --help ja : Shows Japanese online help manual. ; "'=script=' --help ja" で日本語のオンラインマニュアルを表示します。
    --help nopod : Print this online manual using the code insdide this program without using the function of Perl POD.

 Remarks : 
  - \usepackage{graphicx} is needed between \documentclass and \begin{document}, for rotating and magnifying.
  - The output LaTeX snippet does not work well if the column number of each line increase in a table.
  - Please fill in \caption{} and \label{} as neccessary in the output LaTeX code.
  
 Notes for developing : 
   * I want to add -r switching options to specify only right alignment.
   * I have not yet fully investigate good LaTeX books yet. I only developed this program merely mainly by experience.

 # This program has been made since 2018-02-09(Fri) by Toshiyuki Shimono, as a part of TSV hacking toolset for table data.
=begin JapaneseManual
  プログラム名 : '=SCRIPT='    ('=Bin=')

  標準入力からタブ区切りのデータを読取り、それを LaTeX の表で使えるように変換する。
  下記の作業などを省力化することが目的である。
    (1) タブ区切りをアンパサンド区切りに変換すること
    (2) \hline コマンドを書き入れること
    (3) 数値はコンマ3桁区切りで右詰めにすること
    (4) 各種記号や半角カナをLaTeXで出力できるようにすること
    (5) 半角空白と全角空白を目立たせること
    (6) 全角ハイフンも、全角長音と区別させること
オプション : 
    -/ REGEX :  区切り文字を 正規表現で指定する。単純なコンマ区切りであれば、-/ , と指定。未指定ならタブ文字。
    -=   : 標準入力の最初の行は、作りたいテーブルのヘッダであると仮定する。(\hlineの処理に関わる)
    -c N : 表が幅何列かを明示的に指定する。未指定なら先頭行の列数で判定する。
    -j   : 日本語の半角カナに対応する。
    -s N : 出力の拡大率を指定する。未指定なら 1.0。
    -z   : 全角スペース(UTF8)を、LaTeXの出力結果において、正方形の下半分のような形で可視化する。

    -3 n[,n][,n].. :  3桁区切りにして右寄せにしたい列を1始まりで指定する。 ..で範囲指定。
    -9  : LaTeXで表示させる表の全体を90度左回りに回転させる。
    -H : 便宜上のもの。リリース時に消去。16進の長い文字列を短くする。
    -\'   : 1行目を左回りに回転する。

    --help : このコマンド '=SCRIPT=' のオンラインヘルプマニュアルを表示する。
    --help opt ないし --help options : 分かり安くオプションのヘルプのみを表示する。
    --help en : 英語版のオンラインヘルプマニュアルを出力。Online help in English version. 


注意点 : 
  - 途中で列数が変わると、LaTeXの動作がうまくいかなくなるので注意。
  - \caption と \label の中が空白なので、後で書き込む必要がある。
  - LaTeX の \scalebox コマンドなどを使うので \usepackage{graphicx} がプリアンブルに必要となる。
 
 このプログラムの開発上のメモ : 
   * 3桁区切りにしたい数ではなくて、単に右寄せしたい列の指定をする -r を実装したい。
   * ドルマークとバックスラッシュの処理は内部処理上でトリッキーだった。正規表現の \Gで解決した。<-- テストを書くべし。
   * 入力時に、何も入力が3秒程度発生しなかった場合に、催促するメッセージを STDERRに色つきで表示する機能。
   * graphicxを要求することの明示を分かり安く(STDERRにも出力したい)。また、-1で、シンプルな、graphicxを要求しないものを生成する機能を作りたい。
   * 列数が変わる場合に警告を出して、可能なら、空文字列で埋めるようにする。

# このブログラムは 2018年2月9日(金)から表形式データに対する道具作りの一環として、下野寿之が作成したものである。
=end JapaneseManual
=cut