Pragger + DSL ボツねた

作ってみたけれど何かすっきりしない仕様。
作ってはみたけれど、勝手に "Pragger" を名乗るわけにはいかないから、
テキトーに "xry" 変更。


ソースコードでは、
プラグインを読み込むディレクトリは "./plugin"、
設定ファイルは "./pragger.dsl" と固定になっています。

本家の Pragger だと以下のような設定ファイルなら

本家のサイトにあったサンプル設定ファイル。
evaL_pragger() を使っている concat プラグインコメントアウトしている。

- module: const_list
  config: 
   - "http://www1.jp.dell.com/content/products/compare.aspx/tower_servers?c=jp&cs=jpbsd1&l=ja&s=bsd"
- module: Filter::get_html
- module: Filter::find_regex
  config:
    regex: "(\d|,){6,}円(?!OFF)"
- module: Filter::subs
  config:
    regex: "\D"
    to: ""
- module: Filter::to_integer
- module: Filter::sort
- module: first
- module: concat
  config: 
    - module: RSS::load
      config:
        url: dell.rdf
- module: RSS::save
  config: 
    filename: dell.rdf
- module: print

こんな感じの DSL になる

define_task do
  call_plugin 'const_list', ["http://www1.jp.dell.com/content/products/compare.aspx/tower_servers?c=jp&cs=jpbsd1&l=ja&s=bsd"]
  call_plugin 'Filter::get_html', 'cache' => 'D:/home/develop/trunk/ruby/validation/pragger_dsl/cache'
  call_plugin 'Filter::find_regex', 'regex' => '(\d|,){6,}円(?!OFF)'
  call_plugin 'Filter::subs', {'regex' => '\D', 'to' => ""}
  call_plugin 'Filter::to_integer'
  call_plugin 'Filter::sort'
  call_plugin 'first'

# call_plugin 'concat'
# config: 
#   - call_plugin: RSS::load
#     config:
#       url: dell.rdf

  call_plugin 'RSS::save', 'filename' => 'dell.rdf'
  call_plugin 'print'
end

ソースコード

何だか別のものになっちゃった感じがするな。
eval_pragger とか使っていなければ、プラグインはそのまま
使えると思う。

$KCODE='u'

require 'kconv'

module Xry
  class DSL
    def initialize(dir)
      @plugin_dir = dir
    end

    def load(filename)
      @plugin = Xry::Plugin.new.load(@plugin_dir)
      instance_eval(File.read(filename).toutf8, filename, 1)
    end

    def define_task(&block)
      return nil if block.nil?

      core = Xry::Context.new(@plugin)
      core.instance_eval(&block)
      core
    end
  end

  class Plugin
    def initialize
      @methods = {}
    end

    def load(dir)
      Dir::glob("#{dir}/**/*.rb") {|file|
        key = file.sub(%r{^#{dir}/(.+?)\.rb}, "\\1").gsub(%r{/}, "::")
        @methods[key] = Xrr::Plugin::Method.new(file)
      }

      self
    end

    def send(name, *argv)
      return   unless @methods.key?(name)
      @methods[name].send(name.sub(/.*::/, ""), *argv)
    end

    class Method
      def initialize(filename)
        instance_eval(File::open(filename, "r").read.toutf8, filename, 1)
      end
    end
  end

  class Context
    attr_accessor :data

    def initialize(plugin)
      @data = []
      @plugin = plugin
    end

#   def call_plugin(name, config, &block)
    def call_plugin(*argv, &block)
      return self  if argv.size == 0

      if argv.size == 1
        config = {}
      else
        config = argv[1]
      end

      name = argv[0]
      
      self.instance_eval(&block)  unless block.nil?

      puts "execute plugin: #{name}"
      @data = @plugin.send(name, config, @data.clone)

      self
    end

#   def set_config(values)
#     puts "Context::set_config>"
#     @config.update(values)
#   end
  end
end

if $0 == __FILE__
  Xry::DSL.new('./plugin').load('./pragger.dsl')
end