o 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  *~
2
+ Gemfile.lock
data/Gemfile CHANGED
@@ -1,8 +1,10 @@
1
1
  source :rubygems
2
2
 
3
3
  group :development do
4
+ gem 'rspec'
4
5
  gem 'watchr'
5
6
  gem 'rag'
7
+ gem 'pd'
6
8
  end
7
9
 
8
10
  gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- O, a configuration libraray for Ruby
1
+ O, a configuration gem for Ruby
2
2
  ====================================
3
3
 
4
4
  **Homepage**: [https://github.com/GutenYe/o](https://github.com/GutenYe/o) <br/>
@@ -7,32 +7,33 @@ O, a configuration libraray for Ruby
7
7
  **Documentation**: [http://rubydoc.info/gems/o/frames](http://rubydoc.info/gems/o/frames) <br/>
8
8
  **Issue Tracker**: [https://github.com/GutenYe/o/issues](https://github.com/GutenYe/o/issues) <br/>
9
9
 
10
- then name `o` comes from option/setting, short and handy, eh-ah~
10
+ The name `o` comes from option/setting, short and handy, eh-ah~
11
11
 
12
12
  Features
13
13
  --------
14
14
 
15
- * support variable, computed attribute
16
- * DSL syntax in pure ruby
17
- * tree way to do configration.
18
- * hash compatibility
15
+ * Variable and computed attribute support
16
+ * Pure Ruby DSL syntax
17
+ * Multiple configuration levels including system, user, and command-line.
18
+ * Hash compatibility
19
19
 
20
20
  Introduction
21
21
  -------------
22
22
 
23
- do configuration at three levels: system, user, cmdline
23
+ The three levels of configuration include system, user, and cmdline:
24
24
 
25
- lib/guten/rc.rb # system level
25
+ APP/lib/guten/rc.rb # system level
26
26
  ~/.gutenrc # user level
27
27
  $ guten --list or ENV[GEMFILE]=x guten # cmdline level
28
-
28
+
29
29
  module Guten
30
- Rc = O.require("guten/rc") + O.require("~/.gutenrc")
30
+ Rc = O.require("guten/rc") + O.require("~/.gutenrc") # require use $:
31
31
  Rc.list = true or Rc.gemfile = ENV[GEMFILE] # from cmdline.
32
32
  end
33
33
 
34
+ a constant works very well in many places, but you are free to use any variable.
34
35
 
35
- ### a completed example ###
36
+ ### An example ###
36
37
 
37
38
  Rc = O do
38
39
  host "localhost"
@@ -48,7 +49,7 @@ do configuration at three levels: system, user, cmdline
48
49
  time proc{|offset| Time.now} # computed attribute
49
50
  end
50
51
 
51
- alternative syntax
52
+ ### An example using alternative syntax ###
52
53
 
53
54
  Rc = O do |c|
54
55
  c.host = "localhost"
@@ -64,7 +65,7 @@ alternative syntax
64
65
  c.time = proc{|offset| Time.now}
65
66
  end
66
67
 
67
- a sugar syntax. _works in a file only_
68
+ ### An example of some sugar syntax. _works in a file only_ ###
68
69
 
69
70
  # file: guten/rc.rb
70
71
  development:
@@ -80,36 +81,50 @@ a sugar syntax. _works in a file only_
80
81
  username "guten"
81
82
  end
82
83
 
83
- this is not pure ruby syntax, but it works.
84
84
 
85
- **WARNNING**: must use \t to indent for this sugar syntax.
86
85
 
87
- ### initialize ###
86
+ **NOTE**: This is not pure ruby syntax, but it works.
87
+ In order for this to work, a tab ("\t") must be used for indention.
88
+
89
+ ### Initialize ###
88
90
 
89
- either way is fine
91
+ In order to initialize the configuration object either of the two ways can be used.
90
92
 
91
93
  Rc = O.new
92
94
  Rc = O.require "guten/rc" # from file
93
95
  Rc = O do
94
96
  a 1
95
97
  end
96
- Rc = O[a:1] # from hash
97
- Rc._merge! O_or_Hash
98
+ Rc = O[a: 1] # from a hash data
99
+ Rc._merge!(a: 1)
98
100
 
99
101
  file: "guten/rc.rb"
100
102
 
101
103
  a 1
102
104
 
105
+ Initalize with a default value
106
+
107
+ Rc = O.new
108
+ p Rc[:hello] #=> nil
109
+ Rc = O.new 1
110
+ p Rc[:hello] #=> 1
111
+ p Rc.hello #=> <#O> be careful here
112
+
113
+ ### Assignment & Access ###
103
114
 
104
- ### assignment & access ###
115
+ Flexibility has been built in to allow for various ways to assign configuration
116
+ data values and access the same values within your application. Here are some
117
+ examples of how this can be done:
105
118
 
106
- either way is fine
119
+ Assignment:
107
120
 
108
121
  Rc.age 1
109
122
  Rc.age = 1
110
123
  Rc[:age] = 1
111
124
  Rc["age"] = 1
112
- ---
125
+
126
+ Access:
127
+
113
128
  Rc.age #=> 1
114
129
  Rc.age? #=> true
115
130
  Rc[:age] #=> 1
@@ -121,15 +136,23 @@ either way is fine
121
136
  c[:age] = 2
122
137
  end
123
138
 
124
- ### node ###
139
+ ### Node ###
125
140
 
126
- Rc.a.b.c 1
141
+ Rc = O.new
142
+ Rc.a.b.c = 1
127
143
  p Rc.a.b.c #=> <#Fixnum 1>
128
144
  p Rc.a.b #=> <#O>
129
145
  p Rc.a #=> <#O>
130
- p Rc.i.dont.exists #=> <#O> #check use #_empty?
146
+ p Rc.i.dont.exists #=> <#O>
131
147
 
132
- ### variable & path ###
148
+ Rc = O.new
149
+ p Rc.a._empty? #=> true # if a node is empty?
150
+ Rc.a.b = 1
151
+ p Rc.a._empty? #=> false
152
+ p O===Rc.a #=> true # if it is a node?
153
+ p O===Rc.a.b #=> false
154
+
155
+ ### Variable & Path ###
133
156
 
134
157
  O do
135
158
  age 1
@@ -146,9 +169,9 @@ either way is fine
146
169
  end
147
170
  end
148
171
 
149
- ### namespace ###
172
+ ### Namespace ###
150
173
 
151
- either way is fine
174
+ Either way is fine:
152
175
 
153
176
  O do
154
177
  mail.stmp.address "stmp.gmail.com"
@@ -157,7 +180,7 @@ either way is fine
157
180
  end
158
181
  end
159
182
 
160
- another example
183
+ Another namespace example:
161
184
 
162
185
  O do
163
186
  age 1
@@ -172,9 +195,9 @@ another example
172
195
  end
173
196
 
174
197
 
175
- ### group ###
198
+ ### Group ###
176
199
 
177
- use namespace or use some seperate files like rails.
200
+ Use namespace or use some separate files like rails.
178
201
 
179
202
  config/
180
203
  applications.rb
@@ -183,7 +206,7 @@ use namespace or use some seperate files like rails.
183
206
  test.rb
184
207
  production.rb
185
208
 
186
- ### computed attribute ###
209
+ ### Computed attribute ###
187
210
 
188
211
  Rc = O do
189
212
  time proc{|n| Time.now}
@@ -193,19 +216,25 @@ use namespace or use some seperate files like rails.
193
216
  Rc.time = 2 # assign new value
194
217
  p Rc[:time] #=> <#Proc>
195
218
 
196
- ### semantic ###
219
+ ### Semantic ###
197
220
 
198
221
  O do
199
222
  is_started no # yes ...
200
223
  end
201
224
 
202
- for a list of semantic methods, see O::Semantics
225
+ Note: for a list of semantic methods, see O::Semantics
226
+
227
+ ### Hash compatibility ###
203
228
 
204
- ### hash compatibility ###
229
+ Internal, datas are stored as a Hash. You can access all hash methods via `_method`
230
+
231
+ Rc = O.new
232
+ Rc.a = 1
233
+ Rc._child #=> {:a=>1}
205
234
 
206
- Rc._keys # access hash method via `_method`
235
+ Rc._keys #=> [:a]
207
236
 
208
- ### temporarily change ###
237
+ ### Temporarily change ###
209
238
 
210
239
  Rc.a = 1
211
240
  Rc._temp do
@@ -214,17 +243,16 @@ for a list of semantic methods, see O::Semantics
214
243
  p Rc.a #=> 1
215
244
 
216
245
 
217
- ### access builtin method inside block ###
246
+ ### Access built-in method inside block ###
218
247
 
219
248
  Rc = O do
220
249
  sleep 10 # is a data. Rc.sleep #=> 10
221
250
  O.sleep 10 # call builtin 'sleep' method
222
251
  end
223
252
 
224
- a list of blocked methods is in O::BUILTIN_METHODS
225
-
253
+ Note: for a list of blocked methods, see O::BUILTIN_METHODS
226
254
 
227
- ### some other examples ###
255
+ ### Additional examples ###
228
256
 
229
257
  O do
230
258
  name do
@@ -243,16 +271,12 @@ a list of blocked methods is in O::BUILTIN_METHODS
243
271
  c.first = "Guten"
244
272
  end
245
273
 
246
-
247
-
248
274
  Contributing
249
275
  -------------
250
276
 
251
- * join the project.
252
- * report bugs/featues to issue tracker.
253
- * fork it and pull a request.
254
- * improve documentation.
255
- * feel free to post any ideas.
277
+ * Feel free to join the project and make contributions (by submitting a pull request)
278
+ * Submit any bugs/features/ideas to github issue tracker
279
+ * Codeing style: https://gist.github.com/1105334
256
280
 
257
281
  Install
258
282
  ----------
data/lib/o.rb CHANGED
@@ -1,277 +1,338 @@
1
1
  libdir = File.dirname(__FILE__)
2
2
  $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
3
 
4
- %w(semantics hash_method_fix parser).each{|n| require "o/#{n}"}
5
-
4
+ %w(
5
+ semantics
6
+ hash_method_fix
7
+ parser
8
+ ).each { |n| require "o/#{n}" }
9
+
10
+ # <#O> is a node, it has _child, _parent and _root attribute.
11
+ #
12
+ # Rc = O do
13
+ # a.b 1
14
+ # a.c do
15
+ # d 2
16
+ # end
17
+ # end
18
+ #
19
+ # p Rc
20
+ # #=> <#O
21
+ # :a => <#O
22
+ # :b => 1
23
+ # :c => <#O
24
+ # :d => 2>>>
25
+ #
26
+ # Rc.a #=> <#O>
27
+ # Rc.a._child #=> {:b => 1, :c => <#O>}
28
+ # Rc.a._parent #=> is Rc
29
+ # Rc.a._root #=> is Rc
30
+ #
31
+ # Rc._parent #=> nil
32
+ # Rc._root #=> is Rc
33
+ #
6
34
  class O
7
- autoload :VERSION, "o/version"
8
-
9
- Error = Class.new Exception
10
- LoadError = Class.new Error
11
-
12
- BUILTIN_METHODS = [ :p, :raise, :sleep, :rand, :srand, :exit, :require, :at_exit, :autoload, :open]
13
-
14
- class << self
15
- public *BUILTIN_METHODS
16
-
17
- # @params [String] content
18
- def eval content=nil, &blk
19
- o = O.new nil
20
- content ? o.instance_eval(Parser.compile(content)) : o.instance_eval(&blk)
21
- o._root
22
- end
23
-
24
- # convert hash, O to O
25
- # @param [O,Hash] data
26
- def [] data
27
- case data
28
- when O
29
- data
30
- when Hash
31
- o = O.new
32
- o._child = data
33
- o
34
- end
35
- end
36
-
37
- # get hash data from obj
38
- #
39
- # @param [O, Hash] obj
40
- #
41
- # @return [Hash]
42
- def get obj
43
- case obj
44
- when Hash
45
- obj
46
- when O
47
- obj._child
48
- end
49
- end
50
-
51
- # load a configuration file,
52
- # use $: and support '~/.gutenrc'
53
- #
54
- # @example
55
- # option = O.load("~/.gutenrc")
56
- #
57
- # option = O.load("/absolute/path/a.rb")
58
- #
59
- # O::Path << "/home"
60
- # option = O.load("guten") #=> try "guten.rb"; then try "guten"
61
- # option = O.load("guten.rb")
62
- #
63
- # @param [String] name
64
- # @return [O]
65
- def require name
66
- path = nil
67
-
68
- # ~/.gutenrc
69
- if name =~ /^~/
70
- file = File.expand_path(name)
71
- path = file if File.exists?(file)
72
-
73
- # /absolute/path/to/rc
74
- elsif File.absolute_path(name) == name
75
- path = name if File.exists?(name)
76
-
77
- # relative/rc
78
- else
79
- catch :break do
80
- $:.each do |p|
81
- ['.rb', ''].each {|ext|
82
- file = File.join(p, name+ext)
83
- if File.exists? file
84
- path = file
85
- throw :break
86
- end
87
- }
88
- end
89
- end
90
- end
91
-
92
- raise LoadError, "can't find file -- #{name}" unless path
93
-
94
- O.eval File.read(path)
95
- end
96
- end
97
-
98
- undef_method *BUILTIN_METHODS
99
- include Semantics
100
- include HashMethodFix
101
-
102
- attr_accessor :_parent, :_child, :_root
103
-
104
- def initialize default=nil, options={}, &blk
105
- @_root = options[:_root]
106
- @_child = Hash.new(default)
107
-
108
- if blk
109
- method = _blk2method(&blk)
110
- if blk.arity == 0
111
- method.call
112
- else
113
- method.call self
114
- end
115
- end
116
- end
117
-
118
- def _temp &blk
119
- data = _child.dup
120
- blk.call
121
- self._child = data
122
- end
123
-
124
- def _parent
125
- @_parent || nil
126
- end
127
-
128
- def _root
129
- @_root || self
130
- end
131
-
132
- def _child= obj
133
- @_child = O.get(obj)
134
- end
135
-
136
- def []= key, value
137
- key = key.respond_to?(:to_sym) ? key.to_sym : key
138
- @_child[key] = value
139
- end
140
-
141
- def [] key
142
- key = key.respond_to?(:to_sym) ? key.to_sym : key
143
- @_child[key]
144
- end
145
-
146
- def == other
147
- _child == other._child
148
- end
149
-
150
- def _dup
151
- o = O.new
152
- o._child = _child.dup
153
- o
154
- end
155
-
156
- def _replace obj
157
- self._child = O.get(obj)
158
- self
159
- end
160
-
161
- def + other
162
- raise Error, "not support type for + -- #{other.inspect}" unless O === other
163
- O.new(_child, other._child)
164
- end
165
-
166
- # convert block to method.
167
- #
168
- # you can call a block with arguments
169
- #
170
- # @example USAGE
171
- # instance_eval(&blk)
172
- # blk2method(&blk).call *args
173
- #
174
- def _blk2method &blk
175
- self.class.class_eval do
176
- define_method(:__blk2method, &blk)
177
- end
178
- method(:__blk2method)
179
- end
180
-
181
-
182
- #
183
- # .name?
184
- # .name= value
185
- # .name value
186
- # ._name
187
- #
188
- # .c
189
- # .a.b.c
190
- #
191
- def method_missing name, *args, &blk
192
- #O.p d 'missing', name, args, blk
193
-
194
- # path: root
195
- if name == :_
196
- return _root
197
-
198
- # relative path.
199
- elsif name =~ /^__+$/
200
- num = name.to_s.count('_') - 1
201
- node = self
202
- num.times {
203
- return unless node
204
- node = node._parent
205
- }
206
- return node
207
-
208
- # .name=
209
- elsif name =~ /(.*)=$/
210
- return @_child[$1.to_sym] = args[0]
211
-
212
- # .name?
213
- elsif name =~ /(.*)\?$/
214
- return !! @_child[$1.to_sym]
215
-
216
- # ._name
217
- elsif name =~ /^_(.*)/
218
- name = $1.to_sym
219
- args.map!{|arg| O===arg ? arg._child : arg}
220
- return @_child.send(name, *args, &blk)
221
-
222
- elsif Proc === @_child[name]
223
- return @_child[name].call *args
224
-
225
- # a.c # return data if has :c
226
- # a.c # create new <#O> if no :c
227
- #
228
- elsif args.empty?
229
-
230
- # a.b.c 1
231
- # a.b do
232
- # c 2
233
- # end
234
- if @_child.has_key?(name)
235
- o = @_child[name]
236
- o.instance_eval(&blk) if blk
237
- return o
238
-
239
- else
240
- next_o = O.new(nil, {_root: _root})
241
- next_o._parent = self
242
- self._child[name] = next_o
243
- next_o.instance_eval(&blk) if blk
244
- return next_o
245
- end
246
-
247
- # .name value
248
- else
249
- @_child[name] = args[0]
250
- return args[0]
251
- end
252
- end
253
-
254
- #
255
- # <#O
256
- # :b => 1
257
- # :c => 2
258
- # :d => <#O
259
- # :c => 2>>
260
- def inspect(indent=" ")
261
- o={rst: ""}
262
- o[:rst] << "<#O\n"
263
- _child.each do |k,v|
264
- o[:rst] << "#{indent}#{k.inspect} => "
265
- o[:rst] << (O === v ? "#{v.inspect(indent+" ")}\n" : "#{v.inspect}\n")
266
- end
267
- o[:rst].rstrip! << ">"
268
- end
269
-
270
- alias to_s inspect
35
+ autoload :VERSION, "o/version"
36
+
37
+ Error = Class.new Exception
38
+ LoadError = Class.new Error
39
+
40
+ BUILTIN_METHODS = [ :p, :raise, :sleep, :rand, :srand, :exit, :require, :at_exit, :autoload, :open]
41
+
42
+ class << self
43
+ public *BUILTIN_METHODS
44
+
45
+ # eval a file/string configuration.
46
+ #
47
+ # @params [String] content
48
+ # @return [O] configuration
49
+ def eval(content=nil, &blk)
50
+ o = O.new nil
51
+ content ? o.instance_eval(Parser.compile(content)) : o.instance_eval(&blk)
52
+
53
+ o._root
54
+ end
55
+
56
+ # convert Hash, O to O
57
+ # @param [O,Hash] data
58
+ # @return [O]
59
+ def [](data)
60
+ case data
61
+ when O
62
+ data
63
+ when Hash
64
+ o = O.new
65
+ o._child = data
66
+ o
67
+ end
68
+ end
69
+
70
+ # get Hash data from any object
71
+ #
72
+ # @param [O, Hash] obj
73
+ # @return [Hash]
74
+ def get(obj)
75
+ case obj
76
+ when Hash
77
+ obj
78
+ when O
79
+ obj._child
80
+ end
81
+ end
82
+
83
+ # load a configuration file,
84
+ # use $: and support '~/.gutenrc'
85
+ #
86
+ # @example
87
+ # Rc = O.require("~/.gutenrc")
88
+ #
89
+ # Rc = O.require("/absolute/path/rc.rb")
90
+ #
91
+ # Rc = O.require("guten/rc") #=> load 'APP/lib/guten/rc.rb'
92
+ # # first try 'guten/rc.rb', then 'guten/rc'
93
+ #
94
+ # @param [String] name
95
+ # @return [O]
96
+ def require(name)
97
+ path = nil
98
+
99
+ # ~/.gutenrc
100
+ if name =~ /^~/
101
+ file = File.expand_path(name)
102
+ path = file if File.exists?(file)
103
+
104
+ # /absolute/path/to/rc
105
+ elsif File.absolute_path(name) == name
106
+ path = name if File.exists?(name)
107
+
108
+ # relative/rc
109
+ else
110
+ catch :break do
111
+ $:.each { |p|
112
+ ['.rb', ''].each { |ext|
113
+ file = File.join(p, name+ext)
114
+ if File.exists? file
115
+ path = file
116
+ throw :break
117
+ end
118
+ }
119
+ }
120
+ end
121
+ end
122
+
123
+ raise LoadError, "can't find file -- #{name}" unless path
124
+
125
+ O.eval File.read(path)
126
+ end
127
+ end
128
+
129
+ undef_method *BUILTIN_METHODS
130
+ include Semantics
131
+ include HashMethodFix
132
+
133
+ # parent node, a <#O>
134
+ attr_accessor :_parent
135
+
136
+ # child node, a hash data
137
+ attr_accessor :_child
138
+
139
+ # root node, a <#O>
140
+ attr_accessor :_root
141
+
142
+ # @param [Object] (nil) default create a new hash with the defalut value
143
+ def initialize(default=nil, options={}, &blk)
144
+ @_root = options[:_root]
145
+ @_child = Hash.new(default)
146
+
147
+ if blk
148
+ method = _blk2method(&blk)
149
+ if blk.arity == 0
150
+ method.call
151
+ else
152
+ method.call self
153
+ end
154
+ end
155
+ end
156
+
157
+ # a temporarily change
158
+ def _temp(&blk)
159
+ data = _child.dup
160
+ blk.call
161
+ self._child = data
162
+
163
+ self
164
+ end
165
+
166
+ def _parent
167
+ @_parent || nil
168
+ end
169
+
170
+ def _root
171
+ @_root || self
172
+ end
173
+
174
+ def _child=(obj)
175
+ @_child = O.get(obj)
176
+ end
177
+
178
+ # set data
179
+ def []=(key, value)
180
+ key = key.respond_to?(:to_sym) ? key.to_sym : key
181
+
182
+ @_child[key] = value
183
+ end
184
+
185
+ # get data
186
+ def [](key)
187
+ key = key.respond_to?(:to_sym) ? key.to_sym : key
188
+
189
+ @_child[key]
190
+ end
191
+
192
+ def ==(other)
193
+ _child == other._child
194
+ end
195
+
196
+ # duplicate
197
+ #
198
+ # @return [O] new <#O>
199
+ def _dup
200
+ o = O.new
201
+ o._child = _child.dup
202
+
203
+ o
204
+ end
205
+
206
+ # replace with a new data
207
+ #
208
+ # @param [Hash,O] obj
209
+ # @return [O] self
210
+ def _replace(obj)
211
+ self._child = O.get(obj)
212
+
213
+ self
214
+ end
215
+
216
+ def +(other)
217
+ raise Error, "not support type for + -- #{other.inspect}" unless O === other
218
+
219
+ O.new _child, other._child
220
+ end
221
+
222
+ # everything goes here.
223
+ #
224
+ # .name?
225
+ # .name= value
226
+ # .name value
227
+ # ._name
228
+ #
229
+ # .c
230
+ # .a.b.c
231
+ #
232
+ def method_missing(name, *args, &blk)
233
+ # path: root
234
+ if name == :_
235
+ return _root
236
+
237
+ # relative path: __
238
+ elsif name =~ /^__+$/
239
+ num = name.to_s.count('_') - 1
240
+ node = self
241
+ num.times {
242
+ return unless node
243
+ node = node._parent
244
+ }
245
+ return node
246
+
247
+ # .name=
248
+ elsif name =~ /(.*)=$/
249
+ return @_child[$1.to_sym] = args[0]
250
+
251
+ # ._name
252
+ elsif name =~ /^_(.*)/
253
+ name = $1.to_sym
254
+ args.map!{|arg| O===arg ? arg._child : arg}
255
+ return @_child.send(name, *args, &blk)
256
+
257
+ # .name?
258
+ elsif name =~ /(.*)\?$/
259
+ return !! @_child[$1.to_sym]
260
+
261
+ elsif Proc === @_child[name]
262
+ return @_child[name].call *args
263
+
264
+ # a.c # return data if has :c
265
+ # a.c # create new <#O> if no :c
266
+ #
267
+ elsif args.empty?
268
+
269
+ # a.b.c 1
270
+ # a.b do
271
+ # c 2
272
+ # end
273
+ if @_child.has_key?(name)
274
+ o = @_child[name]
275
+ o.instance_eval(&blk) if blk
276
+ return o
277
+
278
+ else
279
+ next_o = O.new(nil, {_root: _root})
280
+ next_o._parent = self
281
+ self._child[name] = next_o
282
+ next_o.instance_eval(&blk) if blk
283
+ return next_o
284
+ end
285
+
286
+ # .name value
287
+ else
288
+ @_child[name] = args[0]
289
+ return args[0]
290
+ end
291
+ end
292
+
293
+ # pretty print
294
+ #
295
+ # <#O
296
+ # :b => 1
297
+ # :c => 2
298
+ # :d => <#O
299
+ # :c => 2>>
300
+ def inspect(indent=" ")
301
+ o={rst: ""}
302
+ o[:rst] << "<#O\n"
303
+ _child.each { |k,v|
304
+ o[:rst] << "#{indent}#{k.inspect} => "
305
+ o[:rst] << (O === v ? "#{v.inspect(indent+" ")}\n" : "#{v.inspect}\n")
306
+ }
307
+ o[:rst].rstrip! << ">"
308
+
309
+ o[:rst]
310
+ end
311
+
312
+ alias to_s inspect
313
+
314
+ private
315
+ # convert block to method.
316
+ #
317
+ # you can call a block with arguments
318
+ #
319
+ # @example USAGE
320
+ # instance_eval(&blk)
321
+ # blk2method(&blk).call *args
322
+ #
323
+ def _blk2method(&blk)
324
+ self.class.class_eval {
325
+ define_method(:__blk2method, &blk)
326
+ }
327
+
328
+ method(:__blk2method)
329
+ end
330
+
271
331
  end
272
332
 
273
333
  module Kernel
274
- def O default=nil, &blk
275
- O.new(default, &blk)
276
- end
334
+ # a handy method
335
+ def O(default=nil, &blk)
336
+ O.new default, &blk
337
+ end
277
338
  end
@@ -1,13 +1,26 @@
1
1
  class O
2
- module HashMethodFix
3
- def _merge! obj
4
- _child.merge! O.get(obj)
5
- self
6
- end
2
+ #
3
+ # make some hash methods works for <#O>
4
+ #
5
+ module HashMethodFix
6
+
7
+ # merge new data IN PLACE
8
+ #
9
+ # @params [Hash,O] obj
10
+ # @return [self]
11
+ def _merge! obj
12
+ _child.merge! O.get(obj)
13
+ self
14
+ end
7
15
 
8
- def _merge obj
9
- data = _child.merge(O.get(obj))
10
- O[data]
11
- end
12
- end
16
+ # merge new data
17
+ #
18
+ # @params [Hash,O] obj
19
+ # @return [O] new <#O>
20
+ def _merge obj
21
+ data = _child.merge(O.get(obj))
22
+ O[data]
23
+ end
24
+
25
+ end
13
26
  end
data/lib/o/parser.rb CHANGED
@@ -1,87 +1,99 @@
1
1
  class O
2
- class Parser
3
- attr_reader :content
2
+ # convert sugar syntax
3
+ #
4
+ # develoment:
5
+ # database 'postgresql'
6
+ #
7
+ # to a pure ruby syntax
8
+ #
9
+ # development do
10
+ # database 'postgresql'
11
+ # end
12
+ #
13
+ class Parser
14
+ # the string data.
15
+ attr_reader :content
4
16
 
5
- class << self
6
- def compile content
7
- parser = Parser.new content
8
- parser.compile
9
- end
10
- end
17
+ class << self
18
+ # a handy method for Parser.new(content).compile
19
+ def compile(content)
20
+ parser = Parser.new(content)
11
21
 
12
- def initialize content
13
- @content = content
14
- end
22
+ parser.compile
23
+ end
24
+ end
15
25
 
16
- def compile
17
- script = ""
18
- indent_counts = 0
19
- block_start = false
26
+ def initialize content
27
+ @content = content
28
+ end
20
29
 
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
30
+ # compile sugar-syntax into ruby-syntax
31
+ def compile
32
+ script = ""
33
+ indent_counts = 0
34
+ block_start = false
51
35
 
52
- content.scan(/(.*?)(\n+|\Z)/).each do |line, newline|
36
+ scan { |token, statement|
37
+ case token
38
+ when :block_start
39
+ block_start = true
40
+ statement = statement.sub(":", " do")
41
+ script << statement << "\n"
42
+ when :statement
43
+ script << statement << "\n"
44
+ when :indent
45
+ indent_counts += 1
46
+ script << "\t"*indent_counts
47
+ when :undent
48
+ script << "\t"*indent_counts
49
+ when :dedent
50
+ if block_start
51
+ block_start = false
52
+ script << "\t"*(indent_counts-1) + "end\n"
53
+ else
54
+ script << "\t"*(indent_counts-1)
55
+ end
56
+ indent_counts -= 1
57
+ end
58
+ }
53
59
 
54
- _, indents, statement = line.match(/^(\t*)(.*)/).to_a
60
+ script
61
+ end
62
+
63
+ private
64
+ def scan
65
+ last_indent = 0
55
66
 
56
- # indent
57
- # a:
58
- # b 1
59
- # c:
60
- # d 1
61
- # e:
62
- # f 1
63
- # g 1
64
- indent = indents.count("\t")
65
- counts = indent - last_indent
66
- last_indent = indent
67
+ content.scan(/(.*?)(\n+|\Z)/).each { |line, newline|
68
+ _, indents, statement = line.match(/^(\t*)(.*)/).to_a
67
69
 
68
- if counts == 0
69
- yield :undent
70
- else
71
- counts.abs.times {
72
- yield (counts>0 ? :indent : :dedent)
73
- }
74
- end
70
+ # indent
71
+ # a:
72
+ # b 1
73
+ # c:
74
+ # d 1
75
+ # e:
76
+ # f 1
77
+ # g 1
78
+ indent = indents.count("\t")
79
+ counts = indent - last_indent
80
+ last_indent = indent
75
81
 
76
- # statement
77
- if statement =~ /:\s*$/
78
- yield :block_start, statement.gsub(/\s*:\s*$/, ':')
79
- else
80
- yield :statement, statement
81
- end
82
- end
82
+ if counts == 0
83
+ yield :undent
84
+ else
85
+ counts.abs.times {
86
+ yield (counts>0 ? :indent : :dedent)
87
+ }
88
+ end
83
89
 
84
-
85
- end
86
- end
90
+ # statement
91
+ if statement =~ /:\s*$/
92
+ yield :block_start, statement.gsub(/\s*:\s*$/, ':')
93
+ else
94
+ yield :statement, statement
95
+ end
96
+ }
97
+ end
98
+ end
87
99
  end
data/lib/o/semantics.rb CHANGED
@@ -1,12 +1,14 @@
1
1
  class O
2
- module Semantics
3
- # semantic
4
- def no
5
- false
6
- end
2
+ # some semantic names for meaningfull configuration.
3
+ module Semantics
4
+ # @return false
5
+ def no
6
+ false
7
+ end
7
8
 
8
- def yes
9
- true
10
- end
11
- end
9
+ # @return true
10
+ def yes
11
+ true
12
+ end
13
+ end
12
14
  end
data/lib/o/version.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  class O
2
- module VERSION
3
- MAJOR = 2
4
- MINOR = 0
5
- PATCH = 2
6
-
7
- IS = [MAJOR, MINOR, PATCH].join(".")
8
- end
2
+ module VERSION
3
+ MAJOR = 2
4
+ MINOR = 0
5
+ PATCH = 3
6
+ PRE = ''
7
+ IS = [MAJOR, MINOR, PATCH].join(".") + PRE
8
+ end
9
9
  end
data/o.gemspec CHANGED
@@ -4,9 +4,9 @@ require "o/version"
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "o"
6
6
  s.version = O::VERSION::IS
7
- s.summary = "a configuration libraray for Ruby"
7
+ s.summary = "a configuration library for Ruby"
8
8
  s.description = <<-EOF
9
- a coonfiguration libraray for Ruby
9
+ a coonfiguration library for Ruby
10
10
  EOF
11
11
 
12
12
  s.author = "Guten"
@@ -15,7 +15,4 @@ a coonfiguration libraray for Ruby
15
15
  s.rubyforge_project = "xx"
16
16
 
17
17
  s.files = `git ls-files`.split("\n")
18
- #s.executables = ["x"]
19
-
20
- #s.add_dependency "x"
21
18
  end
data/spec/o_spec.rb CHANGED
@@ -82,6 +82,19 @@ describe O do
82
82
  @rc[:a].should == 1
83
83
  end
84
84
  end
85
+
86
+ context "initalize with default value" do
87
+ it "default value is nil" do
88
+ rc = O.new
89
+ rc[:foo].should == nil
90
+ end
91
+
92
+ it "init with default value 1" do
93
+ rc = O.new 1
94
+ rc[:foo].should == 1
95
+ end
96
+ end
97
+
85
98
  it "return <#O> if key doesn't exist" do
86
99
  rc = O.new
87
100
  rc.i.dont.exists.should be_an_instance_of O
@@ -245,6 +258,13 @@ describe O do
245
258
 
246
259
  rc._keys.should == [:a]
247
260
  end
261
+
262
+ it "_method? must comes before method?" do
263
+ rc = O.new
264
+ rc.i._empty?.should be_true
265
+ rc.i.empty?.should be_false
266
+ end
267
+
248
268
  end
249
269
 
250
270
  context "temporarily change" do
data/spec/test_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe O do
4
+ it 'works' do
5
+ o = O.new
6
+ #pd o.i
7
+ end
8
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: o
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 2.0.2
5
+ version: 2.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Guten
@@ -10,11 +10,11 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-07-26 00:00:00 Z
13
+ date: 2011-07-27 00:00:00 Z
14
14
  dependencies: []
15
15
 
16
16
  description: |
17
- a coonfiguration libraray for Ruby
17
+ a coonfiguration library for Ruby
18
18
 
19
19
  email: ywzhaifei@Gmail.com
20
20
  executables: []
@@ -27,7 +27,6 @@ files:
27
27
  - .gitignore
28
28
  - .rspec
29
29
  - Gemfile
30
- - Gemfile.lock
31
30
  - LICENSE
32
31
  - README.md
33
32
  - Ragfile
@@ -46,6 +45,7 @@ files:
46
45
  - spec/o/parser_spec.rb
47
46
  - spec/o_spec.rb
48
47
  - spec/spec_helper.rb
48
+ - spec/test_spec.rb
49
49
  homepage: http://github.com/GutenYe/o
50
50
  licenses: []
51
51
 
@@ -72,6 +72,6 @@ rubyforge_project: xx
72
72
  rubygems_version: 1.8.5
73
73
  signing_key:
74
74
  specification_version: 3
75
- summary: a configuration libraray for Ruby
75
+ summary: a configuration library for Ruby
76
76
  test_files: []
77
77
 
data/Gemfile.lock DELETED
@@ -1,31 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- o (2.0.0)
5
-
6
- GEM
7
- remote: http://rubygems.org/
8
- specs:
9
- activesupport (3.0.9)
10
- pa (1.0.2)
11
- pa (~> 1.0.0)
12
- tagen (~> 1.0.0)
13
- thor (~> 0.14.0)
14
- pd (1.0.2)
15
- rag (1.0.6)
16
- pa (~> 1.0.0)
17
- tagen (~> 1.0.0)
18
- thor (~> 0.14.0)
19
- tagen (1.0.2)
20
- activesupport
21
- pd
22
- thor (0.14.6)
23
- watchr (0.7)
24
-
25
- PLATFORMS
26
- ruby
27
-
28
- DEPENDENCIES
29
- o!
30
- rag
31
- watchr