なんだこれは

はてなダイアリーから移転しました。

いろいろあって、cclでつくりなおすことにした。

subversion の verbose log (xml形式) をよんで、各ファイル毎にユーザーを集計するお手軽ツールをperlでつくった。
しかし、perlなどのスクリプトは、Windosでは使いにくいといういわれのない中傷をうけたので、cclで作りなおすことにした。

一応par::packerもためしたんだけど、うまくいかなかった。

これなら、Windowsでもバイナリがつくれるはず、だよね。


これなら、Windowsでもバイナリがつくれるはず、だよね。

(ql:quickload :cl-ppcre) ;;perl 互換正規表現ライブラリ

(defparameter *pathdb* (make-hash-table :test #'equal))
(defparameter *excludes* '("osamu_dazai" "foo_bar"))
(defparameter *replacement* '(("retired" . "newcommer")
			      ("early_bird" . "worms")))

;;; よく使用するマクロ
(defmacro while (test &body body)
  `(do ()
       ((not ,test))
     ,@body))
;;; 正規表現にマッチしたもの(レジスタ)のうち最初のものを文字列で返す
(defun my-regexp-match (regexp line)
  "return first registered string related with regexp in line"
  (ppcre:register-groups-bind (a)
      (regexp line)
    a))

;;; 行を判定する述語
(defun entry-end-p (line)
  "return wheather if the line is end of logentry where author and path are set nil"
  (search "</logentry>" line))

(defun author-line-p (line)
  "return wheather if the line is author line where author value exist"
  (search "<author>" line))

(defun path-line-p (line)
  "return wheather if the line is end of path line where path value exist"
  (search "</path>" line))

(defun author-from-line (line)
  "return author value from line"
  (my-regexp-match "<author>([-.\"_0-9a-zA-Z/]+)</author>" line))

(defun path-from-line (line)
  "return path value from line"
  (my-regexp-match ">([-.\"_0-9a-zA-Z/]+)</path>" line))

(defun register-author (path author db)
  "add author into hash table related path in db"
  (if (gethash path db)
      (push author (gethash path db))
      (setf (gethash path db) (cons author ()))))


(defun read-each-line (file db)
  (with-open-file (stream file :direction :input)
    (let ((line nil)
	  (author nil))
      (while (setf line (read-line stream nil))
	(let ((a (author-from-line line))
	      (path (path-from-line line)))
	  (cond (a (setf author a))
		(path (when author
			(register-author path author db)))
		((entry-end-p line) (progn
				      (setf path nil)
				      (setf author nil)))))))))

(defun remove-non-developer (lst db)
  "replace db to remove non developpers account in the given list"
  (loop for x being the hash-keys in db 
       do (loop for y in lst
	     do (setf (gethash x db) (remove y (gethash x db)))))) 

(defun replace-retires (alist db)
  "replace db to replace retire by new commer accont in the given alist"
  (loop for x being the hash-keys in db 
       do (loop for switch in alist 
	     do (setf (gethash x db) (substitute (cdr switch) (car switch) (gethash x db)))))) 

(defun dump-db (db)
  "dump contents of the given database"
  (loop for x being the hash-keys in db
       do (progn
	    (format t "~a" x)
	    (format t "~{#\Tab~a~}~%" (gethash x db)))))

あとは、read-each-line 関数や、dump-db 関数を呼びだすmain関数をかけば...
とおもったんだけれど、設定をいじるたびにコンパイルしなおさなきゃいけない作りになっていたので作業をストップ。

実行時の引数でファイルを読み込めばいいんだろうけど、もっとこう、モダンな設定ファイルの読み込ませ方みたいなのがわからなかった。