plist4r 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -19,3 +19,5 @@ rdoc
19
19
  pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
+ .yardoc
23
+ doc
data/.nojekyll ADDED
File without changes
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --no-private
data/README.rdoc CHANGED
@@ -1,12 +1,10 @@
1
1
  = plist4r
2
2
 
3
- Welcome to Plist4r, a ruby library for reading and writing plist files.
3
+ Plist4r is a friendly ruby library for reading and writing plist files.
4
4
 
5
- Current status: `Beta`, 0.2.x series
5
+ ==== Current status: Beta, 0.2.x series
6
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.
7
+ We can read / write various kinds of plist files reliably. The API interfaces (for the pluggable backends and plist_types) are mature. The user API works well. Searchable Documentation is included, complete with examples.
10
8
 
11
9
  == Installation
12
10
 
@@ -36,20 +34,6 @@ Future `Stable` will be targeted, 0.3.x series.
36
34
 
37
35
  p.save
38
36
 
39
- == Plist 'Types'
40
-
41
- A Plist type can be one of `%w[info launchd]`, and is the data type for the whole plist file. A plist data type can provide convenience methods to set Type-specific plist structures. For example "Sockets" in a launchd plist.
42
-
43
- Plist types are also useful to disallow keys which arent recognized or supported by that format. Flicking `:unsupported_keys` the Plist4r config will enable this:
44
-
45
- ::Plist4r::Config[:unsupported_keys] = false
46
-
47
- Or individually, per plist object with
48
-
49
- plist.unsupported_keys false
50
-
51
- Default is true, which allows editing of any plist keys. We think thats a good choice, since unsupported keys can already be present in existing plist files, which are loadable by Plist4r.
52
-
53
37
  == Plist4r Backends
54
38
 
55
39
  There are now a number of ruby libraries which can read / write plist files. The aim of plist4r is to utilize the individual best features from all of those libraries, as a series of "backends". And hide those behind a "frontend" that is easy to work with.
@@ -66,6 +50,20 @@ And (as above) the 3 supported Plist file formats are
66
50
 
67
51
  We believe thats allright for most uses, and decided to include `next_step` for completeness. `NextStep` is also known by other names such as `OpenStep` and (more updated version) `GNU Step`. For example the apple `defaults` command on Mac OS-X will still return `NextStep` formatted plist data.
68
52
 
53
+ == Plist4r Types
54
+
55
+ A Plist type can be one of `%w[plist info launchd]`, and is the data type for the whole plist file. The plist data type provides convenience methods for setting the Type-specific data structures. For example "Sockets" in a launchd plist.
56
+
57
+ Plist types are also useful to disallow keys which arent recognized or supported by that format. Setting `:strict_keys true` the Plist4r::Config object will globaly enable strict keys.
58
+
59
+ ::Plist4r::Config[:unsupported_keys] = true
60
+
61
+ Or individually, per plist object with
62
+
63
+ plist.strict_keys false
64
+
65
+ Default is false, which allows editing of any arbitrary plist keys. We think thats a good choice, since unsupported keys can already be present in many existing plist files.
66
+
69
67
  == More Examples
70
68
 
71
69
  module ::Plist4r::Backend::MyPlistReaderWriter
@@ -116,11 +114,8 @@ Plist4r has now moved from alpha to beta - quality software. TBC...
116
114
  * Regression Tests (rspec)
117
115
  * Test harness for the backends
118
116
  * Testing of the individual backends
119
- * Tests for Plist Types
120
- * RDoc Documentation
121
- * Script for embedding / inlining Plist4r into Homebrew
122
117
  * A Plist Type for Info.plist
123
- * Command line interface (hopefully mixlib-cli)
118
+ * Tests for Plist Types
124
119
 
125
120
  == Notes on Patches/Pull Requests
126
121
 
data/Rakefile CHANGED
@@ -47,11 +47,20 @@ end
47
47
 
48
48
  task :default => :spec
49
49
 
