ruby-modeが使いにくいので改造(その3)
なんだかRubyの勉強をしていたつもりがすっかりelispにハマってしまっているな。
前回の改造に続き今回は、class, def, do に対して、end を適切にインデントして補完する機能を書いてみた。
class, def, do の直後でスペースバーを叩くと次の行にend が現れるというもの。
do end と書く作法と、{ } を使う作法が有るようだが、まだRubyを始めたばかりなので、どちらがポピュラーなのかまだ良くわかっていないのだが、とりあえず最初に覚えたdo end で補完ができるようにしてみた。
追加した機能をまとめてみると、
- end の補完機能
- oneliner の直後か、endブロックの直後でC-x C-eとする事で式をirbプロセスへ送って評価する機能
- irbが下に伸びて行くのに併せて、スクロールアウトしてしまわないように、最下行へカーソルを移動する機能
こんな所か。
これでRubyの勉強が加速する予定だ。
使い方は、以下を.emacsに追加するだけ。
;; ruby-mode customize (defun ruby-send-exp () "Send an expression to the inferior Ruby process. Cursol must be after the 'end' symbol or at the end of a oneliner" (interactive) (let* ((last-three-chars (buffer-substring (- (point) 3) (point))) (last-char (buffer-substring (- (point) 1) (point))) (beginning (save-excursion (if (or (string= last-three-chars "end") (string= last-char "}")) (ruby-beginning-of-block) (beginning-of-line)) (point)))) (ruby-send-region beginning (point)) (scroll-down-irb))) (defun scroll-down-irb () (interactive) (setq curbuf (current-buffer)) (if (get-buffer ruby-buffer) (pop-to-buffer ruby-buffer) (error "No current process buffer. See variable ruby-buffer.")) (end-of-buffer) (pop-to-buffer curbuf)) (defun get-indent-spaces () (interactive) (let* ((beginning (save-excursion (beginning-of-line 1) (point))) (beginning-of-word-in-the-line (save-excursion (beginning-of-line 1) (re-search-forward "\\w" (point-max) t) (point))) (number-of-spaces (- beginning-of-word-in-the-line beginning 1))) (if (>= number-of-spaces 0) (make-string number-of-spaces ? )))) (defun ruby-insert-end-ex () (interactive) (let* ((last-word-info (search-last-word)) (last-word (if last-word-info (buffer-substring (car last-word-info) (cdr last-word-info)) "")) (spaces (get-indent-spaces))) (if (and last-word-info (= (cdr last-word-info) (point)) (or (string= last-word "do") (string= last-word "class") (string= last-word "def"))) (progn (insert " ") (save-excursion (insert "\n") (insert spaces) (insert "end"))) (insert " ")))) (defun search-last-word () (save-excursion (let ((current-point (point)) (beginning (save-excursion (beginning-of-line 1) (point))) (beginning-of-last-word (progn (forward-word -1) (point))) (end-of-last-word (progn (forward-word 1) (point)))) (if (or (< beginning-of-last-word beginning) (> end-of-last-word current-point)) nil (cons beginning-of-last-word end-of-last-word))))) (add-hook 'ruby-mode-hook '(lambda () (define-key ruby-mode-map "\C-x\C-e" 'ruby-send-exp) (define-key ruby-mode-map " " 'ruby-insert-end-ex)))
自動補完て、スペース押したときじゃなくてタブの方が使いやすいかなぁ。
まぁ、多分こういうのは既にどこかにあるんだろうけど、elispの勉強がてらに作ってみたのだ。良かったら使ってやってください。
後、もっと補完しろとか有ったらコメントください。