""" This is an example in-game line editor. It uses the state system of Evennia (see gamesrc/examples/state_example.py). Usage: @edit object=attributename The editor is invoked on an object's attribute and allows some more editing facilities over just writing everything in one go. Check the help for more info. If you choose to edit atribute-lists instead of simple strings, the editor adapts by switching to line-mode. """ from src.cmdtable import GLOBAL_CMD_TABLE from src.statetable import GLOBAL_STATE_TABLE from src.objects.models import Object, Attribute import src.defines_global STATENAME = 'line_editor' #editor variables and settings BUF = '_EDITOR_EDITORBUF' LINEMODE = '_EDITOR_LINEMODE' NOUPDATE = '_EDITOR_NOUPDATE' EDIT_ATTR = '_EDITOR_EDIT_ATTR' def cmd_edit(command): """ Edit an attribute using the editor. Usage: @edit[/switches] [object=]attribute switches: clear - if the attribute already had a value, clear it before entering the editor. line - work and save in line mode noup - only updates the buffer when explicitly listing it (avoid large screen-redraws if there's a lot of text) If no object is given, attribute is assumed to be defined on the caller. The editor supports modifying, replacing and inserting text into an attribute in various ways, as well as cancelling your changes. Technically, the 'line' mode of the editor works and saves lines in a list-attribute. This mode supports more formatting operations than just working on a string. When working on a normal string (string mode) the editor has no concept of lines, but new text is added and inserted into the string. See the help text in the editor for more information. """ source_object = command.source_object args = command.command_argument switches = command.command_switches if not args: source_object.emit_to("You must specify an attribute to @edit.") return args = args.strip() if '=' not in args: args = "me=" + args objname, attr = args.split('=',1) obj = validate_obj(source_object, objname, attr) if not obj: return source_object.set_attribute(LINEMODE, 'line' in switches) if not 'clear' in switches: curr_value = obj.get_attribute_value(attr.strip()) if type(curr_value) == type(list()): source_object.set_attribute(LINEMODE,True) source_object.set_attribute(BUF, curr_value) source_object.set_attribute(NOUPDATE, 'noup' in switches) #setup the editor temporary attributes source_object.set_attribute(EDIT_ATTR,args) #enter edit state source_object.set_state(STATENAME) source_object.execute_cmd('list') def cmd_list(command): """ list the buffer """ source_object = command.source_object buf = source_object.get_attribute_value(BUF) linemode = source_object.get_attribute_value(LINEMODE) header = "%s-----------------------------------------%s\n\r" % ('%cy', '%cn') attr = source_object.get_attribute_value(EDIT_ATTR) if linemode: footer = "\n\r%s@edit mode (line) (%s%s%s) (h for help)" % ('%cy','%ch',attr,'%cn%cy') else: footer = "\n\r%s@edit mode (str) (%s%s%s) (h for help)" % ('%cy','%ch',attr,'%cn%cy') if buf: if type(buf)==type(list()): s = "" for i, line in enumerate(buf): s += "%s%2i|%s %s\n\r" % ('%ch%cw', i+1, '%cn', line) s = header + s[:-2] + footer else: if linemode: s = "%s%2i|%s %s\n\r" % ('%ch%cw', 1, '%cn', buf) s = header + s + footer else: s = header + buf + footer else: s = header + footer source_object.emit_to(s) def cmd_append(command): """ Append text to buffer. """ source_object = command.source_object args = command.command_argument buf = source_object.get_attribute_value(BUF) if not args: args = " " if source_object.get_attribute_value(LINEMODE): if not buf: buf = [args] else: if type(buf) != type(list()): buf = [buf] buf.extend([args]) else: if not buf: buf = "" elif buf[-1] in '.,;:': buf += ' ' buf += args source_object.set_attribute(BUF, buf) if not source_object.get_attribute_value(NOUPDATE): cmd_list(command) def cmd_insert(command): """ Insert new line before given line """ source_object = command.source_object args = command.command_argument buf = source_object.get_attribute_value(BUF) if source_object.get_attribute_value(LINEMODE): if args: args = args.split(" ",1) if len(args)>1: linenum, text = args[0],args[1] else: source_object.emit_to("Usage: .i # ") return try: buf.insert(int(linenum)-1, text) except: source_object.emit_to("%s'%s' is not a valid line number." % ('%cr',linenum)) return source_object.set_attribute(BUF, buf) if not source_object.get_attribute_value(NOUPDATE): cmd_list(command) else: source_object.emit_to("%s.i only works in line mode" % '%cr') def cmd_clear(command): """ clears the buffer """ source_object = command.source_object args = command.command_argument buf = source_object.get_attribute_value(BUF) if source_object.get_attribute_value(LINEMODE): if args: try: del buf[int(args)-1] source_object.set_attribute(BUF,buf) except: source_object.emit_to("%sCould not clear line '%s'" % ('%cr',args)) else: source_object.set_attribute(BUF,[]) else: source_object.set_attribute(BUF,"") if not source_object.get_attribute_value(NOUPDATE): cmd_list(command) def cmd_replace(command): """ replace all occurences of a text. """ source_object = command.source_object buf = source_object.get_attribute_value(BUF) if not buf: return args = command.command_argument if not args: source_object.emit_to("Usage: .r old or .r old=new") return if source_object.get_attribute_value(LINEMODE): if args[0].isdigit(): num, args = args.split(" ",1) if '=' in args: old, new = args.split('=') old, new = old, new else: old = args new = "" try: buf[int(num)-1] = buf[int(num)-1].replace(old, new) except: source_object.emit_to("%s%s is not a valid line number." % ('%cr',num)) return else: if '=' in args: old, new = args.split('=') old, new = old, new else: old = args new = "" newbuf = [] for line in buf: newbuf.append(line.replace(old,new)) buf = newbuf else: if '=' in args: old, new = args.split('=') old, new = old, new else: old = args new = "" buf = buf.replace(old, new) source_object.set_attribute(BUF, buf) if not source_object.get_attribute_value(NOUPDATE): cmd_list(command) def cmd_save(command): source_object = command.source_object buf = source_object.get_attribute_value(BUF) if not buf: buf = "" attr = source_object.get_attribute_value(EDIT_ATTR) objname, attr = attr.split('=',1) obj = validate_obj(source_object, objname, attr) if not obj: cmd_exit(command) else: obj.set_attribute(attr, buf) source_object.emit_to("%s%s=%s saved." % ('%cg',objname,attr)) def cmd_save_exit(command): cmd_save(command) util_exit(command) def cmd_exit(command): "exits without saving." source_object = command.source_object attr = source_object.get_attribute_value(EDIT_ATTR) source_object.emit_to('%s%s not saved/changed.' % ('%cr', attr)) util_exit(command) def util_exit(command): "cleans up and exits" source_object = command.source_object source_object.clear_attribute(BUF) source_object.clear_attribute(LINEMODE) source_object.clear_attribute(NOUPDATE) source_object.clear_attribute(EDIT_ATTR) source_object.clear_state() source_object.execute_cmd('look') def cmd_help(command): """ A custom help screen. """ source_object = command.source_object buf = source_object.get_attribute_value(BUF) if source_object.get_attribute_value(LINEMODE): s = \ """ %sEditor commands: . - enter text into the buffer .i # - insert new line before line # .c - clear buffer .c # - clear line # .r - remove all matching .r = - replace all with .r # - replace line # with .r # = - replace with on line # .s - save buffer .xs, .sx - save and exit .x, .q - exit without saving .l, l, list - list buffer .h, h, help - this help """ else: s = \ """ %sEditor commands: . - enter text into the buffer .c - clear buffer .r - remove all matching .r = - replace all with .s - save buffer .xs, .sx - save and exit .x, .q - exit without saving .l, l, list - list buffer .h, h, help - this help """ source_object.emit_to(s % '%cy') # # Helper function # def validate_obj(source_object, objname, attr): "Helper function" #test that object exists. results = Object.objects.local_and_global_search(source_object, objname) if not results: source_object.emit_to("No name matches found for %s." % (objname,)) return None if len(results) > 1: source_object.emit_to("Multiple name matches for: %s" % (objname,)) s = "" for result in results: s += " %s\n\r" % (result.get_name(fullname=False),) s += "%d matches returned." % (len(results),) source_object.emit_to(s) return None obj = results[0] #permission checks if not source_object.controls_other(obj): source_object.emit_to(defines_global.NOCONTROL_MSG) return None if not Attribute.objects.is_modifiable_attrib(attr): source_object.emit_to("You can't modify that attribute.") return None return obj #editor entry command GLOBAL_CMD_TABLE.add_command("@edit", cmd_edit, auto_help=True) #create the state GLOBAL_STATE_TABLE.add_state(STATENAME) #editor commands GLOBAL_STATE_TABLE.add_command(STATENAME, ".", cmd_append) GLOBAL_STATE_TABLE.add_command(STATENAME, ".i", cmd_insert) GLOBAL_STATE_TABLE.add_command(STATENAME, ".r", cmd_replace) GLOBAL_STATE_TABLE.add_command(STATENAME, ".c", cmd_clear) GLOBAL_STATE_TABLE.add_command(STATENAME, ".s", cmd_save) GLOBAL_STATE_TABLE.add_command(STATENAME, ".xs", cmd_save_exit) GLOBAL_STATE_TABLE.add_command(STATENAME, ".sx", cmd_save_exit) GLOBAL_STATE_TABLE.add_command(STATENAME, ".x", cmd_exit) GLOBAL_STATE_TABLE.add_command(STATENAME, ".q", cmd_exit) GLOBAL_STATE_TABLE.add_command(STATENAME, ".l", cmd_list) GLOBAL_STATE_TABLE.add_command(STATENAME, "l", cmd_list) GLOBAL_STATE_TABLE.add_command(STATENAME, "list", cmd_list) GLOBAL_STATE_TABLE.add_command(STATENAME, ".h", cmd_help) GLOBAL_STATE_TABLE.add_command(STATENAME, "h", cmd_help) GLOBAL_STATE_TABLE.add_command(STATENAME, "help", cmd_help)