50
- begin
51
- require 'yard'
52
- YARD::Rake::YardocTask.new
53
- rescue LoadError
54
- task :yardoc do
55
- abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
56
- end
50
+ require 'yard'
51
+ YARD::Rake::YardocTask.new do |t|
52
+ t.after = lambda { `touch doc/.nojekyll` }
57
53
  end
54
+
55
+ Jeweler::GhpagesTasks.new do |ghpages|
56
+ ghpages.push_on_release = true
57
+ ghpages.set_repo_homepage = true
58
+ ghpages.user_github_com = false
59
+ ghpages.doc_task = "yard"
60
+ ghpages.keep_files = []
61
+ ghpages.map_paths = {
62
+ ".nojekyll" => "",
63
+ "doc" => "",
64
+ }
65
+ end
66
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.2.2
data/bin/plist4r ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ dir = File.expand_path "../lib", File.dirname(__FILE__)
4
+ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
5
+
6
+ require 'plist4r/application'
7
+ app = Plist4r::Application.new
8
+
data/lib/plist4r.rb CHANGED
@@ -4,26 +4,44 @@ $LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
4
4
 
5
5
  require 'plist4r/plist'
6
6
 
7
+ # Almost everything required by Plist4r is fully encapsulated within the {Plist4r} namespace.
8
+ # However there are a few exceptions. We had to add a couple methods to {Object} and {String}.
7
9
  module Plist4r
8
10
  class << self
11
+
12
+ # Calls Plist4r::Plist.new with the supplied arguments and block
13
+ #
14
+ # @return [Plist4r::Plist] The new Plist object
15
+ # @see Plist4r::Plist#initialize
16
+ # @example Create new, empty plist
17
+ # Plist4r.new => #<Plist4r::Plist:0x111546c @file_format=nil, ...>
9
18
  def new *args, &blk
10
19
  # puts args.inspect
11
20
  return Plist.new *args, &blk
12
21
  end
13
22
 
23
+ # Opens a plist file
24
+ #
25
+ # @param [String] filename plist file to load
26
+ # @return [Plist4r::Plist] The loaded Plist object
27
+ # @example Load from file
28
+ # Plist4r.open("example.plist") => #<Plist4r::Plist:0x1152d1c @file_format="xml", ...>
29
+ # @see Plist4r::Plist#initialize
30
+ # @see Plist4r::Plist#open
14
31
  def open filename, *args, &blk
15
- # puts args.inspect
16
32
  p = Plist.new filename, *args, &blk
17
33
  p.open
18
34
  end
19
-
35
+
36
+ # Given an string of Plist data, peek the first few bytes and detect the file format
37
+ #
38
+ # @param [String] string of plist data
39
+ # @return [Symbol] A Symbol representing the plist data type. One of: Plist4r::Plist.FileFormats
40
+ # @see Plist4r::Plist.FileFormats
41
+ # @example
42
+ # Plist4r.string_detect_format("{ \"key1\" = \"value1\"; \"key2\" = \"value2\"; }") => :next_step
20
43
  def string_detect_format string
21
- # puts "in string_detect_format"
22
- # puts "string = #{string.inspect}"
23
- # s = string.strip
24
44
  string.strip! if string[0,1] =~ /\s/
25
- # s = string
26
- # puts "s = #{s.inspect}"
27
45
  case string[0,1]
28
46
  when "{","("
29
47
  :next_step
@@ -44,6 +62,11 @@ module Plist4r
44
62
  end
45
63
  end
46
64
 
65
+ # Given a Plist filename, peek the first few bytes and detect the file format
66
+ #
67
+ # @param [String] filename plist file to check
68
+ # @see Plist4r.string_detect_format
69
+ # @see Plist4r::Plist.FileFormats
47
70
  def file_detect_format filename
48
71
  string_detect_format File.read(filename)
49
72
  end
@@ -51,6 +74,11 @@ module Plist4r
51
74
  end
52
75
 
53
76
  class String
