ってわけでCUIベースの単語帳を作ってみたよ

自分で作ってみた感じだとなかなかよさげな気がする。csvにもとのデータを保存しているので、他の用途に使うのも楽チン。紙の単語帳だとできないところ。TOEFL対策講座の勉強に使ってます。

特徴

  • registerって打つとcsvファイルに登録
    • 間違ったらdeleteで消せる
  • questionって打つと問題を出すような形になって止まる
    • cとq以外の任意のキーを押すと答えが出る
    • cを打つと覚えたということで、次回からは出てこない
    • qを打つと問題を出すモードから脱出

自分的には問題を出したときにワンストロークでいけるのがいいかなっと思ったところ。

#!/usr/bin/perl
package My::Tango;

use strict;
use warnings;

use Term::ReadLine;
use Data::Dumper;
use Text::CSV::Simple;
use Term::ReadKey;
use Jcode;
use Smart::Comments;

my %cmds;
$cmds{help} = sub { print join( ' ', sort keys %cmds ), "\n"; };

$cmds{hello_world} = sub { print "hello world!!\n"; };

$cmds{ls} = sub {
    my $self = shift;
    foreach my $key ( keys %{ $self->{dict} } ) {
        printf "%-10s : %s \n", $key,
          Jcode::convert( $self->{dict}->{$key}, 'euc-jp' );
    }
};

$cmds{register} = sub {
    my $self   = shift;
    my $term   = $self->{term};
    my $prompt = "登録したい単語を入力してください: ";
    my $tango  = $term->readline($prompt);
    $prompt = "その意味を登録してください: ";
    my $imi = $term->readline($prompt);
    ${$self}{dict}{$tango} = $imi;
    print "登録が完了しました\n";
};

$cmds{delete} = sub {
    my $self   = shift;
    my $term   = $self->{term};
    my $prompt = "削除したい語を入力してください: ";
    my $tango  = $term->readline($prompt);
    delete ${$self}{dict}{$tango};
    print "削除しました\n";
};

$cmds{exit} = sub {
    my $self = shift;
    print "Good Bye!!\n";
    $self->save();
    $self->save_done();
    exit;
};

$cmds{question} = sub {
    my $self   = shift;
    my $term   = $self->{term};
    my $prompt = $self->{prompt};
    ReadMode 'cbreak';
    foreach my $key ( keys %{ $self->{dict} } ) {
        printf "%-10s : ", $key;
        my $input = ReadKey(0);
        printf "%s \n", Jcode::convert( $self->{dict}->{$key}, 'euc-jp' );
        if ( $input eq "q" ) {
            last;
        }elsif($input eq "c"){
	    $self->complete($key);
	}
    }
    ReadMode 'normal';
};

sub new {
    my ($class) = @_;
    my $term    = Term::ReadLine->new('my tango');
    my $prompt  = "tango> ";
    bless {
        dict   => undef,
	complete => undef,
        term   => $term,
        prompt => $prompt,
    }, $class;
}

sub prepare {
    my $self = shift;
    my $csv  = Text::CSV::Simple->new(
        {
            binary => 1,    #日本語を通すため
        }
    );
    $csv->field_map(qw/tango imi/);
    my @array = $csv->read_file(".tango");
    foreach my $dict (@array) {
        $self->{dict}->{ $dict->{tango} } = $dict->{imi};
    }
}

sub start {
    my $self   = shift;
    my $term   = $self->{term};
    my $prompt = $self->{prompt};
    my $OUT    = $term->OUT || \*STDOUT;

    while ( defined( $_ = $term->readline($prompt) ) ) {
        if ( exists $cmds{$_} ) {    # 入力に対応するコマンドがあれば、
            &{ $cmds{$_} }($self);    # それを実行する
        }
        else {
            print "そのコマンドは存在しません\n";
        }
        $term->addhistory($_) if /\S/;
    }
}

sub complete {
    my $self   = shift;
    my $tango = shift;
    $self->{complete}->{$tango} = $self->{dict}->{$tango};
    delete ${$self}{dict}{$tango};
}

sub save {
    my $self = shift;
    open FILE, "> .tango" or die "$!";
    my $content = "";
    my $tango;
    my $imi;
    my @list;
    foreach my $key ( keys %{ $self->{dict} } ) {
        $tango   = $key;
        $imi     = Jcode::convert( $self->{dict}->{$key}, 'euc-jp' );
        @list    = ( $tango, $imi );
        $content = $content . "\"" . join( "\",\"", @list ) . "\"\n";
    }
    print FILE $content;
    close FILE;
}

sub save_done {
    my $self = shift;
    open FILE, "> .done_tango" or die "$!";
    my $content = "";
    my $tango;
    my $imi;
    my @list;
    foreach my $key ( keys %{ $self->{complete} } ) {
        $tango   = $key;
        $imi     = Jcode::convert( $self->{complete}->{$key}, 'euc-jp' );
        @list    = ( $tango, $imi );
        $content = $content . "\"" . join( "\",\"", @list ) . "\"\n";
    }
    print FILE $content;
    close FILE;
}

package main;

use strict;
use warnings;
use Data::Dumper;

my $tango = My::Tango->new();
$tango->prepare();
$tango->start();

関数のリファレンスとかが出てきたので結構いみふになったが、結構いい勉強になった感じではある。