func getConfigMenuItems(ss map[string]*servers.ServerSetting) map[string]*MenuItem {
	items := defaultItems()
	items["info"] = &MenuItem{
		Help:      "Show all settings",
		Example:   "info",
		Completer: readline.NewPrefixCompleter(),
	}
	items["set"] = &MenuItem{
		Help:      "Choose settings",
		Example:   "set Listen 0.0.0.0",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(getSettings(ss))),
	}
	items["unset"] = &MenuItem{
		Help:      "Remote settings",
		Example:   "unset Listen",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(getSettings(ss))),
	}
	items["start"] = &MenuItem{
		Help:      "Start the server",
		Example:   "start",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(getSettings(ss))),
	}
	items["restart"] = &MenuItem{
		Help:      "Restart the server",
		Example:   "restart",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(getSettings(ss))),
	}
	items["stop"] = &MenuItem{
		Help:      "Stop the server",
		Example:   "stop",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(getSettings(ss))),
	}
	return items
}
These menu items will consist between both http and dns config menus
package cmd
import (
	"fmt"
	"io/ioutil"
	"sort"
	"strings"
	"github.com/chzyer/readline"
	"github.com/leoloobeek/keyserver/servers"
)
type MenuItems struct {
	MenuType  string
	Items     map[string]*MenuItem
	Completer *readline.PrefixCompleter
}
type MenuItem struct {
	Help      string
	Example   string
	Error     string
	Completer *readline.PrefixCompleter
}
func filterInput(r rune) (rune, bool) {
	switch r {
	case readline.CharCtrlZ:
		return r, false
	}
	return r, true
}
func InitializeCompleters() map[string]*readline.Instance {
	mmInst, err := readline.NewEx(&readline.Config{
		Prompt:          "keyserver > ",
		AutoComplete:    nil,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
		HistorySearchFold:   true,
		FuncFilterInputRune: filterInput,
	})
	hmInst, err := readline.NewEx(&readline.Config{
		Prompt:          "keyserver (http) > ",
		AutoComplete:    nil,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
		HistorySearchFold:   true,
		FuncFilterInputRune: filterInput,
	})
	dmInst, err := readline.NewEx(&readline.Config{
		Prompt:          "keyserver (dns) > ",
		AutoComplete:    nil,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
		HistorySearchFold:   true,
		FuncFilterInputRune: filterInput,
	})
	hkmInst, err := readline.NewEx(&readline.Config{
		Prompt:          "keyserver (httpkey) > ",
		AutoComplete:    nil,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
		HistorySearchFold:   true,
		FuncFilterInputRune: filterInput,
	})
	dkmInst, err := readline.NewEx(&readline.Config{
		Prompt:          "keyserver (dnskey) > ",
		AutoComplete:    nil,
		InterruptPrompt: "^C",
		EOFPrompt:       "exit",
		HistorySearchFold:   true,
		FuncFilterInputRune: filterInput,
	})
	if err != nil {
		panic(err)
	}
	return map[string]*readline.Instance{
		"Main":    mmInst,
		"Http":    hmInst,
		"Dns":     dmInst,
		"HttpKey": hkmInst,
		"DnsKey":  dkmInst,
	}
}
func (c *CmdInfo) getMainMenuItems() *MenuItems {
	items := defaultItems()
	items["config"] = &MenuItem{
		Help:    "Configure a server (http or dns)",
		Example: "config http",
		Completer: readline.NewPrefixCompleter(
			readline.PcItem("http"),
			readline.PcItem("dns"),
		),
	}
	items["start"] = &MenuItem{
		Help:    "Start a server (http or dns)",
		Example: "start http",
		Completer: readline.NewPrefixCompleter(
			readline.PcItem("http"),
			readline.PcItem("dns"),
		),
	}
	items["stop"] = &MenuItem{
		Help:    "Stop a server (http or dns)",
		Example: "stop http",
		Completer: readline.NewPrefixCompleter(
			readline.PcItem("http"),
			readline.PcItem("dns"),
		),
	}
	items["restart"] = &MenuItem{
		Help:    "Restart a server (http or dns)",
		Example: "restart http",
		Completer: readline.NewPrefixCompleter(
			readline.PcItem("http"),
			readline.PcItem("dns"),
		),
	}
	items["new"] = &MenuItem{
		Help:    "Create a new dnskey or httpkey",
		Example: "new httpkey",
		Completer: readline.NewPrefixCompleter(
			readline.PcItem("httpkey"),
			readline.PcItem("dnskey"),
		),
	}
	items["status"] = &MenuItem{
		Help:      "Show status of servers and keys",
		Example:   "status",
		Completer: readline.NewPrefixCompleter(),
	}
	items["info"] = &MenuItem{
		Help:      "Show detailed information for a specific key",
		Example:   "info <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["on"] = &MenuItem{
		Help:      "Manually turn on a specific key",
		Example:   "on <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["off"] = &MenuItem{
		Help:      "Manually turn off a specific key",
		Example:   "off <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["disable"] = &MenuItem{
		Help:      "Disable a key and never respond with active key, even if a constraint matches",
		Example:   "off <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["alert"] = &MenuItem{
		Help:      "Enable alerting for a key",
		Example:   "alert <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["noalert"] = &MenuItem{
		Help:      "Disable alerting for a key",
		Example:   "noalert <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["remove"] = &MenuItem{
		Help:      "Remove a key",
		Example:   "remove <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["clearhits"] = &MenuItem{
		Help:      "Disable alerting for a key",
		Example:   "noalert <keyname>",
		Completer: readline.NewPrefixCompleter(readline.PcItemDynamic(c.getAllKeys())),
	}
	items["time"] = &MenuItem{
		Help:      "Display current time on keyserver (useful when setting time constraints)",
		Example:   "time",
		Completer: readline.NewPrefixCompleter(),
	}
	completer := []readline.PrefixCompleterInterface{}
	for name, mi := range items {
		item := readline.PcItem(name)
		item.Children = mi.Completer.Children
		completer = append(completer, item)
	}
	return &MenuItems{
		MenuType:  "Main",
		Items:     items,
		Completer: readline.NewPrefixCompleter(completer...),
	}
}
func getHttpMenuItems(h *servers.HttpServer) *MenuItems {
	items := getConfigMenuItems(h.State)
	items["help"].Completer = readline.NewPrefixCompleter(readline.PcItemDynamic(getSettings(h.State)))
	completer := []readline.PrefixCompleterInterface{}
	for name, mi := range items {
		item := readline.PcItem(name)
		item.Children = mi.Completer.Children
		completer = append(completer, item)
	}
	return &MenuItems{
		MenuType:  "Http",
		Items:     items,
		Completer: readline.NewPrefixCompleter(completer...),
	}
}
func getDnsMenuItems(d *servers.DnsServer) *MenuItems {
	items := getConfigMenuItems(d.State)
	items["help"].Completer = readline.NewPrefixCompleter(readline.PcItemDynamic(getSettings(d.State)))
	completer := []readline.PrefixCompleterInterface{}
	for name, mi := range items {
		item := readline.PcItem(name)
		item.Children = mi.Completer.Children
		completer = append(completer, item)
	}
	return &MenuItems{
		MenuType:  "Dns",
		Items:     items,
		Completer: readline.NewPrefixCompleter(completer...),
	}
}