77
+
78
+ # Converts a string of plist data into a new Plist4r::Plist object
79
+ #
80
+ # @return [Plist4r::Plist] The new Plist object
81
+ # @see Plist4r::Plist#initialize
54
82
  def to_plist
55
83
  return ::Plist4r.new(:from_string => self)
56
84
  end
@@ -0,0 +1,19 @@
1
+ require 'plist4r/config'
2
+ require 'plist4r/options'
3
+ require 'plist4r/commands'
4
+
5
+ module Plist4r
6
+ # The Plist4r Application Object. Instantiated for command-line mode
7
+ # @see Plist4r::CLI
8
+ class Application
9
+
10
+ def initialize *args, &blk
11
+ @cli = Plist4r::CLI.new
12
+ Plist4r::Config[:args] = @cli.parse
13
+
14
+ puts "Plist4r::Config[:args] = " + Plist4r::Config[:args].inspect
15
+ @commands = Plist4r::Commands.new
16
+ @commands.run
17
+ end
18
+ end
19
+ end
@@ -4,9 +4,17 @@ require 'plist4r/backend_base'
4
4
  require 'plist4r/mixin/ordered_hash'
5
5
 
6
6
  module Plist4r
7
+ # This class is the Backend broker. The purpose of this object is to manage and handle API
8
+ # calls, passing them over to the appropriate Plist4r backends.
7
9
  class Backend
10
+ # The list of known backend API methods. Any combination or subset of API methods
11
+ # can be implemented by an individual backend.
12
+ # @see Plist4r::Backend::Example
8
13
  ApiMethods = %w[from_string to_xml to_binary to_next_step open save]
9
-
14
+
15
+ # A new instance of Backend. A single Backend will exist for the the life of
16
+ # the Plist object. The attribute @plist is set during initialization and
17
+ # refers back to the plist instance object.
10
18
  def initialize plist, *args, &blk
11
19
  @plist = plist
12
20
  @backends = plist.backends.collect do |b|
@@ -22,7 +30,20 @@ module Plist4r
22
30
  end
23
31
 
24
32
  # vv We need a version of this to call our matrix test harness vv
25
-
33
+ # Call a Plist4r API Method. Here, we usually pass a {Plist4r::Plist} object
34
+ # as one of the parameters, which will also contain all the input data to work on.
35
+ #
36
+ # This function loops through the array of available backends, and calls the
37
+ # same method on the first backend found to implemente the specific request.
38
+ #
39
+ # If the request fails, the call is re-executed on the next available
40
+ # backend.
41
+ #
42
+ # The plist object is updated in-place.
43
+ #
44
+ # @raise if no backend is able to sucessfully execute the request.
45
+ # @param [Symbol] method_sym The API method call to execute
46
+ # @param *args Any optional arguments to pass to the backend
26
47
  def call method_sym, *args, &blk
27
48
  # puts "in call"
28
49
  # puts "#{method_sym.inspect} #{args.inspect}"
@@ -1,39 +1,77 @@
1
1
 
2
2
  require 'plist4r/backend_base'
3
3
 
4
+ # An example Plist4r Backend.
5
+ # These examples demonstrate the common convenience methods which are available to your backend.
6
+ # Its not necessary to implement all of the API methods in your backend.
7
+ # You may selectively implement any single method or method(s).
8
+ #
9
+ # In the case of {from_string} and {open}, the source plist format is not known beforehand.
10
+ # For those cases you should call {Plist4r.string_detect_format} or {Plist4r.file_detect_format}
11
+ # as appropriate. Then raise an exception for those situation where backend is unable to continue.
12
+ #
13
+ # For example, if your backend is only able to load :xml files, then it should raise an exception
14
+ # whenever it encounters :binary or :next_step formatted files. This is intentional.
15
+ # By throwing the error, it means the API call can be picked up and passed on to the next available backend.
16
+ #
17
+ # @see Plist4r::Backend
4
18
  module Plist4r::Backend::Example
5
19
  class << self
