第4回優しいEmacs Lisp講座 読書会・実践会に参加してきました。

第10回 低レベル勉強会〜普通のやつらの下を行け〜

 やさしいEmacs-Lisp 講座 読書&実践会 - その4
http://atnd.org/events/9003

に参加してきました。

楽しかったー。

初めて勉強会に参加したのですが、一番感じたのは、僕以外全員プロの方で、「僕ってこんなにダメ学生のぼさっとした空気を出してたんだ!」ってことでした。

楽しいことしかしてないというか、実益に結びつかないというか…。

周りの友人は学生でも超がつくほど優秀な人ばかりなのですが、僕はただのひきこもりのアル中なので改めなければならないなぁと思いました。

あと基本みんな実名由来っぽいidで、「げんしょうです」なんて意味わからんHN名乗るのがちょっと恥ずかしかったです。

でもすごく楽しかったです。

Emacsの勉強会ということで、参加者はマニアックな方ばかりでとても刺激的でした。

内容は
"Amazon.co.jp: やさしいEmacsLisp講座: 広瀬 雄二: 本" - http://j.mp/bSzRst

の6章から8章で、僕のイメージしてた輪講とかの、各人がちゃんと予習してきて、担当者が講義形式ですすめるみたいな堅苦しい感じではなくて、その場で音読して気になったことを言いたい人が発言するみたいな感じだったので、正味ぐだぐだになった点はまあまああったのですが、わからなかったことはあとで自分で精読したり調べればいいのだし、気軽に参加できるという点ではすごくよかったなと思いました。

"ちゃんと予習して、あなたはどこどこをまとめて発表してください"とかだったらどのくらいのレベルでやればいいのか分かんなくて参加しなかったかもしれません。

せっかく章末問題があって、わりとゆっくり進めてたっぽいので、その場で解かずとも宿題っぽくして、"僕はこんな風に解きましたけどみんなはどうでした?"的なのがあっても面白かったかなぁとは思いました。

あと、主催者の方がやたらとGoogle waveを押してた(?)のですが、僕は全く使ったことなかったので、"ちょっと高機能なチャット?"くらいの印象しかうけなかったり、

"Google、Waveの開発を中止 - ITmedia News" - http://j.mp/dra4xM

みたいな記事があったりで、どうなんだろ?とは思いました。

ちょっとちゃんと調べてみます。

しかし、Emacsユーザの方や、プログラマの方とお話する機会なんてぼさっとしてたらないので、とても貴重な経験ができました。

楽しかったです。

今度arielがやるLisp脳勉強会は(個人的に)知ってる方が多数参加するみたいでとても興味があったのですが日程が無理くさくて残念です。

が、今後も継続的に勉強会には参加していきたいなと思いました。

今日は本当に参加してよかったです。

主催者の@watsさんならびに参加者のみなさんには本当に感謝しております。

次回も参加できればいいなぁ。

あと、今つくってるEmacs用のニコ生コメビュモードを作る上で使えそうな知識も学べたので、放送でちょこちょこ紹介できればいいなとおもいます。

ニコ生コメビュ進捗

ニコ生のコメントサーバに接続するための情報は、一度ログインしてやらないと見れないのですが、このときhttpsでの接続が必要となります。

Emacs側からこれをするためにちょっと調べてみました。

僕が調べた限りでは、tls.elというファイル中にopen-network-streamと同じように使えるopen-tls-streamという関数が見つかったのですが、これはもともとgnutls-cliまたはopensslという外部コマンドに依存していて、windows環境だとcygwinとかでこれらのコマンドを使わせるか、あるいはtwittering-mode.elのようにcURL.exe等のソフトで同等の操作を行うというのが現実的なようです。

ただ、外部コマンドに頼るのであれば、クッキーの扱いとかも面倒なので、端からそれをやってくれるソフトをつくるか見つけてきたほうがはやいなということで、

http://d.hatena.ne.jp/imakami/20081217/1229517473

ここを参考にさせてもらうことにしました。

あんまりこういう事はしたくなかったのですが、ここで延々と悩むのはなんだか本質的ではない気がするのでとりあえずよしとします。

===========================================================================

余談ですがFMEを使えるようになったっぽいので今後の放送は画質やfpsがちょっとだけよくなると思います。 やったね。

やさしいEmacs-Lisp講座 章末問題1

第10回 低レベル勉強会〜普通のやつらの下を行け〜
 やさしいEmacs-Lisp 講座 読書&実践会 - その4
