plist4r 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -2,7 +2,11 @@
2
2
 
3
3
  Welcome to Plist4r, a ruby library for reading and writing plist files.
4
4
 
5
- Current project status: in alpha
5
+ Current status: `Beta`, 0.2.x series
6
+
7
+ We can read / write a `:launchd` plist. So thats pretty good. The API interfaces (for the pluggable backends and plist_types) are not going to change any more. The user API seems to work. If anyone would like to review the Plist4r code and give feedback / suggestions. Now is the time (whilst were still in beta).
8
+
9
+ Future `Stable` will be targeted, 0.3.x series.
6
10
 
7
11
  == Installation
8
12
 
@@ -107,7 +111,7 @@ We believe thats allright for most uses, and decided to include `next_step` for
107
111
 
108
112
  == Remaining Work
109
113
 
110
- Plist4r is currently alpha - quality software. Yet to be completed...
114
+ Plist4r has now moved from alpha to beta - quality software. TBC...
111
115
 
112
116
  * Regression Tests (rspec)
113
117
  * Test harness for the backends
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/lib/plist4r.rb CHANGED
@@ -18,18 +18,23 @@ module Plist4r
18
18
  end
19
19
 
20
20
  def string_detect_format string
21
- s = string.strip!
22
- case s[0,1]
21
+ # puts "in string_detect_format"
22
+ # puts "string = #{string.inspect}"
23
+ # s = string.strip
24
+ string.strip! if string[0,1] =~ /\s/
25
+ # s = string
26
+ # puts "s = #{s.inspect}"
27
+ case string[0,1]
23
28
  when "{","("
24
29
  :next_step
25
30
  when "b"
26
- if s =~ /^bplist/
31
+ if string =~ /^bplist/
27
32
  :binary
28
33
  else
29
34
  nil
30
35
  end
31
36
  when "<"
32
- if s =~ /^\<\?xml/ && s =~ /\<\!DOCTYPE plist/
37
+ if string =~ /^\<\?xml/ && string =~ /\<\!DOCTYPE plist/
33
38
  :xml
34
39
  else
35
40
  nil
@@ -21,11 +21,11 @@ module Plist4r
21
21
  end
22
22
  end
23
23
 
24
- # vv We also need a version of :call for matrix test harness vv
24
+ # vv We need a version of this to call our matrix test harness vv
25
25
 
26
26
  def call method_sym, *args, &blk
27
- puts "in call"
28
- puts "#{method_sym.inspect} #{args.inspect}"
27
+ # puts "in call"
28
+ # puts "#{method_sym.inspect} #{args.inspect}"
29
29
  raise "Unsupported api call #{method_sym.inspect}" unless ApiMethods.include? method_sym.to_s
30
30
  exceptions = []
31
31
  @backends.each do |backend|
@@ -3,15 +3,16 @@ require 'plist4r/backend_base'
3
3
 
4
4
  module Plist4r::Backend::Example
5
5
  class << self
6
- def from_string plist, string
7
- plist_format = Plist4r.string_detect_format string
6
+ def from_string plist
7
+ plist_string = plist.from_string
8
+ plist_format = Plist4r.string_detect_format plist.from_string
8
9
  unless [:supported_fmt1,:supported_fmt2].include? plist_format
9
10
  raise "#{self} - cant convert string of format #{plist_format}"
10
11
  end
11
12
  hash = ::ActiveSupport::OrderedHash.new
12
13
  # import / convert plist data into ruby ordered hash
13
14
  plist.import_hash hash
14
- plist.file_format = plist_format
15
+ plist.file_format plist_format
15
16
  return plist
16
17
  end
17
18
 
@@ -43,7 +44,7 @@ module Plist4r::Backend::Example
43
44
  hash = ::ActiveSupport::OrderedHash.new
44
45
  # import / convert plist data into ruby ordered hash
45
46
  plist.import_hash hash
46
- plist.file_format = file_format
47
+ plist.file_format file_format
47
48
  return plist
48
49
  end
49
50
 
@@ -2,18 +2,19 @@
2
2
  require 'plist4r/backend_base'
3
3
 
4
4
  module Plist4r::Backend::Plutil
5
- # maybe this should be a helper, included by other backends
5
+ # maybe this could be useful as a helper, used by other backends
6
6
  class << self
7
- # use tempfile to write out data
8
- # convert it into target format
7
+ def convert_file_to_xml
8
+ system "plutil -convert xml1 #{@filename}"
9
+ end
9
10
 
10
- # plutil -convert xml1 @filename
11
- # plutil -convert binary1 @filename
12
- # next step is not supported
13
-
14
- # def validate
15
- # system "plutil #{@filename}"
16
- # end
11
+ def convert_file_to_binary
12
+ system "plutil -convert binary1 #{@filename}"
13
+ end
14
+
15
+ def validate
16
+ system "plutil #{@filename}"
17
+ end
17
18
  end
18
19
  end
19
20
 
@@ -6,16 +6,17 @@ module Plist4r::Backend::RubyCocoa
6
6
  def ruby_cocoa_wrapper_rb
7
7
  @ruby_cocoa_wrapper_rb ||= <<-'EOC'
8
8
  #!/usr/bin/ruby
9
+ raise "No path given to plist4r" unless ARGV[0] && File.exists?("#{ARGV[0]}/plist4r.rb")
9
10
 
10
- include_endpath = "plist4r/mixin/ordered_hash.rb"
11
- raise "No path given to include #{include_endpath}" unless ARGV[0] && ARGV[0] =~ /#{include_endpath}$/
12
- ordered_hash_rb = ARGV[0]
11
+ dir = ARGV[0]
12
+ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
13
13
 
14
- require ordered_hash_rb
14
+ require 'plist4r/mixin/ordered_hash'
15
+ require 'osx/cocoa'
15
16
 
16
17
  class OSX::NSObject
