plist4r 0.2.1 → 0.2.2

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/.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