o 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ class O
2
+ module HashMethodFix
3
+ def _merge! obj
4
+ _child.merge! O.get(obj)
5
+ self
6
+ end
7
+
8
+ def _merge obj
9
+ data = _child.merge(O.get(obj))
10
+ O[data]
11
+ end
12
+ end
13
+ end
data/lib/o/parser.rb ADDED
@@ -0,0 +1,88 @@
1
+ class O
2
+ class Parser
3
+ attr_reader :content
4
+
5
+ class << self
6
+ def compile content
7
+ parser = Parser.new content
8
+ parser.compile
9
+ end
10
+ end
11
+
12
+ def initialize content
13
+ @content = content
14
+ end
15
+
16
+ def compile
17
+ script = ""
18
+ indent_counts = 0
19
+ block_start = false
20
+
21
+ scan do |token, statement|
22
+ case token
23
+ when :block_start
24
+ block_start = true
25
+ statement = statement.sub(":", " do")
26
+ script << statement << "\n"
27
+ when :statement
28
+ script << statement << "\n"
29
+ when :indent
30
+ indent_counts += 1
31
+ script << "\t"*indent_counts
32
+ when :undent
33
+ script << "\t"*indent_counts
34
+ when :dedent
35
+ if block_start
36
+ block_start = false
37
+ script << "\t"*(indent_counts-1) + "end\n"
38
+ else
39
+ script << "\t"*(indent_counts-1)
40
+ end
41
+ indent_counts -= 1
42
+ end
43
+ end
44
+ script
45
+ end
46
+
47
+ private
48
+
49
+ def scan
50
+ last_indent = 0
51
+
52
+ content.scan(/(.*?)(\n+|\Z)/).each do |line, newline|
53
+
54
+ #pd line.match(/^(\t*)(.*)/)
55
+ _, indents, statement = line.match(/^(\t*)(.*)/).to_a
56
+
57
+ # indent
58
+ # a:
59
+ # b 1
60
+ # c:
61
+ # d 1
62
+ # e:
63
+ # f 1
64
+ # g 1
65
+ indent = indents.count("\t")
66
+ counts = indent - last_indent
67
+ last_indent = indent
68
+
69
+ if counts == 0
70
+ yield :undent
71
+ else
72
+ counts.abs.times {
73
+ yield (counts>0 ? :indent : :dedent)
74
+ }
75
+ end
76
+
77
+ # statement
78
+ if statement =~ /:\s*$/
79
+ yield :block_start, statement.gsub(/\s*:\s*$/, ':')
80
+ else
81
+ yield :statement, statement
82
+ end
83
+ end
84
+
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,12 @@
1
+ class O
2
+ module Semantics
3
+ # semantic
4
+ def no
5
+ false
6
+ end
7
+
8
+ def yes
9
+ true
10
+ end
11
+ end
12
+ end
@@ -1,8 +1,8 @@
1
- module O
1
+ class O
2
2
  module VERSION
3
- MAJOR = 1
3
+ MAJOR = 2
4
4
  MINOR = 0
5
- PATCH = 2
5
+ PATCH = 0
6
6
 
7
7
  IS = [MAJOR, MINOR, PATCH].join(".")
8
8
  end
