トップ «前の日記(2011年11月30日) 最新 次の日記(2011年12月26日)» 編集

Masa's blog

検索キーワード:

2011年12月22日 emacs lisp儂(わし)的解釈によるメモ [長年日記]

_ emacs lisp儂(わし)的解釈によるメモ

いつかはMewのようなプログラムを組めるようになりたい。

でも当面は、ちょっとしたemacsの拡張と、emacsが常時起動しているzaurus上で便利プログラムが組めるように...。

elisp scriptの実行の仕方

$ emacs --script hoge.el 引数1 引数2 ...

エディタ内での実行の仕方

M-x load-file hoge.el

emacs lispを書いてみる

;
; 文字列を標準出力に出力する。
;
(princ "Hello World!\n")
;
; コマンドライン引数は変数`argv'にリスト形式 '(foo bar hoge) で格納される。
; 引数の1個目を取り出す。
;
(nth 0 argv)	; 0オリジン
;
; リストの先頭要素の取り出し。
;
(car argv)
;
; リストから先頭要素を除いた残りのリストの取得。
;
(cdr argv)
;
; リストの先頭に新たな要素を追加したリストを取得
;
(cons '10 argv)
;
; リストとリストを結合したリストを取得
;
(append '(foo bar boo) '(FOO BOO BAR))
;
; 変数へ値の代入
;
(setq i '10)
;
; リストの要素数を取得する
;
(length argv)
;
; 引数を元にループ処理を行ってみる(1)。
;
(while argv
       (setq arg (car argv))

	; argを使った処理

       (setq argv (cdr argv))
)
;
; 引数を元にループ処理を行ってみる(2)。
;
(while (> (length argv) 0)
       (setq arg (car argv))

	; argを使った処理

       (setq argv (cdr argv))
)
;
; ファイルをバッファに読み込み、そのバッファを編集対象にする。
;
(find-file "hoge.txt")
;
; バッファの指定した文字位置にカーソルを位置付ける。
;
(goto-char '10)		; 10文字目に位置付ける
(goto-char (point-min))	; 先頭に位置付ける
(goto-char (point-max))	; 末尾に位置付ける
;
; 指定した行数目に位置付ける。
;
(goto-line '10)		; 10行目の先頭に位置付ける
;
; バッファの現在行の先頭に位置付ける。
;
(beginning-of-line)
;
; バッファの現在行の末尾に位置付ける。
;
(end-of-line)
;
; 指定した行数カーソルを移動する。
;
(forward-line '3)	; 3行進む
(forward-line '-3)	; 3行戻る
;
; 文字列を検索し位置付ける
;
(search-forward "hogehoge")	; hogehoge の直後に位置付ける
;
; 正規表現で文字列を検索し位置付ける
;
(re-search-forward "ho.*ge")
;
; 指定した文字数進める
;
(forward-char '10)	; 10文字進む
(forward-char '-10)	; 10文字戻る
;
; バッファの行数を数える。
;
(count-lines (point-min) (point-max))	; 全体の行数を得る
;
; バッファに文字列を挿入する。
;
(insert "hogegoge")
;
; 検索した文字列を置き換える
;
(search-forward "hoge")		; hoge を検索し、
(replace-match "fuga")		; fuga に置き換える
;
; 指定した個数の文字を削除する
;
(delete-char '5)	; 5文字削除する
;
; 指定した行数削除する
;
(kill-line 5)		; 5行削除する
;
; 正規表現で置き換える
;
(replace-regexp "^" "#")	; 行の先頭を # に置き換える
;
; マークを付ける
;
(set-mark-command)
;
; リージョンを削除する
;
(delete-region)
;
; バッファの内容を得る
;
(buffer-string)
;
; バッファを保存する。
;
(save-buffer)
;
; ローカル変数を利用する
;
(let ((i)	; ローカル変数 iの定義
      (j '10))	; ローカル変数 jの定義し、10に初期化

	ローカル変数の有効範囲

)
;
; バッファを1行づつ取り出して表示する。
;
(let    ((maxline) (line) (p1) (p2))
        (setq maxline (count-lines (point-min) (point-max)))
        (setq line '1)
        (while (<= line maxline)

               (goto-line line)
               (beginning-of-line)
               (setq p1 (point))			; 現在位置(point)を p1 に設定
               (end-of-line)
               (setq p2 (point))			; 現在位置(point)を p2 に設定
               (princ (buffer-substring p1 p2))	; バッファから部分文字列を取得
               (princ "\n")

               (setq line (+ 1 line))
        )
)
;
; 現在位置を憶えておいて、元に戻す
;
(save-excursion
  (カーソルを動かす操作)
)
;
; 標準入力から1行読み込む
;
(read-string "Please input:")	; "Please input:"と表示してから、入力する
(read-string "")		; 表示無しに入力する
;
; 標準入力から1文字読み込む。
;
(read-char)
;
; 文字列を編集する
;
(format "int = %d, float = %f, string = %s\n" 123 123.45 "poipoi")
;
; 日時を表す文字列を編集する
;
(format-time-string "%Y/%m/%d(%a) %H:%M:%S") ; 2012/01/29(日) 22:22:42
;
; 何日後とかの日時を表す文字列を編集する
;
(format-time-string "%Y/%m/%d(%a) %H:%M:%S" (encode-time 40 50 0 32 1 2012)) ; 2012/01/32 00:50:40 は 2012/02/01(水) 00:50:40
;
; 文字列の連結
;
(concat "abc " "def " "ghi")
;
; 文字列の取り出し
;
(substring "abcdefg" 2 5)	; => cde
;
; 文字列の分割
;
(split-string "abc\tdef\tghi" "\t")	; "abc\tdef\tghi" を "\t" で分割したリストを返す
;
; 文字列から数値へ変換
;
(string-to-number "123")
;
; 文字列を小文字に変更
;
(downcase "AbCdEfG")	; => abcdefg
;
; 文字列を大文字に変更
;
(upcase "AbCdEfG")	; => ABCDEFG
;
; 文字列から文字列検索
;
(setq str "abcDEFghiDEFjkl")
(string-match "DEF" str)	; strから"DEF"を検索し、その位置を返す
(string-match "DEF" str 4)	; strの4文字目以降から"DEF"を検索し、その位置を返す
;
; 文字列中の正規表現文字列を置換
;
(setq str "abcdefghijk")
(replace-regexp-in-string "d.*h" "-del-" str)	; str中の"d.*h"を"-del-"に置換した文字列を返す
;
; 複数の関数を一つのブロックにまとめる
;
(progn
	(princ "hoge")
	(princ "fuga")
)
;
; 条件式(数値)
;
(setq var1 10)

;(if (/= var1 10)			; var1 は 10 に等しくない
;(if (> var1 10)			; var1 は 10 より大きい
;(if (>= var1 10)			; var1 は 10 以上
;(if (< var1 10)			; var1 は 10 より小さい
;(if (<= var1 10)			; var1 は 10 以下
(if (= var1 10)				; var1 は 10 に等しい
	(progn
		(princ "true1")
		(princ "\n")
	)
	(progn
		(princ "false1")
		(princ "\n")
	)
)
;
; 条件式(文字列)
;
(setq var1 "poipoi")

;(if (string< var1 "poipoi")		; var1 は "poipoi" より小さい
;(if (string-match var1 "^poipoi$")	; var1 は "^poipoi$"(正規表現)にマッチする
(if (string= var1 "poipoi")		; var1 は "poipoi" に等しい
	(progn
		(princ "true1")
		(princ "\n")
	)
	(progn
		(princ "false1")
		(princ "\n")
	)
)
;
; 関数の定義(非対話型)
;
(defun foo (p1 p2 p3)			; 引数は p1 p2 p3
	"説明文"
	(let ((i) (j) (k))		; ローカル変数 i j k

					; 関数の主処理

	)
)
;
; 関数の定義(対話型)
;
(defun foo (p1 p2 p3)			; 引数は p1 p2 p3
	"説明文"
	(interactive "sp1:\nsp2\nsp3")	; メッセージ領域に順番に表示する入力ガイダンス(\nで区切る)
					; "sp1:" は 文字列パラメータで、ガイダンスが "p1:" の意味
; 	(interactive "np1:\nnp2\nnp3")	; メッセージ領域に順番に表示する入力ガイダンス(\nで区切る)
					; "np1:" は 数値パラメータで、ガイダンスが "p1:" の意味
; 	(interactive "bp1:\nbp2\nbp3")	; メッセージ領域に順番に表示する入力ガイダンス(\nで区切る)
					; "bp1:" は 既存バッファパラメータで、ガイダンスが "p1:" の意味
; 	(interactive "Bp1:\nBp2\nBp3")	; メッセージ領域に順番に表示する入力ガイダンス(\nで区切る)
					; "Bp1:" は バッファパラメータで、ガイダンスが "p1:" の意味
; 	(interactive "fp1:\nfp2\nfp3")	; メッセージ領域に順番に表示する入力ガイダンス(\nで区切る)
					; "fp1:" は 既存ファイルパラメータで、ガイダンスが "p1:" の意味
; 	(interactive "Fp1:\nFp2\nFp3")	; メッセージ領域に順番に表示する入力ガイダンス(\nで区切る)
					; "Fp1:" は ファイルパラメータで、ガイダンスが "p1:" の意味
; 	(interactive "Dp1:\nDp2\nDp3")	; メッセージ領域に順番に表示する入力ガイダンス(\nで区切る)
					; "Dp1:" は ディレクトリパラメータで、ガイダンスが "p1:" の意味
	(let ((i) (j) (k))		; ローカル変数 i j k

					; 関数の主処理

	)
)
;
; 同期コマンド起動
;
(setq program "/bin/sh")
(setq infile nil)
(setq destination "buffer-stdout-stderr")
(setq display nil)  ; t だと destinationで指定したバッファを即時に書き換える。
(setq exit_status (call-process program infile destination display "-c" "ls -al | egrep hogehoge"))
;
; 非同期コマンド起動
;
(setq name "process name")
(setq destination "buffer-stdout-stderr")
(setq program "/bin/sh")
(setq process-object (start-process name destination program "-c" "ls -al | egrep hogehoge"))
;
; 非同期コマンドの標準入力へデータを渡す
;
(process-send-string "process name" "String of input date\n")
;
; 非同期コマンドの標準入力へEOFを渡す
;
(process-send-eof "process name")
;
; 非同期プロセスの状態変化を知る
;
(set-process-sentinel (get-process "process name") 'get-status)
(defun get-status (process event)
  (princ (format "Process: %s had the event `%s'" process event))
)

