plist4r 0.1.1 → 0.2.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.
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>