irbをESSのように使いたい!!→refeでヘルプも引けるようにした

ESSを知らない人向けに説明すると

  • C-cC-nで今いる行をirbに飛ばしたい!!
  • C-cC-pで今パラグラフ*1をirbに飛ばしたい!!

ということがやりたいです。inf-ruby-modeとかでできるのかもしれないけど、昔使って思った通りに行かなかった記憶がある。というかESS likeにはできなかったような印象がある。そういうわけで

  • windowを縦に二分割
  • ansi-termよりirbを立ち上げ
  • C-cC-nで今いる行をirbに飛ばし(ry
  • C-cC-pで今パラグラフをirbに(ry

を実行するelispを書いてみました。リージョンとかも同じようにできると思うし、現在書いているファイルを読み込む的なものもあったほうがいいかなーと思いつつ、これ書いておけばあとはどうにかなるからいいかという感じで。save-excursionの付近がよく分かってないし、interactiveもよく分かんないしだけど、とりあえずやりたいことはできたっぽい。

(defun irb ()
  "Start up the irb."
  (interactive)
      (split-window-horizontally)
      (other-window 1)
      (ansi-term "/opt/local/bin/zsh" "irb")
      (other-window 1)
      (process-send-string "*irb*" "irb\n"))

(defun irb-eval-linewise ()
  "Evaluate the line on irb."
  (interactive)
  (save-excursion
    (end-of-line)
    (let ((end (point)))
      (beginning-of-line)
      (process-send-string "*irb*" (concat (buffer-substring (point) end) "\n"))))
  (forward-line))

(defun irb-eval-paragraph ()
  "Send the current paragraph to irb."
  (interactive)
  (save-excursion
    (forward-paragraph)
    (let ((end (point)))
      (backward-paragraph)
      (process-send-string "*irb*" (concat (buffer-substring (point) end) "\n"))))
  (forward-paragraph))

(global-set-key "\C-c\C-n" 'irb-eval-linewise)
(global-set-key "\C-c\C-p" 'irb-eval-paragraph)

名前見ると分かる人には分かるかもしれませんが、ESSのソースを若干ぱくってますw。

分かっているバグ

  • 二回呼び出すと*irb<2>*とかになってしまう
    • 一回終了しないと呼び出せない
    • プロセスは送られているわけだが

あとバッファがあるとプロセスが生きているの判別をどうするのかよく分かっていない。

追記

refeで現在ポイントが置かれている関数のヘルプが引けるようにしました。ESSのキーバインドと同じC-cC-vでいけます。ついでにansi-termだとC-nとかが効かなくなるので、その辺も効くように設定しておきました。Macとかだとrefeは文字化けするので、この辺を見て修正をしておいてください。

(defun refe ()
  "See the help from refe"
  (interactive)
  (save-excursion
    (forward-word)
    (let ((end (point)))
      (backward-word)
      (process-send-string 
       "*irb*" 
       (concat (read-from-minibuffer "Method: " (concat "Object.r" " :"(buffer-substring (point) end))) "\n"))
      )))

(global-set-key "\C-c\C-v" 'refe)

(add-hook 'term-mode-hook '(lambda ()
			     (define-key term-raw-map "\C-p" 'previous-line)
			     (define-key term-raw-map "\C-n" 'next-line)
                             (define-key term-raw-map "\C-z"
                               (lookup-key (current-global-map) "\C-z"))
))

*1:二行連続で改行になるまで、ってことでいいのかな