]> git.lizzy.rs Git - micro.git/blobdiff - cmd/micro/bindings.go
make undothresthold a setting (part 2)
[micro.git] / cmd / micro / bindings.go
index e97d4ed970679aee964dd8e1060a1f8313acfd1c..0869141845b955b132df04d267f1092b2801c9d7 100644 (file)
@@ -2,25 +2,29 @@ package main
 
 import (
        "encoding/json"
-       "errors"
        "io/ioutil"
        "os"
-       "os/exec"
        "strconv"
        "strings"
        "time"
 
        "github.com/mitchellh/go-homedir"
-       "github.com/yuin/gopher-lua"
        "github.com/zyedidia/clipboard"
        "github.com/zyedidia/tcell"
 )
 
-var bindings map[tcell.Key]func(*View) bool
+var bindings map[Key]func(*View) bool
+
+// The Key struct holds the data for a keypress (keycode + modifiers)
+type Key struct {
+       keyCode   tcell.Key
+       modifiers tcell.ModMask
+       r         rune
+}
 
 // InitBindings initializes the keybindings for micro
 func InitBindings() {
-       bindings = make(map[tcell.Key]func(*View) bool)
+       bindings = make(map[Key]func(*View) bool)
 
        actions := map[string]func(*View) bool{
                "CursorUp":            (*View).CursorUp,
@@ -55,6 +59,7 @@ func InitBindings() {
                "Copy":                (*View).Copy,
                "Cut":                 (*View).Cut,
                "CutLine":             (*View).CutLine,
+               "DuplicateLine":       (*View).DuplicateLine,
                "Paste":               (*View).Paste,
                "SelectAll":           (*View).SelectAll,
                "OpenFile":            (*View).OpenFile,
@@ -68,154 +73,154 @@ func InitBindings() {
                "EndOfLine":           (*View).EndOfLine,
                "ToggleRuler":         (*View).ToggleRuler,
                "JumpLine":            (*View).JumpLine,
-       }
-
-       keys := map[string]tcell.Key{
-               "Up":             tcell.KeyUp,
-               "Down":           tcell.KeyDown,
-               "Right":          tcell.KeyRight,
-               "Left":           tcell.KeyLeft,
-               "AltUp":          tcell.KeyAltUp,
-               "AltDown":        tcell.KeyAltDown,
-               "AltLeft":        tcell.KeyAltLeft,
-               "AltRight":       tcell.KeyAltRight,
-               "CtrlUp":         tcell.KeyCtrlUp,
-               "CtrlDown":       tcell.KeyCtrlDown,
-               "CtrlLeft":       tcell.KeyCtrlLeft,
-               "CtrlRight":      tcell.KeyCtrlRight,
-               "ShiftUp":        tcell.KeyShiftUp,
-               "ShiftDown":      tcell.KeyShiftDown,
-               "ShiftLeft":      tcell.KeyShiftLeft,
-               "ShiftRight":     tcell.KeyShiftRight,
-               "AltShiftUp":     tcell.KeyAltShiftUp,
-               "AltShiftDown":   tcell.KeyAltShiftDown,
-               "AltShiftLeft":   tcell.KeyAltShiftLeft,
-               "AltShiftRight":  tcell.KeyAltShiftRight,
-               "CtrlShiftUp":    tcell.KeyCtrlShiftUp,
-               "CtrlShiftDown":  tcell.KeyCtrlShiftDown,
-               "CtrlShiftLeft":  tcell.KeyCtrlShiftLeft,
-               "CtrlShiftRight": tcell.KeyCtrlShiftRight,
-               "UpLeft":         tcell.KeyUpLeft,
-               "UpRight":        tcell.KeyUpRight,
-               "DownLeft":       tcell.KeyDownLeft,
-               "DownRight":      tcell.KeyDownRight,
-               "Center":         tcell.KeyCenter,
-               "PgUp":           tcell.KeyPgUp,
-               "PgDn":           tcell.KeyPgDn,
-               "Home":           tcell.KeyHome,
-               "End":            tcell.KeyEnd,
-               "Insert":         tcell.KeyInsert,
-               "Delete":         tcell.KeyDelete,
-               "Help":           tcell.KeyHelp,
-               "Exit":           tcell.KeyExit,
-               "Clear":          tcell.KeyClear,
-               "Cancel":         tcell.KeyCancel,
-               "Print":          tcell.KeyPrint,
-               "Pause":          tcell.KeyPause,
-               "Backtab":        tcell.KeyBacktab,
-               "F1":             tcell.KeyF1,
-               "F2":             tcell.KeyF2,
-               "F3":             tcell.KeyF3,
-               "F4":             tcell.KeyF4,
-               "F5":             tcell.KeyF5,
-               "F6":             tcell.KeyF6,
-               "F7":             tcell.KeyF7,
-               "F8":             tcell.KeyF8,
-               "F9":             tcell.KeyF9,
-               "F10":            tcell.KeyF10,
-               "F11":            tcell.KeyF11,
-               "F12":            tcell.KeyF12,
-               "F13":            tcell.KeyF13,
-               "F14":            tcell.KeyF14,
-               "F15":            tcell.KeyF15,
-               "F16":            tcell.KeyF16,
-               "F17":            tcell.KeyF17,
-               "F18":            tcell.KeyF18,
-               "F19":            tcell.KeyF19,
-               "F20":            tcell.KeyF20,
-               "F21":            tcell.KeyF21,
-               "F22":            tcell.KeyF22,
-               "F23":            tcell.KeyF23,
-               "F24":            tcell.KeyF24,
-               "F25":            tcell.KeyF25,
-               "F26":            tcell.KeyF26,
-               "F27":            tcell.KeyF27,
-               "F28":            tcell.KeyF28,
-               "F29":            tcell.KeyF29,
-               "F30":            tcell.KeyF30,
-               "F31":            tcell.KeyF31,
-               "F32":            tcell.KeyF32,
-               "F33":            tcell.KeyF33,
-               "F34":            tcell.KeyF34,
-               "F35":            tcell.KeyF35,
-               "F36":            tcell.KeyF36,
-               "F37":            tcell.KeyF37,
-               "F38":            tcell.KeyF38,
-               "F39":            tcell.KeyF39,
-               "F40":            tcell.KeyF40,
-               "F41":            tcell.KeyF41,
-               "F42":            tcell.KeyF42,
-               "F43":            tcell.KeyF43,
-               "F44":            tcell.KeyF44,
-               "F45":            tcell.KeyF45,
-               "F46":            tcell.KeyF46,
-               "F47":            tcell.KeyF47,
-               "F48":            tcell.KeyF48,
-               "F49":            tcell.KeyF49,
-               "F50":            tcell.KeyF50,
-               "F51":            tcell.KeyF51,
-               "F52":            tcell.KeyF52,
-               "F53":            tcell.KeyF53,
-               "F54":            tcell.KeyF54,
-               "F55":            tcell.KeyF55,
-               "F56":            tcell.KeyF56,
-               "F57":            tcell.KeyF57,
-               "F58":            tcell.KeyF58,
-               "F59":            tcell.KeyF59,
-               "F60":            tcell.KeyF60,
-               "F61":            tcell.KeyF61,
-               "F62":            tcell.KeyF62,
-               "F63":            tcell.KeyF63,
-               "F64":            tcell.KeyF64,
-               "CtrlSpace":      tcell.KeyCtrlSpace,
-               "CtrlA":          tcell.KeyCtrlA,
-               "CtrlB":          tcell.KeyCtrlB,
-               "CtrlC":          tcell.KeyCtrlC,
-               "CtrlD":          tcell.KeyCtrlD,
-               "CtrlE":          tcell.KeyCtrlE,
-               "CtrlF":          tcell.KeyCtrlF,
-               "CtrlG":          tcell.KeyCtrlG,
-               "CtrlH":          tcell.KeyCtrlH,
-               "CtrlI":          tcell.KeyCtrlI,
-               "CtrlJ":          tcell.KeyCtrlJ,
-               "CtrlK":          tcell.KeyCtrlK,
-               "CtrlL":          tcell.KeyCtrlL,
-               "CtrlM":          tcell.KeyCtrlM,
-               "CtrlN":          tcell.KeyCtrlN,
-               "CtrlO":          tcell.KeyCtrlO,
-               "CtrlP":          tcell.KeyCtrlP,
-               "CtrlQ":          tcell.KeyCtrlQ,
-               "CtrlR":          tcell.KeyCtrlR,
-               "CtrlS":          tcell.KeyCtrlS,
-               "CtrlT":          tcell.KeyCtrlT,
-               "CtrlU":          tcell.KeyCtrlU,
-               "CtrlV":          tcell.KeyCtrlV,
-               "CtrlW":          tcell.KeyCtrlW,
-               "CtrlX":          tcell.KeyCtrlX,
-               "CtrlY":          tcell.KeyCtrlY,
-               "CtrlZ":          tcell.KeyCtrlZ,
-               "CtrlLeftSq":     tcell.KeyCtrlLeftSq,
-               "CtrlBackslash":  tcell.KeyCtrlBackslash,
-               "CtrlRightSq":    tcell.KeyCtrlRightSq,
-               "CtrlCarat":      tcell.KeyCtrlCarat,
-               "CtrlUnderscore": tcell.KeyCtrlUnderscore,
-               "Backspace":      tcell.KeyBackspace,
-               "Tab":            tcell.KeyTab,
-               "Esc":            tcell.KeyEsc,
-               "Escape":         tcell.KeyEscape,
-               "Enter":          tcell.KeyEnter,
-               "Space":          tcell.KeySpace,
-               "Backspace2":     tcell.KeyBackspace2,
+               "ClearStatus":         (*View).ClearStatus,
+       }
+
+       keys := map[string]Key{
+               "Up":             Key{tcell.KeyUp, tcell.ModNone, 0},
+               "Down":           Key{tcell.KeyDown, tcell.ModNone, 0},
+               "Right":          Key{tcell.KeyRight, tcell.ModNone, 0},
+               "Left":           Key{tcell.KeyLeft, tcell.ModNone, 0},
+               "AltUp":          Key{tcell.KeyUp, tcell.ModAlt, 0},
+               "AltDown":        Key{tcell.KeyDown, tcell.ModAlt, 0},
+               "AltLeft":        Key{tcell.KeyLeft, tcell.ModAlt, 0},
+               "AltRight":       Key{tcell.KeyRight, tcell.ModAlt, 0},
+               "CtrlUp":         Key{tcell.KeyUp, tcell.ModCtrl, 0},
+               "CtrlDown":       Key{tcell.KeyDown, tcell.ModCtrl, 0},
+               "CtrlLeft":       Key{tcell.KeyLeft, tcell.ModCtrl, 0},
+               "CtrlRight":      Key{tcell.KeyRight, tcell.ModCtrl, 0},
+               "ShiftUp":        Key{tcell.KeyUp, tcell.ModShift, 0},
+               "ShiftDown":      Key{tcell.KeyDown, tcell.ModShift, 0},
+               "ShiftLeft":      Key{tcell.KeyLeft, tcell.ModShift, 0},
+               "ShiftRight":     Key{tcell.KeyRight, tcell.ModShift, 0},
+               "AltShiftUp":     Key{tcell.KeyUp, tcell.ModShift | tcell.ModAlt, 0},
+               "AltShiftDown":   Key{tcell.KeyDown, tcell.ModShift | tcell.ModAlt, 0},
+               "AltShiftLeft":   Key{tcell.KeyLeft, tcell.ModShift | tcell.ModAlt, 0},
+               "AltShiftRight":  Key{tcell.KeyRight, tcell.ModShift | tcell.ModAlt, 0},
+               "CtrlShiftUp":    Key{tcell.KeyUp, tcell.ModShift | tcell.ModCtrl, 0},
+               "CtrlShiftDown":  Key{tcell.KeyDown, tcell.ModShift | tcell.ModCtrl, 0},
+               "CtrlShiftLeft":  Key{tcell.KeyLeft, tcell.ModShift | tcell.ModCtrl, 0},
+               "CtrlShiftRight": Key{tcell.KeyRight, tcell.ModShift | tcell.ModCtrl, 0},
+               "UpLeft":         Key{tcell.KeyUpLeft, tcell.ModNone, 0},
+               "UpRight":        Key{tcell.KeyUpRight, tcell.ModNone, 0},
+               "DownLeft":       Key{tcell.KeyDownLeft, tcell.ModNone, 0},
+               "DownRight":      Key{tcell.KeyDownRight, tcell.ModNone, 0},
+               "Center":         Key{tcell.KeyCenter, tcell.ModNone, 0},
+               "PgUp":           Key{tcell.KeyPgUp, tcell.ModNone, 0},
+               "PgDn":           Key{tcell.KeyPgDn, tcell.ModNone, 0},
+               "Home":           Key{tcell.KeyHome, tcell.ModNone, 0},
+               "End":            Key{tcell.KeyEnd, tcell.ModNone, 0},
+               "Insert":         Key{tcell.KeyInsert, tcell.ModNone, 0},
+               "Delete":         Key{tcell.KeyDelete, tcell.ModNone, 0},
+               "Help":           Key{tcell.KeyHelp, tcell.ModNone, 0},
+               "Exit":           Key{tcell.KeyExit, tcell.ModNone, 0},
+               "Clear":          Key{tcell.KeyClear, tcell.ModNone, 0},
+               "Cancel":         Key{tcell.KeyCancel, tcell.ModNone, 0},
+               "Print":          Key{tcell.KeyPrint, tcell.ModNone, 0},
+               "Pause":          Key{tcell.KeyPause, tcell.ModNone, 0},
+               "Backtab":        Key{tcell.KeyBacktab, tcell.ModNone, 0},
+               "F1":             Key{tcell.KeyF1, tcell.ModNone, 0},
+               "F2":             Key{tcell.KeyF2, tcell.ModNone, 0},
+               "F3":             Key{tcell.KeyF3, tcell.ModNone, 0},
+               "F4":             Key{tcell.KeyF4, tcell.ModNone, 0},
+               "F5":             Key{tcell.KeyF5, tcell.ModNone, 0},
+               "F6":             Key{tcell.KeyF6, tcell.ModNone, 0},
+               "F7":             Key{tcell.KeyF7, tcell.ModNone, 0},
+               "F8":             Key{tcell.KeyF8, tcell.ModNone, 0},
+               "F9":             Key{tcell.KeyF9, tcell.ModNone, 0},
+               "F10":            Key{tcell.KeyF10, tcell.ModNone, 0},
+               "F11":            Key{tcell.KeyF11, tcell.ModNone, 0},
+               "F12":            Key{tcell.KeyF12, tcell.ModNone, 0},
+               "F13":            Key{tcell.KeyF13, tcell.ModNone, 0},
+               "F14":            Key{tcell.KeyF14, tcell.ModNone, 0},
+               "F15":            Key{tcell.KeyF15, tcell.ModNone, 0},
+               "F16":            Key{tcell.KeyF16, tcell.ModNone, 0},
+               "F17":            Key{tcell.KeyF17, tcell.ModNone, 0},
+               "F18":            Key{tcell.KeyF18, tcell.ModNone, 0},
+               "F19":            Key{tcell.KeyF19, tcell.ModNone, 0},
+               "F20":            Key{tcell.KeyF20, tcell.ModNone, 0},
+               "F21":            Key{tcell.KeyF21, tcell.ModNone, 0},
+               "F22":            Key{tcell.KeyF22, tcell.ModNone, 0},
+               "F23":            Key{tcell.KeyF23, tcell.ModNone, 0},
+               "F24":            Key{tcell.KeyF24, tcell.ModNone, 0},
+               "F25":            Key{tcell.KeyF25, tcell.ModNone, 0},
+               "F26":            Key{tcell.KeyF26, tcell.ModNone, 0},
+               "F27":            Key{tcell.KeyF27, tcell.ModNone, 0},
+               "F28":            Key{tcell.KeyF28, tcell.ModNone, 0},
+               "F29":            Key{tcell.KeyF29, tcell.ModNone, 0},
+               "F30":            Key{tcell.KeyF30, tcell.ModNone, 0},
+               "F31":            Key{tcell.KeyF31, tcell.ModNone, 0},
+               "F32":            Key{tcell.KeyF32, tcell.ModNone, 0},
+               "F33":            Key{tcell.KeyF33, tcell.ModNone, 0},
+               "F34":            Key{tcell.KeyF34, tcell.ModNone, 0},
+               "F35":            Key{tcell.KeyF35, tcell.ModNone, 0},
+               "F36":            Key{tcell.KeyF36, tcell.ModNone, 0},
+               "F37":            Key{tcell.KeyF37, tcell.ModNone, 0},
+               "F38":            Key{tcell.KeyF38, tcell.ModNone, 0},
+               "F39":            Key{tcell.KeyF39, tcell.ModNone, 0},
+               "F40":            Key{tcell.KeyF40, tcell.ModNone, 0},
+               "F41":            Key{tcell.KeyF41, tcell.ModNone, 0},
+               "F42":            Key{tcell.KeyF42, tcell.ModNone, 0},
+               "F43":            Key{tcell.KeyF43, tcell.ModNone, 0},
+               "F44":            Key{tcell.KeyF44, tcell.ModNone, 0},
+               "F45":            Key{tcell.KeyF45, tcell.ModNone, 0},
+               "F46":            Key{tcell.KeyF46, tcell.ModNone, 0},
+               "F47":            Key{tcell.KeyF47, tcell.ModNone, 0},
+               "F48":            Key{tcell.KeyF48, tcell.ModNone, 0},
+               "F49":            Key{tcell.KeyF49, tcell.ModNone, 0},
+               "F50":            Key{tcell.KeyF50, tcell.ModNone, 0},
+               "F51":            Key{tcell.KeyF51, tcell.ModNone, 0},
+               "F52":            Key{tcell.KeyF52, tcell.ModNone, 0},
+               "F53":            Key{tcell.KeyF53, tcell.ModNone, 0},
+               "F54":            Key{tcell.KeyF54, tcell.ModNone, 0},
+               "F55":            Key{tcell.KeyF55, tcell.ModNone, 0},
+               "F56":            Key{tcell.KeyF56, tcell.ModNone, 0},
+               "F57":            Key{tcell.KeyF57, tcell.ModNone, 0},
+               "F58":            Key{tcell.KeyF58, tcell.ModNone, 0},
+               "F59":            Key{tcell.KeyF59, tcell.ModNone, 0},
+               "F60":            Key{tcell.KeyF60, tcell.ModNone, 0},
+               "F61":            Key{tcell.KeyF61, tcell.ModNone, 0},
+               "F62":            Key{tcell.KeyF62, tcell.ModNone, 0},
+               "F63":            Key{tcell.KeyF63, tcell.ModNone, 0},
+               "F64":            Key{tcell.KeyF64, tcell.ModNone, 0},
+               "CtrlSpace":      Key{tcell.KeyCtrlSpace, tcell.ModCtrl, 0},
+               "CtrlA":          Key{tcell.KeyCtrlA, tcell.ModCtrl, 0},
+               "CtrlB":          Key{tcell.KeyCtrlB, tcell.ModCtrl, 0},
+               "CtrlC":          Key{tcell.KeyCtrlC, tcell.ModCtrl, 0},
+               "CtrlD":          Key{tcell.KeyCtrlD, tcell.ModCtrl, 0},
+               "CtrlE":          Key{tcell.KeyCtrlE, tcell.ModCtrl, 0},
+               "CtrlF":          Key{tcell.KeyCtrlF, tcell.ModCtrl, 0},
+               "CtrlG":          Key{tcell.KeyCtrlG, tcell.ModCtrl, 0},
+               "CtrlH":          Key{tcell.KeyCtrlH, tcell.ModCtrl, 0},
+               "CtrlI":          Key{tcell.KeyCtrlI, tcell.ModCtrl, 0},
+               "CtrlJ":          Key{tcell.KeyCtrlJ, tcell.ModCtrl, 0},
+               "CtrlK":          Key{tcell.KeyCtrlK, tcell.ModCtrl, 0},
+               "CtrlL":          Key{tcell.KeyCtrlL, tcell.ModCtrl, 0},
+               "CtrlM":          Key{tcell.KeyCtrlM, tcell.ModCtrl, 0},
+               "CtrlN":          Key{tcell.KeyCtrlN, tcell.ModCtrl, 0},
+               "CtrlO":          Key{tcell.KeyCtrlO, tcell.ModCtrl, 0},
+               "CtrlP":          Key{tcell.KeyCtrlP, tcell.ModCtrl, 0},
+               "CtrlQ":          Key{tcell.KeyCtrlQ, tcell.ModCtrl, 0},
+               "CtrlR":          Key{tcell.KeyCtrlR, tcell.ModCtrl, 0},
+               "CtrlS":          Key{tcell.KeyCtrlS, tcell.ModCtrl, 0},
+               "CtrlT":          Key{tcell.KeyCtrlT, tcell.ModCtrl, 0},
+               "CtrlU":          Key{tcell.KeyCtrlU, tcell.ModCtrl, 0},
+               "CtrlV":          Key{tcell.KeyCtrlV, tcell.ModCtrl, 0},
+               "CtrlW":          Key{tcell.KeyCtrlW, tcell.ModCtrl, 0},
+               "CtrlX":          Key{tcell.KeyCtrlX, tcell.ModCtrl, 0},
+               "CtrlY":          Key{tcell.KeyCtrlY, tcell.ModCtrl, 0},
+               "CtrlZ":          Key{tcell.KeyCtrlZ, tcell.ModCtrl, 0},
+               "CtrlLeftSq":     Key{tcell.KeyCtrlLeftSq, tcell.ModCtrl, 0},
+               "CtrlBackslash":  Key{tcell.KeyCtrlBackslash, tcell.ModCtrl, 0},
+               "CtrlRightSq":    Key{tcell.KeyCtrlRightSq, tcell.ModCtrl, 0},
+               "CtrlCarat":      Key{tcell.KeyCtrlCarat, tcell.ModCtrl, 0},
+               "CtrlUnderscore": Key{tcell.KeyCtrlUnderscore, tcell.ModCtrl, 0},
+               "Backspace":      Key{tcell.KeyBackspace, tcell.ModNone, 0},
+               "Tab":            Key{tcell.KeyTab, tcell.ModNone, 0},
+               "Esc":            Key{tcell.KeyEsc, tcell.ModNone, 0},
+               "Escape":         Key{tcell.KeyEscape, tcell.ModNone, 0},
+               "Enter":          Key{tcell.KeyEnter, tcell.ModNone, 0},
+               "Backspace2":     Key{tcell.KeyBackspace2, tcell.ModNone, 0},
        }
 
        var parsed map[string]string
@@ -236,10 +241,20 @@ func InitBindings() {
        }
 
        for k, v := range defaults {
-               bindings[keys[k]] = actions[v]
+               if strings.Contains(k, "Alt-") {
+                       key := Key{tcell.KeyRune, tcell.ModAlt, rune(k[len(k)-1])}
+                       bindings[key] = actions[v]
+               } else {
+                       bindings[keys[k]] = actions[v]
+               }
        }
        for k, v := range parsed {
-               bindings[keys[k]] = actions[v]
+               if strings.Contains(k, "Alt-") {
+                       key := Key{tcell.KeyRune, tcell.ModAlt, rune(k[len(k)])}
+                       bindings[key] = actions[v]
+               } else {
+                       bindings[keys[k]] = actions[v]
+               }
        }
 }
 
@@ -281,258 +296,268 @@ func DefaultBindings() map[string]string {
                "CtrlC":          "Copy",
                "CtrlX":          "Cut",
                "CtrlK":          "CutLine",
+               "CtrlD":          "DuplicateLine",
                "CtrlV":          "Paste",
                "CtrlA":          "SelectAll",
                "Home":           "Start",
                "End":            "End",
                "PgUp":           "PageUp",
                "PgDn":           "PageDown",
-               "CtrlU":          "HalfPageUp",
-               "CtrlD":          "HalfPageDown",
-               "CtrlR":          "ToggleRuler",
-               "CtrlL":          "JumpLine",
-               "Delete":         "Delete",
+               // Find alternative key
+               // "CtrlU":          "HalfPageUp",
+               // "CtrlD":          "HalfPageDown",
+               "CtrlR":  "ToggleRuler",
+               "CtrlL":  "JumpLine",
+               "Delete": "Delete",
+               "Esc":    "ClearStatus",
+
+               // Emacs-style keybindings
+               "Alt-f": "WordRight",
+               "Alt-b": "WordLeft",
+               "Alt-a": "StartOfLine",
+               "Alt-e": "EndOfLine",
+               "Alt-p": "CursorUp",
+               "Alt-n": "CursorDown",
        }
 }
 
 // CursorUp moves the cursor up
 func (v *View) CursorUp() bool {
-       if v.cursor.HasSelection() {
-               v.cursor.SetLoc(v.cursor.curSelection[0])
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.SetLoc(v.Cursor.curSelection[0])
+               v.Cursor.ResetSelection()
        }
-       v.cursor.Up()
+       v.Cursor.Up()
        return true
 }
 
 // CursorDown moves the cursor down
 func (v *View) CursorDown() bool {
-       if v.cursor.HasSelection() {
-               v.cursor.SetLoc(v.cursor.curSelection[1])
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.SetLoc(v.Cursor.curSelection[1])
+               v.Cursor.ResetSelection()
        }
-       v.cursor.Down()
+       v.Cursor.Down()
        return true
 }
 
 // CursorLeft moves the cursor left
 func (v *View) CursorLeft() bool {
-       if v.cursor.HasSelection() {
-               v.cursor.SetLoc(v.cursor.curSelection[0])
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.SetLoc(v.Cursor.curSelection[0])
+               v.Cursor.ResetSelection()
        } else {
-               v.cursor.Left()
+               v.Cursor.Left()
        }
        return true
 }
 
 // CursorRight moves the cursor right
 func (v *View) CursorRight() bool {
-       if v.cursor.HasSelection() {
-               v.cursor.SetLoc(v.cursor.curSelection[1] - 1)
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.SetLoc(v.Cursor.curSelection[1] - 1)
+               v.Cursor.ResetSelection()
        } else {
-               v.cursor.Right()
+               v.Cursor.Right()
        }
        return true
 }
 
 // WordRight moves the cursor one word to the right
 func (v *View) WordRight() bool {
-       v.cursor.WordRight()
+       v.Cursor.WordRight()
        return true
 }
 
 // WordLeft moves the cursor one word to the left
 func (v *View) WordLeft() bool {
-       v.cursor.WordLeft()
+       v.Cursor.WordLeft()
        return true
 }
 
 // SelectUp selects up one line
 func (v *View) SelectUp() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.Up()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.Up()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // SelectDown selects down one line
 func (v *View) SelectDown() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.Down()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.Down()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // SelectLeft selects the character to the left of the cursor
 func (v *View) SelectLeft() bool {
-       loc := v.cursor.Loc()
-       count := v.buf.Len() - 1
+       loc := v.Cursor.Loc()
+       count := v.Buf.Len() - 1
        if loc > count {
                loc = count
        }
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.Left()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.Left()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // SelectRight selects the character to the right of the cursor
 func (v *View) SelectRight() bool {
-       loc := v.cursor.Loc()
-       count := v.buf.Len() - 1
+       loc := v.Cursor.Loc()
+       count := v.Buf.Len() - 1
        if loc > count {
                loc = count
        }
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.Right()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.Right()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // SelectWordRight selects the word to the right of the cursor
 func (v *View) SelectWordRight() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.WordRight()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.WordRight()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // SelectWordLeft selects the word to the left of the cursor
 func (v *View) SelectWordLeft() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.WordLeft()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.WordLeft()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // StartOfLine moves the cursor to the start of the line
 func (v *View) StartOfLine() bool {
-       v.cursor.Start()
+       v.Cursor.Start()
        return true
 }
 
 // EndOfLine moves the cursor to the end of the line
 func (v *View) EndOfLine() bool {
-       v.cursor.End()
+       v.Cursor.End()
        return true
 }
 
 // SelectToStartOfLine selects to the start of the current line
 func (v *View) SelectToStartOfLine() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.Start()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.Start()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // SelectToEndOfLine selects to the end of the current line
 func (v *View) SelectToEndOfLine() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
-       v.cursor.End()
-       v.cursor.SelectTo(v.cursor.Loc())
+       v.Cursor.End()
+       v.Cursor.SelectTo(v.Cursor.Loc())
        return true
 }
 
 // CursorStart moves the cursor to the start of the buffer
 func (v *View) CursorStart() bool {
-       v.cursor.x = 0
-       v.cursor.y = 0
+       v.Cursor.x = 0
+       v.Cursor.y = 0
        return true
 }
 
 // CursorEnd moves the cursor to the end of the buffer
 func (v *View) CursorEnd() bool {
-       v.cursor.SetLoc(v.buf.Len())
+       v.Cursor.SetLoc(v.Buf.Len())
        return true
 }
 
 // SelectToStart selects the text from the cursor to the start of the buffer
 func (v *View) SelectToStart() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
        v.CursorStart()
-       v.cursor.SelectTo(0)
+       v.Cursor.SelectTo(0)
        return true
 }
 
 // SelectToEnd selects the text from the cursor to the end of the buffer
 func (v *View) SelectToEnd() bool {
-       loc := v.cursor.Loc()
-       if !v.cursor.HasSelection() {
-               v.cursor.origSelection[0] = loc
+       loc := v.Cursor.Loc()
+       if !v.Cursor.HasSelection() {
+               v.Cursor.origSelection[0] = loc
        }
        v.CursorEnd()
-       v.cursor.SelectTo(v.buf.Len())
+       v.Cursor.SelectTo(v.Buf.Len())
        return true
 }
 
 // InsertSpace inserts a space
 func (v *View) InsertSpace() bool {
-       // Insert a space
-       if v.cursor.HasSelection() {
-               v.cursor.DeleteSelection()
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.DeleteSelection()
+               v.Cursor.ResetSelection()
        }
-       v.eh.Insert(v.cursor.Loc(), " ")
-       v.cursor.Right()
+       v.Buf.Insert(v.Cursor.Loc(), " ")
+       v.Cursor.Right()
        return true
 }
 
 // InsertEnter inserts a newline plus possible some whitespace if autoindent is on
 func (v *View) InsertEnter() bool {
        // Insert a newline
-       if v.cursor.HasSelection() {
-               v.cursor.DeleteSelection()
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.DeleteSelection()
+               v.Cursor.ResetSelection()
        }
 
-       v.eh.Insert(v.cursor.Loc(), "\n")
-       ws := GetLeadingWhitespace(v.buf.lines[v.cursor.y])
-       v.cursor.Right()
+       v.Buf.Insert(v.Cursor.Loc(), "\n")
+       ws := GetLeadingWhitespace(v.Buf.Lines[v.Cursor.y])
+       v.Cursor.Right()
 
        if settings["autoindent"].(bool) {
-               v.eh.Insert(v.cursor.Loc(), ws)
+               v.Buf.Insert(v.Cursor.Loc(), ws)
                for i := 0; i < len(ws); i++ {
-                       v.cursor.Right()
+                       v.Cursor.Right()
                }
        }
-       v.cursor.lastVisualX = v.cursor.GetVisualX()
+       v.Cursor.lastVisualX = v.Cursor.GetVisualX()
        return true
 }
 
 // Backspace deletes the previous character
 func (v *View) Backspace() bool {
        // Delete a character
-       if v.cursor.HasSelection() {
-               v.cursor.DeleteSelection()
-               v.cursor.ResetSelection()
-       } else if v.cursor.Loc() > 0 {
+       if v.Cursor.HasSelection() {
+               v.Cursor.DeleteSelection()
+               v.Cursor.ResetSelection()
+       } else if v.Cursor.Loc() > 0 {
                // We have to do something a bit hacky here because we want to
                // delete the line by first moving left and then deleting backwards
                // but the undo redo would place the cursor in the wrong place
@@ -542,37 +567,37 @@ func (v *View) Backspace() bool {
                // If the user is using spaces instead of tabs and they are deleting
                // whitespace at the start of the line, we should delete as if its a
                // tab (tabSize number of spaces)
-               lineStart := v.buf.lines[v.cursor.y][:v.cursor.x]
+               lineStart := v.Buf.Lines[v.Cursor.y][:v.Cursor.x]
                tabSize := int(settings["tabsize"].(float64))
-               if settings["tabsToSpaces"].(bool) && IsSpaces(lineStart) && len(lineStart) != 0 && len(lineStart)%tabSize == 0 {
-                       loc := v.cursor.Loc()
-                       v.cursor.SetLoc(loc - tabSize)
-                       cx, cy := v.cursor.x, v.cursor.y
-                       v.cursor.SetLoc(loc)
-                       v.eh.Remove(loc-tabSize, loc)
-                       v.cursor.x, v.cursor.y = cx, cy
+               if settings["tabstospaces"].(bool) && IsSpaces(lineStart) && len(lineStart) != 0 && len(lineStart)%tabSize == 0 {
+                       loc := v.Cursor.Loc()
+                       v.Cursor.SetLoc(loc - tabSize)
+                       cx, cy := v.Cursor.x, v.Cursor.y
+                       v.Cursor.SetLoc(loc)
+                       v.Buf.Remove(loc-tabSize, loc)
+                       v.Cursor.x, v.Cursor.y = cx, cy
                } else {
-                       v.cursor.Left()
-                       cx, cy := v.cursor.x, v.cursor.y
-                       v.cursor.Right()
-                       loc := v.cursor.Loc()
-                       v.eh.Remove(loc-1, loc)
-                       v.cursor.x, v.cursor.y = cx, cy
+                       v.Cursor.Left()
+                       cx, cy := v.Cursor.x, v.Cursor.y
+                       v.Cursor.Right()
+                       loc := v.Cursor.Loc()
+                       v.Buf.Remove(loc-1, loc)
+                       v.Cursor.x, v.Cursor.y = cx, cy
                }
        }
-       v.cursor.lastVisualX = v.cursor.GetVisualX()
+       v.Cursor.lastVisualX = v.Cursor.GetVisualX()
        return true
 }
 
 // Delete deletes the next character
 func (v *View) Delete() bool {
-       if v.cursor.HasSelection() {
-               v.cursor.DeleteSelection()
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.DeleteSelection()
+               v.Cursor.ResetSelection()
        } else {
-               loc := v.cursor.Loc()
-               if loc < v.buf.Len() {
-                       v.eh.Remove(loc, loc+1)
+               loc := v.Cursor.Loc()
+               if loc < v.Buf.Len() {
+                       v.Buf.Remove(loc, loc+1)
                }
        }
        return true
@@ -581,19 +606,19 @@ func (v *View) Delete() bool {
 // InsertTab inserts a tab or spaces
 func (v *View) InsertTab() bool {
        // Insert a tab
-       if v.cursor.HasSelection() {
-               v.cursor.DeleteSelection()
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.DeleteSelection()
+               v.Cursor.ResetSelection()
        }
-       if settings["tabsToSpaces"].(bool) {
+       if settings["tabstospaces"].(bool) {
                tabSize := int(settings["tabsize"].(float64))
-               v.eh.Insert(v.cursor.Loc(), Spaces(tabSize))
+               v.Buf.Insert(v.Cursor.Loc(), Spaces(tabSize))
                for i := 0; i < tabSize; i++ {
-                       v.cursor.Right()
+                       v.Cursor.Right()
                }
        } else {
-               v.eh.Insert(v.cursor.Loc(), "\t")
-               v.cursor.Right()
+               v.Buf.Insert(v.Cursor.Loc(), "\t")
+               v.Cursor.Right()
        }
        return true
 }
@@ -601,69 +626,30 @@ func (v *View) InsertTab() bool {
 // Save the buffer to disk
 func (v *View) Save() bool {
        // If this is an empty buffer, ask for a filename
-       if v.buf.path == "" {
+       if v.Buf.Path == "" {
                filename, canceled := messenger.Prompt("Filename: ")
                if !canceled {
-                       v.buf.path = filename
-                       v.buf.name = filename
+                       v.Buf.Path = filename
+                       v.Buf.Name = filename
                } else {
                        return true
                }
        }
-       err := v.buf.Save()
+       err := v.Buf.Save()
        if err != nil {
                messenger.Error(err.Error())
        } else {
-               messenger.Message("Saved " + v.buf.path)
-               switch v.buf.filetype {
-               case "Go":
-                       v.GoSave()
-               }
-       }
-       if err := L.CallByParam(lua.P{
-               Fn:      L.GetGlobal("onSave"),
-               NRet:    1,
-               Protect: true,
-       }); err != nil {
-               // The function isn't defined by this plugin
-               return true
+               messenger.Message("Saved " + v.Buf.Path)
        }
        return true
 }
 
-// GoSave saves the current file (must be a go file) and runs goimports or gofmt
-// depending on the user's configuration
-func (v *View) GoSave() {
-       if settings["goimports"] == true {
-               messenger.Message("Running goimports...")
-               err := goimports(v.buf.path)
-               if err != nil {
-                       messenger.Error(err)
-               } else {
-                       messenger.Message("Saved " + v.buf.path)
-               }
-               v.ReOpen()
-       } else if settings["gofmt"] == true {
-               messenger.Message("Running gofmt...")
-               err := gofmt(v.buf.path)
-               if err != nil {
-                       messenger.Error(err)
-               } else {
-                       messenger.Message("Saved " + v.buf.path)
-               }
-               v.ReOpen()
-               return
-       }
-
-       return
-}
-
 // Find opens a prompt and searches forward for the input
 func (v *View) Find() bool {
-       if v.cursor.HasSelection() {
-               searchStart = v.cursor.curSelection[1]
+       if v.Cursor.HasSelection() {
+               searchStart = v.Cursor.curSelection[1]
        } else {
-               searchStart = ToCharPos(v.cursor.x, v.cursor.y, v.buf)
+               searchStart = ToCharPos(v.Cursor.x, v.Cursor.y, v.Buf)
        }
        BeginSearch()
        return true
@@ -671,59 +657,61 @@ func (v *View) Find() bool {
 
 // FindNext searches forwards for the last used search term
 func (v *View) FindNext() bool {
-       if v.cursor.HasSelection() {
-               searchStart = v.cursor.curSelection[1]
+       if v.Cursor.HasSelection() {
+               searchStart = v.Cursor.curSelection[1]
        } else {
-               searchStart = ToCharPos(v.cursor.x, v.cursor.y, v.buf)
+               searchStart = ToCharPos(v.Cursor.x, v.Cursor.y, v.Buf)
        }
-       messenger.Message("Find: " + lastSearch)
+       messenger.Message("Finding: " + lastSearch)
        Search(lastSearch, v, true)
        return true
 }
 
 // FindPrevious searches backwards for the last used search term
 func (v *View) FindPrevious() bool {
-       if v.cursor.HasSelection() {
-               searchStart = v.cursor.curSelection[0]
+       if v.Cursor.HasSelection() {
+               searchStart = v.Cursor.curSelection[0]
        } else {
-               searchStart = ToCharPos(v.cursor.x, v.cursor.y, v.buf)
+               searchStart = ToCharPos(v.Cursor.x, v.Cursor.y, v.Buf)
        }
-       messenger.Message("Find: " + lastSearch)
+       messenger.Message("Finding: " + lastSearch)
        Search(lastSearch, v, false)
        return true
 }
 
 // Undo undoes the last action
 func (v *View) Undo() bool {
-       v.eh.Undo()
+       v.Buf.Undo()
+       messenger.Message("Undid action")
        return true
 }
 
 // Redo redoes the last action
 func (v *View) Redo() bool {
-       v.eh.Redo()
+       v.Buf.Redo()
+       messenger.Message("Redid action")
        return true
 }
 
 // Copy the selection to the system clipboard
 func (v *View) Copy() bool {
-       if v.cursor.HasSelection() {
-               clipboard.WriteAll(v.cursor.GetSelection())
+       if v.Cursor.HasSelection() {
+               clipboard.WriteAll(v.Cursor.GetSelection())
                v.freshClip = true
+               messenger.Message("Copied selection")
        }
        return true
 }
 
 // CutLine cuts the current line to the clipboard
 func (v *View) CutLine() bool {
-       v.cursor.SelectLine()
+       v.Cursor.SelectLine()
        if v.freshClip == true {
-
-               if v.cursor.HasSelection() {
+               if v.Cursor.HasSelection() {
                        if clip, err := clipboard.ReadAll(); err != nil {
                                messenger.Error(err)
                        } else {
-                               clipboard.WriteAll(clip + v.cursor.GetSelection())
+                               clipboard.WriteAll(clip + v.Cursor.GetSelection())
                        }
                }
        } else if time.Since(v.lastCutTime)/time.Second > 10*time.Second || v.freshClip == false {
@@ -731,43 +719,55 @@ func (v *View) CutLine() bool {
        }
        v.freshClip = true
        v.lastCutTime = time.Now()
-       v.cursor.DeleteSelection()
-       v.cursor.ResetSelection()
+       v.Cursor.DeleteSelection()
+       v.Cursor.ResetSelection()
+       messenger.Message("Cut line")
        return true
 }
 
 // Cut the selection to the system clipboard
 func (v *View) Cut() bool {
-       if v.cursor.HasSelection() {
-               clipboard.WriteAll(v.cursor.GetSelection())
-               v.cursor.DeleteSelection()
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               clipboard.WriteAll(v.Cursor.GetSelection())
+               v.Cursor.DeleteSelection()
+               v.Cursor.ResetSelection()
                v.freshClip = true
+               messenger.Message("Cut selection")
        }
        return true
 }
 
+// DuplicateLine duplicates the current line
+func (v *View) DuplicateLine() bool {
+       v.Cursor.End()
+       v.Buf.Insert(v.Cursor.Loc(), "\n"+v.Buf.Lines[v.Cursor.y])
+       v.Cursor.Right()
+       messenger.Message("Duplicated line")
+       return true
+}
+
 // Paste whatever is in the system clipboard into the buffer
 // Delete and paste if the user has a selection
 func (v *View) Paste() bool {
-       if v.cursor.HasSelection() {
-               v.cursor.DeleteSelection()
-               v.cursor.ResetSelection()
+       if v.Cursor.HasSelection() {
+               v.Cursor.DeleteSelection()
+               v.Cursor.ResetSelection()
        }
        clip, _ := clipboard.ReadAll()
-       v.eh.Insert(v.cursor.Loc(), clip)
-       v.cursor.SetLoc(v.cursor.Loc() + Count(clip))
+       v.Buf.Insert(v.Cursor.Loc(), clip)
+       v.Cursor.SetLoc(v.Cursor.Loc() + Count(clip))
        v.freshClip = false
+       messenger.Message("Pasted clipboard")
        return true
 }
 
 // SelectAll selects the entire buffer
 func (v *View) SelectAll() bool {
-       v.cursor.curSelection[1] = 0
-       v.cursor.curSelection[0] = v.buf.Len()
+       v.Cursor.curSelection[0] = 0
+       v.Cursor.curSelection[1] = v.Buf.Len()
        // Put the cursor at the beginning
-       v.cursor.x = 0
-       v.cursor.y = 0
+       v.Cursor.x = 0
+       v.Cursor.y = 0
        return true
 }
 
@@ -794,57 +794,57 @@ func (v *View) OpenFile() bool {
 
 // Start moves the viewport to the start of the buffer
 func (v *View) Start() bool {
-       v.topline = 0
+       v.Topline = 0
        return false
 }
 
 // End moves the viewport to the end of the buffer
 func (v *View) End() bool {
-       if v.height > v.buf.numLines {
-               v.topline = 0
+       if v.height > v.Buf.NumLines {
+               v.Topline = 0
        } else {
-               v.topline = v.buf.numLines - v.height
+               v.Topline = v.Buf.NumLines - v.height
        }
        return false
 }
 
 // PageUp scrolls the view up a page
 func (v *View) PageUp() bool {
-       if v.topline > v.height {
+       if v.Topline > v.height {
                v.ScrollUp(v.height)
        } else {
-               v.topline = 0
+               v.Topline = 0
        }
        return false
 }
 
 // PageDown scrolls the view down a page
 func (v *View) PageDown() bool {
-       if v.buf.numLines-(v.topline+v.height) > v.height {
+       if v.Buf.NumLines-(v.Topline+v.height) > v.height {
                v.ScrollDown(v.height)
-       } else if v.buf.numLines >= v.height {
-               v.topline = v.buf.numLines - v.height
+       } else if v.Buf.NumLines >= v.height {
+               v.Topline = v.Buf.NumLines - v.height
        }
        return false
 }
 
 // HalfPageUp scrolls the view up half a page
 func (v *View) HalfPageUp() bool {
-       if v.topline > v.height/2 {
+       if v.Topline > v.height/2 {
                v.ScrollUp(v.height / 2)
        } else {
-               v.topline = 0
+               v.Topline = 0
        }
        return false
 }
 
 // HalfPageDown scrolls the view down half a page
 func (v *View) HalfPageDown() bool {
-       if v.buf.numLines-(v.topline+v.height) > v.height/2 {
+       if v.Buf.NumLines-(v.Topline+v.height) > v.height/2 {
                v.ScrollDown(v.height / 2)
        } else {
-               if v.buf.numLines >= v.height {
-                       v.topline = v.buf.numLines - v.height
+               if v.Buf.NumLines >= v.height {
+                       v.Topline = v.Buf.NumLines - v.height
                }
        }
        return false
@@ -854,8 +854,10 @@ func (v *View) HalfPageDown() bool {
 func (v *View) ToggleRuler() bool {
        if settings["ruler"] == false {
                settings["ruler"] = true
+               messenger.Message("Enabled ruler")
        } else {
                settings["ruler"] = false
+               messenger.Message("Disabled ruler")
        }
        return false
 }
@@ -874,38 +876,22 @@ func (v *View) JumpLine() bool {
                return false
        }
        // Move cursor and view if possible.
-       if lineint < v.buf.numLines {
-               v.cursor.x = 0
-               v.cursor.y = lineint
+       if lineint < v.Buf.NumLines {
+               v.Cursor.x = 0
+               v.Cursor.y = lineint
                return true
        }
-       messenger.Error("Only ", v.buf.numLines, " lines to jump")
+       messenger.Error("Only ", v.Buf.NumLines, " lines to jump")
        return false
 }
 
-// None is no action
-func None() bool {
+// ClearStatus clears the messenger bar
+func (v *View) ClearStatus() bool {
+       messenger.Message("")
        return false
 }
 
-// gofmt runs gofmt on a file
-func gofmt(file string) error {
-       cmd := exec.Command("gofmt", "-w", file)
-       cmd.Start()
-       err := cmd.Wait()
-       if err != nil {
-               return errors.New("Check syntax ") //TODO: highlight or display locations
-       }
-       return nil
-}
-
-// goimports runs goimports on a file
-func goimports(file string) error {
-       cmd := exec.Command("goimports", "-w", file)
-       cmd.Start()
-       err := cmd.Wait()
-       if err != nil {
-               return errors.New("Check syntax ") //TODO: highlight or display locations
-       }
-       return nil
+// None is no action
+func None() bool {
+       return false
 }