スクリプトの実装(サンプル その1)

emacs(lisp)をフィルタプログラムとして利用するための足掛かり。

;
; フイルタ処理の雛型
;
; 標準入力を一行読み込んで、一時バッファに挿入し、
; バッファ上で何らかの編集を加えた後に、標準出力
; に出力する。以上の動作をEOFまで繰り返す。
;
(defun edit-buffer ()
        "Edit buffer."

	; 編集処理

)

(defun print-buffer ()
        "Print buffer."
        (princ (buffer-string))
        (princ "\n")
)

(with-temp-buffer			; 一時バッファの利用
        (condition-case nil		; エラーシグナル(EOF)のハンドリングを指定
                (let (line)
                        (while (setq line (read-string ""))
                                (erase-buffer)
                                (insert line)

                                (edit-buffer)

                                (print-buffer)
                        )
                )
                (error nil)		; エラートラップ処理
        )
)

emacsをプチ機能拡張してみる(サンプル その2)

ちょっとした便利関数を実装してみる。

;
; 対話処理の関数定義(指定したリージョンの先頭に`#'を挿入する)
;
(defun insert-sh-comment (point mark)
	"Insert shell style comment into region."
	(interactive "r")		; リージョン(point mark)を引数にセットする
	(let ((min) (max))
		(if (> point mark)
			(progn
				(setq min mark)
				(setq max point)
			)
			(progn
				(setq min point)
				(setq max mark)
			)
		)
		(goto-char min)
		(while (> max (point))
			(beginning-of-line)
			(insert "#")
			(forward-line)
		)
	)
)

command-menu.el(サンプル その3)

コマンドランチャ的なものを実装してみた。

;;
;; コマンド起動メニュー (command-menu)
;;
;------------------------------------------------------------
; 関数定義
;------------------------------------------------------------
;
; メニュー表示
;
(defun insert-menu (menu x y)
  "insert menu into buffer."
  (interactive)
  (let ((line)
        (col))
    (erase-buffer)

    (setq line '1)
    (while (< line y)
      (insert "\n")
      (setq line (+ line 1))
    )

    (setq line '1)
    (while (<= line (length menu))
      (setq col '1)
      (while (< col x)
        (insert " ")
        (setq col (+ col 1))
      )

      (insert (get-menu-char menu line)) (insert ": ")
      (insert (get-menu-title menu line)) (insert "\n")
      (setq line (+ line 1))
    )

    (goto-char (point-min))
    (forward-line (- y 1))
    (forward-char (- x 1))
  )
)
;
; num番目のコマンド起動文字を取得
;
(defun get-menu-char (menu num)
  "get char from menu."
  (interactive)
  (let ()
    (nth 0 (nth (- num 1) menu))
  )
)
;
; num番目のタイトルを取得
;
(defun get-menu-title (menu num)
  "get title from menu."
  (interactive)
  (let ()
    (nth 1 (nth (- num 1) menu))
  )
)
;
; num番目の標準出力の出力先バッファ名取得
;
(defun get-menu-buffer (menu num)
  "get buffer from menu."
  (interactive)
  (let ()
    (nth 2 (nth (- num 1) menu))
  )
)
;
; コマンド起動文字より標準出力の出力先バッファ名取得
;
(defun get-menu-buffer-by-char (menu char)
  "get buffer by char from menu."
  (interactive)
  (let ((endsw "off")
        (line '1)
        (buffer nil))

    (while (and (<= line (length menu))
                (string= endsw "off"))
      (if (string= char (get-menu-char menu line))
        (progn
          (setq buffer (get-menu-buffer menu line))
          (setq endsw "on")
        )
      )
      (setq line (+ line 1))
    )
    buffer
  )
)
;
; num番目のコマンド取得
;
(defun get-menu-command (menu num)
  "get command from menu."
  (interactive)
  (let ()
    (nth 3 (nth (- num 1) menu))
  )
)
;
; コマンド起動文字よりコマンド取得
;
(defun get-menu-command-by-char (menu char)
  "get command by char from menu."
  (interactive)
  (let ((endsw "off")
        (line '1)
        (command nil))

    (while (and (<= line (length menu))
                (string= endsw "off"))
      (if (string= char (get-menu-char menu line))
        (progn
          (setq command (get-menu-command menu line))
          (setq endsw "on")
        )
      )
      (setq line (+ line 1))
    )
    command
  )
)
;------------------------------------------------------------
; 主処理定義
;------------------------------------------------------------
;
; コマンド起動メニューを起動する
;
(defun command-memu ()
  "This is command-menu."
  (interactive)

  (let ((menu)
        (buffer)
        (menu-x)
        (menu-y)
        (cnt)
        (endsw)
        (ks)
        (kss))
;
; メニューの定義
;
;   (1) 起動ショートカット文字(1文字)
;   (2) メニューに表示するタイトル
;   (3) 起動コマンドの標準出力を吐き出すバッファ名
;   (4) 起動コマンド文字列(sh -c への引数)
;
    (setq menu-x '20)
    (setq menu-y '5)
    (setq menu '(
  	          ("L" "ls"    "buffer-ls"    "ls -alrt")
  	          ("D" "date"  "buffer-date"  "date")
  	          ("X" "xeyes" "buffer-xeyes" "xeyes")
                )
    )
;
; バッファ名定義
;
    (setq buffer "buffer-command-menu")
;
; 制御文字定義
;
    (setq C-g "\007")
    (setq C-m "\015")

; バッファ作成
    (get-buffer-create buffer)
; カレントバッファに設定
    (set-buffer buffer)
; バッファを画面に表示
    (switch-to-buffer (get-buffer buffer))

; バッファに書き込み保護をかける
    (setq buffer-read-only t)

; 一時的に書き込み保護を外す
    (let ((buffer-read-only nil))

; メニュー表示
      (insert-menu menu menu-x menu-y)

      (setq cnt '1)
      (setq endsw "off")
      (while (string= endsw "off")

; 一文字取得
        (setq ks (read-key-sequence ""))
        (setq kss (format "%s" ks))

        (condition-case nil
          (let ()
; [↑]処理
            (if (string= kss "[up]")
              (progn
                (if (> cnt 1)
                  (progn
                    (next-line -1)
                    (setq cnt (- cnt 1))
                  )
                )
              )
            )

; [↓]処理
            (if (string= kss "[down]")
              (progn
                (if (< cnt (length menu))
                  (progn
                    (next-line 1)
                    (setq cnt (+ cnt 1))
                  )
                )
              )
            )

; ショートカットキー処理
            (if (get-menu-command-by-char menu kss)
              (progn
                (call-process "sh" nil (get-menu-buffer-by-char menu kss) nil "-c" (get-menu-command-by-char menu kss))
              )
            )

; エンターキー処理
            (if (string= kss C-m)
              (progn
                (call-process "sh" nil (get-menu-buffer menu cnt) nil "-c" (get-menu-command menu cnt))
              )
            )

; 終了キー処理
            (if (or (string= kss C-g)
                    (string= kss "Q"))
              (progn
                (setq endsw "on")
              )
            )
          )
          (error nil)
        )
      )
      (goto-char (point-max))
      (insert "\n終了\n")
    )
  )
)

emacs lispのお勉強を初めて1週間弱の人間が作ったとしてはまあまあかと思う。

が、実はこれは使い物にはならない。なぜなら、ESC-x command-menu すると、emacsを占有してこのlispプログラムが動いてしまうので、emacsでそれ以外の事が出来なくなってしまう。

イメージ的には、C-x bとかで他のバッファに切替えたり出来るような作りにするべきなのだが、根本的に考え直さないといけないようだ。

まあ、実用にはならないが、ある程度まとまった機能を実装できたので良とするか...。

メジャーモード(サンプル その4)

優しい Emacs-Lisp 講座からの引き写しだが...

;;;
;;; メジャーモードの作成関数(washi-mode.el)
;;;
(defun washi-mode ()

;; 対話モード関数の宣言
  (interactive)

;; メジャーモードのシンボルを定義
  (setq major-mode 'washi-mode)

;; メジャーモードの名称を定義
  (setq mode-name "Washi mode")

;; メジャーモード内だけで有効なキーマップを定義
  (setq washi-mode-map (make-keymap))

;; 上記のキーマップ内に独自のキー割当を定義
  (define-key washi-mode-map "h" 'backward-char)
  (define-key washi-mode-map "j" 'next-line)
  (define-key washi-mode-map "k" 'previous-line)
  (define-key washi-mode-map "l" 'forward-char)
  (define-key washi-mode-map "\C-ch" 'hello-world)

;; 上記のキーマップを利用する事を宣言
  (use-local-map washi-mode-map))

;;;
;;; こんにちわ関数
;;;
(defun hello-world ()
  (interactive)
  (insert "Hello, world!\n"))

command-menu.el 再び(サンプル その5)

emacs lisp歴3週間の儂(わし)が、コマンドランチャ的な物を再実装。今度はemacsを独占する事無く機能する。

  • そこはかとなく漂うCOBOL的コーディング
  • 閉じ括弧`)'の位置が独特

