package console import "core:strings" import "core:log" MAX_COMMANDS_IN_REGISTRY :: #config(CONSOLE_MAX_COMMANDS_IN_REGISTRY, 2048) Console :: struct { command_registry: Command_Registry, } Command_Registry :: map[string]Command Command :: struct { description: string, userdata: rawptr, callback: Commmand_Callback, } Commmand_Callback :: proc(c: ^Console, userdata: rawptr, arguments: []string) -> bool // TODO: SS - Return an enum? 'Success', 'Not enough arguments', 'Invalid arguments' etc. init :: proc(console: ^Console) { assert(console.command_registry == nil) console.command_registry = make(Command_Registry, MAX_COMMANDS_IN_REGISTRY) } // TODO: SS - Support routing logs to somewhere else? Maybe add a 'log_callback' procedure? register_command :: proc(console: ^Console, name, description: string, userdata: rawptr, callback: Commmand_Callback) -> bool { elem, ok := &console.command_registry[name] if ok { log.warnf("Command with name '%v' has already been registered.", name) return false } console.command_registry[name] = {} cmd := &console.command_registry[name] cmd.description = description cmd.userdata = userdata cmd.callback = callback log.infof("Registered command with name '%v'.", name) return true } log_available_commands :: proc(console: ^Console) { assert(console != nil) log.infof("Available commands (%v):", len(console.command_registry)) for key, value in console.command_registry { log.infof("- '%v', '%v'.", key, value.description) } } send_input :: proc(console: ^Console, input: string, loc := #caller_location) { // TODO: SS - Decide on a nice name for this. 'run'? 'send_input' is probably alright too. input_strings, err := strings.split(input, " ") if err != .None { log.infof("No input.") return } defer delete(input_strings) command_name := input_strings[0] arguments := input_strings[1:] // log.infof("Command '%v', arguments: '%v'", command_name, arguments) cmd, command_exists := &console.command_registry[command_name] if !command_exists { log.warnf("Command '%v' was not found in registry.", command_name) return } if cmd.callback == nil { log.errorf("Command '%v' is missing a callback.") return } result := cmd.callback(console, cmd.userdata, arguments) if !result { log.warnf("Command '%v' failed. Command description: '%v'. Location: %v", command_name, cmd.description, loc) return } } shutdown :: proc(console: ^Console) { delete(console.command_registry) console.command_registry = nil }