OK I admit that the title of this post is slightly hyperbolic, but I’ve just installed and started using PmWiki to replace my well-worn, dog-eared copy of ASPWiki that I have loved so well since about 2003, I think. And, I’ve gotta say that I love it! Out of the box it’s simple and easy to use, easy to setup, doesn’t require a database (PmWiki uses flat files for storage, which I think makes sense for big slabs of text content), but it’s flexible and extensible and there’s a great ecosystem around it with a metric assload of cutely named “Cookbook Recipes” instead of the over-used “extensions”, “add-ons” or “plug-ins”.
I chose PmWiki because I was looking for a PHP-based (for web-hosting reasons) wiki that’s small and simple, and then found out that it’s also really extensible and easy to customise to your liking, which of course I’ve done as part of my usual procrastination routine — see my snazzy theme in the attached screenshot. I also very much like and agree with its philosophy:
- Favor writers over readers
- Don’t try to replace HTML
- Avoid gratuitous features (or “creeping featurism”)
- Support collaborative maintenance of public web pages
- Be easy to install, configure, and maintain
And just have a look at what PmWiki can do! With the help of the many cookbook recipes you can do all this and more:
- Content Management System Add-Ons (CMS, blogs, forums)
- Web Forms and MySQL queries and reports
- File Uploads
- Multi Media content
- Page Lists / Searching
- Personal Information Management (PIM)
- RSS Feeds
Plus there are a bunch of skins you can use to make your wiki more amenable to your tastes. I also liked the security features, because I use mine like a personal notepad so I don’t want other people being able to scribble all over it, or even to be able to read it, really. So my security needs are pretty simple, but you can go paranoid/berserk if you need to.
Oh, and you can try out PmWiki on your own machine without a full-on web server if you want to by downloading the Standalone recipe which you just need to unzip a directory into your PmWiki directory tree, double-click a .BAT file and type http://localhost/! Easy peasy. You can run on other operating systems with just a PHP script, also provided on the Standalone recipe page. Running locally makes it super easy and quick to customise your PmWiki because you don’t have to upload your changes to a server, or wait for page refreshes to download. Also, you don’t have to worry about messing up your main “production” installation if you have one, you can mess around locally as much as you want to.
Which brings me to my next point, which was that I wanted to do two things:
- Import my data from ye olde ASPWiki
- Experiment with a custom skin that would look decent if you used PmWiki as a way to manage a “normal” website, i.e. use it as a content management system.
I’m mainly a C# developer, so I logically decided that I’d write a tool to import my old data in Python. I’ve written the odd Python script before and this didn’t seem like such a big job — some file I/O and some search/replace stuff. It didn’t turn out to be too difficult but it did take a bit longer than I expected as I learned more about the language; or more specifically, how the expat XML parser works. I’m pretty happy with how it works, I ended up getting my 300+ pages imported just fine.
import xml.parsers.expat
import re
class elhandler:
def __init__(self, filename, wikiGroup):
self.buf = ''
self.wikiGroup = wikiGroup
self._parser = p = xml.parsers.expat.ParserCreate()
p.StartElementHandler = self.start_element
p.EndElementHandler = self.end_element
p.CharacterDataHandler = self.char_data
p.ParseFile(open(filename))
def start_element(self, name, attrs):
self.name = name
def end_element(self, name):
if self.name == 'Title':
self.title = re.search('\w+',self.buf).group(0)
elif self.name == 'PageData':
self.buf = self.wikifix(self.buf)
of = open('import/' + self.wikiGroup + '.' + self.title, 'w')
of.write(self.buf)
of.close
self.buf = ''
def char_data(self, data):
self.buf += data
def wikifix(self, contents):
contents = contents.replace(' * ', '* ')
contents = contents.replace('\t* ', '* ')
contents = contents.replace(' 1.', '# ')
contents = contents.replace('\t1.', '# ')
contents = re.sub(r'(^|\n)+====','\g<1>!!!!', contents)
contents = re.sub(r'(^|\n)+===','\g<1>!!!', contents)
contents = re.sub(r'(^|\n)+==','\g<1>!!', contents)
contents = re.sub(r'(^|\n)+=','\g<1>!', contents)
contents = re.sub(r'\b([A-Z][a-z]+[A-Z]+\w+)','[[\g<1>]]', contents)
contents = re.sub(r'(\n\ .*)+', '\n[@\g<0>\n@]', contents)
return contents
eh = elhandler('aspWiki-export.xml', 'Main')
My second mission, to create a skin that would work if using PmWiki for a normal content-based website, is at least a partial success because I’m happy enough with my skin to use it on my wiki — at least for now. My skin is named PmGk, not too imaginatively.
So if you’re looking for a Wiki that can do everything, or even just something, check out PmWiki, it could save your life!