Trac als Homepage

written by Martin Häcker on

(Zu Amy Amy Amy)

Trac als Homepage hat sich für mich ja schon bewährt. Ein Wiki, eine Versionsverwaltung, Theoretisch auch noch Bug-Tracking (deaktiviert wg. Spammern) - was will man mehr.

Naja, einen Blog. Und da fängt das Problem dann auch schon an.

Traditionell sind Blogs alle in HTML oder mit merkwürdigen Wysiwyg-Editoren die nicht richtig funktionieren oder so beschränkt sind, das man darin gar nicht alles machen kann was man will (z.B. Source-Code highlighten. Noch dazu Objective-C!)

Ausserdem will ich das mein Blog sauber mit meinem Wiki Verlinkt ist und ich die normale Wiki-Syntax zum Bloggen verwenden kann.

Das mache ich bisher mit dem TracBlogPlugin, nachdem ich frĂĽher mal mit dem SimpleBlogPlugin eher... unzufrieden war.

Leider aber ist auch das TracBlogPlugin nicht perfekt. Zwar setzt es auf das TracTags Plugin auf, das ganz excelent ist - aber leider bleiben einige schwächen.

  • History + Archiv ist mehr oder weniger nicht vorhanden
  • Kommentare gehen nicht.
    • Moderation derselben schon gleich gar nicht.
  • RSS-Feeds sind eher... nun ja, mit einigem Experimentieren kriegt man einiges hin, aber schön ist es nicht.
  • WeblogPings und Backlinks werden nicht unterstĂĽtzt.
  • Blogrolls etc... alles von hand.
  • XMLRPC... Ah well.

Weiterentwickelt wurde das Plugin seit fast einem Jahr nicht mehr (ok, in den letzten Tagen passiert wieder etwas, mal schauen wie das weiter geht)

Jetzt hatte ich mir schon ĂĽberlegt [vielleicht selber Hand anzulegen], da stellt sich heraus, das schon jemand anderes deutlich entnervt war und das Plugin FullBlog entwickelt hat.

Pro:

  • Feeds++
  • Kategorien (mit TracTags UnterstĂĽtzung?)
  • Kommentare + Spamfilterung!
  • XMLRPC support

Cons:

  • Seiten sind nicht im normalen Wiki-Namespace (Aber man kann wohl hin und her linken)
  • Ich kann also nicht alle bestehenden Postings direkt ĂĽbernehmen
  • Der Code malt (da er keine normalen Wiki-Seiten verwendet) direkt in der Datenbank herum. Gnah.

Mehr hab ich mir noch nicht angesehen. Aber eine vernünftige Blog-Integration für Trac wäre Gold wert. Will schließlich heute jeder haben, einen Blog. Ah well.

Eye in the Sky Projektideen:

  • Endlich mehr Blogging Features hier im Trac
  • Mehr Release Management UnterstĂĽtzung
    • Upload von neuen Releases
    • App-Cast auto-generieren - mit Wiki-Seite fĂĽr die Change-Notes
  • Buildserver wäre ein Traum - geht aber nicht solange ich auf Linux hoste und fĂĽr den Mac Entwickle.

Diesen Freitag 17:00 Uhr treff ich mich mit Felix und Felix in der Freitagsrunde und wir werden mal weiter beraten was wir mit Trac weiter machen. Wer Trac Hacken mag oder schon tut und dazukommen mag ist natĂĽrlich herzlich eingeladen. :)

Bei Mac Donalds

written by Martin Häcker on

Nicht nur das es jede menge kranke Mc Donalds Werbung gibt.

Noch viel kranker sind nur die Leute die bei McDonalds einkaufen...

LOGen von beliebig vielen Argumenten

written by Martin Häcker on

Fehlt noch ein letzter Schritt - der erstaunlicherweise ganz einfach war und ausserdem noch ein ganz anderes Problem löste...

Zuerst die Implementierung:

