Perl 小品集 ─ fview2
#!/usr/bin/perl
# fview2.pl
# 簡易ファイル閲覧ユティリティ
# Perl モジュール Term::ReadKey が必要
# モジュールの宣言
use Term::ReadKey;
# ReadKey モード
# 0 restore
# 1 normal
# 2 noecho
# 3 cbreak
# 4 raw
# 5 ultra-raw
# global value
# %progs ファイルタイプとそれを動かすプログラムの対応表
# @list ディレクトリに含まれるファイル名のリスト
# @history ディレクトリのヒストリーを保存
# $root 作業中のディレクトリ
# $sum ディレクトリに含まれるファイルの総数
# $pages ファイルを表示する場合のページ数
# 表示パネルのデフォルト
$max = 40; # ページあたりのファイル数
$offset_row = 2; # オフセット
$offset_col = 1;
$width = 80; # スクリーンの幅
$col_space = 40; # 左右の欄の間隔
$park_row = 22; # 修了時のカーソル位置
$park_col = 1;
# ファイルタイプとそれを表示するプログラムを定義する
%progs = (
cgi => vedit,
conf => xz,
html => xz,
pl => xz,
shtml => xz,
txt => xz,
bmp => ee,
gif => ee,
png => ee,
jpg => ee,
tif => ee,
pdf => acroread,
mp3 => mpg123,
mpg => mtvp,
mid => timidity,
rmi => timidity
);
($root) = @ARGV;
# 現在のディレクトリとそのファイル情報を得る
if ($root eq "") {
($root) = `pwd`;
}
chomp $root;
$page = 1;
# ヒストリーの保存
push @history, $root;
push @history, $page;
&get_list;
$page = 1;
&show_list ($page);
$n = 0;
$row = $offset_row;
$col = $offset_col;
print "\033[$row;$col\H\033[7m .. \033[0m";
&select ($page, $n);
exit 0;
# 指定したディレクトリのファイル情報を得る
sub get_list {
local (@dot_list, @file_list, $entry);
# リストの初期化
$list = "";
# ドットファイルを得る
@dot_list = glob "$root/.*";
# 通常のファイルを得る
@file_list = glob "$root/*";
$sum = 0;
# ディレクトリを得る
foreach $entry (@dot_list) {
if (-d $entry) {
$entry =~ /([^\/]+)$/;
if ($1 ne '.') {
$list [$sum] = $1;
$sum++;
}
}
}
foreach $entry (@file_list) {
if (-d $entry) {
$entry =~ /([^\/]+)$/;
$list [$sum] = $1;
$sum++;
}
}
# ファイルの場合
foreach $entry (@dot_list) {
if (-f $entry) {
$entry =~ /([^\/]+)$/;
$list [$sum] = $1;
$sum++;
}
}
foreach $entry (@file_list) {
if (-f $entry) {
$entry =~ /([^\/]+)$/;
$list [$sum] = $1;
$sum++;
}
}
# ファイルのリストが多い場合、複数ページにわける
if ($sum > $max){
$pages = int ($sum / $max);
if ($sum % $max > 0) {
$pages = $pages + 1;
}
}
else {
$pages = 1;
}
}
# ディレクトリの移動、ファイルの選択
sub select {
local ($page, $n) = @_;
ReadMode 3; # cbreak
$key = ReadKey;
# プログラムによって書き込まれたメッセージを消す
print "\033[2K";
# 反転表示していたファイルを通常の表示にもどす
&hilite ($page, $n, 0);
# ファイルの最後を計算
if ($page < $pages) {
$last = $max;
}
else {
$last = $sum - $max * ($page - 1);
}
# 次は上記と同じ条件文
# $last = $max * $page * ($page < $pages) + ($sum - $max * ($page - 1)) * ($page == $pages); # 終了番号
# 入力されたキーの判定
# ESC, q : 終了
if ($key eq 'q' or $key eq 'Q') {
ReadMode 0; # restore
print "\033[$park_row;$park_col\H";
return;
}
# Enter : 表示
elsif (ord $key == 10 or ord $key == 13) {
($page, $n) = &select_2 ($page, $n);
}
# 移動
# BS : ヒストリーをさかのぼる
elsif (ord $key == 8) {
if (scalar @history > 0) {
$page = pop @history;
$root = pop @history;
&get_list;
&show_list ($page);
$n = 0;
}
}
# ↑ : 前のファイルへ
elsif ($key eq 'A') {
# 前のページに
if ($n == 0 and $page > 1) {
push @history, $root;
push @history, $page;
$page--;
&show_list ($page);
$n = $max - 1;
}
elsif ($n > 0) {
$n--;
}
}
# ↓ : 次のファイルへ
elsif ($key eq 'B') {
# 次のページに
if (($n == $max - 1) and ($page < $pages)) {
push @history, $root;
push @history, $page;
$page++;
&show_list ($page);
$n = 0;
}
elsif ($n < $last - 1) {
$n++;
}
}
# → : 次のページ
elsif ($key eq 'C' and $page < $pages) {
push @history, $root;
push @history, $page;
$page++;
&show_list ($page);
$n = 0;
}
# ← : 前のページ
elsif ($key eq 'D') {
# 1ページ目なら上位ディレクトリへ
if ($page == 1) {
push @history, $root;
push @history, $page;
$root =~ s/\/[^\/]+$//;
&get_list;
$page = 1;
&show_list ($page);
$n = 0;
}
elsif ($page > 1) {
push @history, $root;
push @history, $page;
$page--;
&show_list ($page);
$n = 0;
}
}
# 選んだファイルを反転表示する
&hilite ($page, $n, 1);
# ファイルを表示した場合、プログラムによって書き込まれるメッセージ
# がファイル表示を妨げないよう、それを欄外に置く
print "\033[$park_row;$park_col\H";
&select ($page, $n);
}
sub select_2 {
local ($page, $n) = @_;
local $file = $list [$max * ($page - 1) + $n];
# アクセス許可が無い場合
if (!(-r "$root/$file")) {
print "\033[$park_row;$park_col\H No Permissions!";
return ($page, $n);
}
# 上位ディレクトリへの移動
elsif ($file eq "..") {
push @history, $root;
push @history, $page;
$root =~ s/\/[^\/]+$//;
&get_list;
$page = 1;
($last) = &show_list ($page);
$n = 0;
}
# 下位ディレクトリへの移動
elsif (-d "$root/$file") {
push @history, $root;
push @history, $page;
$root = "$root/$file";
&get_list;
$page = 1;
($last) = &show_list ($page);
$n = 0;
}
# ファイルの閲覧
else {
# ファイルを表示した場合、プログラムによって書き込まれるメッセージ
# がファイル表示を妨げないよう、それを欄外に置く
print "\033[$park_row;$park_col\H";
# テキストファイルの場合
if (-T "$root/$file") {
system "xz '$root/$file'";
}
# その他のファイル
else {
$file =~ /\.([^\.]+)$/;
$filetype = $1;
foreach $type (%progs) {
if ($type eq $filetype) {
$program = $progs{$type};
system "$program '$root/$file'";
last;
}
}
}
}
return ($page, $n);
}
# ファイル名のハイライト
sub hilite {
local ($file, $p_row, $p_col);
local ($page, $n, $key) = @_;
$file = $list [$max * ($page - 1) + $n];
$p_row = $offset_row + $n - (($max / 2) * ($n >= $max / 2));
$p_col = $offset_col + $col_space * ($n >= $max / 2);
# ハイライトにする場合
if ($key == 1) {
print "\033[$p_row;$p_col\H\033[7m $file \033[0m";
}
# もとにもどす場合
# アクセス禁止ファイル
elsif (!(-r "$root/$file")) {
print "\033[$p_row;$p_col\H\033[31m $file \033[0m";
}
# ディレクトリ
elsif (-d "$root/$file") {
print "\033[$p_row;$p_col\H\033[34m $file \033[0m";
}
# その他のファイル
else {
print "\033[$p_row;$p_col\H $file ";
}
}
# ディレクトリ、ファイルのページごとのリスト
sub show_list {
local ($line, $i, $row, $col, $start, $last, $p_root, $title_name, $name);
local ($page) = @_;
# スクリーンの初期化とタイトルの表示
if ($root eq "") {
$p_root = "/";
}
else {
$p_root = $root;
}
if ($pages > 1) {
$title_name = " FileView ($p_root) $page/$pages ";
}
else {
$title_name = " FileView ($p_root) ";
}
print "\033[2J\033[1;0H";
$line = int(($width - length ($title_name)) / 2);
$i = 0;
while ($i < $line){
print '=';
$i++;
}
print $title_name;
$i = $i + length ($title_name);
while ($i < $width){
print '=';
$i++;
}
# リストの表示
$start = $max * ($page - 1); # 開始番号
$last = $max * $page * ($page < $pages) + $sum * ($page == $pages); # 終了番号
$row = $offset_row; # 開始位置
$col = $offset_col;
while ($start < $last){
($name) = &print_name ($list [$start++]);
# 欄の折り返し
if ($row == $offset_row + $max / 2) {
$row = $offset_row;
$col = $offset_col + $col_space;
}
print "\033[$row;$col\H $name";
$row++;
}
return;
}
# 表示名の調整
sub print_name {
local (@letters, $i, $p_name);
local ($name) = @_;
# ファイル名が長い場合、それを短くして表示する
if ((length ($name)) > $col_space - 5) {
@letters = split //, $name;
$p_name = "";
$i = 0;
while ($i < $col_space - 5){
$p_name = "$p_name$letters[$i++]";
}
$p_name = "$p_name...";
}
else {
$p_name = $name;
}
# アクセス禁止ファイル
if (!(-r "$root/$name")) {
$p_name = "\033[31m$p_name\033[0m";
}
# ディレクトリーのカラー表示
elsif (-d "$root/$name") {
$p_name = "\033[34m$p_name\033[0m";
}
return $p_name;
}