ワードやエクセルをいじっていてテキストファイルというと、
なんかしょぼい情報量の少ないファイルであるかのように錯覚してしまいますが、
冷静に考えるとそんなものではないことは、明白です。
テキストと一口に言ってもいろいろです。Postscriptやpdfもある意味テキストですし、SVGもそうです。
画像であってそれがテキストなんて、変な話ですが、バイナリ以外全部と言うことにすると、範囲はとても広いものとなります。
Perlが活躍しているのもこういう背景があるんだと思います。
ここで扱うのは、そんなに広いものではありません。
電子メールや掲示板の発達に伴って誰でも見れるファイルとして、重要性は高まっていると思います。
考えておきたいことは、マックのスタイル付きテキストと言うやつとアスキーアートに関してです。
とりあえず考えるだけでプレーンテキストは何の加工もしないことにします。
私は、リソースについて余り詳しくないので、これをうまく活用できてません。
これをリッチテキストとか、htmlとかに変換することは、スキルのある人にとって余り難しいことではないんでしょうけど
perlscriptでいろいろ相互に変換できたら楽しいだろうなと思います。
ハイパーカードのフィールドは、フォントが変えられたりかなりいろいろな表現が可能なわけで、それらをうまく活用する
とさらに素晴らしくなるとは思います。
use Text::ASCIITable;
$t = new Text::ASCIITable;
$t->setCols(['num','Name','Pos']);
$t->addRow('1','藤本','ショート');
$t->addRow('2','赤星','センター');
$t->addRow('3','今岡','セカンド');
$t->addRow('4','金本','レフト');
$t->addRow('5','檜山','ライト');
$t->alignCol('num','right');
$t->alignCol('Name','center');
$t->setOptions('alignHeadRow','center');
$t->setColWidth('Name',30,1);
print $t->draw( ['+','+','-','+'],
['|','|','|'],
['+','+','-','+'],
['|','|','|'],
["+","+",'-','+']
);
+-------------------------------------------------+
| num | Name | Pos |
+-----+--------------------------------+----------+
| 1 | 藤本 | ショート |
| 2 | 赤星 | センター |
| 3 | 今岡 | セカンド |
| 4 | 金本 | レフト |
| 5 | 檜山 | ライト |
+-----+--------------------------------+----------+
自分でもhtmlのテーブルをアスキーアートで書きだすスクリプトをかいてみましたが、表組というのは、本当に難しいものです。
とにかくインターネット上でいちばん多いのがこの形なので、これのビューワを作る事が一番大切です。
htmlのもっとも重要な特徴はハイパーリンクの仕組みだと思います。
HTML::TreeBuilderはかなり強力なので、テキストだけを抜き出すとかいうようなことは簡単にやってくれます。
問題は、ハイパーリンクをどう表現するかとか、表組をどうするかとか、容量の大きいファイルだったらとかいうようなことだと思います。
テーブルレイアウトで作られているものをブラウザ以外でうまくいかすのはとても難しいことです。
自分のページを読んだ図
#!/usr/local/bin/perl-w
use strict;
use HTML::TreeBuilder;
use HTML::Element;
use Jcode;
my @del = qw(script style form) ;#--このタグが来たらこのツリーごと削除する
open(IN,$ARGV[0]);
my $content = join"",<IN>;
close(IN);
$content = jcode($content)->euc;#--eucにする
$content =~ s/\x0D\x0A|\x0D|\x0A/\n/g;#--改行をそろえる
make_tree($content);
sub make_tree {
my $content = shift;
my $tree = HTML::TreeBuilder->new;
$tree->parse($content);
&edit_tree($tree);
my $option = {};#無名のハッシュへのリファレンス。いろんな情報を入れる
&walk_tree($tree,$option);
$tree->delete;
my@output1=();#--(1)
my@output2=();
for (my $i= 0;$i< scalar@{$option->{text}};$i += 2)
{
my($elm1,$elm2)=($option->{text}[$i],$option->{text}[($i+1)]);
unless($elm1 eq "" and $elm2 eq ""){
$elm1= join "\t",reverse split /\t/,$elm1;
push@output1,"$elm2\t$elm1" if $elm1 ne "";
push@output2,$elm2;
}
}
my $output1 = join "\n", map {jcode($_)->sjis} @output1;
my $output2 = join "", map {jcode($_)->sjis} @output2;
my $title = jcode($option->{title})->sjis;
print $title ,"\r","$output1\r$output2";#LFの区切りでデータを返す。マックでは使わないし。
}
sub edit_tree {#--ツリーを加工しやすくする。
my($node)=@_;
if(ref $node){
my $tag = $node->tag();
$node->delete if 1 == scalar grep {$_ eq $tag} @del;#--ツリーごと削除する
&edit_tree($_) for $node->content_list();
}
}
sub walk_tree {#--(2)
my($node,$option) = @_;
if(ref $node){
my$tag=$node->tag();
if ($tag eq "title" ){$option->{title} = $node->as_text;}
elsif ($tag eq "br" or $tag eq "hr"){
if ($option->{text}[-1] ne "")
{
$option->{text}[-1] .= "\n";
++($option->{char}) ;
}
}
elsif ($tag eq "ul" or $tag eq "ol"){
push @{$option->{text}},("","\n");
++($option->{char}) ;
&walk_tree($_,$option) for $node->content_list();
$option->{text}[-1] .= "\n";
++($option->{char}) ;
}
elsif ($tag eq "li" ){
push @{$option->{text}},("","*");
++($option->{char});
&walk_tree($_,$option) for $node->content_list();
$option->{text}[-1] .= "\n";
++($option->{char}) ;
}
#リンクは、絶対指定のものしか拾わない
elsif ($tag eq "a" and $node->attr("href") and $node->attr("href") =~/^http|^www/){
if ($option->{text}[-1] eq "")
{
$option->{text}[-1].=" ";
++($option->{char});
}
push @{$option->{text}},("char ".(($option->{char})+1)." to ","");
my $str= $node->as_text;
$option->{char} += length_euc($str);
$option->{text}[-1] .= $str;
$option->{text}[-2] .= ($option->{char})." of card field 2\t".($node->attr("href"));
push @{$option->{text}},("","");
}
else{
push @{$option->{text}},("","");
&walk_tree($_,$option) for $node->content_list();
}
}
else{
$option->{char} += length_euc($node);
$option->{text}[-1] .= $node;
}
}
sub length_euc { #ハイパーカードの文字の数え方に合わせる
my ($str) = @_;
my ($len,$zen_len) = (length($str),($str =~ tr/\xa1-\xfe//)/2);
return int $len - $zen_len; #intがあるのはうまくいってないから
}
ほとんど見栄えをよくするために長くなっているんですが、無名のハッシュへのリファレンスまでは普通に
分かるとして、無名のハッシュに入れるものは、タイトルと数えている文字数とテキストです。
on mouseUp
do script "set cursor to busy"
--選んだファイルのパスを得る
do script "return the selectedText of me"
set |ファイルの名前| to return value
if it is "" then return
do script "the value of word 2 of the long name of this stack"
set |フォルダ| to return value
set text item delimiters of AppleScript to {":"}
set |フォルダ| to (every text item of |フォルダ|)
set item -1 of |フォルダ| to ""
set |フォルダ| to |フォルダ| as string
set |ファイルパス| to |フォルダ| & |ファイルの名前|--(1)
--MacPerlにファイルパスを渡す
set Perl_script to card field "htmlの解釈"
tell application "MacPerl"
set |テキスト| to Do Script {Perl_script, |ファイルパス|} mode Batch
end tell
set text item delimiters of AppleScript to {"
"}--(2)
--戻り値をフィールドにセットする
set |テキスト| to every text item of |テキスト|
set card field "タイトル" to item 1 of |テキスト|
set card field "リンク" to item 2 of |テキスト|
set card field "テキストの内容" to item 3 of |テキスト|
--ハイパーリンクをつくる準備
set |リンクのリスト| to item 2 of |テキスト|
set text item delimiters of AppleScript to {return}
set |リンクのリスト| to every text item of |リンクのリスト|--(3)
set text item delimiters of AppleScript to {tab}
if item 1 of |リンクのリスト| is not "" then --リンクがない場合もある
set |チャンクリスト| to {}
repeat with i from 1 to length of |リンクのリスト|
set |リンク| to item i of |リンクのリスト|
set |リンク| to every text item of |リンク|--(4)
set |チャンク| to item 3 of |リンク|
set end of |チャンクリスト| to |チャンク|
end repeat
set |リストの長さ| to length of |チャンクリスト|
--リンクが多いと時間がかかるのでやめるかどうか
if |リストの長さ| > 100 then
display dialog |リストの長さ| & "個もリンクがあります" & return & ツ
"時間かかりそうです" buttons {"続ける", "やめる"}
set |結果| to button returned of result
if |結果| = "やめる" then return
end if
--リンクのスタイルを作る
repeat with i from 1 to |リストの長さ|--(5)
set HT to "set textStyle of " & item i of |チャンクリスト| & "to group"
do script HT
end repeat
end if
do script "set the scroll of cd fld \"テキストの内容\" to 0"
set text item delimiters of AppleScript to {""}
end mouseUp
(1)までで選択されたファイルのパスを得てます。