20
+
21
+ # Parse a String of plist data and store it into the supplied {Plist4r::Plist}
22
+ # * Please click "View Source" for the example.
23
+ # @param [Plist4r::Plist] plist The plist object to read the string from
24
+ # @return [Plist4r::Plist] the same plist object, but updated to match its from_string
25
+ # @see Plist4r::Plist#from_string
26
+ # @see Plist4r.string_detect_format
6
27
  def from_string plist
7
28
  plist_string = plist.from_string
8
29
  plist_format = Plist4r.string_detect_format plist.from_string
9
30
  unless [:supported_fmt1,:supported_fmt2].include? plist_format
10
31
  raise "#{self} - cant convert string of format #{plist_format}"
11
32
  end
12
- hash = ::ActiveSupport::OrderedHash.new
33
+ hash = ::Plist4r::OrderedHash.new
13
34
  # import / convert plist data into ruby ordered hash
14
35
  plist.import_hash hash
15
36
  plist.file_format plist_format
16
37
  return plist
17
38
  end
18
39
 
40
+ # Convert a {Plist4r::Plist} into an "xml" formatted plist String
41
+ # * Please click "View Source" for the example.
42
+ # @param [Plist4r::Plist] plist The plist object to convert
43
+ # @return [String] the xml string
19
44
  def to_xml plist
20
45
  hash = plist.to_hash
21
46
  xml_string = "Convert the plists's nested ruby hash into xml here"
22
47
  return xml_string
23
48
  end
24
49
 
25
- def to_binary
50
+ # Convert a {Plist4r::Plist} into an "binary" formatted plist String
51
+ # * Please click "View Source" for the example.
52
+ # @param [Plist4r::Plist] plist The plist object to convert
53
+ # @return [String] the binary string
54
+ def to_binary plist
26
55
  hash = plist.to_hash
27
56
  binary_string = "Convert the plists's nested ruby hash into binary format here"
28
57
  return binary_string
29
58
  end
30
59
 
31
- def to_next_step
60
+ # Convert a {Plist4r::Plist} into a "next_step" formatted plist String
61
+ # * Please click "View Source" for the example.
62
+ # @param [Plist4r::Plist] plist The plist object to convert
63
+ # @return [String] the next_step string
64
+ def to_next_step plist
32
65
  hash = plist.to_hash
33
66
  next_step_string = "Convert the plists's nested ruby hash into next_step format here"
34
67
  return next_step_string
35
68
  end
36
69
 
70
+ # Open a plist file and store the contents into the supplied {Plist4r::Plist}
71
+ # * Please click "View Source" for the example.
72
+ # @param [Plist4r::Plist] plist The plist object to convert
73
+ # @return [String] the next_step string
74
+ # @see Plist4r.file_detect_format
37
75
  def open plist
38
76
  filename = plist.filename_path
39
77
  file_format = Plist4r.file_detect_format filename
@@ -41,13 +79,16 @@ module Plist4r::Backend::Example
41
79
  raise "#{self} - cant load file of format #{file_format}"
42
80
  end
43
81
  plist_file_as_string = File.read(filename)
44
- hash = ::ActiveSupport::OrderedHash.new
82
+ hash = ::Plist4r::OrderedHash.new
45
83
  # import / convert plist data into ruby ordered hash
46
84
  plist.import_hash hash
47
85
  plist.file_format file_format
48
86
  return plist
49
87
  end
50
88
 
89
+ # @param [Plist4r::Plist] plist The plist object to read the filename from
90
+ # @return [Plist4r::Plist] the same plist object, but updated to match the file contents
91
+ # @see Plist4r::Plist#filename_path
51
92
  def save plist
52
93
  filename = plist.filename_path
53
94
  file_format = plist.file_format || Config[:default_format]
@@ -1,6 +1,7 @@
1
1
 
2
2
  require 'plist4r/backend_base'
3
3
 
4
+ # Requires Haml. Implements writing and saving for the :xml file format only.
4
5
  module Plist4r::Backend::Haml
5
6
  class << self
