Today, we’ll use
Tangerine (download at
the end of this post) to convert the ports information file of
RPA into a
Debian-dctrl-like format. This has some
advantages, for example, we will be able to use grep-dctrl
and other
tools that expect the Debian-format.
The ports.info is a simply
YAML file with entries like these:
metadata:
name: progressbar
rpaversion: "0.0"
version: 0.8.0-1
classification:
- Top.Library.Development
description: >
A text progress bar library.
Ruby/ProgressBar is a text progress bar library for Ruby. It can indicate
progress with percentage, a progress bar, and estimated remaining time.
url: http://rpa-base.rubyforge.org/ports/progressbar_0.8.0-1.rps
So, let’s write a small script to load a YAML file and apply a
Tangerine template on it:
require 'yaml'
require 'tangerine'
# Convenient hashes
class Hash
# Defined methods can be accessed by prefixing with _, e.g. _to_s.
def method_missing(name, *args)
name = name.to_s
name = name[1..-1] if name =~ /^_/
self[name]
end
end
object = YAML.load File.read(ARGV[0])
print Tangerine::RFC822.new(STDIN.read).expand(object)
We also added an extension to Hash to write hash.key
instead of
hash[key]
. This makes using Tangerine easier (The better solution
would have been to make YAML generate a OpenStruct, but I just
couldn’t get it doing that…).
For testing, the first template: Simply show all packages:
,,(self){,,(metadata.name)
}
Save that into a file, and run it like this:
$ ruby yaml2whatever.rb ports.info < packages.tng
You should now see a list of packages.
This template is interpreted as follows: For each self
(i.e. the
list of entries), output metadata.name
and a newline.
Now, to our debian-like output:
,,(self){,,([metadata]){Package: ,,name
Section: ,,classification
Version: ,,version
,,requires{Depends: ,,(self)}},,#
Url: ,,(url)
Description: ,,(metadata.description.gsub(/^$/, '.'))
}
This template has a small twist. Usually ,,(array){block}
would
expand the block
for each element. But since we only want to save
writing metadata.
all the time, we need to make an array out of it,
therefore ,,([metadata])
. The ,,#
in the Depends-line stops
Tangerine from outputting a superfluous newline (Think %
in TeX).
$ ruby yaml2whatever.rb ports.info < debian.tng
Voila, a nice package list. Now, let’s query it, for example all
packages related to XML, but show only the package name:
$ ruby yaml2whatever.rb ports.info < debian.tng | grep-dctrl -s Package XML -
Package: copland
Package: gettext
Package: libxml
Package: rake
Package: test-report
Of course, this was an relatively easy job (RPA already has an query
mechanism too :-)), but what if we’d like to have HTML or XML output?
We’d simply need to adjust the templates without changing any code.
The whole job could have been done using plain Ruby of course, but
such programs get confusing quickly due to mixing of code, strings and
their escaping.
Download: tangerine-0.3.1.tar.gz
This is a bugfix release without any new features.
Ich trage einen Sturzhelm, weil ich sturzbesoffen bin.
NP: Bob Dylan — License To Kill (Live in Austria)