X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=cmd%2Fmicro%2Fbindings.go;h=b537a9e12e9241082c1005e2baf533b0c7e63d2e;hb=128dc9fea1587f19ab8fcb176c265c6e4f13c536;hp=f94309ec9f8e411c71c807dd84c7285999529881;hpb=646cdd6a9fd6ef688a5be8a5ef57404ba10a6d24;p=micro.git diff --git a/cmd/micro/bindings.go b/cmd/micro/bindings.go index f94309ec..b537a9e1 100644 --- a/cmd/micro/bindings.go +++ b/cmd/micro/bindings.go @@ -1,22 +1,18 @@ package main import ( - "encoding/json" "io/ioutil" "os" - "strconv" "strings" - "time" - "github.com/mitchellh/go-homedir" - "github.com/zyedidia/clipboard" + "github.com/zyedidia/json5/encoding/json5" "github.com/zyedidia/tcell" ) -var bindings map[Key][]func(*View) bool +var bindings map[Key][]func(*View, bool) bool var helpBinding string -var bindingActions = map[string]func(*View) bool{ +var bindingActions = map[string]func(*View, bool) bool{ "CursorUp": (*View).CursorUp, "CursorDown": (*View).CursorDown, "CursorPageUp": (*View).CursorPageUp, @@ -39,7 +35,7 @@ var bindingActions = map[string]func(*View) bool{ "DeleteWordLeft": (*View).DeleteWordLeft, "SelectToStartOfLine": (*View).SelectToStartOfLine, "SelectToEndOfLine": (*View).SelectToEndOfLine, - "InsertEnter": (*View).InsertEnter, + "InsertNewline": (*View).InsertNewline, "InsertSpace": (*View).InsertSpace, "Backspace": (*View).Backspace, "Delete": (*View).Delete, @@ -48,13 +44,21 @@ var bindingActions = map[string]func(*View) bool{ "Find": (*View).Find, "FindNext": (*View).FindNext, "FindPrevious": (*View).FindPrevious, + "Center": (*View).Center, "Undo": (*View).Undo, "Redo": (*View).Redo, "Copy": (*View).Copy, "Cut": (*View).Cut, "CutLine": (*View).CutLine, "DuplicateLine": (*View).DuplicateLine, + "DeleteLine": (*View).DeleteLine, + "MoveLinesUp": (*View).MoveLinesUp, + "MoveLinesDown": (*View).MoveLinesDown, + "IndentSelection": (*View).IndentSelection, + "OutdentSelection": (*View).OutdentSelection, + "OutdentLine": (*View).OutdentLine, "Paste": (*View).Paste, + "PastePrimary": (*View).PastePrimary, "SelectAll": (*View).SelectAll, "OpenFile": (*View).OpenFile, "Start": (*View).Start, @@ -71,7 +75,22 @@ var bindingActions = map[string]func(*View) bool{ "ClearStatus": (*View).ClearStatus, "ShellMode": (*View).ShellMode, "CommandMode": (*View).CommandMode, + "Escape": (*View).Escape, "Quit": (*View).Quit, + "QuitAll": (*View).QuitAll, + "AddTab": (*View).AddTab, + "PreviousTab": (*View).PreviousTab, + "NextTab": (*View).NextTab, + "NextSplit": (*View).NextSplit, + "PreviousSplit": (*View).PreviousSplit, + "Unsplit": (*View).Unsplit, + "VSplit": (*View).VSplitBinding, + "HSplit": (*View).HSplitBinding, + "ToggleMacro": (*View).ToggleMacro, + "PlayMacro": (*View).PlayMacro, + + // This was changed to InsertNewline but I don't want to break backwards compatibility + "InsertEnter": (*View).InsertNewline, } var bindingKeys = map[string]tcell.Key{ @@ -193,12 +212,11 @@ var bindingKeys = map[string]tcell.Key{ "CtrlRightSq": tcell.KeyCtrlRightSq, "CtrlCarat": tcell.KeyCtrlCarat, "CtrlUnderscore": tcell.KeyCtrlUnderscore, - "Backspace": tcell.KeyBackspace, "Tab": tcell.KeyTab, "Esc": tcell.KeyEsc, "Escape": tcell.KeyEscape, "Enter": tcell.KeyEnter, - "Backspace2": tcell.KeyBackspace2, + "Backspace": tcell.KeyBackspace2, // I renamed these keys to PageUp and PageDown but I don't want to break someone's keybindings "PgUp": tcell.KeyPgUp, @@ -214,7 +232,7 @@ type Key struct { // InitBindings initializes the keybindings for micro func InitBindings() { - bindings = make(map[Key][]func(*View) bool) + bindings = make(map[Key][]func(*View, bool) bool) var parsed map[string]string defaults := DefaultBindings() @@ -227,7 +245,7 @@ func InitBindings() { return } - err = json.Unmarshal(input, &parsed) + err = json5.Unmarshal(input, &parsed) if err != nil { TermMessage("Error reading bindings.json:", err.Error()) } @@ -255,7 +273,8 @@ modSearch: case strings.HasPrefix(k, "-"): // We optionally support dashes between modifiers k = k[1:] - case strings.HasPrefix(k, "Ctrl"): + case strings.HasPrefix(k, "Ctrl") && k != "CtrlH": + // CtrlH technically does not have a 'Ctrl' modifier because it is really backspace k = k[4:] modifiers |= tcell.ModCtrl case strings.HasPrefix(k, "Alt"): @@ -307,7 +326,7 @@ modSearch: } // findAction will find 'action' using string 'v' -func findAction(v string) (action func(*View) bool) { +func findAction(v string) (action func(*View, bool) bool) { action, ok := bindingActions[v] if !ok { // If the user seems to be binding a function that doesn't exist @@ -321,6 +340,7 @@ func findAction(v string) (action func(*View) bool) { func BindKey(k, v string) { key, ok := findKey(k) if !ok { + TermMessage("Unknown keybinding: " + k) return } if v == "ToggleHelp" { @@ -328,7 +348,7 @@ func BindKey(k, v string) { } actionNames := strings.Split(v, ",") - actions := make([]func(*View) bool, 0, len(actionNames)) + actions := make([]func(*View, bool) bool, 0, len(actionNames)) for _, actionName := range actionNames { actions = append(actions, findAction(actionName)) } @@ -349,6 +369,8 @@ func DefaultBindings() map[string]string { "ShiftRight": "SelectRight", "AltLeft": "WordLeft", "AltRight": "WordRight", + "AltUp": "MoveLinesUp", + "AltDown": "MoveLinesDown", "AltShiftRight": "SelectWordRight", "AltShiftLeft": "SelectWordLeft", "CtrlLeft": "StartOfLine", @@ -359,13 +381,13 @@ func DefaultBindings() map[string]string { "CtrlDown": "CursorEnd", "CtrlShiftUp": "SelectToStart", "CtrlShiftDown": "SelectToEnd", - "Enter": "InsertEnter", - "Space": "InsertSpace", + "Enter": "InsertNewline", + "CtrlH": "Backspace", "Backspace": "Backspace", - "Backspace2": "Backspace", + "Alt-CtrlH": "DeleteWordLeft", "Alt-Backspace": "DeleteWordLeft", - "Alt-Backspace2": "DeleteWordLeft", - "Tab": "InsertTab", + "Tab": "IndentSelection,InsertTab", + "Backtab": "OutdentSelection,OutdentLine", "CtrlO": "OpenFile", "CtrlS": "Save", "CtrlF": "Find", @@ -379,18 +401,25 @@ func DefaultBindings() map[string]string { "CtrlD": "DuplicateLine", "CtrlV": "Paste", "CtrlA": "SelectAll", - "Home": "Start", - "End": "End", + "CtrlT": "AddTab", + "CtrlRightSq": "PreviousTab", + "CtrlBackslash": "NextTab", + "Home": "StartOfLine", + "End": "EndOfLine", + "CtrlHome": "CursorStart", + "CtrlEnd": "CursorEnd", "PageUp": "CursorPageUp", "PageDown": "CursorPageDown", "CtrlG": "ToggleHelp", "CtrlR": "ToggleRuler", "CtrlL": "JumpLine", "Delete": "Delete", - "Esc": "ClearStatus", "CtrlB": "ShellMode", "CtrlQ": "Quit", "CtrlE": "CommandMode", + "CtrlW": "NextSplit", + "CtrlU": "ToggleMacro", + "CtrlJ": "PlayMacro", // Emacs-style keybindings "Alt-f": "WordRight", @@ -399,678 +428,13 @@ func DefaultBindings() map[string]string { "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() - } - 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() - } - 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() - } else { - 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() - } else { - v.Cursor.Right() - } - return true -} - -// WordRight moves the cursor one word to the right -func (v *View) WordRight() bool { - v.Cursor.WordRight() - return true -} - -// WordLeft moves the cursor one word to the left -func (v *View) WordLeft() bool { - 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 - } - 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 - } - 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 - if loc > count { - loc = count - } - if !v.Cursor.HasSelection() { - v.Cursor.OrigSelection[0] = 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 - if loc > count { - loc = count - } - if !v.Cursor.HasSelection() { - v.Cursor.OrigSelection[0] = 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 - } - 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 - } - 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() - return true -} - -// EndOfLine moves the cursor to the end of the line -func (v *View) EndOfLine() bool { - 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 - } - 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 - } - 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 - return true -} - -// CursorEnd moves the cursor to the end of the buffer -func (v *View) CursorEnd() bool { - 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 - } - v.CursorStart() - 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 - } - v.CursorEnd() - v.Cursor.SelectTo(v.Buf.Len()) - return true -} - -// InsertSpace inserts a space -func (v *View) InsertSpace() bool { - if v.Cursor.HasSelection() { - v.Cursor.DeleteSelection() - v.Cursor.ResetSelection() - } - 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() - } - - v.Buf.Insert(v.Cursor.Loc(), "\n") - ws := GetLeadingWhitespace(v.Buf.Lines[v.Cursor.Y]) - v.Cursor.Right() - - if settings["autoindent"].(bool) { - v.Buf.Insert(v.Cursor.Loc(), ws) - for i := 0; i < len(ws); i++ { - v.Cursor.Right() - } - } - 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 { - // 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 - // So instead we move left, save the position, move back, delete - // and restore the position - - // 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] - 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.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.Buf.Remove(loc-1, loc) - v.Cursor.X, v.Cursor.Y = cx, cy - } - } - v.Cursor.LastVisualX = v.Cursor.GetVisualX() - return true -} - -// DeleteWordRight deletes the word to the right of the cursor -func (v *View) DeleteWordRight() bool { - v.SelectWordRight() - if v.Cursor.HasSelection() { - v.Cursor.DeleteSelection() - v.Cursor.ResetSelection() - } - return true -} - -// DeleteWordLeft deletes the word to the left of the cursor -func (v *View) DeleteWordLeft() bool { - v.SelectWordLeft() - if v.Cursor.HasSelection() { - v.Cursor.DeleteSelection() - v.Cursor.ResetSelection() - } - return true -} - -// Delete deletes the next character -func (v *View) Delete() bool { - if v.Cursor.HasSelection() { - v.Cursor.DeleteSelection() - v.Cursor.ResetSelection() - } else { - loc := v.Cursor.Loc() - if loc < v.Buf.Len() { - v.Buf.Remove(loc, loc+1) - } - } - return true -} - -// 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 settings["tabstospaces"].(bool) { - tabSize := int(settings["tabsize"].(float64)) - v.Buf.Insert(v.Cursor.Loc(), Spaces(tabSize)) - for i := 0; i < tabSize; i++ { - v.Cursor.Right() - } - } else { - v.Buf.Insert(v.Cursor.Loc(), "\t") - v.Cursor.Right() - } - return true -} - -// Save the buffer to disk -func (v *View) Save() bool { - if v.helpOpen { - // We can't save the help text - return false - } - // If this is an empty buffer, ask for a filename - if v.Buf.Path == "" { - filename, canceled := messenger.Prompt("Filename: ", "Save") - if !canceled { - v.Buf.Path = filename - v.Buf.Name = filename - } else { - return true - } - } - err := v.Buf.Save() - if err != nil { - messenger.Error(err.Error()) - } else { - messenger.Message("Saved " + v.Buf.Path) - } - return true -} - -// Find opens a prompt and searches forward for the input -func (v *View) Find() bool { - if v.Cursor.HasSelection() { - searchStart = v.Cursor.CurSelection[1] - } else { - searchStart = ToCharPos(v.Cursor.X, v.Cursor.Y, v.Buf) - } - BeginSearch() - return true -} - -// FindNext searches forwards for the last used search term -func (v *View) FindNext() bool { - if v.Cursor.HasSelection() { - searchStart = v.Cursor.CurSelection[1] - } else { - searchStart = ToCharPos(v.Cursor.X, v.Cursor.Y, v.Buf) - } - 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] - } else { - searchStart = ToCharPos(v.Cursor.X, v.Cursor.Y, v.Buf) - } - messenger.Message("Finding: " + lastSearch) - Search(lastSearch, v, false) - return true -} - -// Undo undoes the last action -func (v *View) Undo() bool { - v.Buf.Undo() - messenger.Message("Undid action") - return true -} - -// Redo redoes the last action -func (v *View) Redo() bool { - 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()) - 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() - if !v.Cursor.HasSelection() { - return false - } - if v.freshClip == true { - if v.Cursor.HasSelection() { - if clip, err := clipboard.ReadAll(); err != nil { - messenger.Error(err) - } else { - clipboard.WriteAll(clip + v.Cursor.GetSelection()) - } - } - } else if time.Since(v.lastCutTime)/time.Second > 10*time.Second || v.freshClip == false { - v.Copy() - } - v.freshClip = true - v.lastCutTime = time.Now() - 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() - 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() - } - clip, _ := clipboard.ReadAll() - 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[0] = 0 - v.Cursor.CurSelection[1] = v.Buf.Len() - // Put the cursor at the beginning - v.Cursor.X = 0 - v.Cursor.Y = 0 - return true -} - -// OpenFile opens a new file in the buffer -func (v *View) OpenFile() bool { - if v.CanClose("Continue? (yes, no, save) ") { - filename, canceled := messenger.Prompt("File to open: ", "Open") - if canceled { - return true - } - home, _ := homedir.Dir() - filename = strings.Replace(filename, "~", home, 1) - file, err := ioutil.ReadFile(filename) - - if err != nil { - messenger.Error(err.Error()) - return true - } - buf := NewBuffer(string(file), filename) - v.OpenBuffer(buf) - } - return true -} - -// Start moves the viewport to the start of the buffer -func (v *View) Start() bool { - 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 - } else { - v.Topline = v.Buf.NumLines - v.height + // Integration with file managers + "F1": "ToggleHelp", + "F2": "Save", + "F4": "Quit", + "F7": "Find", + "F10": "Quit", + "Esc": "Escape", } - return false -} - -// PageUp scrolls the view up a page -func (v *View) PageUp() bool { - if v.Topline > v.height { - v.ScrollUp(v.height) - } else { - 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 { - v.ScrollDown(v.height) - } else if v.Buf.NumLines >= v.height { - v.Topline = v.Buf.NumLines - v.height - } - return false -} - -// CursorPageUp places the cursor a page up -func (v *View) CursorPageUp() bool { - if v.Cursor.HasSelection() { - v.Cursor.SetLoc(v.Cursor.CurSelection[0]) - v.Cursor.ResetSelection() - } - v.Cursor.UpN(v.height) - return true -} - -// CursorPageDown places the cursor a page up -func (v *View) CursorPageDown() bool { - if v.Cursor.HasSelection() { - v.Cursor.SetLoc(v.Cursor.CurSelection[1]) - v.Cursor.ResetSelection() - } - v.Cursor.DownN(v.height) - return true -} - -// HalfPageUp scrolls the view up half a page -func (v *View) HalfPageUp() bool { - if v.Topline > v.height/2 { - v.ScrollUp(v.height / 2) - } else { - 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 { - v.ScrollDown(v.height / 2) - } else { - if v.Buf.NumLines >= v.height { - v.Topline = v.Buf.NumLines - v.height - } - } - return false -} - -// ToggleRuler turns line numbers off and on -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 -} - -// JumpLine jumps to a line and moves the view accordingly. -func (v *View) JumpLine() bool { - // Prompt for line number - linestring, canceled := messenger.Prompt("Jump to line # ", "LineNumber") - if canceled { - return false - } - lineint, err := strconv.Atoi(linestring) - lineint = lineint - 1 // fix offset - if err != nil { - messenger.Error(err) // return errors - return false - } - // Move cursor and view if possible. - if lineint < v.Buf.NumLines { - v.Cursor.X = 0 - v.Cursor.Y = lineint - return true - } - messenger.Error("Only ", v.Buf.NumLines, " lines to jump") - return false -} - -// ClearStatus clears the messenger bar -func (v *View) ClearStatus() bool { - messenger.Message("") - return false -} - -// ToggleHelp toggles the help screen -func (v *View) ToggleHelp() bool { - if !v.helpOpen { - v.lastBuffer = v.Buf - helpBuffer := NewBuffer(helpTxt, "help.md") - helpBuffer.Name = "Help" - v.helpOpen = true - v.OpenBuffer(helpBuffer) - } else { - v.OpenBuffer(v.lastBuffer) - v.helpOpen = false - } - return true -} - -// ShellMode opens a terminal to run a shell command -func (v *View) ShellMode() bool { - input, canceled := messenger.Prompt("$ ", "Shell") - if !canceled { - // The true here is for openTerm to make the command interactive - HandleShellCommand(input, true) - } - return false -} - -// CommandMode lets the user enter a command -func (v *View) CommandMode() bool { - input, canceled := messenger.Prompt("> ", "Command") - if !canceled { - HandleCommand(input) - } - return false -} - -// Quit quits the editor -// This behavior needs to be changed and should really only quit the editor if this -// is the last view -// However, since micro only supports one view for now, it doesn't really matter -func (v *View) Quit() bool { - if v.helpOpen { - return v.ToggleHelp() - } - // Make sure not to quit if there are unsaved changes - if views[mainView].CanClose("Quit anyway? (yes, no, save) ") { - views[mainView].CloseBuffer() - screen.Fini() - os.Exit(0) - } - return false -} - -// None is no action -func None() bool { - return false }