#!/usr/local/bin/ruby
=begin
         
      

   Ruby Reference/Refe Seeker for Emacsen(RRSE)
          大林一平(ohai@kmc.gr.jp)
        http://www.kmc.gr.jp/~ohai/
          京大マイコンクラブ(KMC)
              大学院生(数学)
     Ruby/SDL(http://www.kmc.gr.jp/~ohai/rubysdl.html)
     Ruby Refactoring Browser(http://www.kmc.gr.jp/proj/rrb)







   RRSE とは？
   * ReFe の情報を Emacs の ミニバッファに表示
   * ReFe だけでは Emacs から使うのに一手間必要(例:require)
   * Haskell-doc-mode がアイデアの元
   * http://www.kmc.gr.jp/~ohai/rrse.html
   * 以下デモ - カーソルとミニバッファに注目してください
=end

require 'refe/database'
require 'refe/searcher'
require 'refe/config'
require 'optparse'

class Description
  attr_reader :spec, :method, :descs
  
  def initialize(spec, str)
    @spec = spec
    @mod, @method = spec.split(/\#|\./)
    @kind = if spec.include?("#") then :instance else :class end
    match_descline = proc do |line|
      /^#{Regexp.quote(@spec)}[ (]/ =~ line ||
        /^#{Regexp.escape(@method)}[ (]/ =~ line ||
        line.include?("self[")
    end
    
    CGI.escape("")
    
    @descs = str.
      split(/\n/).
      select{|line| /^(---|:) / =~ line}.
      map{|line| line.sub(/^(---|:) /, "")}.
      select(&match_descline).
      map{|line| if /\s*ruby 1\.. feature/ =~ line then $` else line end}.
      map{|line| if /^#{Regexp.quote(@spec)}/ =~ line then $' else line end}.
      map{|line| if /^#{Regexp.quote(@method)}/ =~ line then $' else line end}
  end

  def show
    "#{@spec}\t#{@descs.join("\t")}"
  end
end

=begin
    実装
    * Ruby: ReFe のデータを読み込み整形
    * elisp: カーソルの周りを適当に解析、表示, post-command-hook
    RRSEの今後
    * ri, rdoc で生成したドキュメントに対応
    * ちょっとした補完機能(クラスメソッド)
    * 目指すは Visual Studio？

    まとめ
    * Emacs使いなら使ってみてください













=end

opt = OptionParser.new
datadir = nil
reverse = false
opt.on('-d DIR', 'Use DIR as the refe database root directory'){|v| datadir = v}
opt.on('-r', 'Print reverse data'){ reverse = true }
opt.parse!(ARGV)

begin
  db = ReFe::Database.new(datadir)
  descs = []
  db.method_document.complete(nil, nil, '*').each do |spec|
    case spec
    when /^man\..*$/
    when /^[A-Za-z0-9_:]+(#|\.)[^#.]+$/
      descs << Description.new(spec, db.method_document[spec])
    else
      raise "invalid information"
    end
  end
  
  if reverse
    descs.
      inject(Hash.new{|h,k| h[k]=[]}){|h, desc| h[desc.method] << desc.spec; h}.
      sort_by{|method, *| method}.
      each{|method, specs| puts "#{method}\t#{specs.join("\t")}"}
  else
    descs.sort_by{|desc| desc.spec}.each{|desc| puts desc.show }
  end
rescue RuntimeError
  raise
rescue ReFe::Error => err
  $stderr.puts err.message
  exit 1
rescue StandardError => err
  raise if $DEBUG
  $stderr.puts err.message
  exit 1
end

