Something went wrong. Try again.
Fork of micro-editor/micro
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333package action
import ( "bytes" "sort" "strings"
"github.com/micro-editor/micro/v2/internal/buffer" "github.com/micro-editor/micro/v2/internal/config" "github.com/micro-editor/micro/v2/internal/util" "github.com/micro-editor/micro/v2/pkg/highlight")
// 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`.
// CommandComplete autocompletes commandsfunc CommandComplete(b *buffer.Buffer) ([]string, []string) { c := b.GetActiveCursor() input, argstart := b.GetArg()
var suggestions []string for cmd := range commands { if strings.HasPrefix(cmd, input) { suggestions = append(suggestions, cmd) } }
sort.Strings(suggestions) completions := make([]string, len(suggestions)) for i := range suggestions { completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart) }
return completions, suggestions}
// HelpComplete autocompletes help topicsfunc HelpComplete(b *buffer.Buffer) ([]string, []string) { c := b.GetActiveCursor() input, argstart := b.GetArg()
var suggestions []string
for _, file := range config.ListRuntimeFiles(config.RTHelp) { topic := file.Name() if strings.HasPrefix(topic, input) { suggestions = append(suggestions, topic) } }
sort.Strings(suggestions) completions := make([]string, len(suggestions)) for i := range suggestions { completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart) } return completions, suggestions}
// colorschemeComplete tab-completes names of colorschemes.// This is just a heper value for OptionValueCompletefunc 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}
// filetypeComplete autocompletes filetypefunc filetypeComplete(input string) (string, []string) { var suggestions []string
// We cannot match filetypes just by names of syntax files, // since those names may be different from the actual filetype values // specified inside syntax files (e.g. "c++" filetype in cpp.yaml). // So we need to parse filetype values out of those files. for _, f := range config.ListRealRuntimeFiles(config.RTSyntax) { data, err := f.Data() if err != nil { continue } header, err := highlight.MakeHeaderYaml(data) if err != nil { continue } // Prevent duplicated defaults if header.FileType == "off" || header.FileType == "unknown" { continue } if strings.HasPrefix(header.FileType, input) { suggestions = append(suggestions, header.FileType) } }headerLoop: for _, f := range config.ListRuntimeFiles(config.RTSyntaxHeader) { data, err := f.Data() if err != nil { continue } header, err := highlight.MakeHeader(data) if err != nil { continue } for _, v := range suggestions { if v == header.FileType { continue headerLoop } } if strings.HasPrefix(header.FileType, input) { suggestions = append(suggestions, header.FileType) } }
if strings.HasPrefix("off", input) { suggestions = append(suggestions, "off") }
var chosen string if len(suggestions) == 1 { chosen = suggestions[0] }
return chosen, suggestions}
// OptionComplete autocompletes optionsfunc OptionComplete(b *buffer.Buffer) ([]string, []string) { c := b.GetActiveCursor() input, argstart := b.GetArg()
var suggestions []string 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) // } // }
sort.Strings(suggestions) completions := make([]string, len(suggestions)) for i := range suggestions { completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart) } return completions, suggestions}
// OptionValueComplete completes values for various optionsfunc OptionValueComplete(b *buffer.Buffer) ([]string, []string) { c := b.GetActiveCursor() l := b.LineBytes(c.Y) l = util.SliceStart(l, c.X) input, argstart := b.GetArg()
completeValue := false args := bytes.Split(l, []byte{' '}) if len(args) >= 2 { // localSettings := config.DefaultLocalSettings() for option := range config.GlobalSettings { if option == string(args[len(args)-2]) { completeValue = true break } } // for option := range localSettings { // if option == string(args[len(args)-2]) { // completeValue = true // break // } // } } if !completeValue { return OptionComplete(b) }
inputOpt := string(args[len(args)-2])
inputOpt = strings.TrimSpace(inputOpt) var suggestions []string // localSettings := config.DefaultLocalSettings() var optionVal any 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 "filetype": _, suggestions = filetypeComplete(input) case "sucmd": if strings.HasPrefix("sudo", input) { suggestions = append(suggestions, "sudo") } if strings.HasPrefix("doas", input) { suggestions = append(suggestions, "doas") } default: if choices, ok := config.OptionChoices[inputOpt]; ok { for _, choice := range choices { if strings.HasPrefix(choice, input) { suggestions = append(suggestions, choice) } } } } } sort.Strings(suggestions)
completions := make([]string, len(suggestions)) for i := range suggestions { completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart) } return completions, suggestions}
// PluginCmdComplete autocompletes the plugin commandfunc PluginCmdComplete(b *buffer.Buffer) ([]string, []string) { c := b.GetActiveCursor() input, argstart := b.GetArg()
var suggestions []string for _, cmd := range PluginCmds { if strings.HasPrefix(cmd, input) { suggestions = append(suggestions, cmd) } }
sort.Strings(suggestions) completions := make([]string, len(suggestions)) for i := range suggestions { completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart) } return completions, suggestions}
// PluginComplete completes values for the plugin commandfunc PluginComplete(b *buffer.Buffer) ([]string, []string) { c := b.GetActiveCursor() l := b.LineBytes(c.Y) l = util.SliceStart(l, c.X) input, argstart := b.GetArg()
completeValue := false args := bytes.Split(l, []byte{' '}) if len(args) >= 2 { for _, cmd := range PluginCmds { if cmd == string(args[len(args)-2]) { completeValue = true break } } } if !completeValue { return PluginCmdComplete(b) }
var suggestions []string for _, pl := range config.Plugins { if strings.HasPrefix(pl.Name, input) { suggestions = append(suggestions, pl.Name) } } sort.Strings(suggestions)
completions := make([]string, len(suggestions)) for i := range suggestions { completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart) } return completions, suggestions}
// PluginNameComplete completes with the names of loaded plugins// func PluginNameComplete(b *buffer.Buffer) ([]string, []string) {// c := b.GetActiveCursor()// input, argstart := buffer.GetArg(b)//// var suggestions []string// for _, pp := range config.GetAllPluginPackages(nil) {// if strings.HasPrefix(pp.Name, input) {// suggestions = append(suggestions, pp.Name)// }// }//// sort.Strings(suggestions)// completions := make([]string, len(suggestions))// for i := range suggestions {// completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart)// }// return completions, 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))// }