17
18
  def to_ruby
18
- case self
19
+ case self
19
20
  when OSX::NSDate
20
21
  self.to_time
21
22
  when OSX::NSCFBoolean
@@ -45,12 +46,13 @@ end
45
46
  module Plist
46
47
  def to_xml hash
47
48
  # to_plist defaults to NSPropertyListXMLFormat_v1_0
48
- x = hash.to_ruby.to_plist
49
+ x = hash.to_plist
49
50
  puts "#{x}"
50
51
  end
52
+
51
53
  def to_binary hash
52
54
  # Here 200 == NSPropertyListBinaryFormat_v1_0
53
- x = hash.to_ruby.to_plist 200
55
+ x = hash.to_plist 200
54
56
  puts "#{x}"
55
57
  end
56
58
 
@@ -78,15 +80,8 @@ class RubyCocoaWrapper
78
80
  include Plist
79
81
 
80
82
  def exec stdin
81
- begin
82
- require 'osx/cocoa'
83
- instance_eval stdin
84
- exit 0
85
- rescue LoadError
86
- raise $!
87
- rescue
88
- raise $!
89
- end
83
+ instance_eval stdin
84
+ exit 0
90
85
  end
91
86
  end
92
87
 
@@ -104,16 +99,16 @@ EOC
104
99
  require 'plist4r/mixin/popen4'
105
100
 
106
101
  unless @rb_script && File.exists?(@rb_script.path)
107
- @rb_script ||= Tempfile.new("ruby_cocoa_wrapper.rb") do |o|
108
- o << ruby_cocoa_rb
109
- end
102
+ @rb_script = Tempfile.new "ruby_cocoa_wrapper.rb."
103
+ @rb_script.puts ruby_cocoa_wrapper_rb
104
+ @rb_script.close
110
105
  File.chmod 0755, @rb_script.path
111
106
  end
112
-
107
+
108
+ plist4r_root = File.expand_path File.join(File.dirname(__FILE__), "..", "..")
113
109
  cmd = @rb_script.path
114
- ordered_hash_rb = File.join(File.dirname(__FILE__), "..", "mixin", "ordered_hash.rb")
115
110
 
116
- pid, stdin, stdout, stderr = ::Plist4r::Popen4::popen4 cmd, ordered_hash_rb
111
+ pid, stdin, stdout, stderr = ::Plist4r::Popen4::popen4 [cmd, plist4r_root]
117
112
 
118
113
  stdin.puts stdin_str
119
114
 
@@ -126,16 +121,12 @@ EOC
126
121
  return [cmd, status, stdout_result, stderr_result]
127
122
  end
128
123
 
129
- def from_string plist, string
130
- raise "method not implemented yet (unfinished)"
131
- end
132
-
133
124
  def to_xml plist
134
125
  hash = plist.to_hash
135
- result = ruby_cocoa_exec "to_xml(\"#{hash}\")"
126
+ result = ruby_cocoa_exec "to_xml(#{hash.inspect})"
136
127
  case result[1].exitstatus
137
128
  when 0
138
- xml_string = eval result[2]
129
+ xml_string = result[2]
139
130
  return xml_string
140
131
  else
141
132
  $stderr.puts result[3]
@@ -145,40 +136,53 @@ EOC
145
136
 
146
137
  def to_binary plist
147
138
  hash = plist.to_hash
148
- result = ruby_cocoa_exec "to_binary(\"#{hash}\")"
139
+ result = ruby_cocoa_exec "to_binary(#{hash.inspect})"
149
140
  case result[1].exitstatus
150
141
  when 0
151
- binary_string = eval result[2]
142
+ binary_string = result[2]
152
143
  return binary_string
153
144
  else
154
145
  $stderr.puts result[3]
155
146
  raise "Error executing #{result[0]}. See stderr for more information"
156
147
  end
157
148
  end
158
-
159
- def open plist
160
- filename = plist.filename
149
+
150
+ def open_with_args plist, filename
161
151
  result = ruby_cocoa_exec "open(\"#{filename}\")"
162
152
  case result[1].exitstatus
163
153
  when 0
164
- hash = eval result[2]
154
+ hash = ::ActiveSupport::OrderedHash.new
155
+ eval("hash.replace("+result[2]+")")
165
156
  plist.import_hash hash
166
157
  else
167
158
  $stderr.puts result[3]
168
159
  raise "Error executing #{result[0]}. See stderr for more information"
169
160
  end
170
161
  file_format = Plist4r.file_detect_format filename
171
- plist.file_format = file_format
162
+ plist.file_format file_format
172
163
  return plist
173
164
  end
174
165
 
166
+ def from_string plist
167
+ require 'tempfile'
168
+ tf = Tempfile.new "from_string.plist."
169
+ tf.write plist.from_string
170
+ tf.close
171
+ filename = tf.path
172
+ return open_with_args plist, filename
173
+ end
174
+
175
+ def open plist
176
+ return open_with_args plist, plist.filename
177
+ end
178
+
175
179
  def save hash, filename, file_format
176
180
  filename = plist.filename_path
177
181
  file_format = plist.file_format || Config[:default_format]
178
182
  raise "#{self} - cant save file of format #{file_format}" unless [:xml,:binary].include? file_format
179
183
 
180
184
  hash = plist.to_hash
181
- result = ruby_cocoa_exec "save(\"#{hash}\",#{filename},#{file_format})"
185
+ result = ruby_cocoa_exec "save(\"#{hash.inspect}\",#{filename},#{file_format})"
182
186
  case result[1].exitstatus
183
187
  when 0
184
188
  return true
@@ -7,15 +7,18 @@ module Plist4r
7
7
  class Config
8
8
  extend Mixlib::Config
9
9
 
