The Nukumi2 codebase is doing very well, and the code would be fairly ready for release. But there is not a single line of documentation written by now, and lots of things are still specified informally if at all.
At least basic documentation is clearly needed before release of 0.1. (Un)fortunately, I’m a bit sick right now, so I couldn’t code (anything useful) anyway; I hope I can spend some time writing documentation, maybe an introduction to the core concepts and a step-by-step guide to your own blog.
Documentation will be written of course using Nukumi2 itself, to demonstrate it’s hackability and flexiblility.
Then, I need to figure how to package it… I use lots of “vendor”
libraries written by myself, but located in other repositories; I
think I can work around that with some bits of rake
hacking.
(Hey, I package using recursive calls to Rakefiles interspersed
with calls to darcs dist
… :-))
In case anyone wants to contribute artwork, such as a default template or a button/logo, please mail chneukirchen@yahoo.de.
NP: Elliot Smith—Memory Lane
Today, I did a nice hack using Darcs to make a Lines of Code statistic.
Darcs provides a command—darcs trackdown
—that gets run on every
revision of the repository until the given command returns true.
Usually, you’d use that to “trackdown” a certain bug by running the
testcase on every revision.
However, trackdown
also provides a nice way to simply run an
command over each revision. I ran this on the darcs repository:
darcs trackdown 'find . -type f -print | xargs wc -l |
tail -1 | tee -a /tmp/darcsloc; false'
Note the false
, so it will always “fail”.
Now twiddle with that data a bit, and you can quite easily get a diagram like:
Lines Of Code of the Darcs repository
(The “vertical lines” are time skews of the Darcs changelog, as patches only have a “record time”, not a “merge time”…)
NP: Neil Young—My My, Hey Hey
Finally, this blog is converted to Nukumi2!
(Should you ever feel the need to look at the old one, try http://kronavita.de/chris/old-blog.)
Old permalinks will point to the old blog.
As a side-effect, you now can also subscribe to certain categories of
this blog. To do that, simply change the .html
of the URL to .rss
respective .atom
(preferred). Everything else should be the same
for the usual visitor (well, except the new, lighter design…).
The first public release (Will be 0.2, I think) will need some more time, tough… maybe for Christmas. :-)
NP: Die Toten Hosen—Ich bin die Sehnsucht in dir
Was mag sich der Autor wohl gedacht haben, als er das verfasst hat? (Dorn-Bader, Physik Oberstufe, Schrödel 1983, S. 53):
Wir haben nicht bedacht, dass im schwerefreien Raum das Wasser einen geraden Strahl längs der neuen Abspritzgeschwindigkeit v0 schräg nach oben bilden würde. In diese Richtung müssen wir nun deshalb auch die bislang waagerechte Latte drehen. Nun geht der “Laufsteg von Bettina” schräg nach oben. Da die Stäbchen an der Latte gelenkig befestigt sind, bleiben sie vertikal. Sie markieren jetzt die von der schrägen Latte aus gesehenen Fallwege und werden unten naß — wie es sein soll. […] Ihr Scheitel liegt jetzt schräg über der Abspritzdüse.
Nein, was haben wir gelacht… :-)
Final move to Nukumi2 tomorrow!
NP: Tom Waits—Bad Liver And A Broken Heart
Nukumi2 is a very flexible and open framework for building static and dynamic content websites. It was mainly created to allow blogging and has features to ease this, but in general every kind of mainly content providing website can be created with it. For example, it empowers this site.
Also see blog posts about Nukumi2.
This release does not incorporate the Kashmir templating engine yet, just because I lack the time to rewrite the templates.
The switch to Dissident means you need to change your config.rb file,
please read the documentation (especially “A Step-by-step Guide to
Your Own Blog/Designing the TopicTree”) about the new syntax of the
register
block.
In order to run Nukumi2, you need (all available via RPA):
rake is needed for Nukumi2 development.
December 30, 2005: Second public version 0.5 released.
December 30, 2004: First public version 0.1 released.
You can download rand.rb at
http://chneukirchen.org/releases/nukumi2-0.5.0.tar.gz.
md5sum: c3650d4d1adc73b16cbf302385be495b
You can get latest development releases using darcs by executing:
darcs get http://chneukirchen.org/repos/nukumi2.5
darcs send
is the preferred way to send patches, but mailing diffs
is fine too.
Please mail bugs, feature requests or patches to the mail addresses above or use IRC to contact the developers.
Copyright © 2004, 2005 Christian Neukirchen
This work is licensed under the terms of the GNU General Public License.
…doch da sind sie wieder!
Der Mixer ist ein durcheinandergerät.
Der Kot wird kodiert und das Leder lädiert.
Sie gingen ans Wasser um die Pferde zu tranken.
— Was?? Zu
ertränken?
…Alkohol aus dubiosen Quellen…
— Aus Frankreich?!
Was ist eine Mutante?
— Das Gegenteil vom Muonkel?
Hattest du schon Kontakt mit Herr Wulz?
— Ja, aber nur im
Gespräch!
NP: Tom Petty, George Harrison, Neil Young, Eric Clapton, Bob Dylan, Roger McGuinn—My Back Pages
Brilliant song!
Over the weekend, I’ve ported this blog over to Nukumi2. You can try the new version at http://kronavita.de/chris/blog2. Please don’t update any bookmarks, as the new version will be replacing the old.
If you find any errors, bugs or other things (validation errors!), drop me a mail.
Update: Feeds compared with relative links suck, I need to look into how to do that.
Update 2: They suck more than I thought. I’m using absolute links for now…
NP: Tom Waits—Grapefruit Moon
Jamis Buck announced Needle-Extras 1.0.0 today on ruby-talk.
It’s a “collection of additional services that may be used with the Needle dependency injection container for Ruby”.
If you want to do anything that goes further than the most basic use of Needle, I strongly recommend you to get it and look at the sources. You can learn lots from them.
So far, Needle-Extras consists of:
AttrInject
, “an implementation of dependency injection that uses
declared interfaces to determine dependencies.” (Yeah, see
“attr_inject: A step towards interface
injection”.
My idea. :-))
I think it is an good example of how to implement a Needle::Pipeline::Element.
Multicast
, a service that “allows you to easily broadcast messages
to a specified set of objects. It is, in essence, a kind of observer
pattern, with the observers being given to the multicaster when it
is created. Events are then sent to the observers by invoking
methods on the multicaster.”
Read this if you want to define services that behave as if they were in the core Needle library.
RequireLibrary
, “a mini-framework for registering service libraries
with Needle so that they can be imported into other projects with a
minimum of headache.”
This shows how a general-purpose Needle utility can be done.
I have definitely some use for all of them…
NP: Phish—While My Guitar Gently Weeps
Playing a bit with Nukumi2, I discovered a very interesting thing: If I disable BlueCloth, my pages suddenly render a lot slower. “This ain’t possible”, I stumbled. BlueCloth is fairly fast, but still the slowest component of the rendering stage. “What the hell is going on?”
I timed the rendering of a few entries by themselves, they were all faster than with BlueCloth. Well, all except one. Yesterday’s. I trimmed it a bit, and finally found out that if I removed that part, it would run at full speed again:
class Class
def attr_inject(attribute)
(@__attributes_to_inject ||= []) << attribute
end
end
I ran a profiler (ruby -r profile
), and it turned out String#scan
was taking quite long… Where is it used? In RubyPants, look at the code:
def tokenize
tag_soup = /([^<]*)(<[^>]*>)/
tokens = []
prev_end = 0
scan(tag_soup) {
tokens << [:text, 1ドル] if 1ドル != ""
tokens << [:tag, 2ドル]
prev_end = $~.end(0)
}
if prev_end < size
tokens << [:text, self[prev_end..-1]]
end
tokens
end
Ok, it’s a part of the HTML tokenizer… The only reason scan
can be
slow is the regular expression, let’s have a closer look:
tag_soup = /([^<]*)(<[^>]*>)/
Well, it looks alright: First match any preceding text and then a tag. After toying around for fifteen minutes with that regexp, trying various tweaks (e.g. making it non-greedy), I built a proper test case. That string took very long, ~6 seconds to parse it 100 times:
<hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh...
Even more h
to come. I remembered a scary issue about
regular expressions: Under certain circumstances, backtracking can make
Regexps run in exponential time (various string sizes showed that)
because they try every possible match.
It really looked like that was the case… But where the hell does it backtrack? There are no alternations, and the match should run linearly. Well, it should. But it didn’t. It turned out that it really tries every possible match, because the match isn’t anchored.
D’oh! Of course, there is no anchor. Luckily, I remembered \G
from
back when I used Perl. man perlre
says:
\G Match only at pos() (e.g. at the end-of-match position
of prior m//g)
Hey, cool. That should be exactly what we need. Make that line simply
tag_soup = /\G([^<]*)(<[^>]*>)/
and off it goes! Blazingly fast. :-)
Who would have thought two characters can make such a big difference?
(Of course, I’d have never discovered that “bug” if I only ran it on
correct input (as >>
is not valid HTML), so test your code with
“invalid” data too!)
NP: Sum 41—We’re All To Blame
During the needlefication of Nukumi2, I came across a lot of service definitions like this:
class Blog
attr_accessor :backends
attr_accessor :page
attr_accessor :view
attr_accessor :topictree
# ...
end
blog {
b = Nukumi2::Blog.new
b.backends = backends
b.config = config
b.page = page
b.topictree = topictree
b
}
Needing to define all these accessors was a thorn in my side.
Although I would need some attr_reader
s for them, writing is not a
thing I want to allow.
The use of attr_reader
, attr_writer
and attr_accessor
is not
just a shortcut in Ruby; it also has a semantical meaning: You are
allowed to read this attribute, to write this attribute or to do
both. RDoc, for example, will base it’s documentation on them, there
will be a special section Attributes in the class documentation.
Therefore, I whipped up a new kind of
“accessor”—attr_inject
—that allows to declare an attribute for
dependency injection. Now, the class will look like:
class Blog
attr_inject :backends
attr_inject :page
attr_inject :view
attr_inject :topictree
attr_reader :topictree
# ...
end
It only opens the things for the “general public” that are actually wanted. However, having these declarations, we can now simply do:
blog {
Nukumi2::Blog.new.inject_attributes(this_container)
}
Pretty nice, heh? :-)
For now, I just have some very simple code; some additions will be needed to make use of all possibilities. It would be nice to allow users to override attribute mappings (for now, attributes and service names need to match):
blog {
Nukumi2::Blog.new.inject_attributes(this_container,
:backends => my_special_backend)
}
Allowing the use of inject_attributes
exactly once would be good too.
By the way, all that’s needed for attr_inject
is just these 15 lines:
class Class
def attr_inject(attribute)
(@__attributes_to_inject ||= []) << attribute
end
end
class Object
def inject_attributes(registry)
(self.class.instance_variable_get(:@__attributes_to_inject) ||
[]).each { |attribute|
instance_variable_set "@#{attribute}", registry[attribute]
}
self
end
end
For “serious” use, this code will need more checks and features, of
course. Another problem is that attr_inject
is not in the standard
library and therefore will break code that may be used with and
without Needle. This can easily be avoided by defining attr_inject
to do nothing unless it’s already defined, though…
NP: Bob Dylan—Is Your Love in Vain?
As stated on ruby-talk and “Progress of Nukumi2”, I released RubyPants 0.2 yesterday.
You can get it at http://kronavita.de/chris/data/rubypants-0.2.tar.gz.
RubyPants is a Ruby port of the smart-quotes library SmartyPants.
The original SmartyPants is a free web publishing plug-in for Movable Type, Blosxom, and BBEdit that easily translates plain ASCII punctuation characters into “smart” typographic punctuation HTML entities.
RubyPants is a general-purpose library that uses an API compatible to Red- and BlueCloth to perform these punctuation translations.
RubyPants 0.2 is also available via RPA:
rpa install rubypants
Have fun.
Nukumi2 is making nice progress. Today I added RSS and Atom feed support, plus Needlefication.
NP: The Brian Jonestown Massacre—Short Wave
Since I couldn’t find anything in my playlist anymore (Actually, this
is not true. xmms’ J
works excellent for finding single songs, but
grouping and getting stuff together is hard), I decided storing my
MP3/OGG-metadata in a TopicTree. Unfortunately, some of my MP3 are
not tagged, so I needed to do some ugly heuristics to find name and
title…
Ideally, I’d run something like this
musidex --random /artist/bobdylan /year/1/9/8 >playlist.m3u
and get a randomized playlist of all stuff by Bob Dylan he did in the 80’s. I tried running xmms on a playlist coming out of a FIFO, but that didn’t work. For real dynamic playlists, I’d probably need a HTTP server (WEBrick to the rescue!).
Of course, a nice frontend would rock too…
NP: Pearl Jam—Light years
Zum Ende der Herbstferien mal wieder Quotes:
Haha, ich dachte grad’, Seattle wäre Sidney, aber Sidney liegt ja
in Ägypten!
Busenknettag
Die macht immer “mmmm” wenn sie zur Tür reinkommt.
—
Vielleicht muss sie noch schlucken?
Mal wieder etwas langsamer schalten…
Apropos Schalten: Andi, herzlichen Glückwunsch zur bestandenen (auf Anhieb! :D) Führerscheinprüfung!
BTW, Darcs 1.0.0 has been released!
NP: Billy Talent—Try Honesty
Nukumi2 is doing very well, I’m actually writing on code that will be in the first public release 0.1 codename “godspeed”. :-) I hope I’ll publish this release this month, but I can’t promise it.
Not mentioned new features include:
Clotheslines: You can now chain multiple clothes together,
respective any code that follows the StarCloth API (which is
StarCloth.new(text).to_html
). My sample blog runs currently on
this clothesline:
BlueCloth RubyPants NiceHR
Which is essentially the same as:
result = NiceHR.new(RubyPants.new(
BlueCloth.new(text).to_html).to_html).to_html
RubyPants will be there, a proper standalone release will appear this week. (John Gruber already linked to it, thanks a lot ;-))
NiceHR, a sample cloth that will wrap <hr />
into a <div class="separator">
for better taming with CSS. It’s primarily an example on how to use REXML
for tasks that were done with XSLT in Nukumi1.
NP: Bob Dylan—I Want You (At Budokan)
Whee, I’m leaving this evening to Ulm to see Richard M. Stallman in real life! He’ll be giving a speech about the dangers of Software Patents there. Thanks in advance to the CCC Ulm for organizing this.
Pretty excited…
NP: Interpol—Slow Hands
Today, I ported the Perl library SmartyPants to Ruby. SmartyPants calls itself an “web publishing utility that translates plain ASCII punctuation characters into “smart” typographic punctuation HTML entities.” By the way, it’s written by the author of Markdown (which I use for a long time now), John Gruber.
Porting was quite easy, as I had a Perl and a Python implementation available (playing “Rosetta Stone” is fun :-)), I only got stuck at some Perl-specific Regexp stuff, but that was worked around easily.
Before RubyPants, I used some very primitive regexen to make em-dashs (--- gets —) and and ellipses (... gets …). However, I never got around converting quotes ("foo" gets “foo”) because that is quite difficult. Fortunately, SmartyPants handles most cases, and the very special cases can easily get corrected manually.
Grab RubyPants 0.1 while it’s still hot!: rubypants.rb (Proper release comming soon)
NP: Mark Knopfler—Boom Like That
I’m quite disappointed on the election results. (And I have to say that an amazingly big number of people outed as Bush voters—people I’d never have expected to :-/)
The next four years are likely to be “fun”.
Come writers and critics
Who prophesize with your pen
And keep your eyes wide
The chance won’t come again
And don’t speak too soon
For the wheel’s still in spin
And there’s no tellin’ who
That it’s namin’.
For the loser now
Will be later to win
For the times they are a-changin’.
NP: Bob Dylan—The Times They Are A-Changing