/* Do not remove the headers from this file! see /USAGE for more info. */ /* ** Alias module by John Viega (rust@virginia.edu) Jul 2, 1995 ** ** NOTE: ** This had to be munged rather badly to get an alias w/ $1 in it to work ** at all. (I realized after the fact I wanted it to work, since you can ** set an alias to code, and some code uses $1, eg: (: $1 :) ) ** use a \\\$1.... It's ugly, nod, but I don't have time at the moment to ** make it nicer. =/ */ //:PLAYERCOMMAND //USAGE: //There are 3 different versions of the alias command: // //alias -- will give you a menu for adding aliases. some things can only // be done through the alias menu. // //alias str -- shows the value of alias 'str' // //alias str expansion -- sets the alias 'str' to the expansion. // //An alias definition can change each time you use the alias: //$1 -- Wherever you put this in your alias definition, // the $1 will be replaced with the first word after // the alias when you use the alias. // You can do the same with $2, $3, $4, ad infinitum. // If you have $1 in your alias definition, but don't // provide a first argument when you use an alias, // the default value for $1 is used. // // If you're using the alias menu to add an alias, you can set the // default value when you are done with the alias definition. // // Example: If you alias "you're" to: // say Hey, $2, you're $1! // When you type: // you're studly Rust // You'll say: "Hey, Rust, you're studly!" // //$* -- It's the same as $1, but it means 'everything else'. // Example: If you alias "you're" to: // say $2, you're $1! Do you $*? When you type: // you're studly Rust exercise much // You'll say: "Hey, Rust, you're studly! Do you exercise much?" // //Notice $* matches any number of words, whereas $1, $2, etc... //only match one word. // //If you don't put a $* in your expansion, one will be automatically //added to the end of the alias for you. // //If you have an alias, but don't want to use it, you can prepend a \ to //make the game ignore your alias. For example, if you have 'grin' aliased //to 'grin evilly', and you type: // // \grin psychopathically // //you'll get: // You grin psychopathically. // // //To make an alias where you don't need to type a space after the alias, //use the menu, and answer 'y' when the game asks: 'Allow space omission?' #include <classes.h> inherit CLASS_ALIAS; /* ** Xverb aliases are for aliases where you can omit the space between the verb ** and the rest of your command. It's got it's own structure so we can limit ** our search (That is, the side list is an optimization). */ private nosave mapping aliases = ([]); private nosave string * xaliases = ({}); private nosave mapping alias_save = ([]); private nosave string* xalias_save = ({}); protected void init_alias_editor() { new(ALIASMENU)->begin_menu(this_object()); } /* ** Access functions for the alias editor */ nomask int query_alias_count() { return sizeof(aliases); } nomask int is_xalias(string alias_name) { return member_array(alias_name, xaliases) != -1; } nomask void add_xalias(string alias_name) { if ( base_name(previous_object()) != ALIASMENU ) error("invalid attempt to add an xalias\n"); #ifdef MAX_NUMBER_OF_ALIASES if (query_alias_count() >= MAX_NUMBER_OF_ALIASES) { write("Sorry, you already have too many aliases.\n"); return; } #endif xaliases += ({ alias_name }); } nomask string * query_alias_names() { return keys(aliases); } nomask class alias query_one_alias(string alias_name) { return aliases[alias_name]; } //:FUNCTION remove_alias //Add an alias to an alias set. nomask void add_alias_simple(string alias_name, class alias the_alias) { if ( base_name(previous_object()) != ALIASMENU ) error("invalid attempt to add an alias\n"); #ifdef MAX_NUMBER_OF_ALIASES if (query_alias_count() >= MAX_NUMBER_OF_ALIASES) { write("Sorry, you already have too many aliases.\n"); return; } #endif aliases[alias_name] = the_alias; //### really do this? it was in here... leaving it (DB) this_object()->save(); } private nomask void internal_remove_alias(string alias_name) { map_delete(aliases, alias_name); xaliases -= ({ alias_name }); } //:FUNCTION remove_alias //Remove an alias from an alias set. nomask void remove_alias(string alias_name) { if ( base_name(previous_object()) != ALIASMENU ) error("invalid attempt to remove an alias\n"); internal_remove_alias(alias_name); } /* ** Save functions */ private string* prep_aliases_for_save(string state) { string a; class alias expansion; alias_save = ([]); xalias_save = ({}); if(state == "saving") foreach(a, expansion in aliases) { // TMP HACK =( if(sizeof(expansion) != 4) { class alias new_expansion; new_expansion = new(class alias); new_expansion->template = expansion->template; new_expansion->defaults = expansion->defaults; new_expansion->num_args = expansion->num_args; new_expansion->global_alias_status = 0; expansion = new_expansion; } if(!(expansion->global_alias_status)) { alias_save[a] = expansion; if(member_array(a,xaliases) != -1) xalias_save += ({a}); } } return ({ "alias_save", "xalias_save" }); } //:FUNCTION setup_for_save //Sets up M_SAVE to save some variables void setup_for_save() { /* ** Use the call_other() interface so that we are not protectedally ** bound to require M_SAVE. This object this modules is applied ** to may save natively rather than via M_SAVE. */ this_object()->add_save(({ (: prep_aliases_for_save:) })); } //:FUNCTION add_alias //Add an alias to an alias set. varargs void add_alias(string name, string template, string* defaults, int xverb) { class alias new_alias; int i; #ifdef MAX_NUMBER_OF_ALIASES if (query_alias_count() >= MAX_NUMBER_OF_ALIASES) { write("Sorry, you already have too many aliases.\n"); return; } #endif if(strsrch(template,"$*") == -1) template += " $*"; new_alias = new(class alias); new_alias->template = template; new_alias->defaults = defaults; new_alias->num_args = max(map(explode(template[strsrch(template,"$")..],"$"), function(string s){ int d; sscanf(s, "%d%s",d,s); return d;})); // Pad the default array with empty strings if there aren't enough // defaults provided to us. if(!arrayp(new_alias->defaults)) new_alias->defaults = ({}); i = new_alias->num_args - (sizeof(defaults) - 1); while(i--) new_alias->defaults += ({""}); if(xverb) { xaliases += ({name}); } aliases[name] = new_alias; this_object()->save(); } //:FUNCTION expand_alias //Expand an argv with any aliases if applicable. mixed expand_alias(string input) { string * argv = explode(input, " "); class alias this_alias; string* xverb_matches; string expanded_input; int numargs = sizeof(argv) - 1; int i, j; xverb_matches = filter_array(xaliases, (: strsrch($2, $1) == 0 :), argv[0]); switch(sizeof(xverb_matches)) { case 0: break; case 1: sscanf(argv[0],xverb_matches[0]+"%s",argv[0]); if(argv[0]=="") argv[0] = xverb_matches[0]; else { numargs++; argv = xverb_matches + argv; } break; default: printf("ERROR: Alias conflict: can't destinguish between: %s.\n", implode(xverb_matches,", ")); return ""; } if(!(this_alias = aliases[argv[0]])) return trim_spaces(implode(argv, " ")); expanded_input = replace_string(this_alias->template,"\\\\$",sprintf("%c",255)); j = numargs; for(i=1;i<=this_alias->num_args;i++, j--) { if(j<1) expanded_input = replace_string(expanded_input, sprintf("$%d",i), this_alias->defaults[i]); else expanded_input = replace_string(expanded_input, sprintf("$%d",i), argv[i]); } if(j>0) expanded_input = replace_string(expanded_input, "$*", implode(argv[i..]," ")); else expanded_input = replace_string(expanded_input, "$*", this_alias->defaults[0]); return trim_spaces(replace_string(expanded_input,sprintf("%c",255), "$")); } private void initialize_aliases() { mixed info; info = call_other(ALIAS_D,"query_default_aliases"); if(wizardp(this_user())) { aliases = info[0] + info[2] + alias_save; xaliases = clean_array(info[1] + info[3] + xalias_save); } else { aliases = info[0] + alias_save; xaliases = clean_array(info[1] + xalias_save); } } void create() { if ( clonep(this_object()) && base_name(this_object()) != M_ALIAS ) { #if 1 initialize_aliases(); #else call_out((: initialize_aliases :), 0); #endif } } varargs protected void cmd_alias(mixed argv, string array implode_info) { switch(sizeof(argv)) { case 1: init_alias_editor(); return; case 2: ALIASMENU->display_one_alias(argv[1], this_object()); return; default: if(strlen(argv[1]) > 1 && argv[1][0] == '$') { if(implode_info) add_alias(argv[1][1..], implode_by_arr(argv[2..], implode_info[2..])[1..],0,1); else add_alias(argv[1][1..], implode(argv[2..]," "),0,1); printf("Xverb alias '%s' set to: %s.\n", argv[1][1..], ((class alias)aliases[argv[1][1..]])->template); return; } if(implode_info) add_alias(argv[1], implode_by_arr(argv[2..],implode_info[2..])[1..]); else add_alias(argv[1], implode(argv[2..]," ")); printf("Alias '%s' set to: %s.\n", argv[1], ((class alias)aliases[argv[1]])->template); } } varargs protected void cmd_remove_alias(mixed argv) { if ( sizeof(argv) != 2 ) { printf("Usage: unalias <aliasname>\n"); return; } if ( !aliases[argv[1]] ) { printf("You don't have '%s' as an alias.\n", argv[1]); } else { internal_remove_alias(argv[1]); printf("Alias '%s' removed.\n", argv[1]); } }