function CmdPlugin(bot) {
	var self = this;
	self.name = "cmd";
	self.help = "Commands plugin";

	self.chanRe = /^=(\S+)(?:(\s+.*))?$/;
	self.argsRe = /\s+(?:"([^"]*)"|'([^']+)'|([^\s'"]+))/g;

	self.events = {
		"message": function(nick, to, text, message) {
			var m = text.match(self.chanRe);
			if (m) {
				var args2 = [m[2] === undefined ? "" : m[2].trim()];
				for (var res; (res = self.argsRe.exec(m[2])) !== null;) {
					var i;
					for (i = 1; res[i] === undefined; i++);
					args2.push(res[i]);
				}

				bot.emit("cmd", nick, to == bot.nick ? nick : to, m[1], args2, message);
			}
			else
				bot.emit("nocmd", nick, to == bot.nick ? nick : to, text, message);
		},

		"cmd": function(nick, to, cmd, args, message) {
			if (bot.listeners("cmd#" + cmd)[0] !== undefined) {
				bot.out.log("cmd", nick + " in " + to + " called =" + cmd + " with args: [" + args.join(", ") + "]");
				bot.emit("cmd#" + cmd, nick, to, args, message);
			}
			else
				bot.emit("cmd#", nick, to, cmd, args, message);
		},

		"cmd#": function(nick, to, cmd, args, message) {
			//bot.notice(nick, "no such command: " + cmd);
		}
	};
}

module.exports = CmdPlugin;

@@ -88,16 +88,46 @@
 plugin%22;
+%0A%09self.depends = %5B%22editdist%22%5D;
 %0A%0A%09self.
@@ -217,16 +217,219 @@
 +))/g;%0A%0A
+%09self.getCmds = function() %7B%0A%09%09return Object.keys(bot._events).reduce(function(arr, ev) %7B%0A%09%09%09var m = ev.match(/%5Ecmd#(.+)$/);%0A%09%09%09if (m)%0A%09%09%09%09return arr.concat(m%5B1%5D);%0A%09%09%09else%0A%09%09%09%09return arr;%0A%09%09%7D, %5B%5D);%0A%09%7D;%0A%0A
 %09self.ev
@@ -1190,60 +1190,691 @@
 else
+ %7B
 %0A%09%09%09%09
-bot.emit(%22cmd#%22, nick, to, cmd, args, message);
+var cands = self.getCmds().map(function(cmd2) %7B%0A%09%09%09%09%09return %7B%22cmd%22: cmd2, %22dist%22: bot.plugins.editdist.OSA(cmd, cmd2)%7D;%0A%09%09%09%09%7D).sort(function(lhs, rhs) %7B%0A%09%09%09%09%09return lhs.dist - rhs.dist;%0A%09%09%09%09%7D);%0A%09%09%09%09var cand = cands%5B0%5D;%0A%0A%09%09%09%09if (cand.dist %3C= 2) %7B%0A%09%09%09%09%09bot.out.log(%22cmd%22, nick + %22 in %22 + to + %22 called =%22 + cmd + %22 -%3E =%22 + cand.cmd + %22 with args: %5B%22 + args.join(%22, %22) + %22%5D%22);%0A%09%09%09%09%09bot.emit(%22cmd#%22 + cand.cmd, nick, to, args, message);%0A%09%09%09%09%09bot.notice(nick, %22=%22 + cmd + %22: autocorrected to =%22 + cand.cmd);%0A%09%09%09%09%7D%0A%09%09%09%09else %7B%0A%09%09%09%09%09bot.emit(%22cmd#%22, nick, to, cmd, args, message);%0A%0A%09%09%09%09%09if (cand.dist %3C= 4)%0A%09%09%09%09%09%09bot.notice(nick, %22=%22 + cmd + %22: did you mean =%22 + cand.cmd);%0A%09%09%09%09%7D%0A%09%09%09%7D
 %0A%09%09%7D

approximate command name matching