ultra_pow_list 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source :rubygems
2
2
 
3
+ gem 'plist'
4
+
3
5
  group :dev do # not development <-> would add unneeded development dependencies in gemspec
4
6
  gem 'oniguruma', :platform => :ruby_18
5
7
  gem 'rake'
@@ -8,6 +8,7 @@ GEM
8
8
  git (>= 1.2.5)
9
9
  rake
10
10
  oniguruma (1.1.0)
11
+ plist (3.1.0)
11
12
  rake (0.9.2)
12
13
  rspec (2.6.0)
13
14
  rspec-core (~> 2.6.0)
@@ -24,5 +25,6 @@ PLATFORMS
24
25
  DEPENDENCIES
25
26
  jeweler
26
27
  oniguruma
28
+ plist
27
29
  rake
28
30
  rspec (~> 2)
data/Readme.md CHANGED
@@ -1,6 +1,9 @@
1
- Ultraviolet + TextPow + PList for Ruby 1.8 and 1.9
1
+ Ultraviolet + TextPow for Ruby 1.8 and 1.9
2
2
  Because all these libs are kind of broken and dont work well on either platform.
3
3
 
4
+ If you only need ruby 1.9, simply go with `spox-ultraviolet`.</br>
5
+ (which will load spox-plist, a slightly outdated plist flavor)
6
+
4
7
  Install
5
8
  =======
6
9
  gem install ultra_pow_list
@@ -23,8 +26,21 @@ Usage
23
26
  # or separate
24
27
  UltraPowList.make_loadable 'plist'
25
28
 
29
+ # ... whatever you want to do with these libs ...
30
+
31
+ # to html
32
+ require 'textpow'
26
33
  require 'uv'
27
- ... whatever you want to do with these libs ...
34
+ puts Uv.syntaxes.join( ", " )
35
+
36
+ # analyse syntax
37
+ language = 'ruby'
38
+ syntax = File.join(Uv.path.first,'uv', 'syntax',"#{language}.syntax")
39
+ syntax = Textpow::SyntaxNode.load(syntax)
40
+ processor = Textpow::DebugProcessor.new
41
+ puts result = syntax.parse( "class Foo\n def xxx;end\nend", processor )
42
+
43
+
28
44
 
29
45
  TODO
30
46
  ====
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -1,7 +1,7 @@
1
1
  class UltraPowList
2
2
  VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
3
3
 
4
- def self.make_loadable(libs=['plist','uv','textpow'])
4
+ def self.make_loadable(libs=['uv','textpow'])
5
5
  vendor = File.dirname(__FILE__) + "/ultra_pow_list/vendor/"
6
6
 
7
7
  dir = RUBY_VERSION =~ /^1.9/ ? "ruby1.9" : "ruby1.8"
@@ -7,7 +7,6 @@ describe UltraPowList do
7
7
 
8
8
  it "makes stuff loadable" do
9
9
  UltraPowList.make_loadable
10
- require 'plist'
11
10
  require 'textpow'
12
11
  require 'uv'
13
12
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ultra_pow_list}
8
- s.version = "0.1.0"
8
+ s.version = "0.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael Grosser"]
12
- s.date = %q{2011-09-11}
12
+ s.date = %q{2011-09-12}
13
13
  s.email = %q{michael@grosser.it}