10
- backends [
11
- ::Plist4r::Backend::RubyCocoa,
12
- ::Plist4r::Backend::Haml,
13
- ::Plist4r::Backend::Libxml4r
14
- ]
10
+ types [] << Dir.glob(File.dirname(__FILE__) + "/plist_type/**/*.rb").collect {|b| File.basename(b,".rb") }
11
+ types.flatten!.uniq!
12
+
13
+ backends ["ruby_cocoa","haml","libxml4r"]
14
+ backends << Dir.glob(File.dirname(__FILE__) + "/backend/**/*.rb").collect {|b| File.basename(b,".rb") }
15
+ backends.flatten!.uniq!
15
16
 
16
17
  unsupported_keys true
17
- raise_any_failure false
18
+ raise_any_failure true
18
19
  deafult_format :xml
19
20
  default_path nil
20
21
  end
21
22
  end
23
+
24
+
@@ -1,4 +1,5 @@
1
1
 
2
+ require 'plist4r/config'
2
3
  require 'plist4r/mixin/ordered_hash'
3
4
 
4
5
  module Plist4r
@@ -21,13 +22,26 @@ module Plist4r
21
22
  end
22
23
 
23
24
  def method_missing method_symbol, *args, &blk
24
- puts "method_missing: #{method_symbol.inspect}, args: #{args.inspect}"
25
+ # puts "method_missing: #{method_symbol.inspect}, args: #{args.inspect}"
26
+ # puts "@hash = #{@hash.inspect}"
27
+ # puts "hi"
25
28
  valid_keys.each do |key_type, valid_keys_of_those_type|
26
29
  if valid_keys_of_those_type.include?(method_symbol.to_s.camelcase)
27
30
  puts "key_type = #{key_type}, method_symbol.to_s.camelcase = #{method_symbol.to_s.camelcase}, args = #{args.inspect}"
28
- return eval("set_or_return key_type, method_symbol.to_s.camelcase, *args, &blk")
31
+ # return eval("set_or_return key_type, method_symbol.to_s.camelcase, *args, &blk")
32
+ return set_or_return key_type, method_symbol.to_s.camelcase, *args, &blk
29
33
  end
30
34
  end
35
+ # puts "there"
36
+ # puts @plist.inspect
37
+ if @plist.unsupported_keys
38
+ key_type = nil
39
+ # return eval("set_or_return key_type, method_symbol.to_s.camelcase, *args, &blk")
40
+ return set_or_return key_type, method_symbol.to_s.camelcase, *args, &blk
41
+ else
42
+ raise "Unrecognized key for class: #{self.class.inspect}. Tried to set_or_return #{method_symbol.inspect}, with: #{args.inspect}"
43
+ end
44
+ # puts "bob"
31
45
  end
32
46
 
33
47
  def validate_value key_type, key, value
@@ -53,7 +67,7 @@ module Plist4r
53
67
  end
54
68
 
55
69
  def set_or_return key_type, key, value=nil
56
- puts "#{method_name}, key_type: #{key_type.inspect}, value: #{value.inspect}"
70
+ # puts "#{method_name}, key_type: #{key_type.inspect}, key: #{key.inspect}, value: #{value.inspect}"
57
71
  if value
58
72
  validate_value key_type, key, value unless key_type == nil
59
73
  @hash[key] = value
@@ -62,4 +76,8 @@ module Plist4r
62
76
  end
63
77
  end
64
78
  end
65
- end
79
+ end
80
+
81
+
82
+
83
+
@@ -154,9 +154,10 @@ module ActiveSupport
154
154
  self
155
155
  end
156
156
 
157
- def inspect
158
- "#<OrderedHash #{super}>"
159
- end
157
+ # This breaks passing the Hash through Stdin to RubyCocoa
158
+ # def inspect
159
+ # "#<OrderedHash #{super}>"
160
+ # end
160
161
 
161
162
  private
162
163
 
data/lib/plist4r/plist.rb CHANGED
@@ -8,14 +8,16 @@ require 'plist4r/backend'
8
8
 
9
9
  module Plist4r
10
10
  class Plist
11
- PlistOptionsHash = %w[from_string filename path file_format plist_type unsupported_keys backends]
11
+ PlistOptionsHash = %w[filename path file_format plist_type unsupported_keys backends from_string]
12
12
  FileFormats = %w[binary xml next_step]
13
13
 
14
14
  def initialize *args, &blk
15
15
  @hash = ::ActiveSupport::OrderedHash.new
16
- # @plist_type = plist_type PlistType::Plist
16
+ @plist_type = plist_type :plist
17
+
17
18
  @unsupported_keys = Config[:unsupported_keys]
18
19
  @backends = Config[:backends]
20
+
19
21
  @from_string = nil
20
22
  @filename = nil
21
23
  @file_format = nil
@@ -32,19 +34,20 @@ module Plist4r
32
34
  raise "Unrecognized first argument: #{args.first.inspect}"
33
35
  end
34
36
 
35
- @plist_cache = PlistCache.new self
37
+ @plist_cache ||= PlistCache.new self
36
38
  end
37
39
 
38
40
  def from_string string=nil
39
41
  case string
40
42
  when String
41
- plist_format = ::Plist4r.string_detect_format string
43
+ plist_format = ::Plist4r.string_detect_format(string)
42
44
  if plist_format
43
- eval "@plist_cache.from_#{format}, string"
45
+ @from_string = string
46
+ @plist_cache ||= PlistCache.new self
47
+ @plist_cache.from_string
44
48
  else
45
49
  raise "Unknown plist format for string: #{string}"
46
50
  end
47
- @from_string = string
48
51
  when nil
49
52
  @from_string
50
53
  else
@@ -101,25 +104,63 @@ module Plist4r
101
104
  end
102
105
  end
103
106
 
