#!/usr/bin/perl
#
語語(カタリガタリ) by Perl for Windows
# ktrgtr.pl (KaTaRiGaTaRi) by foussin (v0.00) 2016.05.08 Sun
use strict;
use warnings;
use utf8;
use Encode qw/decode/;
use Encode::Guess qw/sjis euc-jp/;
use FindBin;
use Term::ReadKey;
use Win32::Console::ANSI; # Win専用モジュール?(WinでESCシーケンス使用)
print "\e[2J"; # CLS(クリアー・スクリーン)
$| = 1; # STDOUT のバッファリング止め
# ●Act.0:画面表示の文字コード (実行環境をここで特定)
# ":encoding(cp932)" → Windows(コマンドプロンプト)
# ":utf8" → Linux 等
# ※デコード済の内部表現文字列を binmode で 自動エンコード
my $console_code = ($^O eq "MSWin32") ? ":encoding(cp932)" : ":utf8";
binmode STDOUT, $console_code; # 標準出力を画面表示に使う
binmode STDERR, $console_code; # 標準エラー出力を画面表示に使う
# ●Act.1:表示モード選択
print <<"EOT";
0. だらだら表示モード
1. 単語区切りタップ入力モード(主に英文用)
2. 1文字タップ入力モード(主に童謡の歌詞用)
EOT
print "表示モードを選択(0-2)> ";
chomp(my $mode = ); # エラートラップ省いた…
# ●Act.2:初期設定(waitのデフォルト値)
my $wait_sec = 0; # 1文字タップ入力(童謡の歌詞用)
($mode==0) and $wait_sec = 0.06; # だらだら表示モード
($mode==1) and $wait_sec = 0.01; # 単語区切りタップ入力(英文用)
# ●Act.3:入力ファイル読込
my $ifile = $ARGV[0] ? $ARGV[0] : "";
unless ($ifile) {
# 実行中のスクリプトが居る場所をカレントディレクトリにする
chdir $FindBin::Bin;
# glob で "./ktrgtr-*.txt" ファイルリストをメニュー表示
# Windows では open用と表示用、2種類の配列が必要(binmode指定が逆に仇?)
my @files = glob("ktrgtr-*.txt"); # open用リスト
my $num = @files or die "error: 入力テキストが見つからない!";
my $files = decode("Guess", join("\n", @files));
my @decode_names = split /\n/, $files; # メニュー表示用
for (my $i=0; $num>$i; ++$i) { print "\n$i. $decode_names[$i]"; }
if ($num == 1) {
$ifile = $files[0];
} else {
print "\n読込テキストを選択(0-", $num-1, ")> ";
chomp(my $id = );
$ifile = $files[$id];
$ifile or die "error: 番号指定が変かも?";
}
}
# 入力ファイルの文字コードは不明のままオープン
open(IN, "<", $ifile) or die "Error: $!";
# 入力文字列をまるごと配列に入れ、文字コードを推測し内部コード変換
my @src_text = ; close IN;
my $src_text = decode("Guess", join('', @src_text));
# ●Act.4:テキストのコメント行を除去
# ktrgtr.pl では、"# " (#と半角スペース)から始まり "\n" (改行)まで
# をコメント行として除去する。行の途中にコメントを入れると表示が乱
# れる。 コメントの記述は『1行コメント』のみ有効という仕様とする。
$src_text =~ s/# .*\n//g;
#print $src_text; # 動作確認用
# ●Act.5:テキストを表示モードに合わせて分割し @str に格納
my @str;
if ($mode==1) {
# 1. 単語区切りタップ入力モード(主に英文用)
# スペース(全角・半角)、句読点(、。)、\n で区切り文章を分割する
# (区切り文字 の直後に『$■』を挿入し、最後に『$■』で split)
$src_text =~ s/(\n+)/$1$■/g; # 復改
$src_text =~ s/([、。・=])/$1$■/g; # 句読点・他
$src_text =~ s/( +)/$1$■/g; # 全角スペース
$src_text =~ s/( +)/$1$■/g; # 半角スペース
$src_text =~ s/\n$■( +)/\n$1/g; # 行先頭のスペースは対象外
$src_text =~ s/\n$■( +)/\n$1/g; # 行先頭のスペースは対象外
$src_text =~ s/$■(\n+)$■/$1$■/g; # 行末尾をひとまとめにする
@str = split '$■', $src_text; # テキスト → 配列
} elsif ($mode==2) {
# 2. 1文字タップ入力モード(主に童謡の歌詞用)
# 拗音(ゃゅょャュョ)、?(ぁぃぅぇぉァィゥェォ)、促音(っッ)、長音(ー)、
# 句読点(、。,.)、スペース(全角・半角)、復改(\n)、記号等は直前の文字と
# 連結して『1音節扱い』とする。
# ($src_text を substr で 1文字ずつチェックしながら @str に push)
$str[0] = ""; # 初期値はダミー
my $len = length $src_text;
for (my $j=0; $j<$len; ++$j) {
my $ch = substr($src_text, $j, 1);
if ($ch =~ /[ゃゅょぁぃぅぇぉっャュョァィゥェォッ…ー\-!!??==・、。,\.:;:;\(\) \n]/) {
push @str, pop(@str) . $ch; # スタック操作
} else {
push @str, $ch;
}
}
$str[0] or shift @str;
} else {
# 0. だらだら表示モード
$str[0] = $src_text;
}
#print join("●", @str); # 動作確認用
print <<"EOT";
準備完了:
何かキーを押すと CLS(画面クリア)してスタンバイ状態になります。
その後、もう一度適当なキーを押すと表示が始まります。
ご自分のタイミングでキーを押して実行開始してください。
EOT
ReadMode 4; # Turn off controls keys(とりあえず 4 にしとけば OK)
my $x = ReadKey; # 何かキーを押すまで wait を続行
print "\e[2J"; # CLS(クリアー・スクリーン)
#print "\e[5>h"; # カーソル非表示モード(Windows は使えないらしい)
# ●Act.6:@str の先頭要素を shift で取り出し、適度に wait をかけて表示
while (@str) {
my $x = ReadKey; # 何かキーを押すまで wait を続行
my $str = shift @str;
my $len = length($str);
for (my $j=0; $j<$len; ++$j) {
my $ch = substr($str, $j, 1);
wait_on($wait_sec);
print $ch;
}
}
ReadMode 0; # Reset tty mode before exiting
#print "\e[5>l"; # カーソル表示モードに戻す(Windows は使えないらしい)
sleep 2;
$| = 0; # STDOUT のバッファリング復活
1;
# ●サブルーチン:wait_on (wait 実行ルーチン) by foussin
# 2005.11.05 Sat 10:21 (初版)
# 2012.05.15 Tue 23:42 (Perl5 風にリライト)
# 概要:1秒未満の wait をかける
# 最小単位:10ミリ秒=1センチ秒 (Win32 の場合) (Linux は 1ミリ秒)
# 最小単位は times の実装に依存 (Linux と Win32 では仕様が異なる)
# 0.01秒未満の秒数を指定すると 0.01 を指定したと見なされる(Win32)
# 備考:times の実装は 2012年当時の話(現在では仕様が変わっているかも…)
# 書式:$true_time = wait_on($sec);
# 引数:$sec: 0.01秒以上の wait時間(秒数)を指定する。
# 戻値:$true_time: 実際に wait した時間を秒数(実数値)で返す。
# 備考:実際の待ち時間は引数$secを超える可能性アリ (正確なwaitではない)
sub wait_on {
my $start = (times)[0];
my $sec = $_[0];
my $break = $start + $sec;
my $now;
while (1) {
$now = (times)[0];
($now >= $break) && last; # 正確な wait ではない...
}
return $now - $start;
}
__END__
機能:テキストをコンソール(ターミナル)に『ゆっくり標準出力』する
書式:ktrgtr.pl [入力テキストファイル名]
引数:引数を省略すると ktrgtr.pl が居る場所をカレントディレクトリにして
そこにある『ktrgtr-云々.txt』を入力ファイルとして読み込む選択画面
となる。入力ファイルが 1個しかない時は選択プロンプトを表示せずに、
そのファイルを直ちに読み込む。入力ファイルの文字コードは問わない。
カテゴリ:創作支援ツール(映像表現用)
使用方法:はてなダイアリーで説明(長くなりそうなので)