Automatic table layout

GTK+ has a table layout container that lets you render widgets in a grid. The widgets get assigned to the table cells automatically. I haven’t looked at their rendering algorithm, but this does something similar in a Weblocks widget:

(in-package :weblocks)
 
(export '(table-composite render-widget-body))
 
(defwidget table-composite (composite)
  ((cols :type integer :accessor cols :initarg :cols :initform 0))
  (:documentation "Renders a set of widgets in table layout."))
 
(defmethod render-widget-body ((widget table-composite) &rest args)
  (let* ((widgets (composite-widgets widget))
         (num-widgets (list-length widgets))
         (cols (cols widget))
         (rows (ceiling (/ num-widgets cols))))
    (with-html
      (:table :rows rows :cols cols
        (loop for r from 0 below rows
              do (htm (:tr
              (loop for c from 0 below cols
                    do (let ((child (nth (+ c (* r cols)) widgets)))
                         (htm (:td (when child (render-widget child)))))))))))))
 
;;; EXAMPLE CODE:
(make-instance 'table-composite :cols 3
  :widgets (loop for i from 1 to 10
                 collect (write-to-string i)))

Yeah, I know a DOLIST would do the same as the LOOP here, but I really like LOOP.

This should be easily adaptable for generic HTML rendering.

Oldskool tracker music

I really like old tracker tunes, and would like to share my favorite ones with you.

For playback, I recommend a player using the ModPlug engine. There’s ModPlug XMMS for GNU/Linux (which comes with an ModPlug Player for Microsoft Windows.

The first tune is a Protracker module called Tubular Vectors. In the beginning it conveys a serene mood featuring heavy cadences which leads to a second part with a vigorous synth line at 85″.

Have fun!

Laying logging foundations

Gary W. King’s logging library log5 is a lispy way to do logging.

It’s simple to set up and should probably be the first dependency you add to any serious project.

Unfortunately, the User Guide‘s examples are a bit bland.

So here’s some salt (for simplicity let us also ignore log5′s default categories and outputs):

Preliminaries

For comfort.

(defpackage :our-package
  (:use :common-lisp :log5))
 
(in-package :our-package)

Categories

Define new categories every time you add a semantic part to your project:

(defcategory borg-attack)
(defcategory federation-cabal)
(defcategory ion-flux)
(defcategory all-categories (or borg-attack federation-cabal ion-flux))

…or want to differentiate on the seriousness level of logging messages:

(defcategory debug)
(defcategory error)
(defcategory info)
(defcategory all-levels (or debug info error))

Outputs

Outputs get added to every logging message automatically.
They are evaluated at the time the log messages gets sent.

Let’s add one for the time and one for a line break:

(defoutput newline (format nil "~%"))
 
(defoutput time-hms
  (multiple-value-bind (second minute hour day month year)
    (decode-universal-time (get-universal-time))
    (format nil "~D:~2,'0D:~2,'0D" hour minute second)))

And one for the load averages, so we can see whether an error might have occurred due to heavy load (maybe a race condition):

(defoutput load (format nil "[~A]" (load-averages)))

If your project is web-based, you might also want to add the username associated with the current session, like this:

(defoutput username (format nil "[~A]"
  (when (boundp hunchentoot:*session*)
    (session-value 'username))))

Finally, if you’re running SBCL and don’t mind a bit of a hack, you can also identify the function context:

(defmacro current-function-name-log5 ()
  `(caaddr (sb-debug::backtrace-as-list)))

(defoutput function-name (format nil “[~A]” (current-function-name-log5)))

Senders

Senders decide where logging messages from certain categories go, and what they look like.
Here’s one that will log messages from all of the above categories to the standard output, utilizing all of the outputs we defined:

(start-sender 'debug
  (stream-sender :location *standard-output*)
  :category-spec '(all-levels all-categories)
  :output-spec '(time-hms load username function-name message newline))

Usage

You would log a message like this:

(log-for (borg-attack ion-flux)
  "The ion flux of vessel ~A broke down due to a borg attack"
  (get-current-vessel))

That’s already incredibly useful!

HTML tables and exploratory programming

Today (or yesterday, depending on your time zone) Paul Graham has released Arc, his very own successor to Common Lisp and Scheme. I don’t care much about it, at least not in its presents state, but the article that accompanied its release is very interesting in its statements on exploratory programming.

What particularly struck me was his comparison of HTML tables with Lisp’s untyped lists.

First, Paul talks about the evolution of his opinion on untyped lists:

“I went through a stage, after I’d been programming in Lisp for 2 or 3 years, where I thought the old way of using lists to represent everything was just a hack. If you needed to represent points, surely it was better to declare a proper structure with x and y fields than to use a list of two numbers. Lists could contain anything. They might even have varying numbers of elements.

I was wrong. Those are the advantages of using lists to represent points.

Over the years my appreciation for lists has increased. In exploratory programming, the fact that it’s unclear what a list represents is an advantage, because you yourself are unclear about what type of program you’re trying to write. The most important thing is not to constrain the evolution of your ideas. So the less you commit yourself in writing to what your data structures represent, the better.”

I’m sure most Lisp programmers will agree to this.

Now, what about HTML tables?

“Tables are the lists of html. The W3C doesn’t like you to use tables to do more than display tabular data because then it’s unclear what a table cell means. But this sort of ambiguity is not always an error. It might be an accurate reflection of the programmer’s state of mind. In exploratory programming, the programmer is by definition unsure what the program represents.”

And yes, CSS still can’t do more than three columns, and even for three I would have to look it up.

Getting started with CFFI

I really like the Lisp approach of accessing foreign functions; it puts the programmer in charge (as usual) instead of making him wait for some bindings to appear or get updated.

Here’s a little recipe that shows how to get the load averages (the thing uptime shows) in Lisp, which will be useful later when we build a solid logging foundation with Gary’s log5 package.
In case you don’t know, the load average shows an approximation of the number of processes in the system’s task queue, thus serving as indication for machine load.

First, let’s do the initialization work for CFFI, as pointed out in its user guide:

(asdf:oos 'asdf:load-op 'cffi)
 
(defpackage :cffi-user
  (:use :common-lisp :cffi))
 
(in-package :cffi-user)
 
(define-foreign-library libc
  (:unix (:or "libc.so.6" "libc.so.5" "libc.so"))
  (t (:default "libc.so")))
 
(use-foreign-library libc)

Now we actually need to start thinking. How do we get at the numbers?
Let’s find the C function:

% apropos load | egrep -i "average|avg"
getloadavg           (3)  - get system load averages
[...]
% man 3 getloadavg

The man page gives us this prototype:

int getloadavg(double loadavg[], int nelem);

It also tells us that the first parameter will be filled with nelem samples and notes that (at least on my Linux system) the maximum number of samples is three, denoting the load averages of the last 1, 5 and 15 minutes. Let’s say that we want all three.

Now unfortunately the CFFI manual doesn’t say anything about arrays. But we can rewrite the prototype as

int getloadavg(double* loadavg, int nelem);

leading to the following CFFI function spec:

(defcfun "getloadavg" :int (loadavg :pointer) (nelem :int))

Now we are able to use foreign-alloc to allocate a pointer of the correct size (i.e. 3*sizeof(double)), and mem-aref to access the resulting array.

Combined with matching LOOP and FORMAT programs and the manual garbage collection we get:

(defun load-averages ()
  (let ((loadavg (foreign-alloc :double :count 3)))
    (getloadavg loadavg 3) ; note the imperative style we are forced to use
    (prog1 ; we need to clean up after producing the return value
      (format nil "~{~,2F~^ ~}" (loop for i from 0 to 2
                                    collect (mem-aref loadavg :double i)))
      (foreign-free loadavg))))

If you have questions regarding any part of that last snippet, feel free to ask.

Note that we don’t do any error checking here; getloadavg will return -1 on failure, although I can’t imagine why it would do so.

You can access the full code at http://paste.lisp.org/display/54746.

I hope this post wasn’t overly verbose (read: boring) to you.
It was my intention to make this understandable for beginners.

Retro sound effects with sfxr-sdl

About a month ago, sfxr was released.

sfxr is an easy-to-use synthesizer for retro game effects. The author originally wrote it for Microsoft Windows, but an SDL port apparently was a simple thing. With this port, we GNU/Linux users can use it, too. Unfortunately, the port didn’t work on my system; it failed to start when trying to initialize the audio subsystem:

[!] main.cpp:1167  !SDL_OpenAudio(&des, __null)

It turned out that the initialization routine was missing one parameter. I fixed it, and here’s the patch:

--- main.cpp.old        2008-01-24 13:54:01.000000000 +0100
+++ main.cpp    2008-01-24 13:52:37.000000000 +0100
@@ -1164,6 +1164,7 @@ void ddkInit()
        des.channels = 1;
        des.callback = SDLAudioCallback;
        des.userdata = NULL;
+       des.samples = 4096;
        VERIFY(!SDL_OpenAudio(&des, NULL));
        SDL_PauseAudio(0);
 #endif

I’ll try to put up a static binary later.

Locating a font’s files by its name

Over the last months I had a problem when browsing sites using the YUI font library. Those sites would have a hard to read monospaced font instead of a variable-width sans-serif one.

Today I decided to find out what was the culprit of this. I started Firebug and inspected the offending CSS. It turned out that they mention the font name clean in their font-family path, and that removing this from the valid families helped restore order among the glyphs. To make this permanent I had to find the offending font and delete it.

xlsfonts | grep -i clean

told me that the subject was “Schumacher Clean”, but not more. After messing around with Fontmatrix (which doesn’t attempt to find the fonts registered with the X server by itself) and GNOME Specimen (which didn’t knew about or refused to tell me the location of a font’s files), this helped:

fc-cat | grep -i clean
# showed something like clR6x12.pcf.gz
locate clR6x12.pcf.gz
# gave me the location
sudo rm /usr/share/fonts/misc/clR*
# removed all incarnations of the font
sudo fc-cache
# informed the X server

Once again command-line tools proved to be the solution. Great for me, but quite problematic in a world where more than 99% of users don’t use it (because they don’t know what it is or how to use it productively).

Schneemann

Snowmen, or „Schneemänner“, as they are called in Germany, are the subject of a new Inkscape tutorial by Tom. This one is mine.

SVG available on request.

Pacman 3.1.0: better and better

Pacman is the package manager that once having used, you don’t want to go back to others.

Why? Simplicity!

My personal highlights in the new version:

  • Support for xdelta diffs: binary diffs so I can go back to previous package versions if the current one is borked. Previously one had to hope to have the old version in the cache or find some outdated mirror.
  • --ignorearch option for makepkg
  • — no more hacking of PKGBUILD files that don’t have arch information.

  • Topological sorting for dependencies: I suspect this is responsible for the speed-up I noticed.
  • Massive optimization and speed-up for --owns: finding the package a certain file belongs to is a function I often need.
  • single mirrorfile: finally a centralized place for the mirror list.

Classical hack: Apache httpd as CMS

In search of a light-weight content management system, I came across this KISS solution.

It’s obviously not really a CMS that one would install for a customer, but it’s a nice thing
for your typical software projects: a flock of small pages gathering around the most important thing,
namely the downloads.

Well done!

Next Page »