o 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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