6
7
  def to_xml_haml
@@ -1,10 +1,11 @@
1
1
 
2
2
  require 'plist4r/backend_base'
3
3
 
4
+ # Requires Libxml4r. Implements loading / parsing for the :xml file format only.
4
5
  module Plist4r::Backend::Libxml4r
5
6
  class << self
6
7
  def tree_hash n
7
- hash = ::ActiveSupport::OrderedHash.new
8
+ hash = ::Plist4r::OrderedHash.new
8
9
  n_xml_keys = n.nodes["key"]
9
10
  n_xml_keys.each do |n|
10
11
  k = n.inner_xml
@@ -62,7 +63,7 @@ module Plist4r::Backend::Libxml4r
62
63
  else
63
64
  root = doc.node["/plist/array"]
64
65
  if root
65
- ordered_hash = ::ActiveSupport::OrderedHash.new
66
+ ordered_hash = ::Plist4r::OrderedHash.new
66
67
  ordered_hash["Array"] = tree_array root
67
68
  end
68
69
  end
@@ -1,8 +1,11 @@
1
1
 
2
2
  require 'plist4r/backend_base'
3
3
 
4
+ # This backend does not implement any official Plist4r API methods.
5
+ # But can be used to enhance and add functionality to other backends.
6
+ #
7
+ # (Mac OSX operating systems only)
4
8
  module Plist4r::Backend::Plutil
5
- # maybe this could be useful as a helper, used by other backends
6
9
  class << self
7
10
  def convert_file_to_xml
8
11
  system "plutil -convert xml1 #{@filename}"
@@ -1,6 +1,13 @@
1
1
 
2
2
  require 'plist4r/backend_base'
3
3
 
4
+ # This backend only works on MacOSX. It supports everything except {Backend::Example.to_next_step},
5
+ # and saving in the :next_step file format. Here we are calling the stock OSX Ruby in a seperate process.
6
+ # It isolates the runtime from any shared lib (.so) LoadErrors. And allows calling from other installed
7
+ # Ruby instances (eg REE), which dont usually have RubyCocoa enabled.
8
+ #
9
+ # This Backend should work for any 10.5 (Leopard), 10.6 (Snow Leopard) Mac OSX distribution.
10
+ # It will do nothing on non-mac platforms (eg Linux, etc).
4
11
  module Plist4r::Backend::RubyCocoa
5
12
  class << self
6
13
  def ruby_cocoa_wrapper_rb
@@ -30,7 +37,7 @@ class OSX::NSObject
30
37
  when OSX::NSArray
31
38
  self.to_a.map { |x| x.is_a?(OSX::NSObject) ? x.to_ruby : x }
32
39
  when OSX::NSDictionary
33
- h = ::ActiveSupport::OrderedHash.new
40
+ h = ::Plist4r::OrderedHash.new
34
41
  self.each do |x, y|
35
42
  x = x.to_ruby if x.is_a?(OSX::NSObject)
36
43
  y = y.to_ruby if y.is_a?(OSX::NSObject)
@@ -63,7 +70,7 @@ module Plist
63
70
  else
64
71
  plist_array = ::OSX::NSArray.arrayWithContentsOfFile(filename) unless plist_dict
65
72
  raise "Couldnt parse file: #{filename}" unless plist_array
66
- plist_dict = ::ActiveSupport::OrderedHash.new
73
+ plist_dict = ::Plist4r::OrderedHash.new
67
74
  plist_dict["Array"] = plist_array.to_ruby
68
75
  puts "#{plist_dict.inspect}"
69
76
  end
@@ -159,7 +166,7 @@ EOC
159
166
  result = ruby_cocoa_exec "open(\"#{filename}\")"
160
167
  case result[1].exitstatus
161
168
  when 0
162
- hash = ::ActiveSupport::OrderedHash.new
169
+ hash = ::Plist4r::OrderedHash.new
163
170
  eval("hash.replace("+result[2]+")")
164
171
  plist.import_hash hash
165
172
  else