2008/05/26

先日、Open Tech Pressの連載コラム「Vimマスターへの道」の中に「Vim/gVimをユーザフレンドリなエディタに変えるCream」という記事を見つけました。
Creamは以前から知っており、Creamの作者から「calendar.vim」の取り込み可否を尋ねられた事があります。現在は少し古いバージョンがCreamにバンドルされています。
上記本文中に、「...例えばカレンダ機能を追加するCalendarプラグインが使えないと自分は生きていけないと語っていた者と何回か出会ったことがある。」の文言を見つけた時には正直嬉しかったです。
ただ、Calendarに付属している日記機能は現状メモ書き用途にしか使えず、現状のCalendarは単なるカレンダでしかありません。何かとリンクする訳でもなく、このデータを使ってvimと連携する事もありません。しいて言うならば日記ファイルがあるとcalendar.vimで日付が点灯するくらいです。

vim_calendar1

今日は、あまりvimと関係しないかも知れませんが、このcalendar.vimとGoogle Calendarのスケジュールを同期するプログラムをご紹介したいと思います。
Google Calendarは、Googleが無償で提供するカレンダアプリケーションです。
携帯からも使用でき、ホビーユーザからヘビーユーザまで満足出来るアプリケーションです。
Google CalendarにはAPIが公開されており、Googleのアカウントをお持ちで開発経験のある方ならば自前のアプリケーションからGoogle Calendarに対してアクセスする事が出来ます。
今回はPythonを使用しますのでgdata-python-clientから「gdata.py-1.0.5.tar.gz」をダウンロードしました。
calendar.vimでは、ホームディレクトリに置かれた「diary」というディレクトリ(変更可能)から年月日をそれぞれディレクトリに分割した構成で拡張子「.cal」のファイルを管理します。
この「.cal」ファイルにGoogle Calendarのスケジュールを取得し、書き込みたいと思います。
gdata-python-clientでは、Googleアプリケーションのデータストレージ(gdata)に対する認証からカレンダへのアクセスまで行ってくれます。
認証は以下の手順で行います。
cal_client = gdata.calendar.service.CalendarService()
cal_client.email = myemail
cal_client.password = mypasswd
cal_client.source = "Google-Calendar_Python_Sample-1.0"
cal_client.ProgrammaticLogin()
これで、GData認証サービスへのトークン取得、認証までが完了しています。
そして以下がカレンダへのアクセスです。今回は当月から3ヶ月分のスケジュールを取得しています。
today = datetime.date.today()
query = gdata.calendar.service.CalendarEventQuery("default", "private", "full", "")
query.start_min = str(today + relativedelta(day=1))
query.start_max = str(today + relativedelta(months=+3,day=1,days=-1))
feed = cal_client.CalendarQuery(query)
for i, an_event in enumerate(feed.entry):
  for a_when in an_event.when:
    print an_event.title.text, a_when.start_time, a_when.end_time
今回は、横着して月始めと月末の計算に便利な「dateutil」を使用しています。
これで、当月の一日から、2ヵ月後の月末までのイベントオブジェクト(feed)が取得出来ましたので、これをcalendar.vimの日記ファイルとリンクします。
def update_schedule(path, an_event, a_when):
    dir = os.path.dirname(path)
    if not os.path.isdir(dir):
        os.makedirs(dir)
    lines = []
    resep = re.compile("^" + schedule_sep + "$")
    has_data = False
    if os.path.isfile(path):
        fp = open(path)
        for line in fp.readlines():
            if resep.search(line):
                has_data = True
            lines.append(line)
    if not has_data:
        lines.append("%s\n" % schedule_sep)
    lines.append("%s - %s\n" % (
        a_when.start_time.replace("-", "/"),
        a_when.end_time.replace("-", "/")))
    lines.append("\t%s\n" % an_event.title.text.encode("utf-8", "replace"))
    print "updating schedule of '%s'" % path
    fp = open(path, "w")
    fp.writelines(lines)
    fp.close()
schedule_sepは「--- Google Calendar ---」というセパレータを示し、「.cal」ファイルの下部からデータが開始します。
データは、「開始日付 - 終了日付」の次の行にイベント名をインデントした以下の形式にしています。
--- Google Calendar ---
2007/09/25 - 2007/09/26
    休暇予定
上記update_scheduleでは、セパレータ以降にGoogle Calendarから取得した開始日付、終了日付、タイトルを書き込んでいます。

ただ、このアプリケーションを何度も実行すると同じデータが繰り返し追加される事になりますので、update_scheduleと同様の処理でセパレータ以降をクリアするremove_scheduleを実装し
# clean exising schedules
for i, an_event in enumerate(feed.entry):
  for a_when in an_event.when:
    remove_schedule(datetime2diary(a_when.start_time))

# append newer schedules
for i, an_event in enumerate(feed.entry):
  for a_when in an_event.when:
    update_schedule(datetime2diary(a_when.start_time), an_event, a_when)
とする事で毎回データを作り直しています。
これをあとは、プログラム引数からユーザIDとパスワードを貰い、動作するアプリケーションとして仕上げれば以下のようなCalendarの画面が出来上がります。

vim_calendar2

一応、Windows版のPython2.5で検証してますが、おそらく2.4でも動作するかと思います。
このアプリケーションには、まだ更新する機能がありませんが、ぼちぼち暇を見つけて更新して行こうかと思います。

ダウンロード:

Posted at 17:24 | WriteBacks () | Edit
Edit this entry...

wikieditish message: Ready to edit this entry.






















A quick preview will be rendered here when you click "Preview" button.