http://atnd.org/events/9003

に参加することにしたので、

やさしいEmacs-Lisp 講座
http://www.gentei.org/~yuuji/elisp/elisplec.html

を勉強してますが、章末問題1で早速躓いてしまいました。

章末問題1
問 1-1
a-z どのキーを押しても、「僕るねえもんナリよ」が挿入される「るねきちモード」を作りなさい。

(defun insert-runeemon ()
  (interactive)
  (insert "僕るねえもんナリよ\n"))

(defun runekitch-mode ()
  (interactive)
  (setq major-mode 'runekitch-mode
        mode-name "Runekitch Mode")
  (setq runekitch-mode-map (make-keymap))
  (let ((count 97))
    (while (< count 123)
      (eval '(define-key runekitch-mode-map (format "%c" count) 'insert-runeemon))
      (setq count (1+ count))))
  (use-local-map runekitch-mode-map))

で問1-1はたぶんいいんだと思います。

変数countを97から122まででループさせてるのは

?a ; => 97
?z ; => 122

だからです。

問題は問1-2です
問1-2
a-zを押すと、対応するアルファベットで、「僕luneえもんAなりよ」〜「僕luneえもんZなりよ」と、文字列の入るluneえもんモードを作成せよ。

まあ、26個定義書いてもいいんですがDon'tRepeatYourselfの精神で出来ればdefine-keyに引数を渡した関数を設定したいのです。

いろいろ考えたけどだめだったバージョン

(defun insert-luneemon (num)
  (interactive)
  (insert (concat "僕luneえもん" (format "%c" (- count 32)) "ナリよ\n")))

(defun luneemon-mode ()
  (interactive)
  (setq major-mode 'luneemon-mode
        mode-name "Luneemon Mode")
  (setq luneemon-mode-map (make-key-map))

  (let ((count 97))
    (while (< count 123)
      (eval '(define-key luneemon-mode-map (format "%c" count)
               (lambda () (interactive) (insert-luneemon count))))
      (setq count (1+ count))))
  (use-local-map luneemon-mode-map))

これだと、define-keyで定義するときに変数countの値じゃなくてそのまま"(insert-luneemon count)"で定義されるので、どこかでcountが97とかに定義されてれば何をおしても"僕luneえもんAなりよ"しか表示されないのじゃ。

もうちょっとがんばってみます

=========================================================================
やっとでけた。

evalってのは引数にもらったリストをそのまま先頭を関数として解釈して…ってことみたいなので、じゃあ

(define-key lunekitch-mode-map (format "%c" count) 
    (lambda () (interactive) 
               (insert-luneemon 97)))

ってリストをつくってやればいいだけなので完成したのが下

(defun insert-luneemon (count)
  (interactive)
  (insert (concat "僕luneえもん" (format "%c" (- count 32)) "ナリよ\n")))

