中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

ruby-mod(emacs)をちょっと便利に・・・

Emacs

Emacsには{}や()や[]の対応でジャンプする機能

  • forward-sexp
  • backward-sexp

などという関数があります。

これらはソースコードを弄る時に重宝し、例えば以下の様な場合に便利に使えます。

java
int foo ( int a ) { // ※ forward-sexp この関数の終わりって何処?
  int b = 1;
  if ( a >= 0 ) {
    if ( a > 0 ) {
      return a + b;
    } // ※ backward-sexp この'}'はどのif文に対応してるの?
  }else {
    return a - b;
  }
  return 0;
} 
lisp
;; C
(add-hook 'c-mode-common-hook
          ;; ※ forward-sexp lamda式の終わりは何処まで?
          '(lambda ()
             (progn
               (c-toggle-hungry-state 1)
               (c-set-style "k&r")
               (setq c-basic-offset 2 indent-tabs-mode nil)
               (setq c-default-style "k&r")
              ;(setq c-basic-offset 2 indent-tabs-mode t)
               )
             (require 'gtags)
             )
          )
~/.emacs.el

このままでも十分便利ですが、、態々別のショートカットを打つのは面倒なので
カーソール位置の文字から自動判定する様にして置くとさらに便利になります。

;; paren match
(defun paren-match (arg)
  "Go to the matching parenthesis."
  (interactive "p")
  (cond ((looking-at "[[({]")
         (forward-sexp 1)
         (backward-char)
         )
        ((looking-at "[])}]")
         (forward-char)
         (backward-sexp 1)
         )
        (t (self-insert-command arg))
        ))
(global-set-key "\C-]" 'paren-match)

こうして置けば、カッコを見たら何も考えずに Ctrl+] 連打できます。

便利!!

ruby

しかしRubyシンタックスには殆どカッコが無い!

替わりにendがあります!
困った・・・
Ctrl+] じゃ飛べないよ・・・

ruby-mode

言わずとしれたRubyを書く時のお供ですが、、実はこんな関数があったりします。

  • ruby-beginning-of-block
  • ruby-end-of-block

ほほう!
class , def , if , try , rescue , end , 等々をパースして飛んでくれる訳ですな!!

ならばこうだ!

~/.emacs.el
;; ruby
(add-to-list 'load-path "~/.emacs.d/ruby")
(require 'ruby-mode)
(defun ruby-paren-match (arg)
  "RUBY ..."
  (interactive "p")
  (setq cw (thing-at-point 'word))
  (cond ((looking-at "[[({]")
         (forward-sexp 1)
         (backward-char)
         )
        ((looking-at "[])}]")
         (forward-char)
         (backward-sexp 1)
         )
        ((string-match "^\\(end\\|rescue\\|when\\)$" cw)
         (ruby-beginning-of-block)
         )
        ((string-match "^\\(if\\|class\\|def\\|begin\\|do\\|case\\)$" cw)
         (ruby-end-of-block)
         )
        (t (self-insert-command arg))
        ))

(add-hook 'ruby-mode-hook
          '(lambda ()
             (local-set-key "\C-]" 'ruby-paren-match)
             ))

これでめでたくCtrl+]連打出来るようになりました!!

todo

実はこんな時に上手く動かない・・・

 foos.each do |foo|
  foo = 1
 end

この様に動く

  1. end でCtrl+] => foos へジャンプ
  2. foosで Ctrl+] => 何も起こらない・・・

本来はfoosでは無くdo に飛ぶべき
または、foosで Ctrl+] 押した際にもその行のdo を見つけてジャンプすべき!

まあ頑張れば出来るけど面倒なので後回し(爆