Goal

My goal for today is to implement the shortcut directive from ikiwiki in riki. The plugin allows the page shortcuts in the site define shortcuts that can be used on page. A shortcut is defined like this:

[[!shortuct  wikpedia https://en.wikipedia.org/wiki/%W]]
[[!wikipedia   War_of_1812]]

The shortcut directive defines a new directive, which can be invoked as if it were a normal directive. The first nameless parameter is the name of the new directive, and the second is the URL pattern.

In the URL pattern, %s is replaced by the nameless argument to the invocation of the directive added as the shortcut, with URL encoding. %S (upper case) is the same, but without encoding. %W is encoded in a way suitable for Wikipedia. The desc parameter in the definition or invocation sets a description for the link, i.e., link text.

Plan

I don't quite like the way ikiwiki implements shortcuts, so my plan is to be compatible, but different.

  • The shortcut directive can be used anywhere on the site, not just in the page called shortcuts.
  • It's an error to define a shortcut with the name of a directive, or another shortcut.
  • I don't want a dynamic set of directives. I think ikiwiki does things that because it was easy to do in Perl. I'll implement something different.
  • riki does not currently support nameless parameters. I will add those, but I'll tackle the shortcut directive first. While I do that, I'll require named parameters. Once I add support for nameless parameters, I'll change the riki directive to define shortcuts.

Notes

Add phases for directives

  • Some directives depend on other directives having been executed first. The shortcut directive needs to be executed before any shortcut is processed. The inline directive requires other pages to have been processed into HTML first.
  • I can deal with this by adding explicit dependencies on directives, and pages using them, but that seems like a lot of work and prone to bugs.
  • Instead, I'll add the concept of "phases" to execution of directives. Each directive execution will be given the "phase number" currently executing. After phases 0 (the first phase), any invocation of a directive must be either a known builtin directive, or a known shortcut for the site.
  • Each directive will return a value indicating it has been executed in a phase, and does not need to be executed again.
  • The site build process will iterate over invocations of directives, executing them until all directives have been executed.
  • Actually, that seems unnecessarily tricky. New plan: each directive can define three methods, execute_0, execute_1, and execute_2. The site build process will loop over directive invocations three times, calling a successive execution method in each loop. Further, all invocations on all pages are executed in each phase.
  • Adding that was easy and quick.
  • Next I'll implement a datatype for holding known shortcuts. I'll add a field to the type that represents the site to use this. The shortcut directive will be able to add to that.
  • I don't know what the Wikipedia encoding is, so I'll skimp on that. In fact, I'll only implement %s as that's the only thing I use. I'll get back to this later.
  • All directives will need to get a mutable reference to the site.

Ran out of time implementing this today, will continue tomorrow.

Next morning

  • I've coded myself into a corner. I want directives to be able to modify the site, but also the pages, and this results in more than one mutable reference to the site.
  • I'll put the shortcut set in an arc box, or something.
  • But not this early in the morning.
  • I'm juggling too many changes at the same time. That might be a signal that I should start over and do one thing at a time.

Summary

Things did not end well. Mistakes were made. I will try again another day.