anythingでfileをrequireする作業をサポート

rubyでライブラリを読み込むときに、「require"<ここの部分>"」の内容を覚えるのが大変でした><C-c C-uでrequireするファイルを選択したいです。><

その前に

anythingの候補を作るrubyのコードを書きました

tocandidate.rb

~/.emacs.d/tocandidate.rbという感じで保存しました。

#!/usr/bin/env ruby
# -*- encoding: utf-8 -*-
alias __puts puts
def puts(s)
  __puts(%Q{ ("#{s.gsub(/\n/,"\" \"")}")})
end

if __FILE__ == $0
  puts ARGF.read
end

読み込めそうなファイルを出力するコード

~/bin/ruby_all_required.rbという感じで保存しました。
引数で調べる深さを調整できるようにしました。(4くらいが適量そうです)

require 'rubygems'
def dir_walk(a,d,&block)
  return if d <= 0
  a.each do |f|
    if File.directory? f
      dir_walk(Dir[File.join(f,"*")],d-1,&block)
    else
      block.call(f,d)
    end
  end
end

a = Dir[File.join(Gem.dir,"gems/*")].map{ |e| File.join(e,"lib")}
a.concat $:.reject{ |e| e =~ /^\.+/}
$depth = ARGV.first.to_i
$depth = 3 if $depth==0
dir_walk(a,$depth){ |e,d| x =  e.split("/")[(d-$depth)..-1].join("/").gsub!(File.extname(e),""); puts("#{x}\t#{e}")}

emacs側の設定

好きなところに

;;この3つは自分の環境用に設定を変更してください
(defvar tocandidate-program "~/.emacs.d/tocandidate.rb")
(defvar ruby-all-required-program "~/bin/ruby_all_required.rb")
(defvar ruby-require-search-depth 4) ;;探索する深さ

(unless (boundp 'ruby-program)
  (defvar ruby-program "ruby")
)

(defun ruby-require-get-cand () 
  (read (shell-command-to-string
	 (format "%s %s %s | %s" ruby-program ruby-all-required-program ruby-require-search-depth tocandidate-program)))))

(defvar anything-c-insert-ruby-require-source
  '((name . "require")
    (candidates . ruby-require-get-cand)
    (action . (("insert" . (lambda (c)
			     (let ((file (car (split-string c "\t"))))
				   (insert (format "require '%s'\n" file)))))
	       ("find-file" . (lambda (c)
				(let ((path (cadr (split-string c "\t"))))
				  (find-file path)))))
	    )))

(defun insert-ruby-require () (interactive)
  (let ((anything-sources (list anything-c-insert-ruby-require-source)))
    (anything)))

(add-hook 'ruby-mode-hook
	  (lambda ()
	    (define-key ruby-mode-map 'insert-ruby-require)))