data/lib/o1.rb ADDED
@@ -0,0 +1,189 @@
1
+ #
2
+ # internal: store data in a Hash, the key of the Hash is always converted to symbol.
3
+ #
4
+ #
5
+ #
6
+ class O < Hash
7
+ autoload :VERSION, "o/version"
8
+
9
+ # PATH for O.load
10
+ PATH = []
11
+ Error = Exception.new
12
+ LoadError = Exception.new(Error)
13
+
14
+ class O_Eval
15
+ def _data
16
+ _data = {}
17
+ self.instance_variables.each do |k|
18
+ key = k[1..-1].to_sym
19
+ value = self.instance_variable_get(k)
20
+ _data[key] = value
21
+ end
22
+ _data
23
+ end
24
+ end
25
+
26
+ class << self
27
+ # convert <#Hash> to <#O>
28
+ #
29
+ # @param [hash] hash
30
+ # @return O
31
+ def from_hash hash
32
+ o = O.new
33
+ o._replace hash
34
+ end
35
+
36
+ # load a configuration file,
37
+ # support PATH, and '~/.gutenrc'
38
+ #
39
+ # first try name.rb, then use name
40
+ #
41
+ # @example
42
+ # option = O.load("~/.gutenrc")
43
+ #
44
+ # option = O.load("/absolute/path/a.rb")
45
+ #
46
+ # O::Path << "/home"
47
+ # option = O.load("guten") #=> try guten.rb; then try guten
48
+ # option = O.load("guten.rb")
49
+ #
50
+ # @param [String] name
51
+ # @return [O]
52
+ def load name
53
+ path = nil
54
+ if name =~ /^~/
55
+ file = File.expand_path(name)
56
+ path = file if File.exists?(file)
57
+ elsif File.absolute_path(name) == name
58
+ path = name if File.exists?(name)
59
+ else
60
+ catch :break do
61
+ PATH.each do |p|
62
+ ['.rb', ''].each {|ext|
63
+ file = File.join(p, name+ext)
64
+ if File.exists? file
65
+ path = file
66
+ throw :break
67
+ end
68
+ }
69
+ end
70
+ end
71
+ end
72
+
73
+ raise LoadError, "can't find file -- #{name}" unless path
74
+
75
+ eval_file path
76
+ end
77
+
78
+ # relative load a configuration file
79
+ # @see load
80
+ #
81
+ # @param [String] name
82
+ # @return [O] option
83
+ def relative_load name
84
+ pd caller if $TEST
85
+ a,file, line, method = caller[0].match(/^(.*):(\d+):.*`(.*)'$/).to_a
86
+ raise LoadError, "#{type} is called in #{file}" if file=~/\(.*\)/ # eval, etc.
87
+
88
+ file = File.readlink(file) if File.symlink?(file)
89
+
90
+ path = nil
91
+ [".rb", ""].each do |ext|
92
+ f = File.absolute_path(File.join(File.dirname(file), name+ext))
93
+ if File.exists?(f)
94
+ path = f
95
+ break
96
+ end
97
+ end
98
+
99
+ raise LoadError, "can't find file -- #{name}" unless path
100
+
101
+ eval_file path
102
+ end
103
+
104
+ private
105
+ def eval_file path
106
+ content = File.open(path){|f| f.read}
107
+ o_eval = O_Eval.new
108
+ o_eval.instance_eval(content)
109
+ O.from_hash(o_eval._data)
110
+ end
111
+
112
+ end
113
+
114
+ attr_reader :_data
115
+
116
+ def initialize default=nil, &blk
117
+ @_data = Hash.new(default)
118
+ if blk
119
+ o_eval = O_Eval.new
120
+ o_eval.instance_eval &blk
121
+ @_data.merge!(o_eval._data)
122
+ end
123
+ end
124
+
125
+ def []= key, value
126
+ @_data[key.to_sym] = value
127
+ end
128
+
129
+ def [] key
130
+ @_data[key.to_sym]
131
+ end
132
+
133
+ def + other
134
+ O.new(@_data, other._data)
135
+ end
136
+
137
+ def _replace data
138
+ case data
139
+ when Hash
140
+ @_data = data
141
+ when O
142
+ @_data = data._data
143
+ end
144
+ self
145
+ end
146
+
147
+ #
148
+ # _method goes to @_data.send(_method, ..)
149
+ # method? #=> !! @_data[:method]
150
+ # method #=> @_data[:method]
151
+ # method=value #=> @_data[:method]=value
152
+ #
153
+ def method_missing method, *args, &blk
154
+ if method =~ /(.*)=$/
155
+ @_data[$1.to_sym] = args[0]
156
+ elsif method =~ /(.*)\?$/
157
+ !! @_data[$1.to_sym]
158
+ elsif method =~ /^_(.*)/
159
+ method = $1.to_sym
160
+ args.map!{|arg| O===arg ? arg._data : arg}
161
+ rst = @_data.send(method, *args, &blk)
162
+
163
+ if [:merge!].include method
164
+ self
165
+ elsif [:merge].include method
166
+ O.new(rst)
167
+ end
168
+ else
169
+ @_data[method]
170
+ end
171
+ end
172
+
173
+ def inspect
174
+ rst = "<#O "
175
+ @_data.each do |k,v|
176
+ rst << "#{k}:#{v.inspect} "
177
+ end
178
+ rst << " >"
179
+ end
180
+
181
+ alias to_s inspect
182
+
183
+ end
184
+
185
+ module Kernel
186
+ def O default=nil, &blk
187
+ O.new(default, &blk)
188
+ end
189
+ end
data/o.gemspec CHANGED
@@ -1,5 +1,5 @@
1
- $: << "."
2
- require "version"
1
+ $: << "lib"
2
+ require "o/version"
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "o"
data/spec/data/rc.rb ADDED
File without changes
@@ -0,0 +1,120 @@
1
+ require "spec_helper"
2
+
3
+ class O::Parser
4
+ public :compile, :scan
5
+ end
6
+
7
+ describe O::Parser do
8
+ describe "#token" do
9
+ it "tests" do
10
+ content = <<EOF
11
+ a 1
12
+ b:
13
+ c {d: 1}
14
+ d 1
15
+ e:
16
+ f 1
17
+ EOF
18
+ content = <<EOF
19
+ a 1
20
+ b:
21
+ c {d: 1}
22
+ d 1
23
+ e:
24
+ f 1
25
+ g 1
26
+ EOF
27
+
28
+ parser = O::Parser.new content
29
+ parser.scan do |token, statement|
30
+ #pd token, statement
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "#compile" do
36
+ it "tests" do
37
+ content = <<EOF
38
+ a:
39
+ b 1
40
+ EOF
41
+
42
+ content1 = <<EOF
43
+ a 1
44
+ b:
45
+ c {d: 1}
46
+ d 1
47
+ e:
48
+ f 1
49
+ g 1
50
+ EOF
51
+ parser = O::Parser.new content
52
+ parser.scan do |token, statement|
53
+ #pd token, statement
54
+ end
55
+
56
+ parser = O::Parser.new content
57
+ #puts parser.compile
58
+ end
59
+
60
+
61
+ it "has no effects to normal ruby code" do
62
+ content = <<EOF
63
+ a 1
64
+ b do
65
+ c {d: 1}
66
+ d 1
67
+ e do
68
+ f 1
69
+ end
70
+ end
71
+ EOF
72
+ parser = O::Parser.new content
73
+ parser.scan do |token, statement|
74
+ #pd token, statement
75
+ end
76
+
77
+ parser = O::Parser.new content
78
+ #puts parser.compile
79
+ end
80
+
81
+ it "has both yaml-style and ruby-style" do
82
+ content = <<EOF
83
+ a 1
84
+ b:
85
+ c {d: 1}
86
+ d 1
87
+ e do
88
+ f 1
89
+ end
90
+ EOF
91
+ parser = O::Parser.new content
92
+ parser.scan do |token, statement|
93
+ #pd token, statement
94
+ end
95
+
96
+ parser = O::Parser.new content
97
+ #puts parser.compile
98
+ end
99
+
100
+ end
101
+
102
+ describe ".compile" do
103
+ it "works" do
104
+ content = <<EOF
105
+ a:
106
+ b 1
107
+ EOF
108
+ right = <<EOF
109
+ a do
110
+ b 1
111
+ end\n
112
+ EOF
113
+
114
+ O::Parser.compile(content).should == right
115
+
116
+ end
117
+ end
118
+
119
+
120
+ end