107
+ def detect_plist_type
108
+ stat_m = {}
109
+ stat_r = {}
110
+ Config[:types].each do |t|
111
+ case t
112
+ when String, Symbol
113
+ t = eval "::Plist4r::PlistType::#{t.to_s.camelcase}"
114
+ when Class
115
+ t = t
116
+ else
117
+ raise "Unrecognized plist type: #{t.inspect}"
118
+ end
119
+ t_sym = t.to_s.gsub(/.*:/,"").snake_case.to_sym
120
+ stat_t = t.match_stat @hash.keys
121
+
122
+ stat_m.store stat_t[:matches], t_sym
123
+ stat_r.store stat_t[:ratio], t_sym
124
+ end
125
+
126
+ most_matches = stat_m.keys.sort.last
127
+ if most_matches == 0
128
+ plist_type :plist
129
+ elsif stat_m.keys.select{ |m| m == most_matches }.size > 1
130
+ most_matches = stat_r.keys.sort.last
131
+ if stat_r.keys.select{ |m| m == most_matches }.size > 1
132
+ plist_type :plist
133
+ else
134
+ plist_type stat_r[most_matches]
135
+ end
136
+ else
137
+ plist_type stat_m[most_matches]
138
+ end
139
+ return true
140
+ end
141
+
104
142
  def plist_type plist_type=nil
105
143
  begin
106
144
  case plist_type
107
145
  when Class
108
- @plist_type = PlistType::Plist.new :hash => @hash
146
+ unless plist_type.is_a? ::Plist4r::PlistType
147
+ raise "Unrecognized Plist type. Class #{plist_type.inspect} isnt inherited from ::Plist4r::PlistType"
148
+ end
109
149
  when Symbol, String
110
- eval "pt_klass = PlistType::#{plist_type.to_s.camelcase}"
111
- @plist_type = pt_klass.new :hash => @hash
150
+ plist_type = eval "::Plist4r::PlistType::#{plist_type.to_s.camelcase}"
112
151
  when nil
113
- @plist_type
152
+ return @plist_type.to_sym
114
153
  else
115
154
  raise "Please specify a valid plist class name, eg ::Plist4r::PlistType::ClassName, \"class_name\" or :class_name"
116
155
  end
156
+ @plist_type = plist_type.new self
157
+ return @plist_type.to_sym
117
158
  rescue
118
159
  raise "Please specify a valid plist class name, eg ::Plist4r::PlistType::ClassName, \"class_name\" or :class_name"
119
160
  end
120
161
  end
121
-
122
- def unsupported_keys bool
162
+
163
+ def unsupported_keys bool=nil
123
164
  case bool
124
165
  when true,false
125
166
  @unsupported_keys = bool
@@ -143,14 +184,16 @@ module Plist4r
143
184
 
144
185
  def parse_opts opts
145
186
  PlistOptionsHash.each do |opt|
146
- eval "@#{opt} = #{opts[opt.to_sym]}" if opts[opt.to_sym]
187
+ if opts[opt.to_sym]
188
+ value = opts[opt.to_sym]
189
+ eval "self.#{opt}(value)"
190
+ end
147
191
  end
148
192
  end
149
193
 
150
194
  def open filename=nil
151
195
  @filename = filename if filename
152
196
  raise "No filename specified" unless @filename
153
- # @hash = @plist_cache.open
154
197
  @plist_cache.open
155
198
  end
156
199
 
@@ -159,7 +202,10 @@ module Plist4r
159
202
  end
160
203
 
161
204
  def edit *args, &blk
162
- instance_eval &blk
205
+ @plist_type.hash @hash
206
+ instance_eval *args, &blk
207
+ detect_plist_type
208
+ @plist_cache.update_checksum
163
209
  end
164
210
 
165
211
  def method_missing method_sym, *args, &blk
@@ -227,37 +273,24 @@ module Plist4r
227
273
  instance_eval(&@block) if @block
228
274
  end
229
275
 
276
+ def override_plist_keys?
277
+ return true unless @label == @filename.match(/^.*\/(.*)\.plist$/)[1]
278
+ vars = self.instance_variables - ["@filename","@label","@shortname","@block","@hash","@obj"]
279
+ return true unless vars.empty?
280
+ end
281
+
230
282
  def finalize
231
283
  if File.exists? @filename
232
284
  if override_plist_keys?
233
285
  # @hash = @obj = ::LibxmlLaunchdPlistParser.new(@filename).plist_struct
234
286
  # eval_plist_block(&@block) if @block
235
- write_plist
287
+ # write_plist
236
288
  end
237
289
  else
238
- write_plist
290
+ # write_plist
239
291
  end
240
- validate
241
- end
242
-
243
- def override_plist_keys?
244
- return true unless @label == @filename.match(/^.*\/(.*)\.plist$/)[1]
245
- vars = self.instance_variables - ["@filename","@label","@shortname","@block","@hash","@obj"]
246
- return true unless vars.empty?
247
- end
248
-
249
- def write_plist
250
- require 'haml'
251
- engine = Haml::Engine.new File.read("launchd_plist.haml")
252
- rendered_xml_output = engine.render self
253
- File.open(@filename,'w') do |o|
254
- o << rendered_xml_output
255
- end
256
-
257
- end
258
-
259
- def validate
260
- system "/usr/bin/plutil #{@filename}"
261
- end
292
+ end
262
293
  end
263
294
  end
295
+
296
+
@@ -23,19 +23,25 @@ module Plist4r
23
23
  checksum != last_checksum
24
24
  end
25
25
 
26
+ def from_string
27
+ @backend.call :from_string
28
+ update_checksum
29
+ @plist.detect_plist_type
30
+ @plist
31
+ end
32
+
26
33
  def to_xml
27
- puts "in to_xml"
28
- # if needs_update
34
+ if needs_update || @xml.nil?
29
35
  puts "needs update"
30
36
  update_checksum
31
37
  @xml = @backend.call :to_xml
32
- # else
33
- # @xml
34
- # end
38
+ else
39
+ @xml
40
+ end
35
41
  end
