読者です 読者をやめる 読者になる 読者になる

KOYAMA Yoshiaki のブログ

プログラミングについての試行錯誤をつらつら書き溜めていきます。

GNU Emacs、Emacs Lisp 版 Minesweeper、Cocoa Emacs 日本語表示

プログラム mac lisp Emacs

最初に Emacs に触れたのは学生時代購入した X68000 上の Micro Emacs です。もしかしたら Sun のワークステーションの方が早かったかもしれません。インターネットもない時代だったので、本屋で立ち読みしたり、少ない小遣いで購入した書籍で、一生懸命操作を学びました。それ以来、あまり上達していません。X68000 の Micro Emacs では、便利な機能があらかじめ設定されていたので、ファンクションキーを多用していたのを覚えています。


今回、Learning GNU Emacs, Third Edition を読み終えたので、久しぶりに Parallels DesktopWindows XPX68000 エミュレータ XM6 を起動して Micro Emacs (em.x) を実行してみました。

もちろん廉価版なので、本家と違うところがいろいろあるのですが、今思うとすごく良くできていますね。ソースは覗いていませんが、OS に依存しているところは分離されているのかな?


Learning GNU Emacs, Third Edition を読んでる途中で

縦分割や

Window と Frame の違いも理解しました。恥ずかしながら、初めて知りましたが Meta Key として Alt (Option) キーも使えるんですね。Micro Emacs から使い始めたので、てっきり ESC キーだけかと思ってました。


Learning GNU Emacs, Third Edition を読みながら、ATOK Pad にメモした箇所がたくさんあります。ちょっとだけ、紹介しておきます。


GNU Emacs には、強力なヘルプがあります。

Help

C-h ?                   ヘルプ一覧
C-h a PATTERN    正規表現 PATTERN に一致する名前を持つコマンド一覧表示
C-h d PATTERN    PATTERN にマッチする関数、変数などを表示                    
C-h k

Window 操作も C-x と数字を入力するだけで、いろいろな動作をします。

Window

C-x 0       ウィンドウの削除
C-x 1       選択されているウィンドウ以外のウィンドウをすべて閉じる
C-x 2       ウィンドウを上下2つに分割する
C-x 3       ウィンドウを左右2つに分割する
C-x 4 f     他のウィンドウでファイルを開く
C-x 5 2    フレームの作成
C-x 5 o    他のフレームに移動


ディレクトリエディタ dired で、g キーを押せば、ディレクトリの内容を最新の状態に更新します。

dired 

C-x d      dired 起動
u             フラグを外す (Remove mark)
d             削除フラグを付ける (Flag of delection)
x             削除フラグがついたファイルを削除 (Delete)       
g             ディレクトリ再読み込み (Immediate Refresh)
=            比較
C            指定したファイルをコピー (copy)
R            ファイル名変更 (Rename file)
v             View モードで表示 (View file, read-only)
s             ファイル名または日付でソート。トグル。
Enter      スクロール (Scroll down)
#            auto-save files にフラグを付ける
~            Backup files にフラグを付ける
* *          excitable files にフラグを付ける
L            ファイルを読み込む (Load file)
%m         正規表現に当てはまるファイル名にフラグを付ける


決まったファイルを編集するには Bookmark に登録しておくと便利です。

C-x r m  bookmark-set
C-x r l   List bookmarks


GNU Emacs の Window 上に shell も起動することができます。

M-x shell
M-p            最後のコマンドを表示
M−n           次のコマンドを表示


検索と置換には、正規表現も使えます。

検索
C-s
置換
M-%
SPACE    置換して次に移動
DEL        置換しないで次に移動
,             置換して結果を表示。移動はしない
正規表現検索
C-M-s
C-M-r
C-M-%


キーは割り当てられていませんが、指定した領域をコメントアウトするには

M-x comment-region
M-x uncomment-region

が便利です。C や Ruby など、ほとんどの言語が対応しています。

C-@ でマークし、カーソルキーで選択します。

