1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

todoと連動したカレンダー作例

Posted at

背景

~/org/gtd.org というスケジュールテキストに書いた日時が把握しにくかった。
そして1週間の単位が月火水木金土日というのに馴染んでおり、一般のカレンダーの
日曜日スタートに違和感があった。
また、 cal -3 のような複数のカレンダーが横に表示されていくのにも不満があった。
30や31日の月末ごとに意識が分断されていた。30や31の隣に1が表示されてほしかった。
好みに合わない数が多いので作り直すことにした。

概要

gtd.orgと連動した好みに合うように再開発されたカレンダーは以下の特徴を持つ。
~/org/gtd.org を読み込み TODO,Deadline のある日をハイライトする。
それらの日のtodoは右に簡易表示させる。
そのうち、今日行うべきことがあれば当日専用のハイライトで強調する。
月曜日スタートで始まる。
月末を終えても改ページ等々は無し。日付は連続する。
表示する月を増やせる。
祝日など任意の日を自由にハイライトさせられる。

コード説明

org_todo_finder.pl はgtd.orgを簡単に読むためのスクリプトだ。
それは何ヶ月分なのか、見出しだけなのか、本文も必要なのか、について
TODO、Deadlineのあるものを日付順にソートして返してくる。
ソートされるのが便利なので、独立させた。
cal サブルーチンで使う @dye_way が今回のハイライト実装の中心を担っている。
土日だからシアンや赤に染めることと、todoが被ってアンダーバーを引くなど
複数のハイライト修飾ができる限り両立する為には、
1日1日を何年何月の何日であるのか認識してコードを書くのが
理路整然としていて保守がしやすい。
整列も printf や format には頼れないが、
padding_1t_10_day を書くことで矛盾無く整列させられる。

使用例

cal_up.png

コード

#!/usr/bin/env perl
use strict;
use warnings;
require Colorlizer;
sub say {print @_, "\n"};
sub dye {Colorlizer::dye(@_)};
use constant ONE_DAY => 60*60*24;
use Time::Piece;

# private
my $extra_ref = [ 
                    [ 20220824, qw(orange) ],
                    [ 20220825, qw(orange) ],
                    [ 20220826, qw(orange) ],
                    [ 20220829, qw(orange) ],
                    [ 20220830, qw(orange) ],
                    [ 20220831, qw(orange) ],
                    [ 20220901, qw(orange) ],
                    [ 20220902, qw(orange) ],
                    [ 20220919, qw(cyan) ], # 敬老の日
                    [ 20220923, qw(cyan) ], # 秋分の日
                    [ 20230101, qw(blink) ], # happy new year
                ];

# import schedule from org_todo file
my @todo ;
my @dates;
my $numbers_of_month = shift // 2;
{
    for (qx{ ~/bin/org_todo_finder.pl td$numbers_of_month }) {
        chomp;
        /^[*]+ \s+ (.*)$/x        ? push @todo , s/^[*]+ \s+ TODO \s+//xr:
        /(\d{4})-(\d{2})-(\d{2})/ ? push @dates, "$1$2$3"                :
        die "I can't understand $_ as neither date or todo.\n"                  ;
    }

}

my %dates_map = map {$_ => 1} @dates;

sub HEADER () {say " Mo Tu We Th Fr Sa Su"};
my $now = localtime;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
++$mon and $year += 1900;

sub struct_Y4M2D2 {
    my $self = shift;
    sprintf "%4s%02s%02s" , $self->year, $self->mon, $self->mday
};
my $now_Y4M2D2 = struct_Y4M2D2($now);
sub calHeaderYYYYMM_nameMonth {
    my $d= $now + ONE_DAY * (1 - $mday);
    sprintf "%-4s %02s %13s" , $d->year, $d->mon, $d->fullmonth;
}

sub cal {
    my $self = shift;
    my $wd= $self + ONE_DAY * (1 - $mday);
    for my $d (1 .. $self->month_last_day) {

        padding_1st_day($wd);

        my $Y4M2D2 = sprintf "%4s%02s%02s"
            , $wd->year, $wd->mon, $d;

        my @dye_way = qw(itaric);
        # today
        if ($Y4M2D2 == $now_Y4M2D2) {
            push @dye_way, qw(back_white black);
        }
        # org_todo
        if ($dates_map{$Y4M2D2}) {
            push @dye_way, qw(underline);
        }

        for my $d_color_ref (@$extra_ref) {
            my($d, @cs);
            ($d, @cs) = @$d_color_ref;
            if ($Y4M2D2 == $d) {
                push @dye_way, @cs;
            }
        }

        if ($wd->wdayname eq "Sat") {
            push @dye_way, qw(cyan);
        }
        if ($wd->wdayname eq "Sun") {
            push @dye_way, qw(red);
        }

        print q( ) . dye( padding_lt_10_day($d), @dye_way);
        foldingSun($wd);
        $wd += ONE_DAY;
    }
}
sub padding_lt_10_day {
    my $day = shift;
    $day < 10 ? q( ) . $day : $day ;
}

sub padding_1st_day {
    my $self = shift;
    my %pad_map = (
        Mon => 0,
        Tue => 3,
        Wed => 6,
        Thu => 9,
        Fri => 12,
        Sat => 15,
        Sun => 18,
    );
    if ($self->mon == $mon and $self->mday == 1) {
        print q( ) x $pad_map{$self->wdayname};
    }
}

sub foldingSun {
    my $self = shift;
    if ($self->wdayname eq "Sun") {
        my ($t,$d);
        if ($t = shift @todo) {
            $d = shift @dates;
            $d = ($now_Y4M2D2 == $d) ? dye($d , qw(back_white black)) : $d;
            print "\t$d $t" =~ s/\d{4}//r;
        }
        print "\n";
    }
}

sub main {
    say calHeaderYYYYMM_nameMonth();
    HEADER;
    for my $n (1 .. $numbers_of_month) {
        cal($now->add_months($n -1));
    }
}

main();
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?