36
42
 
37
43
  def to_binary
38
- if needs_update
44
+ if needs_update || @binary.nil?
39
45
  update_checksum
40
46
  @binary = @backend.call :to_binary
41
47
  else
@@ -44,7 +50,7 @@ module Plist4r
44
50
  end
45
51
 
46
52
  def to_next_step
47
- if needs_update
53
+ if needs_update || @next_step.nil?
48
54
  update_checksum
49
55
  @next_step = @backend.call :to_next_step
50
56
  else
@@ -55,6 +61,7 @@ module Plist4r
55
61
  def open
56
62
  @backend.call :open
57
63
  update_checksum
64
+ @plist.detect_plist_type
58
65
  @plist
59
66
  end
60
67
 
@@ -5,9 +5,43 @@ module Plist4r
5
5
  class PlistType
6
6
  include ::Plist4r::DataMethods
7
7
 
8
- def initialize opts, *args, &blk
9
- raise unless opts[:hash]
10
- @hash = @orig = opts[:hash]
8
+ def initialize plist, *args, &blk
9
+ @plist = plist
10
+ @hash = @orig = plist.to_hash
11
+ end
12
+
13
+ def hash hash=nil
14
+ case hash
15
+ when ::ActiveSupport::OrderedHash
16
+ @hash = @orig = hash
17
+ when nil
18
+ @hash
19
+ else
20
+ raise "Must hash be an ::ActiveSupport::OrderedHash"
21
+ end
22
+ end
23
+
24
+ def self.valid_keys
25
+ raise "Method not implemented #{method_name.to_sym.inspect}, for class #{self.inspect}"
26
+ end
27
+
28
+ def valid_keys
29
+ self.class.valid_keys
30
+ end
31
+
32
+ def self.match_stat plist_keys
33
+ type_keys = valid_keys.values.flatten
34
+ matches = plist_keys & type_keys
35
+ include_ratio = matches.size.to_f / type_keys.size
36
+ return :matches => matches.size, :ratio => include_ratio
37
+ end
38
+
39
+ def to_s
40
+ return @string ||= self.class.to_s.gsub(/.*:/,"").snake_case
41
+ end
42
+
43
+ def to_sym
44
+ return @sym ||= to_s.to_sym
11
45
  end
12
46
  end
13
47
 
@@ -3,5 +3,11 @@ require 'plist4r/plist_type'
3
3
 
4
4
  module Plist4r
5
5
  class PlistType::Info < PlistType
6
+ def self.valid_keys
7
+ {}
8
+ end
6
9
  end
7
10
  end
11
+
12
+
13
+
@@ -4,16 +4,15 @@ require 'plist4r/plist_type'
4
4
  module Plist4r
5
5
  class PlistType::Launchd < PlistType
6
6
 
7
- def valid_keys
7
+ def self.valid_keys
8
8
  {
9
9
  :string => %w[Label UserName GroupName LimitLoadToSessionType Program RootDirectory WorkingDirectory StandardInPath StandardOutPath StandardErrorPath],
10
10
  :bool => %w[Disabled EnableGlobbing EnableTransactions OnDemand RunAtLoad InitGroups StartOnMount Debug WaitForDebugger AbandonProcessGroup HopefullyExitsFirst HopefullyExitsLast LowPriorityIO LaunchOnlyOnce],
11
11
  :integer => %w[Umask TimeOut ExitTimeOut ThrottleInterval StartInterval Nice],
12
12
  :array_of_strings => %w[LimitLoadToHosts LimitLoadFromHosts ProgramArguments WatchPaths QueueDirectories],
13
- :complex_keys => %w[inetdCompatibility KeepAlive EnvironmentVariables StartCalendarInterval SoftResourceLimits, HardResourceLimits MachServices Sockets]
13
+ :method_defined => %w[inetdCompatibility KeepAlive EnvironmentVariables StartCalendarInterval SoftResourceLimits, HardResourceLimits MachServices Sockets]
14
14
  }
15
15
  end
16
-
17
16
 
18
17
  # :call-seq:
19
18
  # inetdCompatibility({:wait => true})
@@ -3,5 +3,8 @@ require 'plist4r/plist_type'
3
3
 
4
4
  module Plist4r
5
5
  class PlistType::Plist < PlistType
6
+ def self.valid_keys
7
+ {}
8
+ end
6
9
  end
7
10
  end
data/plist4r.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{plist4r}
8
- s.version = "0.1.1"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["dreamcat4"]
12
- s.date = %q{2010-03-17}
12
+ s.date = %q{2010-03-18}
13
13
  s.description = %q{In development. Plist4R is a gem which is striving for 3 things: ease of use, speed, and reliability handling of plists. To help achieve these goals, we may plug-in or re-write this gem with one or several backends. Notably, we try to distinguish this gem by providing easy-to use DSL interface for users. For common plist type(s), such as convenience methods for Launchd Plist}
