summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Brictson <mattbrictson@users.noreply.github.com>2017-08-22 20:57:40 -0700
committerGitHub <noreply@github.com>2017-08-22 20:57:40 -0700
commitf6f8b85e198de7d209ca598bd61715c4bb3eb254 (patch)
tree97a634e878936985f8ee6174800363b49c9d0ab4
parentc9f04a3daf021443841dbb6ca3a782953f24e7b4 (diff)
parent923dd1ce5d6859abe123d4b847620f8c1e5bfe7e (diff)
downloadplist-f6f8b85e198de7d209ca598bd61715c4bb3eb254.tar.gz
Merge pull request #44 from masolin/support_custom_indent_format
Support custom indent string
-rw-r--r--CHANGELOG.rdoc1
-rw-r--r--README.rdoc17
-rw-r--r--lib/plist/generator.rb50
-rw-r--r--test/test_generator.rb37
4 files changed, 84 insertions, 21 deletions
diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc
index 57618f0..efe0157 100644
--- a/CHANGELOG.rdoc
+++ b/CHANGELOG.rdoc
@@ -5,6 +5,7 @@
https://github.com/patsplat/plist/compare/v3.3.0...HEAD
* Your contribution here!
+* Support custom indent string (https://github.com/patsplat/plist/pull/44)
=== 3.3.0 (2017-04-28)
diff --git a/README.rdoc b/README.rdoc
index 648f02b..e7dcd33 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -117,6 +117,23 @@ When you attempt to serialize a +MyFancyString+ object, the +to_plist_node+ meth
If for whatever reason you can't add this method, your object will be serialized with <tt>Marshal.dump</tt> instead.
+==== Custom indent
+
+You can customize the default indent foramt (default format is tab) or specify the indent format on each serialization. For example, if you want to reduce size of plist output, you can set the indent to <tt>nil</tt>.
+
+An example to change default indent format:
+
+ Plist::Emit::DEFAULT_INDENT = nil
+
+An example to specify indent format on dump:
+
+ Plist::Emit.dump({:foo => :bar}, false)
+ => "<dict>\n\t<key>foo</key>\n\t<string>bar</string>\n</dict>\n"
+
+ Plist::Emit.dump({:foo => :bar}, false, :indent => nil)
+ => "<dict>\n<key>foo</key>\n<string>bar</string>\n</dict>\n"
+
+
== Links
[Rubygems] https://rubygems.org/gems/plist
diff --git a/lib/plist/generator.rb b/lib/plist/generator.rb
index 21ef959..fb67f67 100644
--- a/lib/plist/generator.rb
+++ b/lib/plist/generator.rb
@@ -22,14 +22,18 @@ module Plist
#
# For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below.
module Emit
+ DEFAULT_INDENT = "\t"
+
# Helper method for injecting into classes. Calls <tt>Plist::Emit.dump</tt> with +self+.
- def to_plist(envelope = true)
- return Plist::Emit.dump(self, envelope)
+ def to_plist(envelope = true, options = {})
+ options = { :indent => DEFAULT_INDENT }.merge(options)
+ return Plist::Emit.dump(self, envelope, options)
end
# Helper method for injecting into classes. Calls <tt>Plist::Emit.save_plist</tt> with +self+.
- def save_plist(filename)
- Plist::Emit.save_plist(self, filename)
+ def save_plist(filename, options = {})
+ options = { :indent => DEFAULT_INDENT }.merge(options)
+ Plist::Emit.save_plist(self, filename, options)
end
# The following Ruby classes are converted into native plist types:
@@ -40,8 +44,9 @@ module Plist
# +IO+ and +StringIO+ objects are encoded and placed in <data> elements; other objects are <tt>Marshal.dump</tt>'ed unless they implement +to_plist_node+.
#
# The +envelope+ parameters dictates whether or not the resultant plist fragment is wrapped in the normal XML/plist header and footer. Set it to false if you only want the fragment.
- def self.dump(obj, envelope = true)
- output = plist_node(obj)
+ def self.dump(obj, envelope = true, options = {})
+ options = { :indent => DEFAULT_INDENT }.merge(options)
+ output = plist_node(obj, options)
output = wrap(output) if envelope
@@ -49,14 +54,16 @@ module Plist
end
# Writes the serialized object's plist to the specified filename.
- def self.save_plist(obj, filename)
+ def self.save_plist(obj, filename, options = {})
+ options = { :indent => DEFAULT_INDENT }.merge(options)
File.open(filename, 'wb') do |f|
- f.write(obj.to_plist)
+ f.write(obj.to_plist(true, options))
end
end
private
- def self.plist_node(element)
+ def self.plist_node(element, options = {})
+ options = { :indent => DEFAULT_INDENT }.merge(options)
output = ''
if element.respond_to? :to_plist_node
@@ -67,8 +74,8 @@ module Plist
if element.empty?
output << "<array/>\n"
else
- output << tag('array') {
- element.collect {|e| plist_node(e)}
+ output << tag('array', '', options) {
+ element.collect {|e| plist_node(e, options)}
}
end
when Hash
@@ -79,22 +86,22 @@ module Plist
element.keys.sort_by{|k| k.to_s }.each do |k|
v = element[k]
- inner_tags << tag('key', CGI.escapeHTML(k.to_s))
- inner_tags << plist_node(v)
+ inner_tags << tag('key', CGI.escapeHTML(k.to_s), options)
+ inner_tags << plist_node(v, options)
end
- output << tag('dict') {
+ output << tag('dict', '', options) {
inner_tags
}
end
when true, false
output << "<#{element}/>\n"
when Time
- output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
+ output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), options)
when Date # also catches DateTime
- output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
+ output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'), options)
when String, Symbol, Integer, Float
- output << tag(element_type(element), CGI.escapeHTML(element.to_s))
+ output << tag(element_type(element), CGI.escapeHTML(element.to_s), options)
when IO, StringIO
element.rewind
contents = element.read
@@ -104,12 +111,12 @@ module Plist
# because b64encode is b0rked and ignores the length arg.
data = "\n"
Base64.encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
- output << tag('data', data)
+ output << tag('data', data, options)
else
output << comment('The <data> element below contains a Ruby object which has been serialized with Marshal.dump.')
data = "\n"
Base64.encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
- output << tag('data', data)
+ output << tag('data', data, options)
end
end
@@ -120,11 +127,12 @@ module Plist
return "<!-- #{content} -->\n"
end
- def self.tag(type, contents = '', &block)
+ def self.tag(type, contents = '', options = {}, &block)
+ options = { :indent => DEFAULT_INDENT }.merge(options)
out = nil
if block_given?
- out = IndentedString.new
+ out = IndentedString.new(options[:indent])
out << "<#{type}>"
out.raise_indent
diff --git a/test/test_generator.rb b/test/test_generator.rb
index e03c49d..c93073b 100644
--- a/test/test_generator.rb
+++ b/test/test_generator.rb
@@ -70,4 +70,41 @@ class TestGenerator < Test::Unit::TestCase
assert_equal expected, output.gsub(/[\t]/, "\s\s")
end
+
+ def test_custom_indent
+ hsh = { :key1 => 1, 'key2' => 2 }
+ output_plist_node = Plist::Emit.plist_node(hsh, :indent => nil)
+ output_plist_dump_with_envelope = Plist::Emit.dump(hsh, true, :indent => nil)
+ output_plist_dump_no_envelope = Plist::Emit.dump(hsh, false, :indent => nil)
+
+ expected_with_envelope = <<-STR
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+<key>key1</key>
+<integer>1</integer>
+<key>key2</key>
+<integer>2</integer>
+</dict>
+</plist>
+STR
+
+ expected_no_envelope = <<-STR
+<dict>
+<key>key1</key>
+<integer>1</integer>
+<key>key2</key>
+<integer>2</integer>
+</dict>
+STR
+ assert_equal expected_no_envelope, output_plist_node
+ assert_equal expected_with_envelope, output_plist_dump_with_envelope
+ assert_equal expected_no_envelope, output_plist_dump_no_envelope
+
+ hsh.save_plist('test.plist', :indent => nil)
+ output_plist_file = File.read('test.plist')
+ assert_equal expected_with_envelope, output_plist_file
+ File.unlink('test.plist')
+ end
end