Raphi Rambles

MarkyPond out on Github

Kept hacking on my lilypond markdown extension which is now out on Github.

I called it MarkyPond, as it sounds kinda cool, doesn't seem to be already taken, and evokes both markdown and Marky Ramones.

Marky Ramones sitting at his drumkit

It wasn't hard, but boy was it tedious.

Lots of string juggling, which python is pretty good at, but complicated by the Lilypond command line tool1. Painful refactoring due to a brittle test suite (because of a mix of me trying to be too clever and mocking being such a PITB).

I'm not too happy with the code quality, but hey, it's done, and it does what I want it to.

It now supports outputting png:

svg (as before):

And pdf:

I may need to re-think the html integration on that one.

Hmm. I can already see I'll probably need to copy some information in each block, which will become a pain quickly. Glancing at the lilypond docs, I saw things that looked like you can include other files, so I'll probably have to add some option to handle this.

But not now. I need to use the damn thing before I start adding stuff that tries to be helpful but creates more of a mess.

Along the same idea, I won't bother supporting more output formats for now. I don't even remember which ones lilypond handles. Some of them might be easy enough to add, but again, if I start messing with it before knowing more about the way it all actually works I'll just end up with chaos.

Fun with caching

I mentionned in the previous article that the processing was too slow. I solved that by generating a MD5 hash of the lilypond source2, which I then use as the generated file name. Then, it's a simple matter of checking if that file already exists before generating a new one.

With this, the time pelican takes to regenerate the whole site went from almost 2 seconds (for only two, one bar long each exemples!) back to about 0.3 second.

I end up with ugly file names like 502a317d29de43443f02f6372e4dd430.png, but I don't care, as I'm only using the file for a link. I can see how it could not fit some other use case, but again, I'd rather keep this suited to my immediate needs for now and I'll need to know more before I try to solve problems I don't have yet, so I was quite ready to just call it a day.

But then I realized that this would lead to a proliferation of unused files as I keep editing the lilypond source of an article. With each change, the hash changes as well, and a new file is created, with no simple way to know the previous name (so I can't just automagically delete it).

So after a dozen edits, you end up with eleven useless files and have to check the final name to know which ones you have to delete. And also be careful not to delete any file that was used for another article. Great.

This won't do. I need to find a way to name those files in a sane way.

What's my name ?

The trouble with naming the files is that I can't automate it. I could think of some scheme to generate a default name for each one, but once I'm called by the markdown parser, I get exactly zero information about the current file being processed3. I couldn't even find information about the html document. The only thing I get access to is the node that will contain the block I'm generating (which doesn't seem to provide access to its parents).

Maybe I'm missing something, but for now, I'm kinda screwed.

So no way around it, I have to add a way to pass arguments to the markdown block itself.

Again, this is not really hard to do, but it's pretty tedious and requires more testing. And hey, now that I had to do it anyway, might as well go ahead and add a few more arguments to override the extensions's basic configuration.

So that's what I did. And now the syntax looks like this:

{markypond output_file='/subfolder/lol.pdf' output_fmt='pdf'}
mynotes = {
  g,2 g\4 | des1
}

<<
  \new Staff {
    \clef "G_8"
    \omit StringNumber
    \mynotes
  }
  \new TabStaff {
    \mynotes
  }
>>
{/markydown}

So. That's done, I guess.

This was an enjoyable hacking mini project, but tidying things up, writing tests and documenting the whole thing4 took a while and sucked most of the fun out of it, and I'm getting a bit sick of coding right now.

Which is good, as it means the next article won't be yet another piece of tech wank. I'll try and use the damn thing a few times and we'll see if I come back to it when I know what I'm doing.

See ya!

Post Scriptum:

So I wanted to add a subtle tip of the hat to Ozzy Osbourne by adding titles to the generated images. Which doens't work. Great. One more thing to debug.

So here's a funny picture instead, subtility be damned.

The late Ozzy Osbourne, smoking and drinking while sitting on a toilet. With his pants down, od course.

RIP Ozzy.


  1. The tool "helpfully" adds the extensions to the files it spits out. So I had to remove it from the argument I get before calling it and add it back afterwards. Nothing crazy, but annoying all the same. 

  2. I saw it done in an article I read when researching the initial idea, so it felt obvious once it became needed. Not sure if I would had thought of it otherwise. 

  3. Pelican does pass the article metadata to the parser, so I could use that. But then this extension would only work with Pelican. 

  4. The doc is pretty terrible right now, but hey, at least the info's out there. 

^