M-x comment-region を実行すると、上図のように各行を /* */ でコメントアウトしてくれます。

コメントアウトを取り除くには、上図のように同じく領域を選択し、

M-x uncomment-region を実行します。


Learning GNU Emacs, Third Edition で、簡単な Emacs Lisp Programming も学んだので、どんな環境でも最初に挑戦するマインスイーパを作成してみたくなりました。Google で検索してみると

EmacsWiki: Mine Sweeper
http://www.emacswiki.org/emacs/MineSweeper

すでに存在するようです。私の理解の仕方が足りないのか、うまく動作させることができません。それで少し mine-sweeper.el を変更してみることにしました。まず、.emacs ファイルに

;; .========== .emacs ==========

;; load-path
(add-to-list 'load-path "~/lisp/")

;; minesweeper
(autoload 'mine-sweeper "mine-sweeper" nil t)

(autoload 'mine-auto "mine-sweeper-auto" nil t)
(add-hook 'mine-sweeper-mode-hook
	  (lambda ()
	    (define-key mine-sweeper-mode-map "a" 'mine-auto)))

を追加しました。ホームフォルダlisp フォルダを作成し、その中に mine-sweeper.el、mine-sweeper-auto.el ファイルをそれぞれ置きました。

mine-sweeper.el ファイルの mine-sweeper 関数から

(get-buffer-create "Mine")
(set-window-buffer (selected-window) "Mine")

をコメントアウトし

 (pop-to-buffer "*Mine*" nil)

を追加しました。mine-sweeper 関数は、下記のようになります。

;;; main
(defun mine-sweeper ()
  "mine-sweeper
SPC  open
b    mark
m    mark
q    quit"
  (interactive)
  (setq max-lisp-eval-depth 3000)  ;for recursive call of open.           
  (setq max-specpdl-size 3000)     ;for recursive call of open.

;;  (get-buffer-create "Mine")
;; (set-window-buffer (selected-window) "Mine")

  (pop-to-buffer "*Mine*" nil)

  (setq overwrite-mode t)
  (setq major-mode 'mine-sweeper-mode
         mode-name  "Mines")
  (use-local-map mine-sweeper-mode-map)
  (run-hooks 'mine-sweeper-mode-hook)
  (mine-start)
  (setq buffer-read-only t))

次に mine-clean-and-quit 関数を

(defun mine-clean-and-quit () 
  (interactive)
;;  (switch-to-buffer-other-window "*Mine*")
  (delete-window)
  (kill-buffer "*Mine*"))

に変更しました。これで M-x mine-sweeper を実行すると、マインスイーパで遊ぶことができます。


最初にミニバッファ上で縦横のサイズ、地雷の数を入力します。( デフォルトの値を使用する場合は、Return キーを押すだけです。)
画面が表示されると

カーソルキー     セルを移動
スペースキー     セルをオープン
m キー              マーク
a キー               自動で解く

上記キー操作で遊ぶことができます。a キーを押すと mine-sweeper-auto.el の mine-auto 関数が呼ばれ、マインスイーパを自動で解いてくれます。人間が解くようにコンピュータが解くので、ある程度セルが開いている必要があるようです。条件によっては解けない場合があります。a キーを使って自動で解いた後にプログラムを終了させるとミニバッファに無意味な文字列が表示されます。私が、mine-sweeper.el を変更したのが原因のようです。

自作の Emacs Lispマインスイーパを作ってみたいですね。


GNU Emacs 上の日本語が綺麗に表示できるように、Google で検索していろいろ試しましたが、中々上手くいきません。結局、

IPAフォントのダウンロード || OSS iPedia
http://ossipedia.ipa.go.jp/ipafont/index.html

IPAフォントを使いました。表示結果は

のようになりました。.emacs ファイルは、下記リンクでダウンロードできるようにしておきました。よかったら使ってください。

GNU Emacs 設定ファイル (.emacs) サンプル:  emacs.zip (4K)
http://kyoshiaki.sakura.ne.jp/osx/Download/emacs.zip