#define LOG(what, variableArguments...) \
    [[Log sharedLog] logObjcType:@encode(typeof(what)) \
        arguments:(void *)what , ##variableArguments]

- logObjcType:(char *)typeString arguments:(void *) what, ...; {
    id formatString =  [self stringFromType:typeString inValue:what];

    va_list variadicArguments;
    va_start(variadicArguments, what);

    id logString = [[[NSString alloc] initWithFormat:formatString 
                    arguments:variadicArguments] autorelease];

    va_end(variadicArguments);

    return [self log:logString];
}

Eigentlich hatte ich hier mehr Probleme erwartet.

Ganz nebenbei löst das auch noch ein Problem von ganz zu Anfang:

LOG(@"%@", [NSString stringWithFormat:@"%s,%s", "fnord", "fnord"]);

Das macht jetzt keine Probleme mehr, da die zusätzlichen Komas vom Präprozessor (fälschlicherweise) als zusätzliche Argumente zur dem variadischen Makro aufgefasst werden. Hehe...

Jetzt fehlt nur noch ein Backend für den Logger und ich bin glücklich. Andererseits... da gibt es natürlich auch Log4Cocoa das ich einfach erweitern könnte.

Hm. Mal schauen.

C-Typen in die Laufzeitumgebung heben

written by Martin Häcker on

Wendet man @encode() jetzt auf ein paar Deklarationen an, erhält man folgende Ergebnisse:

#define LOG(what) [[Log sharedLog] logObjcType:@encode(typeof(what)) arguments:(void *)what]

LOG(@"fnord"); // @
LOG("foo"); // [3c]
char *string = "fnord";
LOG(string); // *

Ich parse das so:

#define RAISE_UNSUPPORTED_TYPE(encodedType) \
    [NSException raise:NSInvalidArgumentException \
        format:@" you are trying to log something that is not a string: %s", encodedType]

- stringFromType:(char *)encodedType inArray:(void *)what; {
    if ('[' != *encodedType) RAISE_UNSUPPORTED_TYPE(encodedType);

    encodedType++;
    unsigned length = strtol(encodedType, &encodedType, 10);
    if ('c' != *encodedType) RAISE_UNSUPPORTED_TYPE(encodedType);

    return [NSString stringWithCString:what length:length-1]; // \0 ignored
}

- stringFromType:(char *)encodedType inValue:(void *)what; {
    if ('@' == *encodedType) return [(id)what description];
    if ('*' == *encodedType) return [NSString stringWithCString:(char *)what];
    if ('[' == *encodedType) return [self stringFromType:encodedType inArray:what];
    RAISE_UNSUPPORTED_TYPE(encodedType);
    return nil; /* never reached */
}

(Vorschläge wie man das besser machen kann, bitte gerne an mich! ( z.B. via spamfaenger ät gmx de))

Fehlt nur noch die Erweiterung auf beliebig viele Argumente. Dazu aber morgen mehr. :)

Mit C Makros etwas tun, was mit ihnen nicht möglich ist

written by Martin Häcker on

Das Problem ist also ein Makro zu schreiben, das typsicher und nach Typen überladen ist, eine variable Anzahl von Argumenten erhält und zudem einfach und verständlich ist.

Zugegeben, mir ist noch nicht klar wie ich das umsetzen kann.

Aber, wenn man das Problem nur ein klein wenig vereinfacht, und nur versucht eines oder mehrere Argumente zu unterstĂĽtzen...

Also zum Beispiel ein LOG() Macro, dass als erstes Argument irgend etwas erhalten kann (für den Anfang, irgend etwas das sich in einen String umwandeln lässt) dann erhält man etwas das sich so verwenden lässt:

LOG(@"fnord");
LOG("fnord");
char *string = "fnord";
LOG(string);
LOG(@"%@", @"fnord");
LOG(@"%s", "fnord");
LOG(@"%d", 10);
LOG("%s", "fnord");
LOG(@"%@", [NSString stringWithFormat:@"%s,%s", "fnord", "fnord"]);

Die Implementierung ist allerdings etwas tricky.

Typinvariante Makros wie MAX(x, y) schreibt man ĂĽblicherweise so:

#define MAX(x, y) ({ \
    typeof(x) __x = (x); \
    typeof(y) __Y = (y); \
    (__x < __y) ? __x : __y; \
})

Das bedeutet durch die speziellen klammern ({ ... }) wird das Makro wie eine Funktion behandelt (eine GCC-Extension) und die ĂĽbergebenen AusdrĂĽcke nur einmal auswertet und in einer Variablen vom korrekten Typ speichert. int m = MAX(i++, ++j); ist damit also kein Problem. SchlieĂźlich ist der Wert der letzten Zeile der "RĂĽckgabewert" der Makro-Funktion

Loggen ist aber schon noch ein Problem, da mit diesem Trick, der Typ noch nicht herauszufinden ist. Mein erster Ansatz mit __builtin_types_compatible_p(typeof(aValue), char *) etc. brachten mich da nicht weiter. Es braucht noch die @encode() Anweisung von Obj-C. Direkt im Makro mit if (@encode(char *) == @encode(typeof(aValue))) war es dann allerdings auch noch nicht obwohl ich gerne mit __builtin_choose_expr( aConstant, expressionOne, expressionTwo ) zur Compilezeit alles erledigt hätte.