14
14
  s.email = %q{dreamcat4@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -49,11 +49,10 @@ Gem::Specification.new do |s|
49
49
  "lib/plist4r/plist_type/launchd.rb",
50
50
  "lib/plist4r/plist_type/plist.rb",
51
51
  "plist4r.gemspec",
52
- "plists/Picture of Today.plist",
53
- "plists/com.adobe.PDFAdminSettings.plist",
54
- "plists/com.apple.SoftwareUpdate.plist",
55
- "plists/foofoo.xml",
56
- "plists/test.plist",
52
+ "plists/example_big_binary.plist",
53
+ "plists/example_medium_binary_launchd.plist",
54
+ "plists/example_medium_launchd.xml",
55
+ "plists/mini.xml",
57
56
  "spec/examples.rb",
58
57
  "spec/plist4r/plist_spec.rb",
59
58
  "spec/plist4r_spec.rb",
File without changes
File without changes
data/test.rb CHANGED
@@ -2,13 +2,38 @@
2
2
 
3
3
  require 'lib/plist4r'
4
4
 
5
-
5
+ # puts "Backends = #{::Plist4r::Config[:backends].inspect}"
6
6
  # Plist4r.new
7
7
 
8
- p = Plist4r.open "plists/foofoo.xml"
8
+ p = Plist4r.open "plists/mini.xml"
9
9
 
10
10
  # puts p.inspect
11
11
  # puts p.to_hash.inspect
12
+ # puts p.to_xml
13
+
14
+ # b = p.to_binary
15
+ # puts b.inspect
16
+
17
+
18
+ # p2 = b.to_plist
19
+ # puts p2.inspect
20
+ # puts p2.to_xml
21
+
22
+ # puts p2.to_xml
23
+ # puts "plist type is"
24
+ # puts p2.plist_type.inspect
25
+
26
+ # p2.unsupported_keys false
27
+ # puts p2.unsupported_keys.inspect
28
+ # p2.<< do
29
+ # somekey "append"
30
+ # end
31
+
32
+ # puts p2.to_hash.inspect
33
+ # puts p2.to_xml
34
+
35
+
36
+
37
+
12
38
 
13
- puts p.to_xml
14
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plist4r
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dreamcat4
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-03-17 00:00:00 +00:00
12
+ date: 2010-03-18 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -84,11 +84,10 @@ files:
84
84
  - lib/plist4r/plist_type/launchd.rb
85
85
  - lib/plist4r/plist_type/plist.rb
86
86
  - plist4r.gemspec
87
- - plists/Picture of Today.plist
88
- - plists/com.adobe.PDFAdminSettings.plist
89
- - plists/com.apple.SoftwareUpdate.plist
90
- - plists/foofoo.xml
91
- - plists/test.plist
87
+ - plists/example_big_binary.plist
88
+ - plists/example_medium_binary_launchd.plist
89
+ - plists/example_medium_launchd.xml
90
+ - plists/mini.xml
92
91
  - spec/examples.rb
93
92
  - spec/plist4r/plist_spec.rb
94
93
  - spec/plist4r_spec.rb
@@ -1,75 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>autoPoll</key>
6
- <true/>
7
- <key>cMax</key>
8
- <integer>129600</integer>
9
- <key>debug</key>
10
- <true/>
11
- <key>debugInXcode</key>
12
- <false/>
13
- <key>desktopPrefs</key>
14
- <dict>
15
- <key>BackgroundColor</key>
16
- <array>
17
- <real>0.254902</real>
18
- <real>0.4117647</real>
19
- <real>0.6666667</real>
20
- </array>
21
- <key>Change</key>
22
- <string>Never</string>
23
- <key>ChangePath</key>
24
- <string>/Library/Desktop Pictures/Nature</string>
25
- <key>ChangeTime</key>
26
- <real>1800</real>
27
- <key>DrawBackgroundColor</key>
28
- <true/>
29
- <key>ImageFileAlias</key>
30
- <data>AAAAAAC4AAMAAAAAxY+tngAASCsAAAAAAEh7KwBIe0wAAMaUOpUAAAAACSD//gAAAAAAAAAA/////wABAAwASHsrAEh61QBGMgwADgAUAAkARQBhAHIAdABoAC4AagBwAGcADwAaAAwATQBhAGMAaQBuAHQAbwBzAGgAIABIAEQAEgApTGlicmFyeS9EZXNrdG9wIFBpY3R1cmVzL05hdHVyZS9FYXJ0aC5qcGcAABMAAS8A//8AAA==</data>
31
- <key>ImageFilePath</key>
32
- <string>/Library/Desktop Pictures/Nature/Earth.jpg</string>
33
- <key>NewChangePath</key>
34
- <string>/Library/Desktop Pictures/Nature</string>
35
- <key>NewImageFilePath</key>
36
- <string>/Library/Desktop Pictures/Nature/Earth.jpg</string>
37
- <key>Placement</key>
38
- <string>Crop</string>
39
- <key>Random</key>
40
- <false/>
41
- </dict>
42
- <key>error</key>
43
- <data>YnBsaXN0MDDUAQIDBAUIT1BUJHRvcFgkb2JqZWN0c1gkdmVyc2lvblkkYXJjaGl2ZXLRBgdUcm9vdIABrxAUCQoTFCIjJCUmJy00NTo7RUZHSEtVJG51bGzUCwwNDg8QERJWJGNsYXNzVk5TQ29kZVpOU1VzZXJJbmZvWE5TRG9tYWlugBMT/////////BeAA4ACXxAQTlNVUkxFcnJvckRvbWFpbtMVFgsXHCFaTlMub2JqZWN0c1dOUy5rZXlzpBgZGhuACIAJgAuADKQdHh8ggASABYAGgAeAEl8QGk5TRXJyb3JGYWlsaW5nVVJMU3RyaW5nS2V5XxAUTlNFcnJvckZhaWxpbmdVUkxLZXlfEBZOU0xvY2FsaXplZERlc2NyaXB0aW9uXxARTlNVbmRlcmx5aW5nRXJyb3JfEJFodHRwOi8vcGhvdG9ncmFwaHkubmF0aW9uYWxnZW9ncmFwaGljLmNvbS9zdGF0aWNmaWxlcy9OR1MvU2hhcmVkL1N0YXRpY0ZpbGVzL1Bob3RvZ3JhcGh5L0ltYWdlcy9QT0QvYS9hdG9tLWJvbWItYmlraW5pLWF0b2xsLTYzMzE3OC0xMDA1MDkteGwuanBn0ygpCyoYLFdOUy5iYXNlW05TLnJlbGF0aXZlgACACIAK0i4vMDNYJGNsYXNzZXNaJGNsYXNzbmFtZaIxMlVOU1VSTFhOU09iamVjdFVOU1VSTF8QFlRoZSByZXF1ZXN0IHRpbWVkIG91dC7UCwwNDg83ODmAExP////////8F4AOgA1fEBdrQ0ZFcnJvckRvbWFpbkNGTmV0d29ya9MVFgs8QCGjGRgagAmACIALo0FCQ4APgBCAEYASXxAUTlNFcnJvckZhaWxpbmdVUkxLZXlfEBpOU0Vycm9yRmFpbGluZ1VSTFN0cmluZ0tleV8QFk5TTG9jYWxpemVkRGVzY3JpcHRpb27SLi9JSqJKMlxOU0RpY3Rpb25hcnnSLi9MTqJNMldOU0Vycm9yV05TRXJyb3ISAAGGoF8QD05TS2V5ZWRBcmNoaXZlcgAIABEAFgAfACgAMgA1ADoAPABTAFkAYgBpAHAAewCEAIYAjwCRAJMApgCtALgAwADFAMcAyQDLAM0A0gDUANYA2ADaANwA+QEQASkBPQHRAdgB4AHsAe4B8AHyAfcCAAILAg4CFAIdAiMCPAJFAkcCUAJSAlQCbgJ1AnkCewJ9An8CgwKFAocCiQKLAqICvwLYAt0C4ALtAvIC9QL9AwUDCgAAAAAAAAIBAAAAAAAAAFEAAAAAAAAAAAAAAAAAAAMc</data>
44
- <key>filename</key>
45
- <string></string>
46
- <key>frequency</key>
47
- <string>daily</string>
48
- <key>hMin</key>
49
- <integer>240</integer>
50
- <key>ignoreLostConnectivity</key>
51
- <false/>
52
- <key>imageSource</key>
53
- <data>YnBsaXN0MDDUAQIDBAUI2ttUJHRvcFgkb2JqZWN0c1gkdmVyc2lvblkkYXJjaGl2ZXLRBgdUcm9vdIABrxAwCQofICElLC0uNjlBSktMVFlhYmVocHR5eoKGi4ycnZ6foKGnqKyytbm/wMTIzNDVVSRudWxs2gsMDQ4PEBESExQVFhcYGRoYHB0cWGRhdGFGaWxlU3VpZFV0aXRsZVdkYXRhVXJsW2Rlc2NyaXB0aW9uXxAPX29iakluaXRpYWxpemVkWGltYWdlVXJsVXF1ZXJ5ViRjbGFzc1VlcnJvcoADgASAB4ACgAiABoACgACAL4AAXxCRaHR0cDovL3Bob3RvZ3JhcGh5Lm5hdGlvbmFsZ2VvZ3JhcGhpYy5jb20vc3RhdGljZmlsZXMvTkdTL1NoYXJlZC9TdGF0aWNGaWxlcy9QaG90b2dyYXBoeS9JbWFnZXMvUE9EL2EvYXRvbS1ib21iLWJpa2luaS1hdG9sbC02MzMxNzgtMTAwNTA5LXhsLmpwZ18QaC9Vc2Vycy9pZC9QaWN0dXJlIG9mIFRvZGF5L3Rlc3QvcGljdHVyZXMvTmF0aW9uYWwgR2VvZ3JhcGhpYy9hdG9tLWJvbWItYmlraW5pLWF0b2xsLTYzMzE3OC0xMDA1MDkteGwuanBn0iITIyRZTlMuc3RyaW5nXxAoYWJlODJhYmFmY2I2NTM1NzQwNzIxODFlYzMxYzQwMDRjZDBiZjc4YYAF0iYnKClYJGNsYXNzZXNaJGNsYXNzbmFtZaMpKitfEA9OU011dGFibGVTdHJpbmdYTlNTdHJpbmdYTlNPYmplY3QJbxBVAEEAdABvAG0AaQBjACAAQgBvAG0AYgAgAFQAZQBzAHQAIABQAGgAbwB0AG8ALAAgAEIAaQBrAGkAbgBpACAAQQB0AG8AbABsACAAVwBhAGwAbABwAGEAcABlAHIAICATACAATgBhAHQAaQBvAG4AYQBsACAARwBlAG8AZwByAGEAcABoAGkAYwAgAFAAaABvAHQAbwAgAG8AZgAgAHQAaABlACAARABhAHnULzATMTIzNDVfEA9OU0F0dHJpYnV0ZUluZm9cTlNBdHRyaWJ1dGVzWE5TU3RyaW5ngCyACoAugAnSIhM3JF8RAURBdG9tIEJvbWIgVGVzdCwgQmlraW5pIEF0b2xsClBob3RvZ3JhcGggYnkgVS5TLiBOYXZ5ClRoaXMgbW9udGggaW4gUGhvdG8gb2YgdGhlIERheTogSW1hZ2VzIEZyb20gdGhlIE5hdGlvbmFsIEdlb2dyYXBoaWMgQXJjaGl2ZQpUaGUgc2Vjb25kIGF0b21pYyBib21iIHRlc3RlZCBpbiBPcGVyYXRpb24gQ3Jvc3Nyb2FkcwoKRnJvbSB0aGUgdXBjb21pbmcgTmF0aW9uYWwgR2VvZ3JhcGhpYyBib29rIFRoZSBJbWFnZSBDb2xsZWN0aW9uLCBkdWUgZmFsbCAyMDA5LiBTaG9wIGZvciBvdGhlciBwaG90b2dyYXBoeSBib29rcyBmcm9tIE5hdGlvbmFsIEdlb2dyYXBoaWMuCgqABdI6EztAWk5TLm9iamVjdHOkPD0+P4ALgBSAGIAcgCvTOkITQ0ZJV05TLmtleXOiREWADoAQokdIgAyADYATXxAQTlNQYXJhZ3JhcGhTdHlsZVZOU0ZvbnTUTU5PE1AcUlNfEBJOU1BhcmFncmFwaFNwYWNpbmdaTlNUYWJTdG9wc1tOU0FsaWdubWVudCNAGAAAAAAAAIAAEASAD9ImJ1VYo1ZXK18QF05TTXV0YWJsZVBhcmFncmFwaFN0eWxlXxAQTlNQYXJhZ3JhcGhTdHlsZV8QF05TTXV0YWJsZVBhcmFncmFwaFN0eWxl1FpbE1xdXl9gVk5TU2l6ZVZOU05hbWVYTlNmRmxhZ3MjQDYAAAAAAACAEYASEBBfEBFMdWNpZGFHcmFuZGUtQm9sZNImJ2NkomQrVk5TRm9udNImJ2ZnomcrXE5TRGljdGlvbmFyedM6QhNpbEmiamuAFYAWokdIgAyADYAT1E1OTxNxHFJTI0AYAAAAAAAAgACAD9RaWxNcdXZfeCNAJgAAAAAAAIAXgBIQEFxMdWNpZGFHcmFuZGXTOkITe35Jonx9gBmAGqJHSIAMgA2AE9RNTk8TgxxSUyNAGAAAAAAAAIAAgA/UWlsTXIeIX4ojQCYAAAAAAACAG4ASEBBfEBFIZWx2ZXRpY2EtT2JsaXF1ZdM6QhONlEmmjo9rkZKTgCGAIoAWgCWAJ4AoppWWSJhHmoAdgB6ADYAfgAyAIIATW05TVW5kZXJsaW5lVk5TTGlua1dOU0NvbG9yWE5TQ3Vyc29yEAHToqMTHKWmV05TLmJhc2VbTlMucmVsYXRpdmWAAIAjgCRfEG9odHRwOi8vc2hvcC5uYXRpb25hbGdlb2dyYXBoaWMuY29tL2NvdXBvbi5qc3A/Y29kZT1NUjIwMjEyJlVSTD0lMkZqdW1wLmpzcCUzRml0ZW1JRCUzRDQ0NDUlMjZpdGVtVHlwZSUzRFBST0RVQ1TSJiepq6KqK1VOU1VSTFVOU1VSTNOtrhOvsLFVTlNSR0JcTlNDb2xvclNwYWNlTxARMCAwIDAuOTMzMzMzMzM3MwAQAoAm0iYns7SitCtXTlNDb2xvctRNTk8TthxSUyNAGAAAAAAAAIAAgA/TursTvL2+WU5TSG90U3BvdFxOU0N1cnNvclR5cGWAKRAMgCpXezgsIC04fdImJ8HDosIrWE5TQ3Vyc29yWE5TQ3Vyc29y0iYnxcajxscrXk5TTXV0YWJsZUFycmF5V05TQXJyYXnSyRPKy1dOUy5kYXRhTxAQHQAYAUsCYwEUAiABEQMcAYAt0iYnzc6jzs8rXU5TTXV0YWJsZURhdGFWTlNEYXRh0iYn0dSj0tMrXxAZTlNNdXRhYmxlQXR0cmlidXRlZFN0cmluZ18QEk5TQXR0cmlidXRlZFN0cmluZ18QGU5TTXV0YWJsZUF0dHJpYnV0ZWRTdHJpbmfSJifW2aPX2CtdUFRJbWFnZVNvdXJjZVtMT1dlYlNvdXJjZV1QVEltYWdlU291cmNlEgABhqBfEA9OU0tleWVkQXJjaGl2ZXIACAARABYAHwAoADIANQA6ADwAbwB1AIoAkwCXAJ0ApQCxAMMAzADSANkA3wDhAOMA5QDnAOkA6wDtAO8A8QDzAYcB8gH3AgECLAIuAjMCPAJHAksCXQJmAm8CcAMdAyYDOANFA04DUANSA1QDVgNbBKMEpQSqBLUEugS8BL4EwATCBMQEywTTBNYE2ATaBN0E3wThBOME9gT9BQYFGwUmBTIFOwU9BT8FQQVGBUoFZAV3BZEFmgWhBagFsQW6BbwFvgXABdQF2QXcBeMF6AXrBfgF/wYCBgQGBgYJBgsGDQYPBhgGIQYjBiUGLgY3BjkGOwY9BkoGUQZUBlYGWAZbBl0GXwZhBmoGcwZ1BncGgAaJBosGjQaPBqMGqgaxBrMGtQa3BrkGuwa9BsQGxgbIBsoGzAbOBtAG0gbeBuUG7Qb2BvgG/wcHBxMHFQcXBxkHiweQB5MHmQefB6YHrAe5B80HzwfRB9YH2QfhB+oH8wf1B/cH/ggICBUIFwgZCBsIIwgoCCsINAg9CEIIRghVCF0IYghqCH0IfwiECIgIlgidCKIIpgjCCNcI8wj4CPwJCgkWCSQJKQAAAAAAAAIBAAAAAAAAANwAAAAAAAAAAAAAAAAAAAk7</data>
54
- <key>lastUpdate</key>
55
- <date>2009-10-05T16:37:47Z</date>
56
- <key>maxPictures</key>
57
- <integer>1</integer>
58
- <key>nextDueDate</key>
59
- <date>2009-10-05T22:45:00Z</date>
60
- <key>pollingInterval</key>
61
- <integer>28799</integer>
62
- <key>previousPolls</key>
63
- <integer>2</integer>
64
- <key>ptEnabled</key>
65
- <false/>
66
- <key>savePath</key>
67
- <string>~/Picture of Today/test/pictures/National Geographic</string>
68
- <key>selectedSource</key>
69
- <integer>4</integer>
70
- <key>updateInterval</key>
71
- <integer>86400</integer>
72
- <key>updateTime</key>
73
- <date>2000-01-01T23:45:00Z</date>
74
- </dict>
75
- </plist>