[#46732] ヒアドキュメント内の変数展開が正常に行われない — ShingoKintaka <kamuycikap@...>

Ruby  :1.8.7 (Ubuntu9.10)

12 messages 2010/01/05
[#46733] Re: ヒアドキュメント内の変数展開が正常に行われない — rubikitch@... 2010/01/06

From: ShingoKintaka <kamuycikap@tulip.ocn.ne.jp>

[#46800] DLモジュールの使い方 — kouichi_someya@...

染谷と申します。

12 messages 2010/01/20
[#47678] プログラム実行時に「[BUG] Segmentation fault」 — 染谷 康一 <kouichi_someya@...> 2010/12/09

染谷と申します。

[ruby-list:46794] Re: Emacsでメソッドのアウトライン表示

From: rubikitch@...
Date: 2010-01-19 13:03:13 UTC
List: ruby-list #46794
From: ShingoKintaka <kamuycikap@tulip.ocn.ne.jp>
Subject: [ruby-list:46793] Emacsでメソッドのアウトライン表示
Date: Tue, 19 Jan 2010 21:16:06 +0900

るびきちです。

> EmacsでRubyコードをコーディングする時、クラスをツリー表示できたら。。。。
> Rubyで利用できるアウトライン表示を利用している方はいらっしゃいませんか?

大昔にあおきさんが作ったrdefs.rbを改造してクラスツリー表示に使っています。

M-x compile rdefs.rb -nPH ファイル名

を実行すると、クラス名とメソッド名と引数がリストされます。
C-x ` (next-error)で順次たどれるようになっています。

手元では anything.el (現メンテナです)による絞り込みやタグジャンプがで
きるようになっていますが、需要があるならばそのうちファイルに分離して公
開しようかと思っています。


#!/usr/bin/env ruby18
#
# $Id: rdefs.rb,v 1.22 2009/05/31 04:53:02 rubikitch Exp $

require 'optparse'

DEF_RE = /\A\s*(?:
    def\s | class\s | module\s | include[\s\(] | extend[\s\(]
  | alias(?:_\w+)?
  | attr_reader[\s\(]
  | attr_writer[\s\(]
  | attr_accessor[\s\(]
  | attr[\s\(]
  | public[\s\(]
  | private[\s\(]
  | private_class_method[\s\(]
  | public_class_method[\s\(]
  | module_function[\s\(]
  | protected[\s\(]
  | def_delegators?[\s\(]
  | .*Struct(?:\.|::)new[\s\(]
  )/x

CLASS_METH_RE = /\A\s*(?:def|class|module)\s/

REQUIRE_ALL_LIBS = %w[active_support]

def main
  print_line_number_p = false
  print_filename = false
  print_prefix_p = false
  additional_regexp = nil
  tab_width = 8
  include_dependencies = false
  parser = OptionParser.new
  parser.banner = "#{File.basename $0} [-nH] [-r REGEXP] file..."
  parser.on('-n', '--lineno', 'Prints line number.') {
    print_line_number_p = true
  }
  parser.on('-H', '--with-filename', 'Prints filename.'){
    print_filename = true
  }
  parser.on('-P', '--with-prefix', 'Prints prefix.'){
    print_prefix_p = true
  }
  parser.on('--help', 'Prints this message and quit.') {
    puts parser.help
    exit 0
  }
  parser.on('-r REGEXP', '--regexp=REGEXP', 'Print lines matching REGEXP additionally.') {|x|
    additional_regexp = Regexp.new(x)
  }
  parser.on('-t TAB-WIDTH', '--tab-width=TAB-WIDTH', 'Tab width.') {|x|
    tab_width = x.to_i
  }
  parser.on('-d', 'Include dependencies') {|x|
    include_dependencies = true
  }
  parser.on('--dev', 'Add this project\'s bin/ and lib/ to $LOAD_PATH.') {|x|
    $:.unshift "lib", "bin"
  }
  parser.on('--gem', 'Add RubyGems additional load paths to $LOAD_PATH.') {|x|
    require 'rubygems'
    $:.unshift *Gem.latest_load_paths
  }
  parser.on('--rdefs', 'Output RDEFS file.') {|x|
    $> = open("RDEFS", "w")
  }
  parser.on('-a', '--all', 'Output RDEFS file, including -nHPd --dev --rdefs options.') {|x|
    print_line_number_p = true
    print_filename = true
    print_prefix_p = true
    include_dependencies = true
    $:.unshift "lib", "bin"
    require 'rubygems'
    $:.unshift *Gem.latest_load_paths
    $> = open("RDEFS", "w")
  }
  begin
    parser.parse!
  rescue OptionParser::ParseError => err
    $stderr.puts err.message
    exit 1
  end

  # rule out nonexistent files
  ARGV.reject! {|file| ! File.exist?(file) }
  f = Preprocessor.new(ARGF, tab_width)
  re = DEF_RE
  processed = ARGV.uniq
  while line = f.gets
    begin
      if re =~ line
        f.register_line if CLASS_METH_RE === line
        printf '%s:', f.path if print_filename
        printf '%-6s', "#{f.lineno}:" if print_line_number_p
        print format_line(getdef(line,f), f.prefix(line), print_prefix_p)
      elsif additional_regexp and  additional_regexp =~ line
        f.register_line if CLASS_METH_RE === line
        printf '%s:', f.path if print_filename
        printf '%-6s', "#{f.lineno}:" if print_line_number_p
        print format_line(line, f.prefix(line), print_prefix_p)
      elsif include_dependencies and /require ["'](.+?)["']/ === line
        next if $1 == 'rubygems'
        basename = File.basename $1, ".rb"
        lib = which_library $1
        (REQUIRE_ALL_LIBS.include?(basename) ? add_all_libraries(lib) : [lib]).each do |lib2|
          if lib2 and /\.rb$/ === lib2 and not processed.include? lib2
            $stderr.puts "Add #{lib2}"
            ARGV << lib2
            processed << lib2
          end
        end
      end
    rescue
      $stderr.puts $!
      $stderr.puts "Continuing..."
    end
  end
end

def add_all_libraries(baselib)
  dir = File.dirname(baselib)
  Dir["#{dir}/**/*.rb"]
end



# borrowed from devel/which
require 'rbconfig'
def which_library(lib)
  unless lib.is_a? String
    raise TypeError,
    "wrong argument type #{lib.type} (expected String)"
  end
  ext = ["rb", Config::CONFIG["DLEXT"], Config::CONFIG["DLEXT2"]]
  ext.map!{|i| i.length > 0 ? ".#{i}" : nil}
  ext.compact!
  ext.push("")
  
  at = with = nil
  at = $:.find{|path|
    file = "#{File::expand_path(path)}/#{lib}"
    
    begin
      with = ext.find{|i|
        test(?f, file+i) && test(?r, file+i)
      }
    rescue
      next
    end
  }
  
  "#{at}/#{lib}#{with}" if at
end



def getdef(str, f)
  until balanced?(str)
    str << f.gets
  end
  str
end

def balanced?(str)
  str.count('(') == str.count(')')
end

def format_line(line, prefix, print_prefix_p)
  if print_prefix_p and !prefix.empty?
    prefix + " / " + line.lstrip
  else
    line
  end
end

class Preprocessor
  def initialize(f, tab_width)
    @f = f
    @tab_width = tab_width
    @hierarchy = Array.new(7)
    @line = nil
  end

  def gets
    line = @f.gets
    if /\A=begin\s/ === line
      while line = @f.gets
        break if /\A=end\s/ === line
      end
      line = @f.gets
    end
    @line = line
  end

  def indent(line)
    line[/^ */].length
  end
  private :indent

  def register_line
    line = @line.gsub(/\t/, ' ' * @tab_width)
    indent = indent(line)
    @hierarchy[indent] = line.strip
    @hierarchy.fill(nil, indent+1)
  end
  
  def prefix(line)
    hierarchy = @hierarchy.dup.fill(nil, indent(line))
    hierarchy.compact.map{|l| l.sub(/ *#.+$/, '').gsub(/ +/, ' ') }.join(" / ")
  end

  def lineno
    @f.file.lineno
  end

  def path
    @f.path
  end
end

main


--
rubikitch
Blog: http://d.hatena.ne.jp/rubikitch/
Site: http://www.rubyist.net/~rubikitch/
Twit: http://twitter.com/rubikitch/
『Ruby逆引きハンドブック』 http://d.hatena.ne.jp/rubikitch/20090525/rubybook

In This Thread

Prev Next