Nun ja, dann eben zur Laufzeit mit @encode().

#define LOG(aValue) [[Log sharedLog] logObjcType:@encode(typeof(aValue)) value:aValue]

Die erzeugt aus einem Typ nämlich einen C-String - der zur Laufzeit geparst werden kann um daraus herauszulesen wie der void-Pointer auf aValue interpretiert werden muss.

Wie ich das gemacht hab - morgen. :)

Macros in C

written by Martin Häcker on

(Zu "Feuer Frei" von Rammstein)

Makros in C sind ja so eine Sache.

Zum einen kommt man in C an vielen Stellen gar nicht ohne aus, da sie die einzige Möglichkeit sind Ausdrücke OHNE sie zu evaluieren an mehreren stellen zu verwenden. Zum anderen Sind sie rein Textuell, "unhygienisch" und haben keine Ahnung was in ihnen eigentlich passiert.

Das macht vor allem in Objective-C mächtig Schwierigkeiten. Das hier zum Beispiel geht nicht.

#define DO(argument) argument

DO([NSString stringWithFormat:@"%s", "asdf"]);

Der Compiler meckert hier ĂĽber zu viele Kommas und denkt das ich das Makro mit zwei Argumenten aufrufen will. Gnah.

Warum beschäftigt mich das eigentlich?

Ich möchte gerne Macro's haben, die je nach Typ des Arguments etwas anderes machen. Für Unit-Tests z.B. möchte ich sagen:

- (void) testOverloadedAssert
{
    ASSERT_EQUALS(3, 3);
    ASSERT_EQUALS(@"barf", @"barf");
    ASSERT_EQUALS("bar", "bar");

    // These should fail in a sensible manner
    ASSERT_EQUALS("bar", @"bar");
    ASSERT_EQUALS(3, 3.3);
}

Das ist aber schon ein großes Problem. In C++ könnte man den ersten teil ja noch über überladene Funktionen lösen - das geht in reinem Objective-C aber schon mal nicht. Dazu kommt ja noch der zweite Teil - da kriegt man vielleicht noch Compiler-Fehlermeldungen, wenn der Compiler nicht auto-conversion von Parametern anwirft. :-/

Dazu kommt, das ich C++ nicht mag und schon gar nicht in alle meine Tests eine zwingende Abhängigkeit auf C++ einfügen will.

Will man dann aber noch weiter gehen, wird es endgĂĽltig schwierig. Hier ein paar Beispiele:

- (void) testAdvancedAssert
{
    ASSERT_EQUALS(3.3, 3.3, 0.1 /* accuracy */);
    ASSERT_EQUALS(3.3, 3.3, @"important meta information");
    ASSERT_EQUALS(3, 3, @"info contains: %@ in %s:%d",
         @"other info", __PRETTY_FUNCTION__, __LINE__);
}

In reinem C hätte man hier gar keine Möglichkeiten mehr etwas zu machen.

Wie weit ich mit einer Lösung dennoch gekommen bin - morgen. :)

Geek-Humor

written by Martin Häcker on

Schnell noch aus der Kategorie "Geek-Humor".

FĂĽr alle die die Prometheus Seite noch nicht besucht haben.

GroĂźartig.

Fone2Phone

written by Martin Häcker on

Image My first complete piece of work for Nova Media. I did this after working there for about a month.

Fone2Phone allows you to have a one stop solution to transferring everything from your cell phone to your macintosh. From there on you can either put it on your iPhone or iPod (Touch), just use it on your System or sync it to a different cell phone.

As far as the technology is concerned Fone2Phone is a subset of our more capable application FoneLink which allows you to do all this and more. Check it out!

Skewed Lines Screen-saver

written by Martin Häcker on

Image Just two days ago I watched the episode "Wie man sich täuschen kann" of Quarks und Co. (Which has a very nice Video Podcast - by the way)

They had this beautiful illusion - but in an animated form, which I have never seen before.

Well, after two hours, I had a screen-saver running and really like the results.

So, here you go too. :)

  • download
  • [source:open-source/skewed-lines-illusion-screensaver browse source]

God wrote in Lisp-Code!

written by Martin Häcker on

Supreme Geek-Unterhaltung aus dem Vortrag [wiki:2008/02/05/22.00 50 of 50].

download - mp3 (von Prometheus Music)