/plugins/Vimish.cs
using System;
using System.Text.RegularExpressions;
using Gtk;
using WebKit;
using bytex64.WebThing;

public class Vimish : WebThingPlugin {
    WebThing wt;
    Gtk.Entry commandline;

    public override void Init(WebThing wt) {
        this.wt = wt;
        wt.Tabs.ShowTabs = false;

        wt.Window.KeyPressEvent += Window_KeyPress;

        commandline = new Gtk.Entry();
        commandline.Activated += command_Activate;
        commandline.KeyPressEvent += command_KeyPress;
        wt.AttachWidget(commandline, AttachPoint.S, AttachOptions.Fill, AttachOptions.Shrink);

        commandline.Hide();

        ApplyOptions();
    }

    public override void InitWebView(WebView wv) {
        wv.KeyPressEvent += WebView_KeyPress;
    }

    private void Window_KeyPress(object o, KeyPressEventArgs e) {
        if ((Gdk.ModifierType.ControlMask & e.Event.State) != 0) {
            switch(e.Event.Key) {
            case Gdk.Key.n:
                wt.Tabs.NextPage();
                break;
            case Gdk.Key.p:
                wt.Tabs.PrevPage();
                break;
            }
        } else {
            switch(e.Event.Key) {
            case Gdk.Key.o:
                CommandStart("open ");
                break;
            case Gdk.Key.O:
                CommandStart("open " + wt.WebView.MainFrame.Uri);
                break;
            case Gdk.Key.t:
                CommandStart("tabopen ");
                break;
            case Gdk.Key.T:
                CommandStart("tabopen " + wt.WebView.MainFrame.Uri);
                break;
            case Gdk.Key.colon:
                CommandlineShow();
                break;
            }
        }
    }

    private void WebView_KeyPress(object o, KeyPressEventArgs e) {
        WebView wv = (WebView)o;

        Console.WriteLine(e.Event.Key);
        if (e.Event.State == Gdk.ModifierType.None) {
            switch(e.Event.Key) {
            case Gdk.Key.j:
                wt.Bump(0, 1);
                break;
            case Gdk.Key.k:
                wt.Bump(0, -1);
                break;
            case Gdk.Key.l:
                wt.Bump(1, 0);
                break;
            case Gdk.Key.h:
                wt.Bump(-1, 0);
                break;
            case Gdk.Key.r:
                wv.Reload();
                break;
            case Gdk.Key.Escape:
                wv.ExecuteScript("document.activeElement.blur()");
                break;
            }
        }
    }

    public void CommandStart(string text) {
        commandline.Text = text;
        commandline.GrabFocus();
        commandline.Position = text.Length;
        commandline.Show();
    }

    public void CommandlineShow() {
        commandline.Show();
        commandline.GrabFocus();
    }

    public void CommandlineHide() {
        commandline.Hide();
        wt.WebView.GrabFocus();
    }

    private void command_Activate(object o, EventArgs e) {
        string[] args = Regex.Split(commandline.Text, @"\s+");
        if (args.Length == 0) return;
        string cmd = args[0];
        string[] tmp = new string[args.Length - 1];
        Array.Copy(args, 1, tmp, 0, tmp.Length);
        args = tmp;
        string query = Regex.Replace(commandline.Text, String.Format(@"^{0}\s+", cmd), "");

        switch(cmd) {
        case "close":
            wt.CloseTab();
            break;
        case "open":
            if (args.Length < 1) return;
            if (!wt.Open(query))
                Error("Could not open query");
            break;
        case "tabopen":
            if (args.Length < 1) return;
            if (wt.OpenTab(query))
                wt.Tabs.CurrentPage = wt.Tabs.NPages - 1;
            else
                Error("Could not open query");
            break;
        case "n":
            wt.Tabs.NextPage();
            break;
        case "p":
            wt.Tabs.PrevPage();
            break;
        case "q":
            wt.Quit();
            break;
        case "set":
            if (args.Length == 1)
                Options[args[0]] = null;
            else
                Options[args[0]] = args[1];
            ApplyOptions();
            break;
        case "save":
            SaveConfig();
            break;
        default:
            bool found;
            if (args.Length > 0) {
                found = wt.Plugins.Call(cmd, args);
                if (!found)
                    Error("No function {0}({1}) found", cmd, String.Join(", ", args));
            } else {
                found = wt.Plugins.Call(cmd);
                if (!found)
                    Error("No function {0}() found", cmd);
            }
            if (found)
                Console.WriteLine("Plugin function {0} called successfully", cmd);
            break;
        }
        CommandlineHide();
    }

    private void ApplyOptions() {
        foreach (string key in Options.Keys) {
            switch(key) {
            case "ShowTabs":
                bool v = Config.ParseBool(Options[key]);
                wt.Tabs.ShowTabs = v;
                break;
            default:
                Error("No variable {0}", key);
                break;
            }
        }
    }

    private void Error(string format, params object[] values) {
        Console.WriteLine(format, values);
    }

    private void command_KeyPress(object o, KeyPressEventArgs e) {
        if (e.Event.Key == Gdk.Key.Escape)
            CommandlineHide();
    }
}