| 1 | # |
|---|
| 2 | # |
|---|
| 3 | # .. yaml.rb ..... |
|---|
| 4 | # . . |
|---|
| 5 | # . . |
|---|
| 6 | # . . |
|---|
| 7 | # ....... v0.60 .. |
|---|
| 8 | # |
|---|
| 9 | # |
|---|
| 10 | # |
|---|
| 11 | # {o} |
|---|
| 12 | # ^ |
|---|
| 13 | # {o} |
|---|
| 14 | # ^ |
|---|
| 15 | # |
|---|
| 16 | # Load this README! |
|---|
| 17 | # |
|---|
| 18 | # >> YAML::load( File.open( 'README' ) ) |
|---|
| 19 | # |
|---|
| 20 | --- %YAML:1.0 |
|---|
| 21 | title: YAML.rb |
|---|
| 22 | version: 0.65 |
|---|
| 23 | author: [Why the Lucky Stiff, yaml-core@whytheluckystiff.net] |
|---|
| 24 | websites: [http://www.yaml.org, http://yaml4r.sf.net, http://sf.net/projects/yaml4r/] |
|---|
| 25 | installation: > |
|---|
| 26 | YAML.rb depends on Racc, available in the RAA: |
|---|
| 27 | |
|---|
| 28 | http://www.ruby-lang.org/en/raa-list.rhtml?name=Racc |
|---|
| 29 | |
|---|
| 30 | Once Racc is installed, run the install.rb script in this |
|---|
| 31 | distribution: |
|---|
| 32 | |
|---|
| 33 | ruby install.rb |
|---|
| 34 | |
|---|
| 35 | To run the included unit tests: |
|---|
| 36 | |
|---|
| 37 | ruby tests/basic.rb |
|---|
| 38 | |
|---|
| 39 | To run the new YamlTestingSuite: |
|---|
| 40 | |
|---|
| 41 | cd yts |
|---|
| 42 | ruby yts.rb |
|---|
| 43 | |
|---|
| 44 | about: > |
|---|
| 45 | From the specification: |
|---|
| 46 | |
|---|
| 47 | "YAML(tm) (rhymes with 'camel') is a |
|---|
| 48 | straightforward machine parsable data serialization format designed for |
|---|
| 49 | human readability and interaction with scripting languages such as Perl |
|---|
| 50 | and Python. YAML is optimized for data serialization, formatted |
|---|
| 51 | dumping, configuration files, log files, Internet messaging and |
|---|
| 52 | filtering. This specification describes the YAML information model and |
|---|
| 53 | serialization format. Together with the Unicode standard for characters, it |
|---|
| 54 | provides all the information necessary to understand YAML Version 1.0 |
|---|
| 55 | and construct computer programs to process it." |
|---|
| 56 | |
|---|
| 57 | For Ruby developers, YAML is a natural fit for object serialization and |
|---|
| 58 | general data storage. Really, it's quite fantastic. Spreads right on |
|---|
| 59 | your Rubyware like butter on bread! |
|---|
| 60 | |
|---|
| 61 | The possible uses for YAML are innumerable. Configuration files, |
|---|
| 62 | custom internet protocols, documentation, the list goes on and on. |
|---|
| 63 | Also, with YAML readers popping up for other languages (see YAML.pm |
|---|
| 64 | and others), you can pass data easily to colleagues in distant lands, |
|---|
| 65 | swamped in their archaic languages. |
|---|
| 66 | |
|---|
| 67 | YAML is a beacon of light, reaching out to them all. ;) |
|---|
| 68 | |
|---|
| 69 | If I can-- quickly, of course-- in the Pickaxe book-- my all-time favorite |
|---|
| 70 | coding book-- Dave Thomas and Andy Hunt say: |
|---|
| 71 | |
|---|
| 72 | "When we discovered Ruby, we realized that we'd found what we'd been looking |
|---|
| 73 | for. More than any other language with which we have worked, Ruby stays |
|---|
| 74 | out of your way. You can concentrate on solving the problem at hand, instead |
|---|
| 75 | of struggling with compiler and language issues. That's how it can help you |
|---|
| 76 | become a better programmer: by giving you the chance to spend your time |
|---|
| 77 | creating solutions for your users, not for the compiler." |
|---|
| 78 | |
|---|
| 79 | HeiL! So true. Ruby's elegance, its readability, its common sense! Such |
|---|
| 80 | it is with YAML. YAML is completely readable, in fact much of its syntax |
|---|
| 81 | parallels Ruby's own data structure syntax! |
|---|
| 82 | |
|---|
| 83 | Another one from the Pickaxe: |
|---|
| 84 | |
|---|
| 85 | "Ruby is easy to learn. Everyday tasks are simple to code and once you've done |
|---|
| 86 | them, they are easy to maintain and grow. Apparently difficult things often |
|---|
| 87 | turn out not to have been difficult after all. Ruby follows the Principle |
|---|
| 88 | of Least Surprise--things work the way you would expect them to, with very |
|---|
| 89 | few special cases or exceptions. And that really does make a difference |
|---|
| 90 | when you're programming." |
|---|
| 91 | |
|---|
| 92 | A quick look at YAML and you can see your data structure immediately. If |
|---|
| 93 | I compare it to SOAP or XML-RPC, the difference is immense. With XML-RPC, |
|---|
| 94 | you can see the data structures, but its terribly verbose. More time is |
|---|
| 95 | spent describing the structure than anything else. Again, the Principle |
|---|
| 96 | of Least Surprise is wholly present in YAML. Thank God! |
|---|
| 97 | |
|---|
| 98 | Well, welcome to YAML.rb. Now let's look at the API and see what we're |
|---|
| 99 | dealing with! |
|---|
| 100 | |
|---|
| 101 | lets show off: |
|---|
| 102 | - section: Exporting objects to YAML |
|---|
| 103 | explanation: > |
|---|
| 104 | |
|---|
| 105 | Ruby encourages objects to have their own exporting methods. Hence, YAML.rb |
|---|
| 106 | adds #to_yaml methods for built-in types. The NilClass, FalseClass, TrueClass, Symbol, Range, |
|---|
| 107 | Numeric, Date, Time, Regexp, String, Array, and Hash all contain the to_yaml method. |
|---|
| 108 | |
|---|
| 109 | example: | |
|---|
| 110 | |
|---|
| 111 | require 'yaml' |
|---|
| 112 | h = { 'test' => 12, 'another' => 13 } |
|---|
| 113 | puts h.to_yaml |
|---|
| 114 | |
|---|
| 115 | - section: Loading a single YAML document |
|---|
| 116 | explanation: > |
|---|
| 117 | |
|---|
| 118 | Although you'll often want to store multiple YAML documents in a single |
|---|
| 119 | file, YAML.rb has a mechanism for loading and storing a single document in |
|---|
| 120 | a single file. I wanted to offer a simpler API for those who don't care |
|---|
| 121 | for the multiple document styling and just want to store a single object. |
|---|
| 122 | |
|---|
| 123 | example: | |
|---|
| 124 | |
|---|
| 125 | require 'yaml' |
|---|
| 126 | obj = YAML::load( File::open( "/tmp/yaml.store.1" ) ) |
|---|
| 127 | |
|---|
| 128 | - section: Loading an object from a string |
|---|
| 129 | explanation: > |
|---|
| 130 | |
|---|
| 131 | Perhaps you get an object from an HTTP post. String objects can be |
|---|
| 132 | loaded through the same YAML::load used with the File object above. |
|---|
| 133 | You can also pass StringIO into YAML::load. |
|---|
| 134 | |
|---|
| 135 | example: | |
|---|
| 136 | |
|---|
| 137 | require 'yaml' |
|---|
| 138 | obj = YAML::load( <<EOY |
|---|
| 139 | --- %YAML:1.0 |
|---|
| 140 | - armless |
|---|
| 141 | - falling |
|---|
| 142 | - birds |
|---|
| 143 | EOY |
|---|
| 144 | ) |
|---|
| 145 | p obj |
|---|
| 146 | #=> [ 'armless', 'falling', 'birds' ] |
|---|
| 147 | |
|---|
| 148 | - section: Replacing PStore with YAML |
|---|
| 149 | explanation: > |
|---|
| 150 | |
|---|
| 151 | PStore is an excellent utility for Ruby developers. Akin to Python's pickle, |
|---|
| 152 | objects can be serialized to a file. In YAML.rb, the PStore API is replicated |
|---|
| 153 | identically, as a drop-in replacement for PStore code. |
|---|
| 154 | |
|---|
| 155 | example: | |
|---|
| 156 | |
|---|
| 157 | require 'yaml' |
|---|
| 158 | y = YAML::Store.new( "/tmp/yaml.store.1", :Indent => 2, :Separator => '---.pstore' ) |
|---|
| 159 | y.transaction do |
|---|
| 160 | y['names'] = ['Crispin', 'Glover'] |
|---|
| 161 | y['hello'] = {'hi' => 'hello', 'yes' => 'YES!!' } |
|---|
| 162 | end |
|---|
| 163 | |
|---|
| 164 | - section: Exporting multiple documents to YAML |
|---|
| 165 | explanation: > |
|---|
| 166 | |
|---|
| 167 | A single YAML file can store several documents, each opened with a YAML separator ('---'). |
|---|
| 168 | This can be especially useful for streaming data over a socket or for separating |
|---|
| 169 | log file entries (as see in the spec -- http://yaml.org/spec/). |
|---|
| 170 | |
|---|
| 171 | This release writes all documents out upon calling YAML::Stream#emit, but future |
|---|
| 172 | releases will allow document writing to stream individually. |
|---|
| 173 | |
|---|
| 174 | example: | |
|---|
| 175 | |
|---|
| 176 | y = YAML::Stream.new( :Indent => 2, :UseVersion => true ) |
|---|
| 177 | y.add( {'my_regex' => /hello [Jj][Aa][Mm][Ee][Ss]/, 'my_age' => 90 } ) |
|---|
| 178 | y.add( {'hi' => 'wow!', 'bye' => 'wow!'} ) |
|---|
| 179 | y.add( {['Red Socks','Boston'] => ['One', 'Two', 'Three']} ) |
|---|
| 180 | y.add( [true, false, false] ) |
|---|
| 181 | puts y.emit |
|---|
| 182 | |
|---|
| 183 | - section: Loading multiple documents at once into a YAML::Stream |
|---|
| 184 | explanation: > |
|---|
| 185 | |
|---|
| 186 | In using YAML::Stream to write your objects, you may find that |
|---|
| 187 | you want a quick way to load several documents at once back into |
|---|
| 188 | a YAML::Stream, for editing and rewriting. |
|---|
| 189 | |
|---|
| 190 | example: | |
|---|
| 191 | |
|---|
| 192 | require 'yaml' |
|---|
| 193 | File.open( "/home/why/.personalrc", "rw" ) { |rc| |
|---|
| 194 | # Load the objects from the file |
|---|
| 195 | y = YAML::load_stream( rc ) |
|---|
| 196 | # Make edits to the objects |
|---|
| 197 | doc2 = y.documents[2] |
|---|
| 198 | doc2['car'] = '1997 Subaru Outback' |
|---|
| 199 | y.edit( 2, doc2 ) |
|---|
| 200 | # Save back out |
|---|
| 201 | rc.rewind |
|---|
| 202 | rc.write( y.emit ) |
|---|
| 203 | rc.close |
|---|
| 204 | } |
|---|
| 205 | |
|---|
| 206 | - section: Loading multiple documents from a YAML stream |
|---|
| 207 | explanation: | |
|---|
| 208 | |
|---|
| 209 | When reading YAML from a socket or a pipe, you should |
|---|
| 210 | consider using the event-based parser, which will parse |
|---|
| 211 | documents one at a time. |
|---|
| 212 | |
|---|
| 213 | example: | |
|---|
| 214 | |
|---|
| 215 | require 'yaml' |
|---|
| 216 | log = File.open( "/var/log/apache.yaml" ) |
|---|
| 217 | yp = YAML::load_documents( log ) { |doc| |
|---|
| 218 | puts "#{doc['at']} #{doc['type']} #{doc['url}" |
|---|
| 219 | } |
|---|
| 220 | |
|---|
| 221 | # Note the YAML document embedded in the YAML document! |
|---|
| 222 | cheat sheet: | |
|---|
| 223 | # A YAML reference card |
|---|
| 224 | --- %YAML:1.0 |
|---|
| 225 | |
|---|
| 226 | Collection indicators: |
|---|
| 227 | '? ' : Key indicator. |
|---|
| 228 | ': ' : Key / value separator. |
|---|
| 229 | '- ' : Nested series entry indicator. |
|---|
| 230 | ', ' : Separate in-line branch entries. |
|---|
| 231 | '[]' : Surround in-line series branch. |
|---|
| 232 | '{}' : Surround in-line keyed branch. |
|---|
| 233 | |
|---|
| 234 | Scalar indicators: |
|---|
| 235 | '''' : Surround in-line unescaped scalar ('' escaped '). |
|---|
| 236 | '"' : Surround in-line escaped scalar (see escape codes below). |
|---|
| 237 | '|' : Block scalar indicator. |
|---|
| 238 | '>' : Folded scalar indicator. |
|---|
| 239 | '-' : Strip chomp modifier ('|-' or '>-'). |
|---|
| 240 | '+' : Keep chomp modifier ('|+' or '>+'). |
|---|
| 241 | int : Explicit indentation modifier ('|10' or '>2'). |
|---|
| 242 | # Modifiers can be combined ('|2-', '>+10'). |
|---|
| 243 | |
|---|
| 244 | Alias indicators: |
|---|
| 245 | '&' : Anchor property. |
|---|
| 246 | '*' : Alias indicator. |
|---|
| 247 | |
|---|
| 248 | Transfer indicators: |
|---|
| 249 | '!' : Transfer method indicator. |
|---|
| 250 | '!!' : Transfer method with private type family. |
|---|
| 251 | '^' : Establish/use global type family prefix. |
|---|
| 252 | '|' : Separate global type family from format. |
|---|
| 253 | |
|---|
| 254 | Document indicators: |
|---|
| 255 | '%' : Directive indicator. |
|---|
| 256 | '---' : Document separator. |
|---|
| 257 | '...' : Document terminator. |
|---|
| 258 | |
|---|
| 259 | Misc indicators: |
|---|
| 260 | ' #' : Throwaway comment indicator. |
|---|
| 261 | '=' : Default value map key. |
|---|
| 262 | '<<' : Insert keys from map key. |
|---|
| 263 | |
|---|
| 264 | Core types: ### Almost never given explicitly |
|---|
| 265 | '!map' : [ Hash table, dictionary, mapping ] |
|---|
| 266 | '!seq' : [ List, array, tuple, vector, sequence ] |
|---|
| 267 | '!str' : Unicode string |
|---|
| 268 | |
|---|
| 269 | Language Independent Scalar types: |
|---|
| 270 | [ , ~, null ] : Null (no value). |
|---|
| 271 | [ 1,234, 0x4D2, 02333, 20:34 ] : [ Decimal int, Hexadecimal, Octal, Base60 ] |
|---|
| 272 | [ 1,230.15, 12.3015e+02, 20:20.15 ] : [ Fixed float, Exponential, Base60 ] |
|---|
| 273 | [ .inf, -.Inf, .NAN ] : [ Infinity (float), Negative, Not a number ] |
|---|
| 274 | [ +, true, Yes, ON ] : Boolean true |
|---|
| 275 | [ -, false, No, OFF ] : Boolean false |
|---|
| 276 | ? !binary > |
|---|
| 277 | R0lG...BADS= |
|---|
| 278 | : |
|---|
| 279 | Base 64 binary value. |
|---|
| 280 | |
|---|
| 281 | Escape codes: |
|---|
| 282 | Numeric : { "\xXX": 8-bit, "\uXXXX": 16-bit, "\UXXXXXXXX": 32-bit } |
|---|
| 283 | Protective: { "\\": '\', "\"": '"', "\ ": ' ' } |
|---|
| 284 | C: { "\a": BEL, "\b": BS, "\f": FF, "\n": LF, "\r": CR, "\t": TAB, "\v": VTAB } |
|---|
| 285 | Additional: { "\e": ESC, "\0": NUL, "\_": NBSP, "\N": NEL, "\L": LS, "\P": PS } |
|---|
| 286 | |
|---|
| 287 | compliance: |
|---|
| 288 | - feature: YAML Separators |
|---|
| 289 | supported?: (Yes) |
|---|
| 290 | notes: Custom YAML separators are allowed and will be used in exporting multiple documents. |
|---|
| 291 | - feature: YAML directives |
|---|
| 292 | supported?: (Yes) |
|---|
| 293 | notes: > |
|---|
| 294 | Directives are parsed correctly, but are of little use. The TAB directive is completely |
|---|
| 295 | ignored, as tabs are not supported at this time. |
|---|
| 296 | - feature: Transfer methods |
|---|
| 297 | supported?: (Yes) |
|---|
| 298 | - feature: Private types |
|---|
| 299 | supported?: (Yes) |
|---|
| 300 | - feature: URI Escaping |
|---|
| 301 | supported?: (Yes) |
|---|
| 302 | - feature: URI Prefixing |
|---|
| 303 | supported?: (Yes) |
|---|
| 304 | - feature: Throwaway comments |
|---|
| 305 | supported?: (Yes) |
|---|
| 306 | - feature: Anchors |
|---|
| 307 | supported?: (Yes) |
|---|
| 308 | - feature: Aliases |
|---|
| 309 | supported?: (Yes) |
|---|
| 310 | - feature: Sequences |
|---|
| 311 | supported?: (Yes) |
|---|
| 312 | notes: Nested and flow both supported. |
|---|
| 313 | - feature: Mappings |
|---|
| 314 | supported?: (Yes) |
|---|
| 315 | notes: Nested and flow both supported. |
|---|
| 316 | - feature: Key indicators |
|---|
| 317 | supported?: (Yes) |
|---|
| 318 | - feature: Explicit indent |
|---|
| 319 | supported?: (Yes) |
|---|
| 320 | - feature: Chomping |
|---|
| 321 | supported?: (Yes) |
|---|
| 322 | - feature: Literal scalar |
|---|
| 323 | supported?: (Yes) |
|---|
| 324 | - feature: Folded scalar |
|---|
| 325 | supported?: (Yes) |
|---|
| 326 | - feature: Unquoted scalars |
|---|
| 327 | supported?: (Yes) |
|---|
| 328 | notes: No support for spanning unquoted. |
|---|
| 329 | - feature: Single-quoted scalars |
|---|
| 330 | supported?: (Yes) |
|---|
| 331 | - feature: Double-quoted scalars |
|---|
| 332 | supported?: (Yes) |
|---|
| 333 | - feature: Escape characters |
|---|
| 334 | supported?: (Yes) |
|---|
| 335 | notes: Most should be. |
|---|
| 336 | - feature: Strings |
|---|
| 337 | supported?: (Yes) |
|---|
| 338 | - feature: Null |
|---|
| 339 | supported?: (Yes) |
|---|
| 340 | feature: Canonical and english. |
|---|
| 341 | - feature: Boolean |
|---|
| 342 | supported?: (Yes) |
|---|
| 343 | notes: Canonical and english. |
|---|
| 344 | - feature: Integer |
|---|
| 345 | supported?: (Yes) |
|---|
| 346 | notes: Canonical, oct, dec, and hex. |
|---|
| 347 | - feature: Float |
|---|
| 348 | supported?: (Yes) |
|---|
| 349 | notes: Canonical, exp, fix, english |
|---|
| 350 | - feature: Time |
|---|
| 351 | supported?: (Yes) |
|---|
| 352 | notes: Canonical, iso8601, spaced and ymd (as Date). |
|---|
| 353 | - feature: Binary |
|---|
| 354 | supported?: (Yes) |
|---|
| 355 | - feature: Default key |
|---|
| 356 | supported?: (Yes) |
|---|
| 357 | |
|---|
| 358 | acknowledgements: |
|---|
| 359 | - who: Brian Ingerson |
|---|
| 360 | why?: | |
|---|
| 361 | Ingy's YAML.pm was INDISPENSABLE in writing this library. In fact, |
|---|
| 362 | most of the emitter code follows the YAML.pm code quite closely. |
|---|
| 363 | I also borrowed from his testing suite. Hopefully in the near |
|---|
| 364 | future, YAML.rb and YAML.pm will use the same testing suite. |
|---|
| 365 | |
|---|
| 366 | Brian is also the creator of YAML. I'd say he's the free software |
|---|
| 367 | equivalent of an Olympic long jumper. |
|---|
| 368 | email: ingy@ttul.org |
|---|
| 369 | |
|---|
| 370 | - who: Steve Howell |
|---|
| 371 | why?: | |
|---|
| 372 | Comrade on the Yaml-core mailing list. He's working on the |
|---|
| 373 | Python YAML implementation. Very encouraging of this project. |
|---|
| 374 | I plan on stealing his Ruby code to handle circular data structures. |
|---|
| 375 | Steve has also contributed to the YAML Testing Suite. |
|---|
| 376 | email: showell@zipcon.net |
|---|
| 377 | |
|---|
| 378 | - who: Clark Evans |
|---|
| 379 | why?: | |
|---|
| 380 | Clark showed immediate excitement upon discovery of YAML.rb. |
|---|
| 381 | And at that point I hadn't really done much yet, but the |
|---|
| 382 | encouragement sure helped alot. |
|---|
| 383 | |
|---|
| 384 | - who: Oren Ben-Kiki |
|---|
| 385 | why?: | |
|---|
| 386 | For his work on the spec and the quick reference. All three |
|---|
| 387 | of these guys have built a well-written specification, paying |
|---|
| 388 | great attention to details. |
|---|
| 389 | |
|---|
| 390 | - who: Yukihiro Matsumoto |
|---|
| 391 | why?: | |
|---|
| 392 | Creator of the Ruby language. The most innovative man in |
|---|
| 393 | software development bar none! |
|---|
| 394 | |
|---|
| 395 | - who: qwilk |
|---|
| 396 | why?: | |
|---|
| 397 | Long-time friend at desktopian.org, developer of Blackbox for |
|---|
| 398 | Windows, Robin Hood web server. Excellent chum, persistent |
|---|
| 399 | BeOS fanatic and leader of a generation of shell folk. |
|---|
| 400 | |
|---|