Zurzeit heftige vokalseismische Aktivitäten in der Klasse:
Meine Mutter hat Angst vor der Wäschespinne!
Wasserdamf
Wenn’s Jungen wären, wären es viereiige Zwillinge.
Können wir nicht einfach in’s Pornokino gehen? Das ist auch
moralisch nicht bedenklich.
NP: Bob Dylan—Just My Imagination
‘Mal wieder paar Quotes:
Grüß Rock, Herr Gott!
Natürlich, die ganzen Wichsflecken gehen ja bei 60° auch raus!
Einmal blasen 1,ドル ergo: 1€-Job.
Mein Onkel wird bald General!
— Bei Henkel?
AAH! Ich hab’ alle Vorzeichen vergessen!
Glotzt nicht so romantisch!
Der schnucklige, alte Trottel.
Irgendjemand wird hier Windowmanager!
NP: Manda Clair—Mama Can’t Hear You (Mama Don’t Feel No Pain)
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)
… könnte man denken, wenn man so liest, was bei uns alles abgeht:
Ich weiß, dass ihr Latein könnt!
— Da wissen sie aber mehr
als wir.
Was gibt’s im indischen Café zu essen und trinken?
—
Buddhamilch, Buddhabrot und Buddhakuchen.
Die Trägheit der Masse ist unantastbar.
Rettet den Drogenwald!
Da machen wir paar Ausflüge in die…
— Zukunft!
Vielleicht liegt’s aber auch daran, das zur Zeit eher Kaffee Trinkwasser bevorzugt wird. =:-)
NP: Starfuck—Masquerade
I’ve decided to drop the plan to use Emacs as the interface to Scribble, instead writing it in Ruby/Tk too. This allows smaller size of binaries around (I’d RigRag and Scribble to be portable and small, easily fetchable from the web.), at the cost of editing convenience. But I’ll add external editor support (after all, every page is a simple text file), thereby outweighing that issue.
I have to say that Ruby/Tk is really great for getting a GUI done quickly although the API really sucks at times. For example, why can’t I index contents of a TkText widget by character count? Instead I need to twiddle with lines and chars. D’oh. (Of course, this is all being inherited from Tcl/Tk.)
Here a screenhot:
Scribble screenshot showing a test page
I think that page is great: Japanese Death Poems.
NP: Leadbelly—Where Did You Sleep Last Night?
Man gönnt sich ja sonst nix:
Wuzaspitze
Der Papst ist Alkoholiker!
Ihr faulen Schwanz!
Persönliche Neigung?
— Linksträger.
Dann, Sport:
Das war filmreif!
Du musst mehr laufen! … sonst frierst du bei dem Wetter!
NP: Redrum—Blue Blood
ein paar Quotes der letzten Tage:
Does it make you think?
— I think so.
I love you.
[Zum Englischlehrer als Demonstration von Ironie.]
Wo wachsen Kiefern?
— Im Wald!
Hackt’s euch?
Freitags kann ich nicht.
— Und ‘ne Woche vorher?
NP: Bob Dylan — Hard Rain (Live in Japan)
I just released Tangerine 0.3. Grab it here.
New features over 0.2.1 include:
Tag libraries provide an easy way to build and structure complex
templates. Tags starting with @
are looked up using the tag
library which is given as the second argument to
Tangerine.new
.
Tag libraries are objects that implement resolve(tag)
and
return a string that gets evaluated as a Tangerine template
instead of the tag upon calling that method.
One sample tag library that maps tags to files is included as
Tangerine::FileLib
.
Support for RFC(2)822 message escaping.
Header values can be escaped automatically to conform to RFC(2)822.
Better error handlers.
The erroneous line in the generated code should now be the same as the erroneous template line.
Download: tangerine-0.3.tar.gz
NP: Billy Talent—Nothing to Loose
I’ve spent the whole afternoon writing two small scripts. What did I do?
My desktop is basically one Emacs instance beneath one Aterm. (Well,
there’s a lot of stuff around it, but that doesn’t matter here.) When
I code, I write the programs in Emacs, and run them in Aterm.
Switching between those two windows is easy, I simply press M-Tab
.
This is a feature by Enlightenment. However, when my code raises an
unhandled exception, there was no easy way to jump directly to the
error; I had to jump to and retype the line number of the erroneous
file.
This has changed now. I simply run my programs as usual, but write ete
before:
$ ete ruby fuckup.rb
fuckup.rb:1: undefined method `fuckup' for main:Object (NoMethodError)
To handle this (trivial) error, I simply switch to Emacs and type C-x
:
. Emacs will now load the output of ete
and jump to the first
(mostly only) error. I could use C-x `
if I had several errors.
(Unlikely with Ruby, but maybe a C extension…)
You can download ete
here: ete
(shell script), ete.el
(elisp).
On a side note, put this into your .emacs
:
;; Make ruby-mode usable for hs-minor-mode.
(add-to-list 'hs-special-modes-alist
(list 'ruby-mode
(concat ruby-block-beg-re "\|{")
(concat ruby-block-end-re "\|}")
"#"
'ruby-forward-sexp nil))
Now open some lengthy Ruby file, and do:
M-x hs-minor-mode
M-x reveal-mode
Move over some def
s, press C-c @ C-l
(better rebind that :P), and be astonished
moving your cursor in and out. ;-) Cool, eh?
NP: Velvet Revolver—Superhuman
I just released Tangerine version 0.2.1.
This is the first public release. All user-visible methods are fully documented, the same is true for the template language.
Use Tangerine::XML
instead of plain Tangerine
if you want your
data to be escaped automatically (this is overridable).
Tangerine 0.2.1 can be downloaded here: tangerine-0.2.1.tar.gz.
Osmöse
Lehrer zeichnet Brown’sche-Molekularbewegung an die Tafel.
—
Hat der grad’ seine Schamhaare hingemalt?
Knietief im Wochenende
Hallo, Herr Rotz
NP: Redrum—Heroin Girl
Since there are more Ruby packages for templating than there are real users of them (:-P), I’ve decided it can’t hurt to make one myself.
It’s called Tangerine, and is the first library I’ve developed using TDD. (Thanks, dragonkh :-)).
Of course it’s hard to design (and not only implement) something new,
therefore I did two spikes before, dubbed AllOfMyLove which was a 20
lines gsub
for experimentation, and DeepBlueTea, a lot longer code
that used a “real” parser (as needed for nested parentheses).
(I guess I’m a grand-master in inventing silly project names :-P).
Tangerine finally implements a compiler which creates a Proc out of
the template for good performance. In benchmarks I did myself (never
trust a benchmark…), Tangerine turned out to be 2 times faster than
a comparable ERB template. (ERB eval
s all the time.)
Finally, I’ll show a short sample to show how it feels like:
<h1>,,title</h1>
<h2>,,tagline</h2>
<p>,,(Time.now)</p>
,,# overview
<ul id="toc">
,,entries{
[<li>,,(title.upcase)</li>]
}
</ul>
,,entries{
<h3>,,title</h3>
,,recent?{<em>[New]</em>}
<p>,,body</p>
<hr />
}
<p>,,title -- ,,tagline. ,,(Time.now.strftime("%d%b%Y").downcase)</p>
This is a very primitive template for a simple weblog, and will result in something like this:
<h1>chris blogs</h1>
<h2>a blog by christian neukirchen</h2>
<p>Mon Sep 13 19:29:04 CEST 2004</p>
<ul id="toc">
[<li>HEAD</li>]
[<li>ANOTHER</li>]
</ul>
<h3>head</h3>
<em>[New]</em>
<p>some <content></p>
<hr />
<h3>another</h3>
<p>again</p>
<hr />
<p>chris blogs -- a blog by christian neukirchen. 13sep2004</p>
A few issues still need to be handled better, I’ll do a release soon.
Name für eine jüdische Kneipe: Bar Mitzwah.
Zustand des Religionsbuches bei Erhalt: lächerlich.
:-)
NP: Led Zeppelin—Tangerine
Und schon wieder sind die Sommerferien rum…
Ging das nicht schnell?
Ab morgen wieder die neusten Quotes aus dem Klassenzimmer!
NP: Led Zeppelin—Stairway to Heaven
I spent some time to get into conTeXt, an alternative macro package for TeX. I prefer it over LaTeX, because it has full plain TeX under the hood and is more easy to customize.
To start, I’ve decided to re-invent the wheel by mimicking Richard P. Gabriels slide style that he used for “Form & Function in Software” (available at his site, http://www.dreamsongs.com).
Basically, it’s a very easy style. Just white P22Typewriter on black background. After deciding to use pdfTeX, I figured how to use a TTF with it. Basically, you need these steps (teTeX on debian):
ttf2afm -e /usr/share/texmf/ttf2tfm/T1-WGL4.enc -o FONT.afm FONT.ttf
afm2tfm FONT.afm -T /usr/share/texmf/ttf2tfm/T1-WGL4.enc
echo `afm2tfm FONT.afm -T /usr/share/texmf/ttf2tfm/T1-WGL4.enc` \
'<FONT.ttf' >> fonts.map
However, be sure fonts.map is being loaded in some pdftex.cfg by adding that line:
map +fonts.map
It turns out that was the easiest part. :-) After fighting a bit with the conTeXt documentation (nice manual actually, but kind of confusing and incomplete…), I’ve finally managed to copy that style.
See a sample document: a hash of my life [src]
NP: The Hives—Love In Plaster
Today I’ve spent some time to implement the counterpart of RigRag, a wiki-like hypertext system which I dub Scribble.
I decided to write it in Emacs Lisp, since I use Emacs for most of my
other stuff too (I keep all my addresses in bbdb
, for example), so
that would be a nice fit.
I’d have liked to implement RigRag in elisp too, but it’s too graphical to be practical to be used inside a text editor (if you want to call Emacs that way :-)).
Well, I discovered that my elisp knowledge leaves a lot to be desired, so it’s probably going to take some time until I get into it again. However, I need to say that the Emacs documentation really is superb: Being clearly written, covering just about everything one needs to know, and having a comprehensive index is not something you see every day when working with software.
NP: Presidents of the USA—Last Girl On Earth
After I managed to keep my irssi
open for more than 100 days,
Irssi uptime: 101d 22h 13m 1s
empi leave message made me rofl:
22:59 -!- empi [~moar@dsl-XXX-XXX-XXX-XXX.arcor-ip.net] has quit
["Girlfriend pregnant error, [A]bort, [M]arry, [I]gnore ?"]
Yeah, nothing happening here. Go along.
NP: Billy Talent—Prisoners Of Today
My organizing tool (see RigRag) now looks fairly acceptable, so I’ve decided to put some screenshots up:
RigRag shot
RigRag shot
These shots show the “Holm Family”-Example known from the original ZigZag distribution. Both display the same dataset, the first shows first- and surname, the latter one children and spouses.
RigRag is still unusable, as I need to think a bit more about editing and moving the data; therefore is no source available yet.
NP: Bob Dylan—Mr. Tambourine Man
Es ist doch tatsächlich möglich, mit Einwegpfand zu sparen: Am diesjährigen “sun&fun Radio 7 bla bla blub — Der beste Mix die meisten Hits” (das mit den Hits stimmt wohl nicht für die Website :-P) hat mich die Halbe Schussenrieder nur 70¢ gekostet.
Wie man das macht? Ganz einfach.
Geh’ zur Aral und kauf’ eine Flasche Schussenrieder Original No°1. Kostet 1.05€ + 15¢ Pfand, also 1.20€.
Bei sun&fun kostet genau dieselbe Flasche (etwas wärmer ;-)), 1.50€ + 50¢ Pfand, also 2€. Wenn man das Pfand der Aral-Flasche aber bei sun&fun abgibt, bekommt man ja auch 50¢ raus, ergo: Die Halbe kostet 70¢. q.e.d
Schön, dass sun&fun keine Pfandmarken ausgeteilt hat. :-)
NP: Bob Dylan—Talking World War III Blues
For some time now I’ve been thinking of and how to organize
information of all kinds. Many people like to use wikis for that, and
so would I (I’d probably prefer a standalone wiki, for example
emacs-wiki
), but they lack one important thing: Getting an overview.
A wiki is essentially a set of nodes, each having links to other nodes—a.k.a. a graph. Graphs can be drawn in lots of different ways, but it’s hard to make that visually appealing, and lot’s of algorithms related to graphs have large complexity, both in space and time.
Recently, I learned about ZigZag, a tool to organize data in n-dimensional hyperspace. This may sound complicated, but once you get into it, it’s really easy. Basically, you have a spreadsheet where each field can have neighbors in every dimension. In usual implementations, only two dimensions are visible at once, being mapped to the x- and the y-axis. You now can move between these fields and change the dimensions shown.
One example of the original ZigZag disk shows how to build a family tree. First you see a list of first names of the people, ordered alphabetically. On the right-hand side, they’re linked to their surnames. If you now go over to these, they’ll be ordered too, and the first names will be shown on the left, unordered this time.
By rotating the dimensions, one can now see how these people are
linked. There are two additional dimensions, marriage
and
children
. If one enables both, he’ll see a family diagram with the
parents on top and the children going downward. If you put marriage
on the x-axis and 1
on the y-axis, you’ll get a list of all people
with their spouses.
As you can see—or at least guess—, this is a very powerful way of structurizing data. However, you can’t simply do “cross-links”, since your number of links per dimension is limited to two (one at each side).
Therefore I’ve decided to build something that will unite the both approaches: The wiki and ZigZag.
I’ll simply build a ZigZag where each cell contains the name of a Wiki-page. I’ve already taken a shot at implementing ZigZag in Ruby (therefore the name, RigRag), and a wiki will be easy to hook up.
I already can view and browse simple graphs, but editing and persistance is still missing. More soon. ;-)
NP: Josh Ritter—Lawrence, KS
A first public version of my Ruby library to script Enlightenment is available in eesh.rb.
It’s still very alpha, and I some code too complicated, but I don’t know yet how do make it better.
The library can also be used as a binary, where it calls it’s first command-line argument on the current window.
These methods are useful to be called in this context:
move_{left,right,top,bottom}_to
: Move the current window to the
corresponding direction until it hits a different window. If two
windows are already touching each other, move over that window
(sounds awkward, but it very nice to use; try it!)
focus_{left,right,top,bottom}
: Focus the next window placed at
that direction. (These methods behave inconsistent, I’ll fix that
soon; they work fine if the windows are near each other, though)
focus_{left,right,top,bottom}_neighbor
: Focus the next window
placed at that direction which is on the same height (width)
as the current window.
I use vi-like key-bindings (h, j, k, l) plus Windows-key to focus the windows, and move them with Windows+Shift.
You can set your keys easily using e16keyedit
, which is also
available as an Debian package.
NP: Dead Moon—In The Altitudes