mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-30 06:37:14 +09:00
Infobar history
This commit is contained in:
@@ -1,266 +0,0 @@
|
||||
package info
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/zyedidia/micro/cmd/micro/config"
|
||||
"github.com/zyedidia/micro/cmd/micro/util"
|
||||
)
|
||||
|
||||
// Completion represents a type of completion
|
||||
type Completion int
|
||||
|
||||
const (
|
||||
NoCompletion Completion = iota
|
||||
FileCompletion
|
||||
CommandCompletion
|
||||
HelpCompletion
|
||||
OptionCompletion
|
||||
PluginCmdCompletion
|
||||
PluginNameCompletion
|
||||
OptionValueCompletion
|
||||
)
|
||||
|
||||
var pluginCompletions []func(string) []string
|
||||
|
||||
// This file is meant (for now) for autocompletion in command mode, not
|
||||
// while coding. This helps micro autocomplete commands and then filenames
|
||||
// for example with `vsplit filename`.
|
||||
|
||||
// FileComplete autocompletes filenames
|
||||
func FileComplete(input string) (string, []string) {
|
||||
var sep string = string(os.PathSeparator)
|
||||
dirs := strings.Split(input, sep)
|
||||
|
||||
var files []os.FileInfo
|
||||
var err error
|
||||
if len(dirs) > 1 {
|
||||
directories := strings.Join(dirs[:len(dirs)-1], sep) + sep
|
||||
|
||||
directories, _ = util.ReplaceHome(directories)
|
||||
files, err = ioutil.ReadDir(directories)
|
||||
} else {
|
||||
files, err = ioutil.ReadDir(".")
|
||||
}
|
||||
|
||||
var suggestions []string
|
||||
if err != nil {
|
||||
return "", suggestions
|
||||
}
|
||||
for _, f := range files {
|
||||
name := f.Name()
|
||||
if f.IsDir() {
|
||||
name += sep
|
||||
}
|
||||
if strings.HasPrefix(name, dirs[len(dirs)-1]) {
|
||||
suggestions = append(suggestions, name)
|
||||
}
|
||||
}
|
||||
|
||||
var chosen string
|
||||
if len(suggestions) == 1 {
|
||||
if len(dirs) > 1 {
|
||||
chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep + suggestions[0]
|
||||
} else {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
} else {
|
||||
if len(dirs) > 1 {
|
||||
chosen = strings.Join(dirs[:len(dirs)-1], sep) + sep
|
||||
}
|
||||
}
|
||||
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
// CommandComplete autocompletes commands
|
||||
// func CommandComplete(input string) (string, []string) {
|
||||
// var suggestions []string
|
||||
// for cmd := range commands {
|
||||
// if strings.HasPrefix(cmd, input) {
|
||||
// suggestions = append(suggestions, cmd)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var chosen string
|
||||
// if len(suggestions) == 1 {
|
||||
// chosen = suggestions[0]
|
||||
// }
|
||||
// return chosen, suggestions
|
||||
// }
|
||||
|
||||
// HelpComplete autocompletes help topics
|
||||
func HelpComplete(input string) (string, []string) {
|
||||
var suggestions []string
|
||||
|
||||
for _, file := range config.ListRuntimeFiles(config.RTHelp) {
|
||||
topic := file.Name()
|
||||
if strings.HasPrefix(topic, input) {
|
||||
suggestions = append(suggestions, topic)
|
||||
}
|
||||
}
|
||||
|
||||
var chosen string
|
||||
if len(suggestions) == 1 {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
// ColorschemeComplete tab-completes names of colorschemes.
|
||||
func ColorschemeComplete(input string) (string, []string) {
|
||||
var suggestions []string
|
||||
files := config.ListRuntimeFiles(config.RTColorscheme)
|
||||
|
||||
for _, f := range files {
|
||||
if strings.HasPrefix(f.Name(), input) {
|
||||
suggestions = append(suggestions, f.Name())
|
||||
}
|
||||
}
|
||||
|
||||
var chosen string
|
||||
if len(suggestions) == 1 {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
func contains(s []string, e string) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// OptionComplete autocompletes options
|
||||
func OptionComplete(input string) (string, []string) {
|
||||
var suggestions []string
|
||||
localSettings := config.DefaultLocalSettings()
|
||||
for option := range config.GlobalSettings {
|
||||
if strings.HasPrefix(option, input) {
|
||||
suggestions = append(suggestions, option)
|
||||
}
|
||||
}
|
||||
for option := range localSettings {
|
||||
if strings.HasPrefix(option, input) && !contains(suggestions, option) {
|
||||
suggestions = append(suggestions, option)
|
||||
}
|
||||
}
|
||||
|
||||
var chosen string
|
||||
if len(suggestions) == 1 {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
// OptionValueComplete completes values for various options
|
||||
func OptionValueComplete(inputOpt, input string) (string, []string) {
|
||||
inputOpt = strings.TrimSpace(inputOpt)
|
||||
var suggestions []string
|
||||
localSettings := config.DefaultLocalSettings()
|
||||
var optionVal interface{}
|
||||
for k, option := range config.GlobalSettings {
|
||||
if k == inputOpt {
|
||||
optionVal = option
|
||||
}
|
||||
}
|
||||
for k, option := range localSettings {
|
||||
if k == inputOpt {
|
||||
optionVal = option
|
||||
}
|
||||
}
|
||||
|
||||
switch optionVal.(type) {
|
||||
case bool:
|
||||
if strings.HasPrefix("on", input) {
|
||||
suggestions = append(suggestions, "on")
|
||||
} else if strings.HasPrefix("true", input) {
|
||||
suggestions = append(suggestions, "true")
|
||||
}
|
||||
if strings.HasPrefix("off", input) {
|
||||
suggestions = append(suggestions, "off")
|
||||
} else if strings.HasPrefix("false", input) {
|
||||
suggestions = append(suggestions, "false")
|
||||
}
|
||||
case string:
|
||||
switch inputOpt {
|
||||
case "colorscheme":
|
||||
_, suggestions = ColorschemeComplete(input)
|
||||
case "fileformat":
|
||||
if strings.HasPrefix("unix", input) {
|
||||
suggestions = append(suggestions, "unix")
|
||||
}
|
||||
if strings.HasPrefix("dos", input) {
|
||||
suggestions = append(suggestions, "dos")
|
||||
}
|
||||
case "sucmd":
|
||||
if strings.HasPrefix("sudo", input) {
|
||||
suggestions = append(suggestions, "sudo")
|
||||
}
|
||||
if strings.HasPrefix("doas", input) {
|
||||
suggestions = append(suggestions, "doas")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var chosen string
|
||||
if len(suggestions) == 1 {
|
||||
chosen = suggestions[0]
|
||||
}
|
||||
return chosen, suggestions
|
||||
}
|
||||
|
||||
// // MakeCompletion registers a function from a plugin for autocomplete commands
|
||||
// func MakeCompletion(function string) Completion {
|
||||
// pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))
|
||||
// return Completion(-len(pluginCompletions))
|
||||
// }
|
||||
//
|
||||
// // PluginComplete autocompletes from plugin function
|
||||
// func PluginComplete(complete Completion, input string) (chosen string, suggestions []string) {
|
||||
// idx := int(-complete) - 1
|
||||
//
|
||||
// if len(pluginCompletions) <= idx {
|
||||
// return "", nil
|
||||
// }
|
||||
// suggestions = pluginCompletions[idx](input)
|
||||
//
|
||||
// if len(suggestions) == 1 {
|
||||
// chosen = suggestions[0]
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // PluginCmdComplete completes with possible choices for the `> plugin` command
|
||||
// func PluginCmdComplete(input string) (chosen string, suggestions []string) {
|
||||
// for _, cmd := range []string{"install", "remove", "search", "update", "list"} {
|
||||
// if strings.HasPrefix(cmd, input) {
|
||||
// suggestions = append(suggestions, cmd)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if len(suggestions) == 1 {
|
||||
// chosen = suggestions[0]
|
||||
// }
|
||||
// return chosen, suggestions
|
||||
// }
|
||||
//
|
||||
// // PluginnameComplete completes with the names of loaded plugins
|
||||
// func PluginNameComplete(input string) (chosen string, suggestions []string) {
|
||||
// for _, pp := range GetAllPluginPackages() {
|
||||
// if strings.HasPrefix(pp.Name, input) {
|
||||
// suggestions = append(suggestions, pp.Name)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if len(suggestions) == 1 {
|
||||
// chosen = suggestions[0]
|
||||
// }
|
||||
// return chosen, suggestions
|
||||
// }
|
||||
@@ -59,3 +59,21 @@ func (i *InfoBuf) SaveHistory() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpHistory fetches the previous item in the history
|
||||
func (i *InfoBuf) UpHistory(history []string) {
|
||||
if i.HistoryNum > 0 {
|
||||
i.HistoryNum--
|
||||
i.Replace(i.Start(), i.End(), history[i.HistoryNum])
|
||||
i.Buffer.GetActiveCursor().GotoLoc(i.End())
|
||||
}
|
||||
}
|
||||
|
||||
// DownHistory fetches the next item in the history
|
||||
func (i *InfoBuf) DownHistory(history []string) {
|
||||
if i.HistoryNum < len(history)-1 {
|
||||
i.HistoryNum++
|
||||
i.Replace(i.Start(), i.End(), history[i.HistoryNum])
|
||||
i.Buffer.GetActiveCursor().GotoLoc(i.End())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ type InfoBuf struct {
|
||||
HasMessage bool
|
||||
HasError bool
|
||||
|
||||
PromptType string
|
||||
|
||||
Msg string
|
||||
|
||||
// This map stores the history for all the different kinds of uses Prompt has
|
||||
@@ -36,10 +38,16 @@ func NewBuffer() *InfoBuf {
|
||||
ib.History = make(map[string][]string)
|
||||
|
||||
ib.Buffer = buffer.NewBufferFromString("", "infobar", buffer.BTInfo)
|
||||
ib.LoadHistory()
|
||||
|
||||
return ib
|
||||
}
|
||||
|
||||
// Close performs any cleanup necessary when shutting down the infobuffer
|
||||
func (i *InfoBuf) Close() {
|
||||
i.SaveHistory()
|
||||
}
|
||||
|
||||
// Message sends a message to the user
|
||||
func (i *InfoBuf) Message(msg ...interface{}) {
|
||||
// only display a new message if there isn't an active prompt
|
||||
@@ -68,12 +76,20 @@ func (i *InfoBuf) Error(msg ...interface{}) {
|
||||
// and callbacks executed when the user executes an event and when the user finishes the prompt
|
||||
// The eventcb passes the current user response as the argument and donecb passes the user's message
|
||||
// and a boolean indicating if the prompt was canceled
|
||||
func (i *InfoBuf) Prompt(prompt string, msg string, eventcb func(string), donecb func(string, bool)) {
|
||||
func (i *InfoBuf) Prompt(prompt string, msg string, ptype string, eventcb func(string), donecb func(string, bool)) {
|
||||
// If we get another prompt mid-prompt we cancel the one getting overwritten
|
||||
if i.HasPrompt {
|
||||
i.DonePrompt(true)
|
||||
}
|
||||
|
||||
if _, ok := i.History[ptype]; !ok {
|
||||
i.History[ptype] = []string{""}
|
||||
} else {
|
||||
i.History[ptype] = append(i.History[ptype], "")
|
||||
}
|
||||
i.HistoryNum = len(i.History[ptype]) - 1
|
||||
|
||||
i.PromptType = ptype
|
||||
i.Msg = prompt
|
||||
i.HasPrompt = true
|
||||
i.HasMessage, i.HasError = false, false
|
||||
@@ -88,8 +104,13 @@ func (i *InfoBuf) DonePrompt(canceled bool) {
|
||||
if i.PromptCallback != nil {
|
||||
if canceled {
|
||||
i.PromptCallback("", true)
|
||||
h := i.History[i.PromptType]
|
||||
i.History[i.PromptType] = h[:len(h)-1]
|
||||
} else {
|
||||
i.PromptCallback(strings.TrimSpace(string(i.LineBytes(0))), false)
|
||||
resp := strings.TrimSpace(string(i.LineBytes(0)))
|
||||
i.PromptCallback(resp, false)
|
||||
h := i.History[i.PromptType]
|
||||
h[len(h)-1] = resp
|
||||
}
|
||||
}
|
||||
i.PromptCallback = nil
|
||||
|
||||
Reference in New Issue
Block a user