File: dsl.rb

package info (click to toggle)
ruby-eim-xml 1.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 236 kB
  • sloc: ruby: 2,015; makefile: 5
file content (113 lines) | stat: -rw-r--r-- 2,785 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# Easy IMplementation of XML
#
# Copyright (C) 2006,2008, KURODA Hiraku <hiraku@hinet.mydns.jp>
# You can redistribute it and/or modify it under GPL2.
#

require 'eim_xml'

module EimXML
  class BaseDSL
    def add(content)
      @_container << content
    end
    alias << add

    def import_variables(src)
      src.instance_variables.each do |v|
        instance_variable_set(v, src.instance_variable_get(v)) unless v =~ /\A@_[^_]/
      end
      self
    end

    def _build(klass, *arg, &proc)
      e = klass.new(*arg)
      @_container << e if @_container
      if proc
        oc = @_container
        @_container = e
        begin
          instance_eval(&proc)
        ensure
          @_container = oc
        end
      end
      e
    end
    private :_build

    def _push(container)
      oc = @_container
      @_container = container
      begin
        yield if block_given?
        container
      ensure
        @_container = oc
      end
    end
    private :_push

    def self.register(*args)
      args.each do |klass, name|
        name ||= klass.name.downcase[/(?:.*::)?(.*)$/, 1]

        # rubocop:disable Security/Eval, Layout/LineLength
        eval("def #{name}(*a, &p);_build(#{klass}, *a, &p);end", binding, __FILE__, __LINE__) # def element(*a, &p);_build(Element, *a, &p);end
        eval("def self.#{name}(*a, &p);new.#{name}(*a, &p);end", binding, __FILE__, __LINE__) # def self.element(*a, &p);new.element(*a, &p);end
        # rubocop:enable Security/Eval, Layout/LineLength
      end
    end
  end

  class DSL < BaseDSL
  end

  class OpenDSL
    def _build(klass, *arg, &proc)
      e = klass.new(*arg)
      oc = @_container
      oc << e if oc.is_a?(Element)
      @_container = e
      begin
        proc&.call(self)
        e
      ensure
        @_container = oc
      end
    end
    private :_build

    def self.register_base(_dsl, binding, *args)
      args.each do |klass, name|
        name ||= klass.name.downcase[/(?:.*::)?(.*)$/, 1]

        # rubocop:disable Security/Eval, Layout/LineLength
        eval("def #{name}(*a, &p);_build(#{klass}, *a, &p);end", binding, __FILE__, __LINE__) # def element(*a, &p);_build(Element, *a, &p);end
        eval("def self.#{name}(*a, &p);self.new.#{name}(*a, &p);end", binding, __FILE__, __LINE__) # def self.element(*a, &p);self.new.element(*a, &p);end
        # rubocop:enable Security/Eval, Layout/LineLength
      end
    end

    def self.register(*)
      register_base(self, binding, *)
    end

    def initialize
      @_container = nil
      yield(self) if block_given?
    end

    def add(content)
      @_container.add(content)
    end
    alias << add

    def container
      @_container
    end
  end

  DSL.register Element, Comment
  OpenDSL.register Element, Comment
end