def build_named_args_command(self): com = Command('named my_arg <-f filename> [-g othername]', 'Demonstrate arguments') def _val(*args, **kwargs): success,message = com.default_validate(*args, **kwargs) if not success: if len(args) == 0 and len(kwargs) == 0: self.put(""" Some commands accept command line arguments. When creating a command, you specify these arguments with a special (simple) syntax. For example, this command is called "%s". It accepts both positional and named arguments. Positional arguments are indicated by a bare word following the command's name in the command definition. Named arguments are wrapped in either <> or [], and contain both the argument name (starting with '-') and a helpful tip about the argument function. Named arguments with <> are required, those with [] are optional. This command also demonstrates customizable tab completion hooks. Try pressing Tab after typing '%s s' and before typing enter. You'll see a list of possible completions for your argument. You can customize these commands by supplying callbacks to Command.tabcomplete_hooks. Try passing arguments to this command! """ % (com.name, com.name)) else: self.put(""" This command requires one unnamed argument followed by a named argument (-f). Try this: %s helloworld -f data.txt """ % com.name) return (False, message) return (success, message) com.validate = _val def _run(*args, **kwargs): self.put("Got arguments:") self.put(args) self.put(kwargs) self.put("Arguments are passed around in a format quite familiar to python:") self.put("Positional arguments in a list, named arguments in a dictionary") return constants.CHOICE_VALID com.run = _run def _complete_myarg(frag): return ['some', 'random', 'choices'] com.tabcomplete_hooks['my_arg'] = _complete_myarg def _complete_file(frag): from os import listdir from os.path import isfile, join onlyfiles = [f for f in listdir('.') if isfile(join('.',f))] return onlyfiles com.tabcomplete_hooks['filename'] = _complete_file return com
def build_sticker_command(self): com = Command('make_sticker text', 'Make a new sticker') def _run(*args, **kwargs): self.put(""" This command places a 'sticker' on the terminal. Use these to present persistent data to the user. """) self.sticker(" ".join(args)) return constants.CHOICE_VALID com.run = _run return com
def build_hello_command(self): com = Command('first_command', 'Intro to commands') def _run(*args, **kwargs): self.put(""" Congratulations, you just invoked your first command in Candela. This text is being printed from inside a callback function passed to the library via a Command object. You can print text to your shell from anywhere in your Shell subclass by calling self.put(). """) return constants.CHOICE_VALID com.run = _run return com
def build_builtin_command(self): com = Command('builtins', 'Go to builtin commands menu') def _run(*args, **kwargs): self.put(""" Commands can conditionally lead the user to other menus. This demo app has two menus defined: the main menu and the built-in commands menu. The command you just ran has returned the string 'builtins' to point to the builtins menu. 'builtins' is the name of the new menu. Notice that the options menu has changed to reflect the new commands available in this menu. """) return 'builtins' com.run = _run return com
def _next_step(self, entry): success = self.editor.load_file(entry) sentences_menu = Menu(entry.lower()) sentences_menu.title = entry for i,sen in zip(range(len(self.editor.sentences)), self.editor.sentences): _id,tags,text = sen com = Command(str(i), text) com.run = self.build_run(text, _id, self.chartype, self.mood) sentences_menu.commands.append(com) sentences_menu.commands += self.defaults return sentences_menu
def build_complex_command(self): com = Command('cat <-f filename>', 'Demonstrate arbitrary python running') def _run(*args, **kwargs): self.put(""" Commands can run arbitrary python via a callback. Here's a callback that reads a file from your local drive and prints it to the shell. """) try: with open(kwargs['f'], 'r') as f: self.put(f.read()) except IOError: self.put("%s : No such file!" % kwargs['f']) return constants.CHOICE_VALID com.run = _run return com
def build_builtin_command(self): com = Command('builtins', 'Go to builtin commands menu') def _run(*args, **kwargs): self.put(""" Commands can conditionally lead the user to other menus. This demo app has two menus defined: the main menu and the built-in commands menu. The command you just ran has defined the attribute self.new_menu to point to the builtins menu. Notice that the options menu has changed to reflect the new commands available in this menu. """) return constants.CHOICE_VALID com.run = _run com.new_menu = 'builtins' return com
def setup_defaults(self): quit_com = QuitCommand('converse') quit_com.alias('q') clear_com = ClearCommand(self.shell) back_com = BackCommand('main') set_com = Command('set type mood', 'Change the current character type and mood') def _run(*args, **kwargs): self.chartype = args[0] self.mood = args[1] self.shell.put("Set chartype %s and mood %s\nThe change will take effect after the next sentence." % (self.chartype, self.mood)) return constants.CHOICE_VALID set_com.run = _run return [set_com, back_com, clear_com, quit_com]
def build_invalid_command(self): com = Command('broken', 'Demonstrate invalid command') def _run(*args, **kwargs): self.put("I will never print") return constants.CHOICE_VALID com.run = _run def _val(*args, **kwargs): message = """ You can write custom validation functions for your commands. A validation function will run before execution of the command. If the validation returns False, the command is not run. The default validation function checks for the presence of all required arguments, but you can override this behavior by setting the Command's validate member. This is a command that always fails to validate. """ return (False, message) com.validate = _val return com
def build_named_args_command(self): com = Command('named my_arg <-f filename> [-g othername]', 'Demonstrate arguments') def _val(*args, **kwargs): success,message = com.default_validate(*args, **kwargs) if not success: if len(args) == 0 and len(kwargs) == 0: self.put(""" Some commands accept command line arguments. When creating a command, you specify these arguments with a special (simple) syntax. For example, this command is called "%s". It accepts both positional and named arguments. Positional arguments are indicated by a bare word following the command's name in the command definition. Named arguments are wrapped in either <> or [], and contain both the argument name (starting with '-') and a helpful tip about the argument function. Named arguments with <> are required, those with [] are optional. Try passing arguments to this command! """ % com.name) else: self.put(""" This command requires one unnamed argument followed by a named argument (-f). Try this: %s helloworld -f data.txt """ % com.name) return (False, message) return (success, message) com.validate = _val def _run(*args, **kwargs): self.put("Got arguments:") self.put(args) self.put(kwargs) self.put("Arguments are passed around in a format quite familiar to python:") self.put("Positional arguments in a list, named arguments in a dictionary") return constants.CHOICE_VALID com.run = _run return com
def setup_menus(self): # completions def _complete_chartype(frag): return self.editor.list_all_chartypes() def _complete_mood(frag): return self.editor.list_all_moods() def _complete_topic(frag): return list(set(self.editor.get_available_topics() + self.editor.list_new_topics())) new_com = Command('new topic', 'Create a new topic') def _run(*args, **kwargs): topic = " ".join(args[0:]) if topic in self.editor.get_available_topics(): self.put("Topic %s already exists." % topic) self.editor.load_file(topic) self.sticker("Topic: '%s'" % self.editor.cwt) else: self.editor.cwt = topic self.put("New topic %s" % self.editor.cwt) self.sticker("Topic: '%s'" % self.editor.cwt) return 'edit' new_com.run = _run load_com = Command('load topic', 'Load a previous topic') def _run(*args, **kwargs): topic = " ".join(args[0:]) success = self.editor.load_file(topic) if success: self.sticker("Topic: '%s'" % self.editor.cwt) return 'edit' return constants.FAILURE load_com.run = _run def _complete_topic(frag): return self.editor.get_available_topics() load_com.tabcomplete_hooks['topic'] = _complete_topic list_com = Command('list', 'Show available topics') def _run(*args, **kwargs): self.editor.list_topic_files() return constants.CHOICE_VALID list_com.run = _run sen_com = Command('sentence tags text', 'Create a new player sentence') def _run(*args, **kwargs): sentence = " ".join(args[1:]) tag = args[0] self.editor.create_sentence(tag, sentence) return constants.CHOICE_VALID sen_com.run = _run def _complete(frag): tags = [] for _id,tag,sentence in self.editor.sentences: for t in tag.split(','): tags.append(t) return list(set(tags)) sen_com.tabcomplete_hooks['tags'] = _complete res_com = Command('response sID chartype mood next_topic text', 'Create a new NPC response') def _run(*args, **kwargs): text = " ".join(args[4:]) sen_id = int(args[0]) _type = args[1] mood = args[2] _next = args[3] self.editor.create_response(sen_id, _type, mood, _next, text) return constants.CHOICE_VALID res_com.run = _run res_com.alias('res') res_com.tabcomplete_hooks['chartype'] = _complete_chartype res_com.tabcomplete_hooks['mood'] = _complete_mood res_com.tabcomplete_hooks['next_topic'] = _complete_topic list_topic_com = Command('list', 'Show current player sentences') def _run(*args, **kwargs): self.editor.list_topic() return constants.CHOICE_VALID list_topic_com.run = _run list_topic_com.alias('ls') del_res_com = Command('delete_r sen_id type res_id', 'Delete an NPC response') def _run(*args, **kwargs): sen_id = int(args[0]) _type = args[1] res_id = int(args[2]) self.editor.delete_response(sen_id, _type, res_id) return constants.CHOICE_VALID del_res_com.run = _run del_res_com.alias('delr') del_res_com.tabcomplete_hooks['type'] = _complete_chartype del_res_com.tabcomplete_hooks['mood'] = _complete_mood del_sen_com = Command('delete_s sen_id', 'Delete sentence by ID') def _run(*args, **kwargs): sen_id = int(args[0]) self.editor.delete_sentence(sen_id) return constants.CHOICE_VALID del_sen_com.run = _run del_sen_com.alias('dels') edit_sen_com = Command('edit_s sen_id tags text', 'Edit an existing sentence') def _run(*args, **kwargs): sen_id = int(args[0]) sentence = " ".join(args[2:]) tag = args[1] self.editor.edit_sentence(sen_id, tag, sentence) return constants.CHOICE_VALID edit_sen_com.run = _run def _complete(frag): tags = [] for _id,tag,sentence in self.editor.sentences: for t in tag.split(','): tags.append(t) return list(set(tags)) edit_sen_com.tabcomplete_hooks['tags'] = _complete write_com = Command('save', 'Save to a file') def _run(*args, **kwargs): self.editor.write_out(from_command=True) return constants.CHOICE_VALID write_com.run = _run cd_com = Command('cd path', 'Change current directory') def _run(*args, **kwargs): path = "" for part in args: path += part path = path.replace('\\', ' ') self.editor.path = path return constants.CHOICE_VALID cd_com.run = _run pwd_com = Command('pwd', 'Print current directory') def _run(*args, **kwargs): self.put(self.editor.path) return constants.CHOICE_VALID pwd_com.run = _run convoplay_com = Command('play chartype mood [-e entry_point]', 'Run a conversation') def _run(*args, **kwargs): entry = kwargs.get('e', 'greetings') char = args[0] mood = args[1] self.convoplayer.run(char, mood, entry=entry) return entry.lower() convoplay_com.run = _run # builtins back_com = BackCommand('main') def _run(*args, **kwargs): self.remove_sticker("Topic: '%s'" % self.editor.cwt) self.editor.unload_file(self.editor.cwt) return back_com.default_run(*args, **kwargs) back_com.run = _run quit_com = QuitCommand(self.name) quit_com.alias('q') run_com = RunScriptCommand(self) clear_com = ClearCommand(self) defaults = [quit_com, run_com, clear_com] main_menu = Menu('main') main_menu.title = "Main menu" main_menu.commands = [new_com, load_com, list_com, cd_com, pwd_com, convoplay_com] + defaults edit_menu = Menu('edit') edit_menu.title = "Editing menu" edit_menu.commands = [sen_com, edit_sen_com, del_sen_com, res_com, del_res_com, list_topic_com, back_com, convoplay_com, write_com] + defaults self.menus = [main_menu, edit_menu] self.menu = 'main' # TODO - hide this somehow?