From: Sean Russell Date: 2002-01-19T04:18:59+09:00 Subject: Re: Submission: Ruby shard for config files I got a request to do a line-by-line walkthrough of this code, so here it is: The code goes through a file and executes the lines in finds in the file as if they were instance methods. The including class defines those methods, which get called when the config file is loaded. > module Config > def load file > lines = IO.readlines(file) Should be straightforward down to here. At this point, I grab each line and split it up into chunks. This is done by the line.scan(/.../) segment; the regex is just looking for series of non-spaces -- \S+ -- or things enclosed in quotes (or apostrophes) -- (["']).*\3. Each of these matches forms a chunk; because of how scan works, you get back an array of arrays, most of the contents of which we don't care about. We just want the first item in each sub-array, so we collect! the array, turning each sub array into the first element of that sub-array -- collect{|ar|ar[0]}. Of course, we don't care about comments or blank lines in the config file, so we scan the line unless /^\s*(#.*)?$/ (matches comments or blank lines). This is pretty simple, and doesn't allow comments on the same line as a valid command. Put it all together, and you get: > lines.collect! do |line| > line.scan(/(((["']).*\3)|\S+)/). > collect { |ar| ar[0] } unless /^\s*(#.*)?$/ > end The rest should be fairly self-explainatory. Now that we have an array of the chunks, we explode it (with *) and pass it to self.send() as arguments. > lines.each do |args| > self.send( *args ) > end > end > end Example: something chunk "another chunk" gets turned into [["something", nil, nil], ["chunk", nil, nil], ["\"another chunk\"", "\"another chunk\"", "\""]] by the scan. The collect turns it into: ["something", "chunk", "\"another chunk\""] and this gets passed to send() as: self.send( "something", "chunk", "\"another chunk\"" ) Quotes and all, so you have to account for them in your code, or strip them out, probably in the collect: ... collect { |ar| ar[0].gsub( /(^["'])|(["']$)/, '' ) } unless /^\s*(#.*)?$/ ... Hope this clarifies things a bit. --- SER