Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2011-04-05

適当にCSVファイルを作成する

| 19:03 | 適当にCSVファイルを作成する - わだばLisperになる を含むブックマーク はてなブックマーク - 適当にCSVファイルを作成する - わだばLisperになる

いつものごとく書き捨てスクリプト的な日常LISPの紹介ですが、今回は趣向を変えてASDFでプロジェクトを作りつつやってみることにします。

タスク: CSVファイルの生成

今回のタスクの内容ですが、Redmineにタスクを登録するのに、csvファイルで一括登録できるプラグインがありまして、それで一括でタスクを登録するためのcsvファイルを作る、というものです。

そもそもRedmineの使い方を知らないんじゃないか等の疑問はありますが、それはおいておきます。

ASDFのプロジェクトを作成する

プロジェクトの作成には、QuickLispで有名な Zach Beane氏作の、quickprojectという便利なものがあるのでこれを使います。

(quickproject:make-project "/foo/bar/redmine-schedule/"
                           :depends-on '(:g000001 :fare-csv :date-calc :lets))

のようなものを実行すると、

/foo/bar以下に、

README.txt
package.lisp
redmine-schedule.asd
redmine-schedule.lisp

のような一式が用意されます。仕組みとしてはシンプルなものですが重宝しています。

ちなみにディレクトリ名の最後のスラッシュが肝なので忘れないようにしましょう。

上記ファイルですが、asdファイルは

(asdf:defsystem #:redmine-schedule
  :serial t
  :depends-on (:g000001 :fare-csv :date-calc :lets)
  :components ((:file "package")
               (:file "redmine-schedule")))

のように生成。:depends-onというのは、依存しているパッケージの指定になります。

package.lispは、:use #:cl位しかされていないので

(defpackage #:redmine-schedule
  (:use #:cl #:lets #:g000001))

のように適当にuseしたいものを追加で配置。

上記で使っているパッケージのざっとした説明ですが、g000001は自分のユーティリティ集で私にしか役に立たないもの、LetSは80年代初期のMacLISPのコードをCLで動くように私が盆栽しているもので完全なる趣味のもの、date-calcはPerlのDate::Calcを範にした日時を扱うのに便利なユーティリティです。

;; 2011/4/4の30日後
(date-calc:add-delta-days 2011 4 4 
                          30)
;=> 2011
;   5
;   4

のようなことができます。

また、fare-csvは、csvファイルとリストを相互変換できる便利ユーティリティです。

ということで、これらを使って、

(defun foo (delta)
  (multiple-value-list
   (date-calc:add-delta-days 2011 4 4 delta)))

(defun every-monday (text)
  (letS* ((d (Erange 1 52)))
    (cons
     '("題名" "説明" "担当者" "開始日" "期限日" "予定工数")
     (Rlist
       (list
        #0=(format nil "~A ~{~A/~A/~A更新~}" text (foo (* 7 d)))
        #0#
        "鈴木"
        (format nil "~{~A~^/~}" (foo (- (* 7 d) 3)))
        (format nil "~{~A~^/~}" (foo (* 7 d)))
        "1")))))

のようなものを書き殴り。

#=と##はコピペ代わりに使えて殴り書きのようなものには便利に使えます。

動作の説明ですが、2011/4/4の次の週から1年分のエントリーを作成するというものです。

再利用を考えてプロジェクトを作成しているのにハードコードな部分がありますが気にしない方向で進みます。

上記のような内容を適当に作成したら、asdファイルをロードしてみます。

そもそも対話的に作っていたりするとロードする必要もなかったりしますが、なんとなくプロジェクトを作っているっぽいという気分の問題です。

asdファイルがASDFに捕捉されていれば、上記プロジェクトの場合、

(asdf:load-system :redmine-schedule)
;; もしくは、
(ql:quickload :redmine-schedule)

でロードできますが、うんともすんとも言わない場合は、めんどくさいので、

(load "/foo/bar/redmine-schedule/redmine-schedule.asd" )

と、asdファイルを直に読み込んでからロードすると、大抵は動きます (あくまでめんどくさい場合)

ロードができたら、上の関数を使ってタスクのエントリーのリストを作成し、それをfare-csvを使ってcsvファイルに書き出します。

(with-> "/tmp/foo.csv"
  (fare-csv:write-csv-lines (every-monday "腹筋") >))

これで

"題名","説明","担当者","開始日","期限日","予定工数"
"腹筋 2011/4/11更新","腹筋 2011/4/11更新","鈴木",2011/4/8,2011/4/11,1
"腹筋 2011/4/18更新","腹筋 2011/4/18更新","鈴木",2011/4/15,2011/4/18,1
"腹筋 2011/4/25更新","腹筋 2011/4/25更新","鈴木",2011/4/22,2011/4/25,1

というファイルができました。

とりあえず簡単にプロジェクトは作れるので、とりあえずASDFでプロジェクトを作成しておいて、また使いたいようなことがあればその時に改良、というのもありかなと思っている最近です。