Verb Editor (#50)

(an instance of Generic Editor made by Hacker)




VERB SOURCE CODE:

e*dit:
if (!args)
    player:tell("edit what?");
else
    this:invoke(argstr, verb);
endif
.


com*pile:
pas = {{}, {}};
if (!(who = this:loaded(player)))
    player:tell(this:nothing_loaded_msg());
    return;
elseif (!args)
    object = this.objects[who];
    vname = this.verbnames[who];
    if (typeof(vname) == LIST)
        vargs = listdelete(vname, 1);
        vname = vname[1];
    else
        vargs = {};
    endif
    changeverb = 0;
elseif ((args[1] != "as") || ((length(args) < 2) || ((!(spec = $code_utils:parse_verbref(args[2]))) 
|| ((typeof(pas = $code_utils:parse_argspec(@args[3..length(args)])) != LIST) || 
pas[2]))))
    if (typeof(pas) != LIST)
        player:tell(pas);
    elseif (pas[2])
        player:tell("I don't understand \"", $string_utils:from_list(pas[2], " "), 
"\"");
    endif
    player:tell("Usage: ", verb, " [as :]");
    return;
elseif ($command_utils:object_match_failed(object = player:my_match_object(spec[1], 
this:get_room(player)), spec[1]))
    return;
else
    vname = spec[2];
    vargs = pas[1] && {@pas[1], "none", "none"}[1..3];
    if (vargs)
        vargs[2] = $code_utils:full_prep(vargs[2]) || vargs[2];
    endif
    changeverb = 1;
endif
if (vargs)
    vnum = $code_utils:find_verb_named(object, vname);
    while ((vnum >= 0) && (verb_args(object, tostr(vnum)) != vargs))
        vnum = $code_utils:find_verb_named(object, vname, vnum + 1);
    endwhile
    if (vnum < 0)
        player:tell("There is no ", object, ":", vname, " verb with args (", $string_utils:from_list(vargs, 
" "), ").");
        if (!changeverb)
            player:tell("Use 'compile as ...' to write your code to another verb.");
        endif
        return;
    endif
    objverbname = tostr(object, ":", vname, " (", $string_utils:from_list(vargs, 
" "), ")");
else
    vnum = -1;
    objverbname = tostr(object, ":", ($code_utils:tonum(vname) == E_TYPE) ? vname 
| this:verb_name(object, vname));
endif
"...";
"...perform eval_subs on verb code if necessary...";
"...";
if (player.eval_subs && player:edit_option("eval_subs"))
    verbcode = {};
    for x in (this:text(who))
        verbcode = {@verbcode, $code_utils:substitute(x, player.eval_subs)};
    endfor
else
    verbcode = this:text(who);
endif
"...";
"...write it out...";
"...";
if (result = this:set_verb_code(object, (vnum >= 0) ? tostr(vnum) | vname, verbcode))
    player:tell(objverbname, " not compiled because:");
    for x in (result)
        player:tell("  ", x);
    endfor
elseif (typeof(result) == ERR)
    player:tell({result, ("You do not have write permission on " + objverbname) + 
".", ("The verb " + objverbname) + " does not exist (!?!)", ("The object " + tostr(object)) 
+ " does not exist (!?!)"}[1 + (result in {E_PERM, E_VERBNF, E_INVARG})]);
    if (!changeverb)
        player:tell("Do 'compile as :' to write your code to another 
verb.");
    endif
    changeverb = 0;
else
    player:tell(objverbname, verbcode ? " successfully compiled." | " verbcode removed.");
    this:set_changed(who, 0);
endif
if (changeverb)
    this.objects[who] = object;
    this.verbnames[who] = vargs ? {vname, @vargs} | vname;
endif
.



working_on:
if (!(fuckup = this:ok(who = args[1])))
    return fuckup;
else
    object = this.objects[who];
    verbname = this.verbnames[who];
    if (typeof(verbname) == LIST)
        return tostr(object, ":", verbname[1], " (", $string_utils:from_list(listdelete(verbname, 
1), " "), ")");
    else
        return tostr(object, ":", this:verb_name(object, verbname), " (", this:verb_args(object, 
verbname), ")");
    endif
endif
"return this:ok(who = args[1]) && tostr(this.objects[who]) + \":\" + this.verbnames[who];";
.


init_session:
if (this:ok(who = args[1]))
    object = args[2];
    vname = args[3];
    this:load(who, args[4]);
    this.verbnames[who] = vname;
    this.objects[who] = object;
    this.active[who]:tell("Now editing ", this:working_on(who), ".");
    "this.active[who]:tell(\"Now editing \", object, \":\", vname, \".\");";
endif
.


parse_invoke:
":parse_invoke(string,v)";
"  string is the commandline string to parse to obtain the obj:verb to edit";
"  v is the actual command verb used to invoke the editor";
" => {object, verbname, verb_code} or error";
vref = $string_utils:words(args[1]);
if ((!vref) || (!(spec = $code_utils:parse_verbref(vref[1]))))
    player:tell("Usage: ", args[2], " object:verb");
    return;
endif
if (argspec = listdelete(vref, 1))
    if (typeof(pas = $code_utils:parse_argspec(@argspec)) == LIST)
        if (pas[2])
            player:tell("I don't understand \"", $string_utils:from_list(pas[2], 
" "), "\"");
            return;
        endif
        argspec = {@pas[1], "none", "none"}[1..3];
        argspec[2] = $code_utils:full_prep(argspec[2]) || argspec[2];
    else
        player:tell(pas);
        return;
    endif
endif
if (!$command_utils:object_match_failed(object = player:my_match_object(spec[1], 
this:get_room(player)), spec[1]))
    vnum = $code_utils:find_verb_named(object, vname = spec[2], 0);
    if (argspec)
        while ((vnum >= 0) && (verb_args(object, tostr(vnum)) != argspec))
            vnum = $code_utils:find_verb_named(object, vname, vnum + 1);
        endwhile
        if (vnum >= 0)
            code = this:fetch_verb_code(object, tostr(vnum));
        else
            code = E_VERBNF;
        endif
    else
        code = this:fetch_verb_code(object, tostr(vnum));
    endif
    if (typeof(code) == ERR)
        player:tell((code != E_VERBNF) ? code | "That object does not define that 
verb", argspec ? " with those args." | ".");
        return code;
    else
        return {object, argspec ? {vname, @argspec} | vname, code};
    endif
endif
return 0;
.


fetch_verb_code:
"WIZARDLY";
if ((caller != $verb_editor) || (caller_perms() != $verb_editor.owner))
    return E_PERM;
else
    set_task_perms(player);
    return verb_code(args[1], args[2], !player:edit_option("no_parens"));
endif
.


set_verb_code:
"WIZARDLY";
if ((caller != $verb_editor) || (caller_perms() != $verb_editor.owner))
    return E_PERM;
else
    set_task_perms(player);
    return set_verb_code(args[1], args[2], args[3]);
endif
.


local_editing_info:
if (caller == $verb_editor)
    set_task_perms(player);
endif
object = args[1];
vname = args[2];
if (typeof(vname) == LIST)
    vargs = tostr(" ", vname[2], " ", $code_utils:short_prep(vname[3]), " ", vname[4]);
    vname = vname[1];
else
    vargs = "";
endif
code = args[3];
name = tostr(object.name, ":", vname);
"... so the next 2 lines are actually wrong, since verb_info won't";
"... necessarily retrieve the correct verb if we have more than one";
"... matching the given same name; anyway, if parse_invoke understood vname,";
"... so will @program.  I suspect these were put here because in the";
"... old scheme of things, vname was always a number.";
"vname = strsub($string_utils:explode(verb_info(object, vname)[3])[1], \"*\", \"\")";
"vargs = verb_args(object, vname)";
"";
return {name, code, tostr("@program ", object, ":", vname, vargs)};
.


verb_name:
"verb_name(object, vname)";
"Find vname on object and return its full name (quoted).";
"This is useful for when we're working with verb numbers.";
if ((caller != $verb_editor) || (caller_perms() != $verb_editor.owner))
    return E_PERM;
else
    set_task_perms(player);
    given = args[2];
    if (typeof(info = verb_info(args[1], given)) == ERR)
        return tostr(given, "[", info, "]");
    elseif (info[3] == given)
        return given;
    else
        return tostr(given, "/\"", info[3], "\"");
    endif
endif
.


verb_args:
"verb_name(object, vname)";
"Find vname on object and return its full name (quoted).";
"This is useful for when we're working with verb numbers.";
if ((caller != $verb_editor) || (caller_perms() != $verb_editor.owner))
    return E_PERM;
else
    set_task_perms(player);
    return $string_utils:from_list(verb_args(args[1], args[2]), " ");
endif
.



PROPERTY DATA:
      objects
      verbnames