anythingに魅かれてlisp始めました
Emacs歴約10年。
今までカンでlispをカスタマイズしていたが、Anythingを活用したくて、本格的にlispの勉強を始めました。
しかし良くカンだけでやってきたなぁと思ったり思わなかったり。
↓は約3年前にマニュアルを見つつ格闘した自作lisp。
C++のUnitTestをサポートするツール「河童」を更にサポートするためのlispです。
;;-*- emacs-lisp -*- ;; 河童プロジェクトの子馬/子河童サポートLisp ;; (defun cocuppa () "河童プロジェクトの子河童をサポートするLisp。 cocuppa --include *1 --skeleton *2 *3 *4 ....... インクルードファイル … *1に相当(複数指定可能) 作成クラス名 … *2 に相当。.cppはcocuppa側がつけるので、不要。 作成メソッド名 … *3、*4...に相当 " (interactive) (let ( include-files class-name method-names found) ;; include-filesの取得 (catch 'found (let (file-name) (while t (setq file-name (read-file-name "インクルードするファイル(RETのみで終了) : " "" "" t)) ;; 要マッチ (if (equal file-name "") (throw 'found t)) (setq include-files (concat include-files " --include ")) (setq include-files (concat include-files file-name))))) ;; 作成クラス名取得(何かを入力するまでは、抜けない) (catch 'found (let ( (now-buffer-name (buffer-name (current-buffer))) (default-name "") match-index) (if (string-match "^[^ ].*\\.cpp.*" now-buffer-name) (progn (setq match-index (string-match "\\.cpp" now-buffer-name)) (setq default-name (substring now-buffer-name 0 match-index)) (setq default-name (concat default-name "Test")) )) (while t (setq class-name (read-string "作成クラス名 : " default-name)) (if (not (equal class-name "")) (throw 'found t))))) ;; メソッドネームの取得 (catch 'found (let (m-name) (while t (setq m-name (read-string "作成メソッド名(RETのみで終了) : " "test")) (if (or (equal m-name "") (equal m-name "test")) (throw 'found t)) (setq method-names (concat method-names " " )) (setq method-names (concat method-names m-name))))) ;; cocuppa呼び出し (let ( (command-str "cocuppa " )) (if (not (equal include-files nil)) (progn (setq command-str (concat command-str include-files)) (setq command-str (concat command-str " ")))) (setq command-str (concat command-str " --skeleton ")) (setq command-str (concat command-str class-name)) (setq command-str (concat command-str " " )) (setq command-str (concat command-str method-names)) (call-process shell-file-name nil nil t shell-command-switch command-str)) ;; ファイルを開く (find-file (concat class-name ".cpp")) ) ;; let ) ;; defun (defun couma () "河童プロジェクトの子馬をサポートするLispです" (interactive) ; buffer-alist キー=ファイル名-.cpp : 値=バッファ名の連想配列 ; cuppa-class-name 子馬に渡すクラス名 ; cuppa-function-name 子馬に渡す関数名 ; b-name バッファ名 (let (buffer-alist cuppa-class-name cuppa-function-name b-name found ) ;; クラス名(ファイル名-.cpp) と バッファ名の連想リストを作成 (let (fname bname match-index (blist (buffer-list))) ; fname = ファイル名 : bname = バッファ名 (while blist (setq bname (buffer-name (car blist))) (setq fname (buffer-file-name (car blist))) (if (and fname ;; ファイルが存在する時のみ (string-match "^[^ ].*Test\\.cpp.*" bname )) ;; .cppバッファのみ対象にする (progn (setq match-index (string-match "\\.cpp" fname )) (if match-index (progn (let (cname) (setq cname (substring fname 0 match-index)) ; (setq class-names (cons cname class-names)) (if (not (assoc cname buffer-alist)) (setq buffer-alist (cons (list cname bname) buffer-alist)))))))) (setq blist (cdr blist)))) ;; クラス名の入力 (let ( (completion-ignore-case t)) (setq cuppa-class-name (completing-read "クラス: " buffer-alist nil t ))) ;; 初期値を後で入れる ; (setq cuppa-function-name (read-string "メソッド名: " "test")) ;;メソッド名の入力 (catch 'found (let (tmp-function-name) (while t (setq tmp-function-name (read-string "メソッド名: (RETのみで終了) : " "test")) (if (not (string-match "^test.+" tmp-function-name)) (throw 'found t)) (setq cuppa-function-name (concat cuppa-function-name " ")) (setq cuppa-function-name (concat cuppa-function-name tmp-function-name))))) ;; バッファ名を取得する (let ( tmp-list ) (setq tmp-list (assoc cuppa-class-name buffer-alist) ) (setq b-name (cdr tmp-list)) (setq b-name (car b-name)) ) ;; バッファが未セーブならば、問い合わせ後、セーブする (if (buffer-modified-p (get-buffer b-name)) (if (yes-or-no-p "ファイルを書き込みますか?") (save-excursion (set-buffer (get-buffer b-name)) (basic-save-buffer)) ) ) ;; couma呼び出し ; file-path-str /home/user/xxxx/FooTest の path部分(/home/user/xxxx/) ; class-name-str /home/user/xxxx/FooTest のクラス名部分 (FooTest) (let ( (class-str-index 0) (file-path-str "./") (class-name-str "") (command-str "")) (setq class-str-index (string-match "[^/]+$" cuppa-class-name)) (if (not (equal class-str-index nil)) (progn (setq file-path-str (substring cuppa-class-name 0 class-str-index)) ;; file-path-str 取得 (setq class-name-str (substring cuppa-class-name class-str-index nil)) ;; class-name-str 取得 )) ;; cd コマンド (setq command-str (concat command-str "cd ")) (setq command-str (concat command-str file-path-str)) (setq command-str (concat command-str "; ")) ;; couma コマンド (if (not (string= class-name-str "")) (progn (setq command-str (concat command-str "couma ")) (setq command-str (concat command-str "--skeleton ")) (setq command-str (concat command-str class-name-str)) ; (setq command-str (concat command-str cuppa-class-name)) (setq command-str (concat command-str cuppa-function-name)) (setq command-str (concat command-str ".")) ;;関数名の直後に'.'をつけると、メソッドの定義位置をクラスの外に変更出来る (call-process shell-file-name nil nil t shell-command-switch command-str) )) ) ;; ;; バッファを新しいファイルに更新 (if (not (buffer-modified-p (get-buffer b-name))) (save-excursion (set-buffer (get-buffer b-name)) (find-alternate-file (concat cuppa-class-name ".cpp") ))) ) )