Add file completion to OpenFile (CtrlO) with tab

This commit is contained in:
Zachary Yedidia 2016-06-09 10:03:50 -04:00
parent 1f89b41070
commit e2079ac88e
3 changed files with 46 additions and 9 deletions

View file

@ -731,7 +731,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: ", "Save")
filename, canceled := messenger.Prompt("Filename: ", "Save", NoCompletion)
if !canceled {
v.Buf.Path = filename
v.Buf.Name = filename
@ -906,7 +906,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: ", "Open")
filename, canceled := messenger.Prompt("File to open: ", "Open", FileCompletion)
if canceled {
return false
}
@ -1018,7 +1018,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 # ", "LineNumber")
linestring, canceled := messenger.Prompt("Jump to line # ", "LineNumber", NoCompletion)
if canceled {
return false
}
@ -1061,7 +1061,7 @@ func (v *View) ToggleHelp() bool {
// ShellMode opens a terminal to run a shell command
func (v *View) ShellMode() bool {
input, canceled := messenger.Prompt("$ ", "Shell")
input, canceled := messenger.Prompt("$ ", "Shell", NoCompletion)
if !canceled {
// The true here is for openTerm to make the command interactive
HandleShellCommand(input, true)
@ -1071,7 +1071,7 @@ func (v *View) ShellMode() bool {
// CommandMode lets the user enter a command
func (v *View) CommandMode() bool {
input, canceled := messenger.Prompt("> ", "Command")
input, canceled := messenger.Prompt("> ", "Command", NoCompletion)
if !canceled {
HandleCommand(input)
}

View file

@ -4,8 +4,10 @@ import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"github.com/zyedidia/tcell"
)
@ -122,9 +124,16 @@ func (m *Messenger) YesNoPrompt(prompt string) (bool, bool) {
}
}
type Completion int
const (
NoCompletion Completion = iota
FileCompletion
)
// 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, historyType string) (string, bool) {
func (m *Messenger) Prompt(prompt, historyType string, completionType Completion) (string, bool) {
m.hasPrompt = true
m.Message(prompt)
if _, ok := m.history[historyType]; !ok {
@ -153,6 +162,34 @@ func (m *Messenger) Prompt(prompt, historyType string) (string, bool) {
m.hasPrompt = false
response, canceled = m.response, false
m.history[historyType][len(m.history[historyType])-1] = response
case tcell.KeyTab:
if completionType == FileCompletion {
dirs := strings.Split(m.response, "/")
var files []os.FileInfo
var err error
if len(dirs) > 1 {
files, err = ioutil.ReadDir(strings.Join(dirs[:len(dirs)-1], "/"))
} else {
files, err = ioutil.ReadDir(".")
}
if err != nil {
continue
}
var suggestions []string
for _, f := range files {
name := f.Name()
if f.IsDir() {
name += "/"
}
if strings.HasPrefix(name, dirs[len(dirs)-1]) {
suggestions = append(suggestions, name)
}
}
if len(suggestions) == 1 {
m.response = strings.Join(dirs[:len(dirs)-1], "/") + "/" + suggestions[0]
m.cursorx = Count(m.response)
}
}
}
}
@ -177,13 +214,13 @@ func (m *Messenger) HandleEvent(event tcell.Event, history []string) {
if m.historyNum > 0 {
m.historyNum--
m.response = history[m.historyNum]
m.cursorx = len(m.response)
m.cursorx = Count(m.response)
}
case tcell.KeyDown:
if m.historyNum < len(history)-1 {
m.historyNum++
m.response = history[m.historyNum]
m.cursorx = len(m.response)
m.cursorx = Count(m.response)
}
case tcell.KeyLeft:
if m.cursorx > 0 {

View file

@ -165,7 +165,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, "Unsaved")
quit, canceled := messenger.Prompt("You have unsaved changes. "+msg, "Unsaved", NoCompletion)
if !canceled {
if strings.ToLower(quit) == "yes" || strings.ToLower(quit) == "y" {
return true