な事(、その他本物のlisperには当然の御作法を無視している点)には目をつぶってくれ。

;;;
;;; command-menu.el (コマンドランチャ機能)
;;;
;;; 起動方法
;;;
;;;   M-x load-file command-menu.el
;;;   M-x command-menu
;;;
;;; 操作方法 (1)または(2)
;;;
;;;   (1) [up][down]キーでカーソルを位置付けて、[ENTER]を入力
;;;   (2) 各メニュー行の先頭に表示されている[起動ショートカット文字]を入力
;;;
;;============================================================
;; 大局変数の定義
;;============================================================
;;
;; メニューの定義
;;
;;   1行目
;;     (1) COLMUN位置
;;     (2) LINE位置
;;   2行目以降
;;     (1) 起動ショートカット文字(1文字)
;;     (2) メニューに表示するタイトル
;;     (3) 起動コマンドの標準出力を吐き出すバッファ名
;;     (4) 起動コマンド文字列(sh -c への引数)
;;
(defvar command-menu-list
  '(
     (20 5)
     ("L" "ls"    "buffer-ls"    "ls -alrt")
     ("D" "date"  "buffer-date"  "date")
     ("X" "xeyes" "buffer-xeyes" "xeyes")
  )
)
;;
;; メニューの現在位置付けられている番号
;;
(defvar command-menu-number '1)

;;============================================================
;; 関数定義
;;============================================================
;;------------------------------------------------------------
;; command-menuモード
;;------------------------------------------------------------
(defun command-menu ()
  "execute command-menu mode"
;; 対話モード関数の宣言
  (interactive)

  (let ((buffer)
        (number))

;;
;; バッファ設定
;;

;; バッファ名定義
    (setq buffer "buffer-command-menu")
;; バッファ作成
    (get-buffer-create buffer)
;; カレントバッファに設定
    (set-buffer buffer)
;; バッファを画面に表示
    (switch-to-buffer (get-buffer buffer))

;;
;; メジャーモード設定
;;

;; メジャーモードのシンボルを定義
    (setq major-mode 'command-menu-mode)
;; メジャーモードの名称を定義
    (setq mode-name "command-menu")
;; メジャーモード内だけで有効なキーマップを定義
    (setq command-menu-mode-map (make-keymap))
;; 上記のキーマップ内に独自のキー割当を定義
    (define-key command-menu-mode-map [up] 'command-menu-up)
    (define-key command-menu-mode-map [down] 'command-menu-down)
    (define-key command-menu-mode-map "\C-M" 'command-menu-exec)
    (define-key command-menu-mode-map "q" 'command-menu-quit)
    (setq number '1)
    (while (<= number (command-menu-get-length))
      (define-key command-menu-mode-map (command-menu-get-char number) 'command-menu-exec-by-char)
      (setq number (+ number 1))
    )
;; 上記のキーマップを利用する事を宣言
    (use-local-map command-menu-mode-map)

;;
;; その他の処理
;;

;; バッファに書き込み保護をかける
    (setq buffer-read-only t)

;; 一時的に書き込み保護を外す
    (let ((buffer-read-only nil))
;; メニュー表示
      (command-menu-insert)
    )
  )
)
;;------------------------------------------------------------
;; メニュー表示
;;------------------------------------------------------------
(defun command-menu-insert ()
  "insert menu into buffer."
  (interactive)
  (let ((line)
        (number)
        (col))
    (erase-buffer)

    (setq line '1)
    (while (< line (command-menu-get-y))
      (insert "\n")
      (setq line (+ line 1))
    )

    (setq number '1)
    (while (<= number (command-menu-get-length))
      (setq col '1)
      (while (< col (command-menu-get-x))
        (insert " ")
        (setq col (+ col 1))
      )

      (insert (command-menu-get-char number)) (insert ": ")
      (insert (command-menu-get-title number)) (insert "\n")
      (setq number (+ number 1))
    )

    (command-menu-goto-current)
  )
)
;;------------------------------------------------------------
;; メニュー位置付け処理
;;------------------------------------------------------------
(defun command-menu-goto-current ()
  "goto current menu position"
  (interactive)
  (let ()
    (goto-line (- (+ command-menu-number (command-menu-get-y)) 1))
    (forward-char (- (command-menu-get-x) 1))
  )
)
;;------------------------------------------------------------
;; menuの登録件数を取得
;;------------------------------------------------------------
(defun command-menu-get-length ()
  "get length from menu."
  (interactive)
  (let (ret)
    (setq ret (- (length command-menu-list) 1))
    ret
  )
)
;;------------------------------------------------------------
;; menuのx位置取得
;;------------------------------------------------------------
(defun command-menu-get-x ()
  "get x position of menu."
  (interactive)
  (let (ret)
    (setq ret (nth 0 (nth 0 command-menu-list)))
    ret
  )
)
;;------------------------------------------------------------
;; menuのy位置取得
;;------------------------------------------------------------
(defun command-menu-get-y ()
  "get y position of menu."
  (interactive)
  (let (ret)
    (setq ret (nth 1 (nth 0 command-menu-list)))
    ret
  )
)
;;------------------------------------------------------------
;; num番目のコマンド起動文字を取得
;;------------------------------------------------------------
(defun command-menu-get-char (num)
  "get char from menu."
  (interactive)
  (let (ret)
    (setq ret (nth 0 (nth num command-menu-list)))
    ret
  )
)
;;------------------------------------------------------------
;; num番目のタイトルを取得
;;------------------------------------------------------------
(defun command-menu-get-title (num)
  "get title from menu."
  (interactive)
  (let (ret)
    (setq ret (nth 1 (nth num command-menu-list)))
    ret
  )
)
;;------------------------------------------------------------
;; num番目の標準出力の出力先バッファ名取得
;;------------------------------------------------------------
(defun command-menu-get-buffer (num)
  "get buffer from menu."
  (interactive)
  (let (ret)
    (setq ret (nth 2 (nth num command-menu-list)))
    ret
  )
)
;;------------------------------------------------------------
;; num番目のコマンド取得
;;------------------------------------------------------------
(defun command-menu-get-command (num)
  "get command from menu."
  (interactive)
  (let (ret)
    (setq ret (nth 3 (nth num command-menu-list)))
    ret
  )
)
;;------------------------------------------------------------
;; コマンド起動文字より何番目のメニュー項目か取得
;;------------------------------------------------------------
(defun command-menu-get-number-by-char (char)
  "get number by char from menu."
  (interactive)
  (let ((endsw "off")
        (number '1)
        (ret))

    (while (and (<= number (command-menu-get-length))
                (string= endsw "off"))
      (if (string= char (command-menu-get-char number))
        (progn
          (setq ret number)
          (setq endsw "on")
        )
      )
      (setq number (+ number 1))
    )
    ret
  )
)
;;------------------------------------------------------------
;; コマンド起動文字より標準出力の出力先バッファ名取得
;;------------------------------------------------------------
(defun command-menu-get-buffer-by-char (char)
  "get buffer by char from menu."
  (interactive)
  (let ((ret))
    (setq ret (command-menu-get-buffer (command-menu-get-number-by-char char)))
    ret
  )
)
;;------------------------------------------------------------
;; コマンド起動文字よりコマンド取得
;;------------------------------------------------------------
(defun command-menu-get-command-by-char (char)
  "get command by char from menu."
  (interactive)
  (let ((ret))
    (setq ret (command-menu-get-command (command-menu-get-number-by-char char)))
    ret
  )
)
;;------------------------------------------------------------
;; [↑]
;;------------------------------------------------------------
(defun command-menu-up ()
  "[up] handle"
  (interactive)
  (let ()
    (if (> command-menu-number 1)
      (progn
        (setq command-menu-number (- command-menu-number 1))
        (command-menu-goto-current)
     )
    )
  )
)
;;------------------------------------------------------------
;; [↓]処理
;;------------------------------------------------------------
(defun command-menu-down ()
  "[down] handle"
  (interactive)
  (let ()
    (if (< command-menu-number (command-menu-get-length))
      (progn
        (setq command-menu-number (+ command-menu-number 1))
        (command-menu-goto-current)
      )
    )
  )
)
;;------------------------------------------------------------
;; C-M 処理
;;------------------------------------------------------------
(defun command-menu-exec ()
  "C-M handle"
  (interactive)
  (let ()
;; 同期起動
;;    (call-process "/bin/sh" nil (command-menu-get-buffer command-menu-number) nil "-c" (command-menu-get-command command-menu-number))

;; 非同期起動
    (start-process (command-menu-get-title command-menu-number) (command-menu-get-buffer command-menu-number) "/bin/sh" "-c" (command-menu-get-command command-menu-number))
  )
)
;;------------------------------------------------------------
;; 起動文字 処理
;;------------------------------------------------------------
(defun command-menu-exec-by-char ()
  "execute char handle"
  (interactive)
  (let ((char))
    (with-temp-buffer
      (self-insert-command 1)
      (setq char (buffer-string))
    )
    (setq command-menu-number (command-menu-get-number-by-char char))
    (command-menu-goto-current)
    (command-menu-exec)
  )
)
;;------------------------------------------------------------
;; 終了 処理
;;------------------------------------------------------------
(defun command-menu-quit ()
  "kill buffers and quit"
  (interactive)
  (let ((num '1))
    (while (<= num (command-menu-get-length))
      (if (get-buffer (command-menu-get-buffer num))
        (progn
          (kill-buffer (command-menu-get-buffer num))
        )
      )
      (setq num (+ num 1))
    )
    (kill-buffer)
  )
)

C-xBでバッファを次々に切替える(サンプル その6)

(global-set-key "\C-xB" 'switch-to-next-buffer)
(defun switch-to-next-buffer ()
       "switch to next buffer"
       (interactive)
       (let ((buffer))
            (setq buffer (other-buffer))
            (switch-to-buffer buffer)  ; バッファを`buffer'に切替える
            (bury-buffer buffer)       ; `buffer'の(other-buffer)で選択される優先度を最も低くなるように(buffer-list)を作り直す
       )
)

タイマー起動

2012年1月13日 13:09:00(JST-9)に関数`insert'を引数"POIPOI\n"で起動する。

(setq timer (run-at-time "13:09:00 JST-9 01/13/2012" nil 'insert "POIPOI\n"))

2012年1月13日 13:09:00(JST-9)に関数`insert'を引数"POIPOI\n"で5秒おきに起動する。

(setq timer (run-at-time "13:09:00 JST-9 01/13/2012" 5 'insert "POIPOI\n"))

13:09:00に関数`insert'を引数"POIPOI\n"で起動する。

(setq timer (run-at-time "13:09:00" nil 'insert "POIPOI\n"))

1分後に関数`insert'を引数"POIPOI\n"で起動する。

(setq timer (run-at-time "1 min" nil 'insert "POIPOI\n"))

タイマーをキャンセルする。

(cancel-timer timer)

メッセージを指定時間だけ別ウインドウに表示する(サンプル その7)

;;;
;;; Usage
;;;
;;;   (popup-window-open "hello\nWorld\n" "2 sec")
;;;   (popup-window-open "hello\nWorld\n" "")        ; show forever
;;;
(defvar popup-window-buffer-name "popup-window-buffer")
;;------------------------------------------------------------
;; バッファとそれを表示しているウインドウを破壊
;;------------------------------------------------------------
(defun popup-window-kill (buffer)
  "kill window by buffer"
  (interactive)
  (let ()
    (save-current-buffer
      (set-buffer buffer)
      (kill-buffer-and-window)
    )
  )
)
;;------------------------------------------------------------
;; 指定した文字列(string)を、指定した時間(time)別ウインドウで表示
;;------------------------------------------------------------
(defun popup-window-open (string time)
  "popup window with string in time"
  (interactive)
  (let ((window))
    (get-buffer-create popup-window-buffer-name)
    (save-current-buffer
      (set-buffer popup-window-buffer-name)
      (insert string)
    )
    (set-window-buffer (split-window-vertically) popup-window-buffer-name)
    (if (string= time "")
      (progn
      )
      (progn
	 (run-at-time time nil 'popup-window-kill popup-window-buffer-name)
      )
    )
  )
)

画像ファイル名の一覧をサムネイル付きのHTMLリンクに編集する(サンプル その8)

(defun pic2link-search (re)
  "search and return \"OK\" or \"NG\""
  (interactive)
  (let ((ret "OK"))
    (condition-case nil
      (progn
        (re-search-forward re)
      )
      (error (setq ret "NG"))
    )
    ret
  )
)

(defun pic2link (re)
  "convert picture name to link thumbnail"
  (interactive "sREGEXP:")
  (let ()
    (while (string= (pic2link-search re) "OK")
      (replace-match
        (format
          "<a href=\"%-s\"><img src=\"%-s_thumb%-s\"></a>"
          (match-string 0) (match-string 1) (match-string 2)
        )
        t
      )
    )
  )
)

例えば以下のようなファイルがあったとして、

P12345.JPG
P12334545.JPG
P1233553545.JPG
P1233545.JPG
P1237345.JPG
P1234747345.JPG
P1234545.JPG

以下のように入力すると、

M-x load-file
pic2link.el
M-x pic2link
REGEXP:\(P[0-9]*\)\(.JPG\)

このような結果になる。

<a href="P12345.JPG"><img src="P12345_thumb.JPG"></a>
<a href="P12334545.JPG"><img src="P12334545_thumb.JPG"></a>
<a href="P1233553545.JPG"><img src="P1233553545_thumb.JPG"></a>
<a href="P1233545.JPG"><img src="P1233545_thumb.JPG"></a>
<a href="P1237345.JPG"><img src="P1237345_thumb.JPG"></a>
<a href="P1234747345.JPG"><img src="P1234747345_thumb.JPG"></a>
<a href="P1234545.JPG"><img src="P1234545_thumb.JPG"></a>

行儀の良いemacs lispファイル

ロードされるファイル(foo.el)の末尾辺りに、

(provide 'foo)

が記述されている。呼び出し側は、

(require 'foo)

と呼び出す。検索パスは変数 load-path にリストとして設定する。

(load "foo.el")

と同じ効果だが、requireの方は既に読み込まれているファイルは読み込まないので効率的らしい。