Hilbish/readline/completers/hint-completer.go

181 lines
5.8 KiB
Go

package completers
import (
"strings"
"github.com/jessevdk/go-flags"
"github.com/maxlandon/readline"
)
// HintCompleter - Entrypoint to all hints in the Wiregost console
func (c *CommandCompleter) HintCompleter(line []rune, pos int) (hint []rune) {
// Format and sanitize input
// @args => All items of the input line
// @last => The last word detected in input line as []rune
// @lastWord => The last word detected in input as string
args, last, lastWord := formatInput(line)
// Detect base command automatically
var command = c.detectedCommand(args)
// Menu hints (command line is empty, or nothing recognized)
if noCommandOrEmpty(args, last, command) {
hint = MenuHint(args, last)
}
// Check environment variables
if envVarAsked(args, lastWord) {
return envVarHint(args, last)
}
// Command Hint
if commandFound(command) {
// Command hint by default (no space between cursor and last command character)
hint = CommandHint(command)
// Check environment variables
if envVarAsked(args, lastWord) {
return envVarHint(args, last)
}
// If options are asked for root command, return commpletions.
if len(command.Groups()) > 0 {
for _, grp := range command.Groups() {
if opt, yes := optionArgRequired(args, last, grp); yes {
hint = OptionArgumentHint(args, last, opt)
}
}
}
// If command has args, hint for args
if arg, yes := commandArgumentRequired(lastWord, args, command); yes {
hint = []rune(CommandArgumentHints(args, last, command, arg))
}
// Brief subcommand hint
if lastIsSubCommand(lastWord, command) {
hint = []rune(commandHint + command.Find(string(last)).ShortDescription)
}
// Handle subcommand if found
if sub, ok := subCommandFound(lastWord, args, command); ok {
return HandleSubcommandHints(args, last, sub)
}
}
// Handle system binaries, shell commands, etc...
if commandFoundInPath(args[0]) {
// hint = []rune(exeHint + util.ParseSummary(util.GetManPages(args[0])))
}
return
}
// CommandHint - Yields the hint of a Wiregost command
func CommandHint(command *flags.Command) (hint []rune) {
return []rune(commandHint + command.ShortDescription)
}
// HandleSubcommandHints - Handles hints for a subcommand and its arguments, options, etc.
func HandleSubcommandHints(args []string, last []rune, command *flags.Command) (hint []rune) {
// If command has args, hint for args
if arg, yes := commandArgumentRequired(string(last), args, command); yes {
hint = []rune(CommandArgumentHints(args, last, command, arg))
return
}
// Environment variables
if envVarAsked(args, string(last)) {
hint = envVarHint(args, last)
}
// If the last word in input is an option --name, yield argument hint if needed
if len(command.Groups()) > 0 {
for _, grp := range command.Groups() {
if opt, yes := optionArgRequired(args, last, grp); yes {
hint = OptionArgumentHint(args, last, opt)
}
}
}
// If user asks for completions with "-" or "--".
// (Note: This takes precedence on any argument hints, as it is evaluated after them)
if commandOptionsAsked(args, string(last), command) {
return OptionHints(args, last, command)
}
return
}
// CommandArgumentHints - Yields hints for arguments to commands if they have some
func CommandArgumentHints(args []string, last []rune, command *flags.Command, arg string) (hint []rune) {
found := argumentByName(command, arg)
// Base Hint is just a description of the command argument
hint = []rune(argHint + found.Description)
return
}
// ModuleOptionHints - If the option being set has a description, show it
func ModuleOptionHints(opt string) (hint []rune) {
return
}
// OptionHints - Yields hints for proposed options lists/groups
func OptionHints(args []string, last []rune, command *flags.Command) (hint []rune) {
return
}
// OptionArgumentHint - Yields hints for arguments to an option (generally the last word in input)
func OptionArgumentHint(args []string, last []rune, opt *flags.Option) (hint []rune) {
return []rune(valueHint + opt.Description)
}
// MenuHint - Returns the Hint for a given menu context
func MenuHint(args []string, current []rune) (hint []rune) {
return
}
// SpecialCommandHint - Shows hints for Wiregost special commands
func SpecialCommandHint(args []string, current []rune) (hint []rune) {
return current
}
// envVarHint - Yields hints for environment variables
func envVarHint(args []string, last []rune) (hint []rune) {
// Trim last in case its a path with multiple vars
allVars := strings.Split(string(last), "/")
lastVar := allVars[len(allVars)-1]
// Base hint
hint = []rune(envHint + lastVar)
envVar := strings.TrimPrefix(lastVar, "$")
if v, ok := clientEnv[envVar]; ok {
if v != "" {
hintStr := string(hint) + " => " + clientEnv[envVar]
hint = []rune(hintStr)
}
}
return
}
var (
// Hint signs
menuHint = readline.RESET + readline.DIM + readline.BOLD + " menu " + readline.RESET // Dim
envHint = readline.RESET + readline.GREEN + readline.BOLD + " env " + readline.RESET + readline.DIM + readline.GREEN // Green
commandHint = readline.RESET + readline.DIM + readline.BOLD + " command " + readline.RESET + readline.DIM + "\033[38;5;244m" // Cream
exeHint = readline.RESET + readline.DIM + readline.BOLD + " shell " + readline.RESET + readline.DIM // Dim
optionHint = "\033[38;5;222m" + readline.BOLD + " options " + readline.RESET + readline.DIM + "\033[38;5;222m" // Cream-Yellow
valueHint = readline.RESET + readline.DIM + readline.BOLD + " value " + readline.RESET + readline.DIM + "\033[38;5;244m" // Pink-Cream
// valueHint = "\033[38;5;217m" + readline.BOLD + " Value " + readline.RESET + readline.DIM + "\033[38;5;244m" // Pink-Cream
argHint = readline.DIM + "\033[38;5;217m" + readline.BOLD + " arg " + readline.RESET + readline.DIM + "\033[38;5;244m" // Pink-Cream
)