Add history navigation with up and down arrows

Fixes #145
This commit is contained in:
Zachary Yedidia
2016-05-28 18:41:53 -04:00
parent 1c127a6c3f
commit 1fe18eecb7
5 changed files with 42 additions and 10 deletions

View File

@@ -643,7 +643,7 @@ func (v *View) Save() bool {
}
// If this is an empty buffer, ask for a filename
if v.Buf.Path == "" {
filename, canceled := messenger.Prompt("Filename: ")
filename, canceled := messenger.Prompt("Filename: ", "Save")
if !canceled {
v.Buf.Path = filename
v.Buf.Name = filename
@@ -793,7 +793,7 @@ func (v *View) SelectAll() bool {
// 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: ")
filename, canceled := messenger.Prompt("File to open: ", "Open")
if canceled {
return true
}
@@ -884,7 +884,7 @@ func (v *View) ToggleRuler() bool {
// 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 # ")
linestring, canceled := messenger.Prompt("Jump to line # ", "LineNumber")
if canceled {
return false
}
@@ -927,7 +927,7 @@ func (v *View) ToggleHelp() bool {
// ShellMode opens a terminal to run a shell command
func (v *View) ShellMode() bool {
input, canceled := messenger.Prompt("$ ")
input, canceled := messenger.Prompt("$ ", "Shell")
if !canceled {
// The true here is for openTerm to make the command interactive
HandleShellCommand(input, true)
@@ -937,7 +937,7 @@ func (v *View) ShellMode() bool {
// CommandMode lets the user enter a command
func (v *View) CommandMode() bool {
input, canceled := messenger.Prompt("> ")
input, canceled := messenger.Prompt("> ", "Command")
if !canceled {
HandleCommand(input)
}

View File

@@ -57,6 +57,11 @@ type Messenger struct {
// We have to keep track of the cursor for prompting
cursorx int
// This map stores the history for all the different kinds of uses Prompt has
// It's a map of history type -> history array
history map[string][]string
historyNum int
// Is the current message a message from the gutter
gutterMessage bool
}
@@ -117,9 +122,15 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
// Prompt sends the user a message and waits for a response to be typed in
// This function blocks the main loop while waiting for input
func (m *Messenger) Prompt(prompt string) (string, bool) {
func (m *Messenger) Prompt(prompt, historyType string) (string, bool) {
m.hasPrompt = true
m.Message(prompt)
if _, ok := m.history[historyType]; !ok {
m.history[historyType] = []string{""}
} else {
m.history[historyType] = append(m.history[historyType], "")
}
m.historyNum = len(m.history[historyType]) - 1
response, canceled := "", true
@@ -139,10 +150,11 @@ func (m *Messenger) Prompt(prompt string) (string, bool) {
// User is done entering their response
m.hasPrompt = false
response, canceled = m.response, false
m.history[historyType][len(m.history[historyType])-1] = response
}
}
m.HandleEvent(event)
m.HandleEvent(event, m.history[historyType])
if m.cursorx < 0 {
// Cancel
@@ -155,10 +167,22 @@ func (m *Messenger) Prompt(prompt string) (string, bool) {
}
// HandleEvent handles an event for the prompter
func (m *Messenger) HandleEvent(event tcell.Event) {
func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
switch e := event.(type) {
case *tcell.EventKey:
switch e.Key() {
case tcell.KeyUp:
if m.historyNum > 0 {
m.historyNum--
m.response = history[m.historyNum]
m.cursorx = len(m.response)
}
case tcell.KeyDown:
if m.historyNum < len(history)-1 {
m.historyNum++
m.response = history[m.historyNum]
m.cursorx = len(m.response)
}
case tcell.KeyLeft:
if m.cursorx > 0 {
m.cursorx--
@@ -176,6 +200,7 @@ func (m *Messenger) HandleEvent(event tcell.Event) {
m.response = Insert(m.response, m.cursorx, string(e.Rune()))
m.cursorx++
}
history[m.historyNum] = m.response
}
}

View File

@@ -227,6 +227,7 @@ func main() {
}()
messenger = new(Messenger)
messenger.history = make(map[string][]string)
views = make([]*View, 1)
views[0] = NewView(buf)

View File

@@ -15,10 +15,15 @@ var (
// Is there currently a search in progress
searching bool
// Stores the history for searching
searchHistory []string
)
// BeginSearch starts a search
func BeginSearch() {
searchHistory = append(searchHistory, "")
messenger.historyNum = len(searchHistory) - 1
searching = true
messenger.hasPrompt = true
messenger.Message("Find: ")
@@ -26,6 +31,7 @@ func BeginSearch() {
// EndSearch stops the current search
func EndSearch() {
searchHistory[len(searchHistory)-1] = messenger.response
searching = false
messenger.hasPrompt = false
messenger.Clear()
@@ -48,7 +54,7 @@ func HandleSearchEvent(event tcell.Event, v *View) {
}
}
messenger.HandleEvent(event)
messenger.HandleEvent(event, searchHistory)
if messenger.cursorx < 0 {
// Done

View File

@@ -148,7 +148,7 @@ func (v *View) ScrollDown(n int) {
// The message is what to print after saying "You have unsaved changes. "
func (v *View) CanClose(msg string) bool {
if v.Buf.IsModified {
quit, canceled := messenger.Prompt("You have unsaved changes. " + msg)
quit, canceled := messenger.Prompt("You have unsaved changes. "+msg, "Unsaved")
if !canceled {
if strings.ToLower(quit) == "yes" || strings.ToLower(quit) == "y" {
return true