14
14
  s.files = [
15
15
  "Gemfile",
@@ -18,9 +18,6 @@ Gem::Specification.new do |s|
18
18
  "Readme.md",
19
19
  "VERSION",
20
20
  "lib/ultra_pow_list.rb",
21
- "lib/ultra_pow_list/vendor/ruby1.8/plist/plist.rb",
22
- "lib/ultra_pow_list/vendor/ruby1.8/plist/plist/generator.rb",
23
- "lib/ultra_pow_list/vendor/ruby1.8/plist/plist/parser.rb",
24
21
  "lib/ultra_pow_list/vendor/ruby1.8/textpow/textpow.rb",
25
22
  "lib/ultra_pow_list/vendor/ruby1.8/textpow/textpow/debug_processor.rb",
26
23
  "lib/ultra_pow_list/vendor/ruby1.8/textpow/textpow/score_manager.rb",
@@ -231,9 +228,6 @@ Gem::Specification.new do |s|
231
228
  "lib/ultra_pow_list/vendor/ruby1.8/uv/uv.rb",
232
229
  "lib/ultra_pow_list/vendor/ruby1.8/uv/uv/render_processor.rb",
233
230
  "lib/ultra_pow_list/vendor/ruby1.8/uv/uv/utility.rb",
234
- "lib/ultra_pow_list/vendor/ruby1.9/plist/plist.rb",
235
- "lib/ultra_pow_list/vendor/ruby1.9/plist/plist/generator.rb",
236
- "lib/ultra_pow_list/vendor/ruby1.9/plist/plist/parser.rb",
237
231
  "lib/ultra_pow_list/vendor/ruby1.9/textpow/textpow.rb",
238
232
  "lib/ultra_pow_list/vendor/ruby1.9/textpow/textpow/debug_processor.rb",
239
233
  "lib/ultra_pow_list/vendor/ruby1.9/textpow/textpow/score_manager.rb",
@@ -444,9 +438,12 @@ Gem::Specification.new do |s|
444
438
  s.specification_version = 3
445
439
 
446
440
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
441
+ s.add_runtime_dependency(%q<plist>, [">= 0"])
447
442
  else
443
+ s.add_dependency(%q<plist>, [">= 0"])
448
444
  end
449
445
  else
446
+ s.add_dependency(%q<plist>, [">= 0"])
450
447
  end
451
448
  end
452
449
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ultra_pow_list
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Michael Grosser
@@ -15,10 +15,23 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-09-11 00:00:00 +02:00
18
+ date: 2011-09-12 00:00:00 +02:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ name: plist
33
+ version_requirements: *id001
34
+ prerelease: false
22
35
  description:
23
36
  email: michael@grosser.it
24
37
  executables: []
@@ -34,9 +47,6 @@ files:
34
47
  - Readme.md
35
48
  - VERSION
36
49
  - lib/ultra_pow_list.rb
37
- - lib/ultra_pow_list/vendor/ruby1.8/plist/plist.rb
38
- - lib/ultra_pow_list/vendor/ruby1.8/plist/plist/generator.rb
39
- - lib/ultra_pow_list/vendor/ruby1.8/plist/plist/parser.rb
40
50
  - lib/ultra_pow_list/vendor/ruby1.8/textpow/textpow.rb
41
51
  - lib/ultra_pow_list/vendor/ruby1.8/textpow/textpow/debug_processor.rb
42
52
  - lib/ultra_pow_list/vendor/ruby1.8/textpow/textpow/score_manager.rb
@@ -247,9 +257,6 @@ files:
247
257
  - lib/ultra_pow_list/vendor/ruby1.8/uv/uv.rb
248
258
  - lib/ultra_pow_list/vendor/ruby1.8/uv/uv/render_processor.rb
249
259
  - lib/ultra_pow_list/vendor/ruby1.8/uv/uv/utility.rb
250
- - lib/ultra_pow_list/vendor/ruby1.9/plist/plist.rb
251
- - lib/ultra_pow_list/vendor/ruby1.9/plist/plist/generator.rb
252
- - lib/ultra_pow_list/vendor/ruby1.9/plist/plist/parser.rb
253
260
  - lib/ultra_pow_list/vendor/ruby1.9/textpow/textpow.rb
254
261
  - lib/ultra_pow_list/vendor/ruby1.9/textpow/textpow/debug_processor.rb
255
262
  - lib/ultra_pow_list/vendor/ruby1.9/textpow/textpow/score_manager.rb
@@ -1,22 +0,0 @@
1
- #--
2
- ##############################################################
3
- # Copyright 2006, Ben Bleything <ben@bleything.net> and #
4
- # Patrick May <patrick@hexane.org> #
5
- # #
6
- # Distributed under the MIT license. #
7
- ##############################################################
8
- #++
9
- # = Plist
10
- #
11
- # This is the main file for plist. Everything interesting happens in Plist and Plist::Emit.
12
-
13
- require 'base64'
14
- require 'cgi'
15
- require 'stringio'
16
-
17
- require 'plist/generator'
18
- require 'plist/parser'
19
-
20
- module Plist
21
- VERSION = '3.0.0'
22
- end
@@ -1,224 +0,0 @@
1
- #--###########################################################
2
- # Copyright 2006, Ben Bleything <ben@bleything.net> and #
3
- # Patrick May <patrick@hexane.org> #
4
- # #
5
- # Distributed under the MIT license. #
6
- ##############################################################
7
- #++
8
- # See Plist::Emit.
9
- module Plist
10
- # === Create a plist
11
- # You can dump an object to a plist in one of two ways:
12
- #
13
- # * <tt>Plist::Emit.dump(obj)</tt>
14
- # * <tt>obj.to_plist</tt>
15
- # * This requires that you mixin the <tt>Plist::Emit</tt> module, which is already done for +Array+ and +Hash+.
16
- #
17
- # The following Ruby classes are converted into native plist types:
18
- # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
19
- # * +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the <array> and <dict> containers (respectively).
20
- # * +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a <data> element.
21
- # * User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to <tt>Marshal.dump</tt> and the result placed in a <data> element.
22
- #
23
- # For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below.
24
- module Emit
25
- # Helper method for injecting into classes. Calls <tt>Plist::Emit.dump</tt> with +self+.
26
- def to_plist(envelope = true)
27
- return Plist::Emit.dump(self, envelope)
28
- end
29
-
30
- # Helper method for injecting into classes. Calls <tt>Plist::Emit.save_plist</tt> with +self+.
31
- def save_plist(filename)
32
- Plist::Emit.save_plist(self, filename)
33
- end
34
-
35
- # The following Ruby classes are converted into native plist types:
36
- # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time
37
- #
38
- # Write us (via RubyForge) if you think another class can be coerced safely into one of the expected plist classes.
39
- #
40
- # +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+.
41
- #
42
- # 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.
43
- def self.dump(obj, envelope = true)
44
- output = plist_node(obj)
45
-
46
- output = wrap(output) if envelope
47
-
48
- return output
49
- end
50
-
51
- # Writes the serialized object's plist to the specified filename.
52
- def self.save_plist(obj, filename)
53
- File.open(filename, 'wb') do |f|
54
- f.write(obj.to_plist)
55
- end
56
- end
57
-
58
- private
59
- def self.plist_node(element)
60
- output = ''
61
-
62
- if element.respond_to? :to_plist_node
63
- output << element.to_plist_node
64
- else
65
- case element
66
- when Array
67
- if element.empty?
68
- output << "<array/>\n"
69
- else
70
- output << tag('array') {
71
- element.collect {|e| plist_node(e)}
72
- }
73
- end
74
- when Hash
75
- if element.empty?
76
- output << "<dict/>\n"
77
- else
78
- inner_tags = []
79
-
80
- element.keys.sort.each do |k|
81
- v = element[k]
82
- inner_tags << tag('key', CGI::escapeHTML(k.to_s))
83
- inner_tags << plist_node(v)
84
- end
85
-
86
- output << tag('dict') {
87
- inner_tags
88
- }
89
- end
90
- when true, false
91
- output << "<#{element}/>\n"
92
- when Time
93
- output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
94
- when Date # also catches DateTime
95
- output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
96
- when String, Symbol, Fixnum, Bignum, Integer, Float
97
- output << tag(element_type(element), CGI::escapeHTML(element.to_s))
98
- when IO, StringIO
99
- element.rewind
100
- contents = element.read
101
- # note that apple plists are wrapped at a different length then
102
- # what ruby's base64 wraps by default.
103
- # I used #encode64 instead of #b64encode (which allows a length arg)
104
- # because b64encode is b0rked and ignores the length arg.
105
- data = "\n"
106
- Base64::encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
107
- output << tag('data', data)
108
- else
109
- output << comment( 'The <data> element below contains a Ruby object which has been serialized with Marshal.dump.' )
110
- data = "\n"
111
- Base64::encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
112
- output << tag('data', data )
113
- end
114
- end
115
-
116
- return output
117
- end
118
-
119
- def self.comment(content)
120
- return "<!-- #{content} -->\n"
121
- end
122
-
123
- def self.tag(type, contents = '', &block)
124
- out = nil
125
-
126
- if block_given?
127
- out = IndentedString.new
128
- out << "<#{type}>"
129
- out.raise_indent
130
-
131
- out << block.call
132
-
133
- out.lower_indent
134
- out << "</#{type}>"
135
- else
136
- out = "<#{type}>#{contents.to_s}</#{type}>\n"
137
- end
138
-
139
- return out.to_s
140
- end
141
-
142
- def self.wrap(contents)
143
- output = ''
144
-
145
- output << '<?xml version="1.0" encoding="UTF-8"?>' + "\n"
146
- output << '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' + "\n"
147
- output << '<plist version="1.0">' + "\n"
148
-
149
- output << contents
150
-
151
- output << '</plist>' + "\n"
152
-
153
- return output
154
- end
155
-
156
- def self.element_type(item)
157
- return case item
158
- when String, Symbol: 'string'
159
- when Fixnum, Bignum, Integer: 'integer'
160
- when Float: 'real'
161
- else
162
- raise "Don't know about this data type... something must be wrong!"
163
- end
164
- end
165
- private
166
- class IndentedString #:nodoc:
167
- attr_accessor :indent_string
168
-
169
- @@indent_level = 0
170
-
171
- def initialize(str = "\t")
172
- @indent_string = str
173
- @contents = ''
174
- end
175
-
176
- def to_s
177
- return @contents
178
- end
179
-
180
- def raise_indent
181
- @@indent_level += 1
182
- end
183
-
184
- def lower_indent
185
- @@indent_level -= 1 if @@indent_level > 0
186
- end
187
-
188
- def <<(val)
189
- if val.is_a? Array
190
- val.each do |f|
191
- self << f
192
- end
193
- else
194
- # if it's already indented, don't bother indenting further
195
- unless val =~ /\A#{@indent_string}/
196
- indent = @indent_string * @@indent_level
197
-
198
- @contents << val.gsub(/^/, indent)
199
- else
200
- @contents << val
201
- end
202
-
203
- # it already has a newline, don't add another
204
- @contents << "\n" unless val =~ /\n$/
205
- end
206
- end
207
- end
208
- end
209
- end
210
-
211
- # we need to add this so sorting hash keys works properly
212
- class Symbol #:nodoc:
213
- def <=> (other)
214
- self.to_s <=> other.to_s
215
- end
216
- end
217
-
218
- class Array #:nodoc:
219
- include Plist::Emit
220
- end
221
-
222
- class Hash #:nodoc:
223
- include Plist::Emit
224
- end
@@ -1,224 +0,0 @@
1
- #--###########################################################
2
- # Copyright 2006, Ben Bleything <ben@bleything.net> and #
3
- # Patrick May <patrick@hexane.org> #
4
- # #
5
- # Distributed under the MIT license. #
6
- ##############################################################
7
- #++
8
- # Plist parses Mac OS X xml property list files into ruby data structures.
9
- #
10
- # === Load a plist file
11
- # This is the main point of the library:
12
- #
13
- # r = Plist::parse_xml( filename_or_xml )
14
- module Plist
15
- # Note that I don't use these two elements much:
16
- #
17
- # + Date elements are returned as DateTime objects.
18
- # + Data elements are implemented as Tempfiles
19
- #
20
- # Plist::parse_xml will blow up if it encounters a data element.
21
- # If you encounter such an error, or if you have a Date element which
22
- # can't be parsed into a Time object, please send your plist file to
23
- # plist@hexane.org so that I can implement the proper support.
24
- def Plist::parse_xml( filename_or_xml )
25
- listener = Listener.new
26
- #parser = REXML::Parsers::StreamParser.new(File.new(filename), listener)
27
- parser = StreamParser.new(filename_or_xml, listener)
28
- parser.parse
29
- listener.result
30
- end
31
-
32
- class Listener
33
- #include REXML::StreamListener
34
-
35
- attr_accessor :result, :open
36
-
37
- def initialize
38
- @result = nil
39
- @open = Array.new
40
- end
41
-
42
-
43
- def tag_start(name, attributes)
44
- @open.push PTag::mappings[name].new
45
- end
46
-
47
- def text( contents )
48
- @open.last.text = contents if @open.last
49
- end
50
-
51
- def tag_end(name)
52
- last = @open.pop
53
- if @open.empty?
54
- @result = last.to_ruby
55
- else
56
- @open.last.children.push last
57
- end
58
- end
59
- end
60
-
61
- class StreamParser
62
- def initialize( plist_data_or_file, listener )
63
- if plist_data_or_file.respond_to? :read
64
- @xml = plist_data_or_file.read
65
- elsif File.exists? plist_data_or_file
66
- @xml = File.read( plist_data_or_file )
67
- else
68
- @xml = plist_data_or_file
69
- end
70
-
71
- @listener = listener
72
- end
73
-
74
- TEXT = /([^<]+)/
75
- XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
76
- DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
77
- COMMENT_START = /\A<!--/u
78
- COMMENT_END = /.*?-->/um
79
-
80
-
81
- def parse
82
- plist_tags = PTag::mappings.keys.join('|')
83
- start_tag = /<(#{plist_tags})([^>]*)>/i
84
- end_tag = /<\/(#{plist_tags})[^>]*>/i
85
-
86
- require 'strscan'
87
-
88
- @scanner = StringScanner.new( @xml )
89
- until @scanner.eos?
90
- if @scanner.scan(COMMENT_START)
91
- @scanner.scan(COMMENT_END)
92
- elsif @scanner.scan(XMLDECL_PATTERN)
93
- elsif @scanner.scan(DOCTYPE_PATTERN)
94
- elsif @scanner.scan(start_tag)
95
- @listener.tag_start(@scanner[1], nil)
96
- if (@scanner[2] =~ /\/$/)
97
- @listener.tag_end(@scanner[1])
98
- end
99
- elsif @scanner.scan(TEXT)
100
- @listener.text(@scanner[1])
101
- elsif @scanner.scan(end_tag)
102
- @listener.tag_end(@scanner[1])
103
- else
104
- raise "Unimplemented element"
105
- end
106
- end
107
- end
108
- end
109
-
110
- class PTag
111
- @@mappings = { }
112
- def PTag::mappings
113
- @@mappings
114
- end
115
-
116
- def PTag::inherited( sub_class )
117
- key = sub_class.to_s.downcase
118
- key.gsub!(/^plist::/, '' )
119
- key.gsub!(/^p/, '') unless key == "plist"
120
-
121
- @@mappings[key] = sub_class
122
- end
123
-
124
- attr_accessor :text, :children
125
- def initialize
126
- @children = Array.new
127
- end
128
-
129
- def to_ruby
130
- raise "Unimplemented: " + self.class.to_s + "#to_ruby on #{self.inspect}"
131
- end
132
- end
133
-
134
- class PList < PTag
135
- def to_ruby
136
- children.first.to_ruby if children.first
137
- end
138
- end
139
-
140
- class PDict < PTag
141
- def to_ruby
142
- dict = Hash.new
143
- key = nil
144
-
145
- children.each do |c|
146
- if key.nil?
147
- key = c.to_ruby
148
- else
149
- dict[key] = c.to_ruby
150
- key = nil
151
- end
152
- end
153
-
154
- dict
155
- end
156
- end
157
-
158
- class PKey < PTag
159
- def to_ruby
160
- CGI::unescapeHTML(text || '')
161
- end
162
- end
163
-
164
- class PString < PTag
165
- def to_ruby
166
- CGI::unescapeHTML(text || '')
167
- end
168
- end
169
-
170
- class PArray < PTag
171
- def to_ruby
172
- children.collect do |c|
173
- c.to_ruby
174
- end
175
- end
176
- end
177
-
178
- class PInteger < PTag
179
- def to_ruby
180
- text.to_i
181
- end
182
- end
183
-
184
- class PTrue < PTag
185
- def to_ruby
186
- true
187
- end
188
- end
189
-
190
- class PFalse < PTag
191
- def to_ruby
192
- false
193
- end
194
- end
195
-
196
- class PReal < PTag
197
- def to_ruby
198
- text.to_f
199
- end
200
- end
201
-
202
- require 'date'
203
- class PDate < PTag
204
- def to_ruby
205
- DateTime.parse(text)
206
- end
207
- end
208
-
209
- require 'base64'
210
- class PData < PTag
211
- def to_ruby
212
- data = Base64.decode64(text.gsub(/\s+/, ''))
213
-
214
- begin
215
- return Marshal.load(data)
216
- rescue Exception => e
217
- io = StringIO.new
218
- io.write data
219
- io.rewind
220
- return io
221
- end
222
- end
223
- end
224
- end
@@ -1,23 +0,0 @@
1
- #--
2
- ##############################################################
3
- # Copyright 2006, Ben Bleything <ben@bleything.net> and #
4
- # Patrick May <patrick@hexane.org> #
5
- # #
6
- # Distributed under the MIT license. #
7
- ##############################################################
8
- #++
9
- # = Plist
10
- #
11
- # This is the main file for plist. Everything interesting happens in Plist and Plist::Emit.
12
-
13
- # encoding: utf-8
14
- require 'base64'
15
- require 'cgi'
16
- require 'stringio'
17
-
18
- require 'plist/generator'
19
- require 'plist/parser'
20
-
21
- module Plist
22
- VERSION = '3.0.0'
23
- end
@@ -1,228 +0,0 @@
1
- # encoding: utf-8
2
- #--###########################################################
3
- # Copyright 2006, Ben Bleything <ben@bleything.net> and #
4
- # Patrick May <patrick@hexane.org> #
5
- # #
6
- # Distributed under the MIT license. #
7
- ##############################################################
8
- #++
9
- # See Plist::Emit.
10
- module Plist
11
- # === Create a plist
12
- # You can dump an object to a plist in one of two ways:
13
- #
14
- # * <tt>Plist::Emit.dump(obj)</tt>
15
- # * <tt>obj.to_plist</tt>
16
- # * This requires that you mixin the <tt>Plist::Emit</tt> module, which is already done for +Array+ and +Hash+.
17
- #
18
- # The following Ruby classes are converted into native plist types:
19
- # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time, true, false
20
- # * +Array+ and +Hash+ are both recursive; their elements will be converted into plist nodes inside the <array> and <dict> containers (respectively).
21
- # * +IO+ (and its descendants) and +StringIO+ objects are read from and their contents placed in a <data> element.
22
- # * User classes may implement +to_plist_node+ to dictate how they should be serialized; otherwise the object will be passed to <tt>Marshal.dump</tt> and the result placed in a <data> element.
23
- #
24
- # For detailed usage instructions, refer to USAGE[link:files/docs/USAGE.html] and the methods documented below.
25
- module Emit
26
- # Helper method for injecting into classes. Calls <tt>Plist::Emit.dump</tt> with +self+.
27
- def to_plist(envelope = true)
28
- return Plist::Emit.dump(self, envelope)
29
- end
30
-
31
- # Helper method for injecting into classes. Calls <tt>Plist::Emit.save_plist</tt> with +self+.
32
- def save_plist(filename)
33
- Plist::Emit.save_plist(self, filename)
34
- end
35
-
36
- # The following Ruby classes are converted into native plist types:
37
- # Array, Bignum, Date, DateTime, Fixnum, Float, Hash, Integer, String, Symbol, Time
38
- #
39
- # Write us (via RubyForge) if you think another class can be coerced safely into one of the expected plist classes.
40
- #
41
- # +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+.
42
- #
43
- # 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.
44
- def self.dump(obj, envelope = true)
45
- output = plist_node(obj)
46
-
47
- output = wrap(output) if envelope
48
-
49
- return output
50
- end
51
-
52
- # Writes the serialized object's plist to the specified filename.
53
- def self.save_plist(obj, filename)
54
- File.open(filename, 'wb') do |f|
55
- f.write(obj.to_plist)
56
- end
57
- end
58
-
59
- private
60
- def self.plist_node(element)
61
- output = ''
62
-
63
- if element.respond_to? :to_plist_node
64
- output << element.to_plist_node
65
- else
66
- case element
67
- when Array
68
- if element.empty?
69
- output << "<array/>\n"
70
- else
71
- output << tag('array') {
72
- element.collect {|e| plist_node(e)}
73
- }
74
- end
75
- when Hash
76
- if element.empty?
77
- output << "<dict/>\n"
78
- else
79
- inner_tags = []
80
-
81
- element.keys.sort.each do |k|
82
- v = element[k]
83
- inner_tags << tag('key', CGI::escapeHTML(k.to_s))
84
- inner_tags << plist_node(v)
85
- end
86
-
87
- output << tag('dict') {
88
- inner_tags
89
- }
90
- end
91
- when true, false
92
- output << "<#{element}/>\n"
93
- when Time
94
- output << tag('date', element.utc.strftime('%Y-%m-%dT%H:%M:%SZ'))
95
- when Date # also catches DateTime
96
- output << tag('date', element.strftime('%Y-%m-%dT%H:%M:%SZ'))
97
- when String, Symbol, Fixnum, Bignum, Integer, Float
98
- output << tag(element_type(element), CGI::escapeHTML(element.to_s))
99
- when IO, StringIO
100
- element.rewind
101
- contents = element.read
102
- # note that apple plists are wrapped at a different length then
103
- # what ruby's base64 wraps by default.
104
- # I used #encode64 instead of #b64encode (which allows a length arg)
105
- # because b64encode is b0rked and ignores the length arg.
106
- data = "\n"
107
- Base64::encode64(contents).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
108
- output << tag('data', data)
109
- else
110
- output << comment( 'The <data> element below contains a Ruby object which has been serialized with Marshal.dump.' )
111
- data = "\n"
112
- Base64::encode64(Marshal.dump(element)).gsub(/\s+/, '').scan(/.{1,68}/o) { data << $& << "\n" }
113
- output << tag('data', data )
114
- end
115
- end
116
-
117
- return output
118
- end
119
-
120
- def self.comment(content)
121
- return "<!-- #{content} -->\n"
122
- end
123
-
124
- def self.tag(type, contents = '', &block)
125
- out = nil
126
-
127
- if block_given?
128
- out = IndentedString.new
129
- out << "<#{type}>"
130
- out.raise_indent
131
-
132
- out << block.call
133
-
134
- out.lower_indent
135
- out << "</#{type}>"
136
- else
137
- out = "<#{type}>#{contents.to_s}</#{type}>\n"
138
- end
139
-
140
- return out.to_s
141
- end
142
-
143
- def self.wrap(contents)
144
- output = ''
145
-
146
- output << '<?xml version="1.0" encoding="UTF-8"?>' + "\n"
147
- output << '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' + "\n"
148
- output << '<plist version="1.0">' + "\n"
149
-
150
- output << contents
151
-
152
- output << '</plist>' + "\n"
153
-
154
- return output
155
- end
156
-
157
- def self.element_type(item)
158
- return case item
159
- when String, Symbol
160
- 'string'
161
- when Fixnum, Bignum, Integer
162
- 'integer'
163
- when Float
164
- 'real'
165
- else
166
- raise "Don't know about this data type... something must be wrong!"
167
- end
168
- end
169
- private
170
- class IndentedString #:nodoc:
171
- attr_accessor :indent_string
172
-
173
- @@indent_level = 0
174
-
175
- def initialize(str = "\t")
176
- @indent_string = str
177
- @contents = ''
178
- end
179
-
180
- def to_s
181
- return @contents
182
- end
183
-
184
- def raise_indent
185
- @@indent_level += 1
186
- end
187
-
188
- def lower_indent
189
- @@indent_level -= 1 if @@indent_level > 0
190
- end
191
-
192
- def <<(val)
193
- if val.is_a? Array
194
- val.each do |f|
195
- self << f
196
- end
197
- else
198
- # if it's already indented, don't bother indenting further
199
- unless val =~ /\A#{@indent_string}/
200
- indent = @indent_string * @@indent_level
201
-
202
- @contents << val.gsub(/^/, indent)
203
- else
204
- @contents << val
205
- end
206
-
207
- # it already has a newline, don't add another
208
- @contents << "\n" unless val =~ /\n$/
209
- end
210
- end
211
- end
212
- end
213
- end
214
-
215
- # we need to add this so sorting hash keys works properly
216
- class Symbol #:nodoc:
217
- def <=> (other)
218
- self.to_s <=> other.to_s
219
- end
220
- end
221
-
222
- class Array #:nodoc:
223
- include Plist::Emit
224
- end
225
-
226
- class Hash #:nodoc:
227
- include Plist::Emit
228
- end
@@ -1,225 +0,0 @@
1
- # encoding: utf-8
2
- #--###########################################################
3
- # Copyright 2006, Ben Bleything <ben@bleything.net> and #
4
- # Patrick May <patrick@hexane.org> #
5
- # #
6
- # Distributed under the MIT license. #
7
- ##############################################################
8
- #++
9
- # Plist parses Mac OS X xml property list files into ruby data structures.
10
- #
11
- # === Load a plist file
12
- # This is the main point of the library:
13
- #
14
- # r = Plist::parse_xml( filename_or_xml )
15
- module Plist
16
- # Note that I don't use these two elements much:
17
- #
18
- # + Date elements are returned as DateTime objects.
19
- # + Data elements are implemented as Tempfiles
20
- #
21
- # Plist::parse_xml will blow up if it encounters a data element.
22
- # If you encounter such an error, or if you have a Date element which
23
- # can't be parsed into a Time object, please send your plist file to
24
- # plist@hexane.org so that I can implement the proper support.
25
- def Plist::parse_xml( filename_or_xml )
26
- listener = Listener.new
27
- #parser = REXML::Parsers::StreamParser.new(File.new(filename), listener)
28
- parser = StreamParser.new(filename_or_xml, listener)
29
- parser.parse
30
- listener.result
31
- end
32
-
33
- class Listener
34
- #include REXML::StreamListener
35
-
36
- attr_accessor :result, :open
37
-
38
- def initialize
39
- @result = nil
40
- @open = Array.new
41
- end
42
-
43
-
44
- def tag_start(name, attributes)
45
- @open.push PTag::mappings[name].new
46
- end
47
-
48
- def text( contents )
49
- @open.last.text = contents if @open.last
50
- end
51
-
52
- def tag_end(name)
53
- last = @open.pop
54
- if @open.empty?
55
- @result = last.to_ruby
56
- else
57
- @open.last.children.push last
58
- end
59
- end
60
- end
61
-
62
- class StreamParser
63
- def initialize( plist_data_or_file, listener )
64
- if plist_data_or_file.respond_to? :read
65
- @xml = plist_data_or_file.read
66
- elsif File.exists? plist_data_or_file
67
- @xml = File.read( plist_data_or_file )
68
- else
69
- @xml = plist_data_or_file
70
- end
71
-
72
- @listener = listener
73
- end
74
-
75
- TEXT = /([^<]+)/
76
- XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>*/um
77
- DOCTYPE_PATTERN = /\s*<!DOCTYPE\s+(.*?)(\[|>)/um
78
- COMMENT_START = /\A<!--/u
79
- COMMENT_END = /.*?-->/um
80
-
81
-
82
- def parse
83
- plist_tags = PTag::mappings.keys.join('|')
84
- start_tag = /<(#{plist_tags})([^>]*)>/i
85
- end_tag = /<\/(#{plist_tags})[^>]*>/i
86
-
87
- require 'strscan'
88
-
89
- @scanner = StringScanner.new( @xml )
90
- until @scanner.eos?
91
- if @scanner.scan(COMMENT_START)
92
- @scanner.scan(COMMENT_END)
93
- elsif @scanner.scan(XMLDECL_PATTERN)
94
- elsif @scanner.scan(DOCTYPE_PATTERN)
95
- elsif @scanner.scan(start_tag)
96
- @listener.tag_start(@scanner[1], nil)
97
- if (@scanner[2] =~ /\/$/)
98
- @listener.tag_end(@scanner[1])
99
- end
100
- elsif @scanner.scan(TEXT)
101
- @listener.text(@scanner[1])
102
- elsif @scanner.scan(end_tag)
103
- @listener.tag_end(@scanner[1])
104
- else
105
- raise "Unimplemented element"
106
- end
107
- end
108
- end
109
- end
110
-
111
- class PTag
112
- @@mappings = { }
113
- def PTag::mappings
114
- @@mappings
115
- end
116
-
117
- def PTag::inherited( sub_class )
118
- key = sub_class.to_s.downcase
119
- key.gsub!(/^plist::/, '' )
120
- key.gsub!(/^p/, '') unless key == "plist"
121
-
122
- @@mappings[key] = sub_class
123
- end
124
-
125
- attr_accessor :text, :children
126
- def initialize
127
- @children = Array.new
128
- end
129
-
130
- def to_ruby
131
- raise "Unimplemented: " + self.class.to_s + "#to_ruby on #{self.inspect}"
132
- end
133
- end
134
-
135
- class PList < PTag
136
- def to_ruby
137
- children.first.to_ruby if children.first
138
- end
139
- end
140
-
141
- class PDict < PTag
142
- def to_ruby
143
- dict = Hash.new
144
- key = nil
145
-
146
- children.each do |c|
147
- if key.nil?
148
- key = c.to_ruby
149
- else
150
- dict[key] = c.to_ruby
151
- key = nil
152
- end
153
- end
154
-
155
- dict
156
- end
157
- end
158
-
159
- class PKey < PTag
160
- def to_ruby
161
- CGI::unescapeHTML(text || '')
162
- end
163
- end
164
-
165
- class PString < PTag
166
- def to_ruby
167
- CGI::unescapeHTML(text || '')
168
- end
169
- end
170
-
171
- class PArray < PTag
172
- def to_ruby
173
- children.collect do |c|
174
- c.to_ruby
175
- end
176
- end
177
- end
178
-
179
- class PInteger < PTag
180
- def to_ruby
181
- text.to_i
182
- end
183
- end
184
-
185
- class PTrue < PTag
186
- def to_ruby
187
- true
188
- end
189
- end
190
-
191
- class PFalse < PTag
192
- def to_ruby
193
- false
194
- end
195
- end
196
-
197
- class PReal < PTag
198
- def to_ruby
199
- text.to_f
200
- end
201
- end
202
-
203
- require 'date'
204
- class PDate < PTag
205
- def to_ruby
206
- DateTime.parse(text)
207
- end
208
- end
209
-
210
- require 'base64'
211
- class PData < PTag
212
- def to_ruby
213
- data = Base64.decode64(text.gsub(/\s+/, ''))
214
-
215
- begin
216
- return Marshal.load(data)
217
- rescue Exception => e
218
- io = StringIO.new
219
- io.write data
220
- io.rewind
221
- return io
222
- end
223
- end
224
- end
225
- end