### Install Reeflective Console Example CLI Source: https://github.com/reeflective/console/blob/main/example/README.md This command installs the example console application for the Reeflective library. It assumes a working Go toolchain is already set up on your system. ```Bash go install github.com/reeflective/console/example ``` -------------------------------- ### Command to Switch Menus in Go Source: https://github.com/reeflective/console/wiki/Menus An example of a command (`connectHost`) that switches to a different menu ('client') after successfully executing its primary logic (simulated SSH connection). It also demonstrates accessing the current menu before the switch. ```go // connectHost - A command that might be used to connect to a remote host, via SSH or something. type connectHost struct { Args struct { URL string `description:"SSH URL of the host we want to connect to" required:"yes"` } `positional-args:"yes" required:"yes"` } func (ch *connectHost) Execute(args []string) (err error) { // At the beginning, we are in our main context (the default one) // where we have a bunch of server commands. current := console.CurrentMenu() // Name: "" // Here we connect over to our host with our application code, etc. // Maybe this might give you state to use later for prompts, etc. err = mysshlib.Connect(ch.Args.URL) if err != nil { // In case of failure we don't switch menus. fmt.Println(err) return } // Now we switch menus. At the next readline loop, the prompt, command set, etc. // will be those of the new menu: you don't have to deal with any of this. console.SwitchMenu("client") return } ``` -------------------------------- ### Create New Menu in Go Source: https://github.com/reeflective/console/wiki/Menus Demonstrates how to create a new menu within the console application. New menus can be named and later used to group specific commands, prompts, and history sources. This example shows creating a 'client' menu. ```go func createMenu(c *console.Console) { clientMenu := c.NewMenu("client") // ... here we will setup the menu stuff. } ``` ```go func main() { app := console.New() createMenu(app) } ``` -------------------------------- ### Go: Bind reeflective/flags Commands to Console Source: https://github.com/reeflective/console/wiki/Binding-Commands Provides a Go snippet for binding commands generated by reeflective/flags to the console. This setup automatically handles completions and resets, making the application ready to run. ```Go func flagsCommands() *cobra.Command { // Our root command structure encapsulates // the entire command tree for our application. rootData := &commands.Root{} // Options can be used for several purposes: // influence the flags naming conventions, register // other scan handlers for specialized work, etc... var opts []flags.OptFunc // One example of specialized handler is the validator, // which checks for struct tags specifying validations: // when found, this handler wraps the generated flag into // a special value which will validate the user input. opts = append(opts, flags.Validator(validator.New())) // Run the scan: this generates the entire command tree // into a cobra root command (and its subcommands). // By default, the name of the command is os.Args[0]. rootCmd := genflags.Generate(rootData, opts...) // Since we now dispose of a cobra command, we can further // set it up to our liking: modify/set fields and options, etc. // There is virtually no restriction to the modifications one // can do on them, except that their RunE() is already bound. rootCmd.SilenceUsage = true rootCmd.Short = shortUsage rootCmd.Long = shortUsage + "\n" + commands.LongUsage // We might also have longer help strings contained in our // various commands' packages, which we also bind now. commands.AddCommandsLongHelp(rootCmd) // The completion generator is another example of specialized // scan handler: it will generate completers if it finds tags // specifying what to complete, or completer implementations // by the positional arguments / command flags' types themselves. completions.Generate(rootCmd, rootData, nil) return rootCmd } ``` -------------------------------- ### Load Custom Prompt Configuration with Segment (Go) Source: https://github.com/reeflective/console/wiki/Prompts Provides a Go code example for creating a menu within the Reeflective Console and loading a custom oh-my-posh prompt configuration that utilizes a custom segment. This function demonstrates registering the segment and then loading a configuration file (e.g., 'prompt.omp.json') that references it. ```Go func createMenu(c *console.Console) { clientMenu := c.NewMenu("client") prompt := clientMenu.Prompt() // Add custom segments to the prompt library. // (again, can be used by all menu engines) engine.Segments[engine.SegmentType("module")] = func() engine.SegmentWriter { return module } // Load a configuration file on the system, // where we actually use our new prompt segment. prompt.LoadConfig("prompt.omp.json") } ``` -------------------------------- ### Simple Segment Example in Go Source: https://github.com/reeflective/console/wiki/Prompts Provides a minimal implementation of the SegmentWriter interface, aliasing a string and returning its value in the Template method. ```go type Module struct { Type string Path string } func (m Module) Enabled() bool { return string(m.Path) != "" } func (m Module) Template() string { return string(m.Path) } func (m Module) Init(props properties.Properties, env platform.Environment) { } var module = Module{"scan", "protocol/tcp"} ``` -------------------------------- ### Switch Menus in Go Source: https://github.com/reeflective/console/wiki/Menus Shows how to switch the active menu in the console. This allows for context switching, for example, moving from server-related commands to client-related commands. It includes switching to the 'client' menu and back to the default empty menu. ```go console.SwitchMenu("client") console.SwitchMenu("") ``` -------------------------------- ### Custom Client History Implementation (Go) Source: https://github.com/reeflective/console/wiki/History-Sources Provides a Go implementation of the `History` interface for a client-side history. It includes methods to write commands, retrieve lines, get the history length, and dump the history, interacting with a hypothetical gRPC transport. ```Go // ClientHistory - Writes and queries only the Client's history type ClientHistory struct { LinesSinceStart int // Keeps count of line since session items []string } // Write - Sends the last command to the server for saving func (h *ClientHistory) Write(s string) (int, error) { res, err := transport.RPC.AddToHistory(context.Background(), &clientpb.AddCmdHistoryRequest{Line: s}) if err != nil { return 0, err } // The server sent us back the whole user history, // so we give it to the user history (the latter never // actually uses its Write() method. UserHist.cache = res.Lines h.items = append(h.items, s) return len(h.items), nil } // GetLine returns a line from history func (h *ClientHistory) GetLine(i int) (string, error) { if len(h.items) == 0 { return "", nil } return h.items[i], nil } // Len returns the number of lines in history func (h *ClientHistory) Len() int { return len(h.items) } // Dump returns the entire history func (h *ClientHistory) Dump() interface{} { return h.items } ``` -------------------------------- ### Reeflective Console History Interface Definition (Go) Source: https://github.com/reeflective/console/wiki/History-Sources Defines the `History` interface for custom history sources in the Reeflective console. It includes methods for writing, getting lines, returning the length, and dumping history content. ```Go type History interface { // Append takes the line and returns an updated number of lines or an error Write(string) (int, error) // GetLine takes the historic line number and returns the line or an error GetLine(int) (string, error) // Len returns the number of history lines Len() int // Dump returns everything in readline. The return is an interface{} because // not all LineHistory implementations will want to structure the history in the same way. And since Dump() is not actually used by the readline API // internally, this methods return can be structured in whichever way is most convenient for your own applications (or even just create an empty function which returns `nil` if you don't require Dump() either) Dump() interface{} } ``` -------------------------------- ### Get Active Menu in Go Source: https://github.com/reeflective/console/wiki/Menus Retrieves the currently active menu in the console. This is useful for understanding the current context of commands and prompts. The default menu has an empty string name. ```go mainMenu := console.ActiveMenu() ``` -------------------------------- ### Reference Custom Segment in Oh My Posh Configuration (JSON) Source: https://github.com/reeflective/console/wiki/Prompts Shows how to reference a custom segment, identified by the type 'module', within an oh-my-posh prompt configuration file. The example snippet illustrates the structure for defining blocks and segments, including the template for displaying the custom segment's output. ```JSON "blocks": [ { "alignment": "left", "newline": true, "segments": [ { "style": "plain", "template": " using (<#df2e1c>{{ .Segment }}) ", "type": "module" } ... other segments ``` -------------------------------- ### Create New Console Application (Go) Source: https://github.com/reeflective/console/wiki/Getting-Started Instantiates a new console application with default settings, including a readline shell, a default menu, and an in-memory history source. Requires an application name for per-application configuration. ```Go package main import "fmt" func main() { // Instantiate a new app, with a single, default menu. // All defaults are set, and nothing is needed to make it work. // // The call requires an application name (which can be left empty), which will be used // by the underlying readline shell to load per-application options and command binds. // See below. app := console.New("ApplicationName") // ... We will include code in here as we go through the documentation... // And will run the console application. app.Start() } ``` -------------------------------- ### Define and Bind Cobra Commands to Menu Source: https://github.com/reeflective/console/wiki/Binding-Commands Demonstrates how to create a root Cobra command, configure its properties like help commands and pre/post runners, add subcommands (e.g., 'version'), and bind this command tree to a console menu. ```go func myMenuCommands() *cobra.Command { // Root ----------------------------------------------------------- root := &cobra.Command{} root.Long = `An introduction help string before the commands list` root.SetHelpCommand(&customHelpCommand) root.PreRunE = myMenuPreRunFunc root.PostRunE = myMenuPostRunFunc // Commands -------------------------------------------------------- versioncmd := &cobra.command{ use: "version", short: "print the version number of hugo", long: `all software has versions. this is hugo's`, run: func(cmd *cobra.command, args []string) { fmt.println("hugo static site generator v0.9 -- head") }, } root.AddCommand(versioncmd) return root } // Bind the command tree to the menu menu.SetCommands(myMenuCommands) ``` -------------------------------- ### Load Oh-My-Posh Configuration in Go Source: https://github.com/reeflective/console/wiki/Prompts Shows how to load an oh-my-posh JSON configuration file for the console prompt engine, setting up shell and configuration paths. ```go import ( "os" "github.com/jandedobbeleer/oh-my-posh/src/engine" "github.com/jandedobbeleer/oh-my-posh/src/shell" ) // prompt wraps an oh-my-posh prompt engine, so as to be able // to be configured/enhanced and used the same way oh-my-posh is. // Some methods have been added for ordering the application to // recompute prompts, print logs in sync with them, etc. type prompt struct { *engine.Engine app *console.Console } // LoadConfig loads the prompt JSON configuration at the specified path. // It returns an error if the file is not found, or could not be read. func (p *prompt) LoadConfig(path string) error { if _, err := os.Stat(path); err != nil { return err } flags := &platform.Flags{ Shell: shell.GENERIC, Config: path, } p.Engine = engine.New(flags) return nil } ``` -------------------------------- ### Implement Custom Syntax Highlighting (Go) Source: https://github.com/reeflective/console/wiki/Getting-Started Shows how to bind a custom syntax highlighter function to the console application. This function takes the input line as runes and returns a string with syntax highlighting, potentially using external libraries like Chroma for advanced highlighting. ```Go // SyntaxHighlighter is a helper function to provide syntax highlighting. // Once enabled, set to nil to disable again. SyntaxHighlighter func(line []rune) string import "github.com/alecthomas/chroma/quick" // highlighter uses chroma to highlight the line in an SQL dialect. func highlighter(line []rune) string { var highlighted strings.Builder err := quick.Highlight(&highlighted, string(line), "sql", "terminal16m", "xcode-dark") if err != nil { return string(line) } return highlighted.String() } // Binding the syntax highlighter app := console.New("App") // The default highlighter is bound in this call. app.Shell().SyntaxHighlighter = highlighter // And is overridden like this. ``` -------------------------------- ### Go: Generate Command Completions with Carapace Source: https://github.com/reeflective/console/wiki/Binding-Commands Demonstrates how to use the carapace completion engine to generate command completions for a cobra command. It shows the integration of `carapace.Gen()` to set up positional and flag completions. ```Go import ( "github.com/rsteube/carapace" ) func myMenuCommands() *cobra.Command { // Root ----------------------------------------------------------- // Our root command does not need any name. Even if it had one, // it will be ignored when the menu is being passed a command-line. root := &cobra.Command{} // ... root command settings ... // Commands -------------------------------------------------------- versioncmd := &cobra.command{ use: "version", short: "print the version number of hugo", long: `all software has versions. this is hugo's`, run: func(cmd *cobra.command, args []string) { fmt.println("hugo static site generator v0.9 -- head") }, // flags, positional args functions, pre/post runners, etc. root.AddCommand(versionCmd) // Our version command might have positional arguments, or flags // arguments to complete: we also generate an engine for this // command, and register completers to it. comps := carapace.Gen(versionCmd) comps.PositionalCompletion(myPositionalCompleter) comps.FlagCompletion(myFlagsCompletion) } ``` -------------------------------- ### Bind Simple Prompt Handlers in Go Source: https://github.com/reeflective/console/wiki/Prompts Demonstrates how to bind simple string-returning functions to different prompt types (Primary, Secondary, Right, Transient, Tooltip) for a given console menu. ```go mainMenu := app.Menu("") prompt := mainMenu.Prompt() // Assigning handlers to each prompt type prompt.Primary = func() string { return "application >" } prompt.Secondary = func() string { return ">" } prompt.Right = func() string { return fmt.Sprintf(time.Now().Format("03:04:05.000")) } prompt.Transient = func() string { return ">>>" } prompt.Tooltip = func(tip string) string { switch tip { case "git": return "branch something" case "command": return "status needed by command" default: return "" } } ``` -------------------------------- ### Go - Integrate oh-my-posh prompts Source: https://github.com/reeflective/console/blob/main/README.md This snippet shows how to integrate oh-my-posh for customizable prompts within the console application. It allows setting prompts per menu and binding application/menu-specific prompt segments, enhancing the user interface. ```Go package main import ( "fmt" "github.com/spf13/cobra" "github.com/reeflective/console" ) func main() { cons := console.NewConsole() // Configure oh-my-posh prompt (example: using a default config) // Replace with your actual path to the oh-my-posh config file promptConfigPath := "/path/to/your/oh-my-posh.json" cons.SetPrompt(console.NewOhMyPoshPrompt(promptConfigPath)) // Add commands as usual var rootCmd = &cobra.Command{ Use: "myapp", Short: "A sample application", } var helloCmd = &cobra.Command{ Use: "hello", Short: "Says hello", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Hello, World!") }, } rootCmd.AddCommand(helloCmd) cons.AddRootCommand(rootCmd) cons.Run() } ``` -------------------------------- ### Configure Global Console Settings (Go) Source: https://github.com/reeflective/console/wiki/Getting-Started Sets global options for the console application, such as adding newlines before and after command output, asynchronous logs, and interrupt handlers. Also demonstrates setting a custom logo function. ```Go // Surround command output, asynchronous logs and interrupt handlers with a newline. app.NewlineBefore = true app.NewlineAfter = true // Set the logo function app.SetPrintLogo(func(_ *console.Console) { fmt.Print(` _____ __ _ _ _ _____ _ | __ \ / _| | | | (_) / ____| | | | |__) |___ ___| |_| | ___ ___| |_ ___ _____ | | ___ _ __ ___ ___ | | ___ | _ // _ \/ _ \ _| |/ _ \/ __| __| \ \ / / _ \ | | / _ \| '_ \/ __|/ _ \| |/ _ \ | | \ \ __/ __/ | | | __/ (__| |_| |\ V / __/ | |___| (_) | | | \__ \ (_) | | __/ |_| \_\___|\___|_| |_|\___|\___|\__|_| \_/ \___| \____\___/|_| |_|___/\___/|_|\___| `) }) ``` -------------------------------- ### Configure Per-Application Readline Settings (Bash) Source: https://github.com/reeflective/console/wiki/Getting-Started Defines per-application settings for the readline shell using an inputrc file. This allows for custom configurations like enabling autocomplete, setting history behavior, and defining key bindings specific to an application named 'ApplicationName'. ```Bash # github.com/reeflective/readline Go readline library $if ApplicationName set autocomplete on set usage-hint-always on set history-autosuggest off set autopairs on set prompt-transient off # Other per-application command bindings/macros/etc. $endif ``` -------------------------------- ### Customize Readline Shell Options (Go) Source: https://github.com/reeflective/console/wiki/Getting-Started Provides methods to customize the readline shell's behavior by specifying options, such as forcing a specific configuration file or terminal mode. These options can be applied when the shell is initialized or reloaded. ```Go import "github.com/reeflective/readline/inputrc" var opts []inputrc.Option opts = append(opts, inputrc.WithName("/path/to/app_config.inputrc")) // Force a specific configuration file. opts = append(opts, inputrc.WithMode("xterm-256colors")) // Force a specific terminal // Set the shell options and/or reload the configuration. app.Shell().Opts = opts // If assigned, those will be used on each user-triggered reload app.Shell().Keymap.ReloadConfig(opts) // If only reloaded through this call, will apply only once. ``` -------------------------------- ### Go - Bind Cobra commands to console menus Source: https://github.com/reeflective/console/blob/main/README.md This snippet demonstrates how to bind Cobra commands to create the core functionality of the console application. It allows for multiple menus, each with its own command tree, prompt engines, and special handlers, leveraging all Cobra settings. ```Go package main import ( "fmt" "github.com/spf13/cobra" "github.com/reeflective/console" ) func main() { // Create a new console instance cons := console.NewConsole() // Define a root command var rootCmd = &cobra.Command{ Use: "myapp", Short: "A sample application", } // Add a simple command var helloCmd = &cobra.Command{ Use: "hello", Short: "Says hello", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Hello, World!") }, } rootCmd.AddCommand(helloCmd) // Bind the root command to the console cons.AddRootCommand(rootCmd) // Run the console cons.Run() } ``` -------------------------------- ### Go - Configure readline shell features Source: https://github.com/reeflective/console/blob/main/README.md This snippet illustrates how to leverage the readline shell integration within the console library. It highlights support for inputrc, configurable keymaps, commands, options, and advanced completions for commands, flags, and arguments, powered by readline and carapace. ```Go package main import ( "fmt" "github.com/spf13/cobra" "github.com/reeflective/console" "github.com/reeflective/console/input" ) func main() { cons := console.NewConsole() // Configure readline options (example: enable history search) cons.SetReadlineConfig(func(cfg *input.Config) { cfg.HistorySearch = true cfg.HistoryFiles = []string{".myapp_history"} }) // Add commands as usual var rootCmd = &cobra.Command{ Use: "myapp", Short: "A sample application", } var helloCmd = &cobra.Command{ Use: "hello", Short: "Says hello", Run: func(cmd *cobra.Command, args []string) { fmt.Println("Hello, World!") }, } rootCmd.AddCommand(helloCmd) cons.AddRootCommand(rootCmd) cons.Run() } ``` -------------------------------- ### Implement SegmentWriter Interface in Go Source: https://github.com/reeflective/console/wiki/Prompts Defines the SegmentWriter interface for oh-my-posh, including Enabled, Template, and Init methods, allowing custom prompt segments. ```go import ( "github.com/jandedobbeleer/oh-my-posh/src/platform" "github.com/jandedobbeleer/oh-my-posh/src/properties" ) type SegmentWriter interface { Enabled() bool Template() string Init(props properties.Properties, env platform.Environment) { } ``` -------------------------------- ### Add Environment Variable Expansion Completion in Go Source: https://github.com/reeflective/console/wiki/Expansion-Completers This Go code snippet demonstrates how to add environment variable expansion completions to a server menu in the Gonsole library. It binds the '$' prefix to the default environment variable completer, allowing users to access environment variables within the shell. ```go serverMenu.AddExpansionCompletion('$', console.Completer.EnvironmentVariables) ``` -------------------------------- ### Register Custom Segment with Oh My Posh (Go) Source: https://github.com/reeflective/console/wiki/Prompts Demonstrates how to directly register a custom segment to the oh-my-posh library using Go. This allows the segment to be used without going through the console's direct registration process. It requires importing the 'engine' package from oh-my-posh. ```Go import ( "github.com/jandedobbeleer/oh-my-posh/src/engine" ) func main() { engine.Segments[engine.SegmentType("module")] = func() engine.SegmentWriter { return module } } ``` -------------------------------- ### Go: Handling OS Signals Source: https://github.com/reeflective/console/wiki/Interrupt-Handlers This Go snippet illustrates how the console library handles specific OS signals by wrapping them into errors. It shows the creation of errors for SIGINT, SIGTERM, and SIGQUIT signals, which can then be caught and processed by interrupt handlers. ```go import ( "errors" "syscall" ) errors.New(syscall.SIGINT.String()) errors.New(syscall.SIGTERM.String()) errors.New(syscall.SIGQUIT.String()) ``` -------------------------------- ### Go: Access Cobra Command Tree from Console Source: https://github.com/reeflective/console/wiki/Binding-Commands Illustrates how to access the root cobra.Command embedded within a reeflective console. This allows interaction with the command tree during command execution, ensuring it's always up-to-date. ```Go // Your console should be a global variable somewhere. var app *console.Console run := func(cmd *cobra.Command, args []string) { menuRoot := app.CurrentMenu().Command } ``` -------------------------------- ### Bind Oh-My-Posh Handlers in Go Source: https://github.com/reeflective/console/wiki/Prompts Binds oh-my-posh prompt handlers (Primary, Right, Secondary, Transient, Tooltip) to the main menu prompt using custom functions. ```go func (p *Prompt) bind() { prompt := p.app.Menu("").Prompt() prompt.Primary(p.PrintPrimary) prompt.Right(p.PrintRPrompt) secondary := func() string { return p.PrintExtraPrompt(engine.Secondary) } prompt.Secondary(secondary) transient := func() string { return p.PrintExtraPrompt(engine.Transient) } prompt.Transient(transient) prompt.Tooltip(p.PrintTooltip) } ``` -------------------------------- ### Log Transient Output with Go Source: https://github.com/reeflective/console/wiki/Logging Logs arbitrary output to the console by clearing the current prompt, printing the message, and redisplaying the prompt below. Useful for asynchronous logging or status updates within commands. ```go func (c *Console) TransientPrintf(msg string, args ...any) ``` ```go asyncLog <-logChan // Refresh the prompt just below. console.TransientPrintf(asyncLog.String()) ``` ```go func myCommandRun(cmd *cobra.Command, args []string) error { console.TransientPrintf("Starting the command") ... do stuff ... console.TransientPrintf("Doing stuff") } ``` -------------------------------- ### Add File History Source to Console Menu (Go) Source: https://github.com/reeflective/console/wiki/History-Sources Demonstrates how to add a file-based command history source to a console menu using the `AddHistorySourceFile` method. This appends to the existing history sources for the specified menu. ```Go func main() { menu := app.CurrentMenu() // "local history" is the title of the history, used when completing/searching it. menu.AddHistorySourceFile("file history", "/path/to/.example-history") // Add a custom source, like the one implemented in the next section menu.AddHistorySource("custom history", new(ClientHistory)) } ``` -------------------------------- ### Log Output Below Current Prompt with Go Source: https://github.com/reeflective/console/wiki/Logging Prints a log event below the current prompt and displays a new prompt line below the log. This method is suitable when you want to maintain the current input line while logging. ```go func (c *Console) Printf(msg string, args ...any) ``` -------------------------------- ### Override AcceptMultiline Callback in Reeflective Console Source: https://github.com/reeflective/console/wiki/Getting-Started Demonstrates how to override the default `AcceptMultiline()` callback in the Reeflective console's `app.Shell()` to customize multiline input behavior. This is useful for scenarios where the default conditions (unclosed quotes or trailing backslashes) need to be modified. ```Go package main import ( "github.com/reeflective/console" ) func main() { app := console.NewApp() // Override the default AcceptMultiline behavior app.Shell().AcceptMultiline(func(input string) bool { // Custom logic to determine if multiline input should be accepted // For example, always accept multiline: return true }) app.Run() } ``` -------------------------------- ### Filter Commands in Console Source: https://github.com/reeflective/console/wiki/Binding-Commands Explains how to hide or show commands based on filter words using the `HideCommands` and `ShowCommands` methods. Commands annotated with a specific key and filter words will be hidden from the menu and completions. ```go func (c *Console) HideCommands(filters ...string) func (c *Console) ShowCommands(filters ...string) // Annotate a command with filters var myCmd &cobra.Command{Annotations: make(map[string]string{})} myCmd.Annotations[console.CommandFilterKey] = "filter1,filter2" // Example usage when switching menus console.SwitchMenu("client") if offline { console.HideCommands("networked-commands") } else { console.ShowCommands("networked-commands") } ``` -------------------------------- ### Go: Binding Interrupt Handlers to Menus Source: https://github.com/reeflective/console/wiki/Interrupt-Handlers This Go code demonstrates how to bind custom interrupt handlers to specific menus within the Reeflective Console application. It shows the process of creating a new console application, defining handlers for different interrupt types (io.EOF and console.ErrCtrlC), and associating them with the main and client menus. ```go import ( "io" "github.com/reeflective/console" ) func main() { app := console.New() // Main menu interrupts menu := app.CurrentMenu() menu.AddInterrupt(io.EOF, exitCtrlD) // Client menu interrupts clientMenu := console.Menu("client") clientMenu.AddInterrupt(console.ErrCtrlC, switchMenu) } ``` -------------------------------- ### Console Menu Command Binding Type Source: https://github.com/reeflective/console/wiki/Binding-Commands Defines the `Commands` type, which is a function that yields a root `cobra.Command`. This type is used by the `SetCommands` method to bind command trees to a console menu. ```go // Commands is a function yielding a root cobra.Commmand. type Commands func() *cobra.Command // SetCommands binds the yielder function to the menu. func (m *Menu) SetCommands(cmds Commands) ``` -------------------------------- ### Go: Switch Menu on Ctrl+C Source: https://github.com/reeflective/console/wiki/Interrupt-Handlers This Go function acts as an interrupt handler for switching menus within the console application. It is intended to be invoked when the console encounters the ErrCtrlC error, commonly associated with a Ctrl+C keystroke, and facilitates navigation back to the main menu. ```go import ( "fmt" "github.com/reeflective/console" ) func switchMenu(c *console.Console) { fmt.Println("Switching to main menu") c.SwitchMenu("") } ``` -------------------------------- ### Go: Exit Application on Ctrl+D Source: https://github.com/reeflective/console/wiki/Interrupt-Handlers This Go function serves as a custom interrupt handler. It is designed to be triggered when the console's readline encounters an io.EOF error, typically generated by a Ctrl+D keystroke. The handler prompts the user for confirmation before exiting the application. ```go import ( "bufio" "fmt" "os" "strings" "github.com/reeflective/console" ) // exitCtrlD is a custom interrupt handler to use when the shell // readline receives an io.EOF error, which is returned with CtrlD. func exitCtrlD(c *console.Console) { reader := bufio.NewReader(os.Stdin) fmt.Print("Confirm exit (Y/y): ") text, _ := reader.ReadString('\n') answer := strings.TrimSpace(text) if (answer == "Y") || (answer == "y") { os.Exit(0) } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.