(defun set-list (c)
  (let ((cmd '(define-key luneemon-mode-map (format "%c" count)))
        (temp-list-1 (cons 'insert-luneemon (cons c())))
        (temp-list-2 '(lambda () (interactive))))
    (setq temp-list-2 (append temp-list-2 (cons temp-list-1 ())))
    (append cmd (cons temp-list-2 ())))))

(defun luneemon-mode ()
  (interactive)
  (setq major-mode 'luneemon-mode
        mode-name "Luneemon Mode")
  (setq luneemon-mode-map (make-keymap))
  (let ((count 97))
    (while (< count 123)
      (eval (set-list count))
      (setq count (1+ count))))
  (use-local-map luneemon-mode-map))

ごり押し感が半端ないですが出来たので良しとします。

今日入れたelisp

; sense-region
; http://taiyaki.org/elisp/sense-region/src/sense-region.el
(auto-load 'sense-region-on "sense-region")
(sense-region-on)

; auto-highlight-symbol
; http://github.com/mitsuo-saito/Junk/raw/master/elisp/auto-highlight-symbol.el
(require 'auto-highlight-symbol-mode t)

; C-l と C-M-l入れ替え
(global-set-key (kbd "C-l") 'reposition-window)
(global-set-key (kbd "C-M-l") 'recenter-top-bottom)

sense-regionは領域選択に関するもので、C-SPC連打でカーソル下の単語を選択したり現在行を選択したりできる。 
矩形選択も便利になるっぽいけどそもそも矩形選択をほとんどしない。
C-SPC連打で領域をさまざま変えてくってアイディアはすごく好きだけどC-gでキャンセルしたときにカーソル位置が変わっちゃったりとかちょっと微妙かも。

auto-highlight-symbolはカーソル下の単語を現在表示されてる画面中から検索して自動でハイライトしてくれるやつ。
eclipseみたいなIDEでやってくれるのを思い浮かべていただければいいかと。
これはたぶん使い続けると思う。
ただ、C-xC-aで現在ハイライトされてる単語を同時に編集できるモードに入るんだけど画面に表示されてる部分しか同時編集できないので変数名とか変えたいときにはちょっと不便。
バッファ全体でやってくれればいいのに。
あとで自分でいじってみます。

最後はC-M-l(reposition-window : 現在のカーソル行が画面最上部になるように表示)の存在を今日はじめて知って、こっちのほうが僕は使用頻度が高いと思ったのでC-lと入れ替え。

コメビュ製作は今日は進みません。

ログインするためにhttpsで接続しなきゃならんのですがそもそもネットワーク関連のプログラムは組んだことがない上に、JavaとかPythonとかみたいに「意味はわかんないけどとりあえずネットで見つけたサンプルをちょちょっと変えたらなんか動いた」とうまくいくほど情報も多くないので今はurl-http.elを読んでます。

xmlも使ったことはないのでxml.el、dom.elもちゃんと読まなきゃいけません。

が、よくわかりません。

引数が具体的にどんな形のもので、返り値は何で、副作用はなんだってのがちゃんと書いてればいいのに、と思ったので、「人にされて嫌なことはするな」の精神にのっとり自分がコードを書くときはちゃんと書きたいと思いました。

「んなもんコード見りゃすぐわかんじゃん」

ってことなんだろうけど。

Emacs上のニコ生コメビュ 進捗

とりあえずサーバからコメントもってこれた!

今は受け取ったデータをxml.elでパースして、dom.elで扱える形にしたところ。

まだまだ先は長そうですが、コメントをもってこれた時点で勝ちゲーだと思うので、あとはこまごましたパーツを作っていくだけですね。

ただし、ログイン関係がうまくいくかが問題です。

一通り形になったらgithubかどっかにあげるつもりなので、もしよかったらつかってみたりだめだししたりしてね。

global-set-keyとかで引数付きの関数をバインドしたいとき

M-l(downcase-word)やM-u(upcase-word)は現在のカーソル位置の後の単語を小文字にしたり大文字にしたりするのです。

英文やプログラムを修正するときは連打できて便利かもですが、僕の場合はその用途よりも、プログラムを作ってて全部大文字の定数の識別子とか入力するときに、

hogehoge

ってとりあえず打ってからM-uで

HOGEHOGE

ってなってくれたらシフト押しっぱなしにしなくていいので楽だなぁと思ったのです。

upcase-wordとかは引数を-1とかにすると、これをしてくれるのですがそれをどうしようかと思って最初は

(defun my-upcase-word ()
    (interactive)
    (upcase-word -1))
(global-set-key (kbd "M-u") 'my-upcase-word)

とかしたんですが、

(global-set-key (kbd "M-u") (lambda () (interactive) (upcase-word -1)))

のほうがいいなと思ったのでメモとして残します。

============================================================================
追記 10/26
案の定同じようなことをしてる人がいました。

http://at-aka.blogspot.com/2006/07/emacs.html

EmacsにおけるC-w

C-wはデフォルトでkill-regionがバインドされてるけど領域を選択してないと何もしてくれないのはもったない。

カレントウィンドウを消す、delete-windowのデフォルトのキーバインドC-x 0が押しづらいし、firefoxで"タブを閉じる(C-w)"に似てるから、領域選択がなされてない時はこれを呼ぶことにしたらすこぶるゴキゲンだぜべいべ。

ただ、領域が選択されてるかどうかの判定に使ったmark-active変数がEmacs起動直後はちょっとおかしいみたいで起動直後は領域を選択してなくてもkill-regionが呼ばれちゃって悲しい。

一回ちゃんと領域選択してkill-regionしてやるとその後は大丈夫みたいだけど。。。

(defun kill-region-or-delete-window (beg end)
  (interactive "r")
  (if mark-active 
      (kill-region beg end)
    (delete-window)))
;;(global-set-key (kbd "C-w") 'kill-region-or-delete-window)