Support fuer Familienaliase.
Familienaliase werden mit den normalen aus dem individuellen
Char zusammgenefasst und behandelt.
Mit dem Argument -f fuer alias + unalias koennen sie
gesetzt und geloescht werden.
Alias aus dem jeweiligen Char haben Prioritaet vor den
Aliasen aus der Familie.
Nebenbei ein bisschen Code-Modernisierung und Dokumentation.
Change-Id: I3ed4b64689b1fa6a49d411a8c4796f5a64cbda2b
diff --git a/std/player/command.c b/std/player/command.c
index 301782c..df6d86a 100644
--- a/std/player/command.c
+++ b/std/player/command.c
@@ -27,11 +27,17 @@
#include <strings.h>
#define CBLOG(x) log_file(SHELLLOG("DISABLECOMMANDS"),x,200000)
+#define FALIASDB "/secure/zweities"
#define HIST_SIZE 40
#define EPMASTER "/secure/explorationmaster"
+// Im Char gespeicherte Aliase
private mapping aliases;
+// Vereinigte Liste aktiver Aliase aus im Char gespeicherten und
+// Familienaliases. Wird nicht gespeichert, sondern bei Login erzeugt!
+private nosave mapping active_aliases = ([]);
+
private string *commands;
private int hist_size, show_processing, histmin;
private string default_notify_fail;
@@ -48,7 +54,6 @@
static varargs int __auswerten(string str, string intern);
varargs int SoulComm(string str, string _verb);
varargs mixed More(string str, int fflag, string returnto);
-static int _starts_with(string str, string start);
static void reallocate_histbuf();
private void AddHistory(string str)
@@ -130,17 +135,26 @@
return 1;
}
+private void merge_family_aliases()
+{
+ // Char- und Familienaliase addieren.
+ // Die Aliase des Char haben Prioritaet und ueberdecken die der Familie.
+ active_aliases = FALIASDB->QueryFamilyAlias() + aliases;
+}
+
static void initialize()
{
- if (!pointerp(history)||sizeof(history)!=hist_size)
- reallocate_histbuf();
- add_action("__auswerten","",1);
+ if (!pointerp(history)||sizeof(history)!=hist_size)
+ reallocate_histbuf();
+ add_action("__auswerten","",1);
max_commands = EPMASTER->QueryCommands();
cmd_types = EPMASTER->QueryCmdTypes() || ({});
if ( !mappingp(aliases) )
aliases = ([]);
+ merge_family_aliases();
+
if ( !pointerp(commands) )
commands = ({});
@@ -191,7 +205,10 @@
void reconnect()
{
- if (!mappingp(aliases)) aliases=([]);
+ if (!mappingp(aliases))
+ aliases=([]);
+
+ merge_family_aliases();
if ( !pointerp(commands) )
commands = ({});
@@ -214,17 +231,18 @@
return 1;
}
-static string present_alias(mixed *ali)
+static string present_alias(<string|int>* ali)
{
- int j,k;
+ int j;
+ <string|int> k;
string s,s2;
for (s="",j=sizeof(ali)-1;j>=0;j--)
if (intp(ali[j]))
if ((k=ali[j])<0)
- s="$"+(k==-1?"":(string)-k)+"*"+s;
+ s="$"+(k==-1?"":(string)-k)+"*"+s;
else
- s="$"+(string)k+s;
+ s="$"+(string)k+s;
else
{
s2=implode(explode(ali[j],"\\"),"\\\\");
@@ -234,48 +252,51 @@
}
#define ALIFORMAT ({" %s\t= %s", "alias %s %s"})[display_as_aliascommand]
+#define FALIFORMAT ({" %s\t= %s", "alias -f %s %s"})[display_as_aliascommand]
// Ich weiss, den Variablennamen im define zu haben ist unfein, aber das
// macht es im Code dann angenehm uebersichtlich. -HrT
-static int query_aliases(int display_as_aliascommand)
+static int query_aliases(int display_as_aliascommand, int familymode)
{
- int i;
- string *a,*ali;
+ mapping selected_aliases;
- if(i=sizeof(ali=sort_array(m_indices(aliases),#'<))) //')))
+ if (familymode)
+ selected_aliases=FALIASDB->QueryFamilyAlias();
+ else
+ selected_aliases = aliases;
+
+ string *alis = sort_array(m_indices(selected_aliases),#'<);
+
+ if(sizeof(alis))
{
- for(a=({}),i--; i>=0; i--)
- a+=({sprintf(ALIFORMAT, ali[i], present_alias( aliases[ali[i]] ) ) });
- More("Du hast folgende Aliase definiert:\n"+implode(a,"\n"));
+ foreach(string a : &alis)
+ a = sprintf( (familymode ? FALIFORMAT : ALIFORMAT),
+ a, present_alias(selected_aliases[a]) );
+ More("Du hast folgende "
+ + (familymode ? "Familien-" : "")
+ + "Aliase definiert:\n" + CountUp(alis, "\n"));
}
else
- write("Du hast keine Aliase definiert.\n");
+ write("Du hast keine "
+ +(familymode ? "Familien-" : "") + "Aliase definiert.\n");
return 1;
}
-static int
-_starts_with(string str, string start)
-{
- return (sizeof(start)>sizeof(str) ? 0
- : str[0..sizeof(start)-1]==start);
-}
-
static int alias(string str)
{
- string commandverb;
- string *tmp,um,*hits;
- int num, l, pos, cont;
- int display_as_aliascommand, familymode;
-
// unbearbeitetes Kommando ohne Verb ermitteln (auch ohne Trim an Anfang und
// Ende)
+ string um;
if (unmodified && unmodified!="")
um=implode(old_explode(unmodified," ")[1..]," ");
if (um=="") um=0;
if( !(str = um||_unparsed_args()) || str=="*")
- return query_aliases(0);
+ return query_aliases(0, 0);
+ // optionen auswerten bis keine mehr kommen, dabei vorne den String
+ // verkuerzen
+ int display_as_aliascommand, familymode;
while(sizeof(str) >= 2 && str[0] == '-')
{
if (str[1] == 'a')
@@ -288,25 +309,41 @@
str = trim(str[2..], TRIM_LEFT);
}
if (!sizeof(str) || str=="*")
- return query_aliases(display_as_aliascommand);
+ return query_aliases(display_as_aliascommand, familymode);
- pos=member(str,' ');
+ int pos=member(str,' ');
if (pos < 0) // Nur 1 Arg, Alias abfragen
{
- if ((tmp=aliases[str])) // genau eins angegebenen
- printf(ALIFORMAT+"\n",str,present_alias(tmp));
+ <string|int>* tmp;
+ if (familymode)
+ tmp=FALIASDB->QueryFamilyAlias(str);
+ else
+ tmp=aliases[str];
+
+ if (tmp) // genau eins angegebenen
+ printf((familymode ? FALIFORMAT : ALIFORMAT)
+ +"\n",str,present_alias(tmp));
else if (str[<1]=='*') // * am Ende, alle ausgeben, die passend anfangen
{
str=str[0..<2];
- hits=filter(m_indices(aliases), #'_starts_with, str);
+ mapping selected_aliases;
+ if (familymode)
+ selected_aliases=FALIASDB->QueryFamilyAlias();
+ else
+ selected_aliases = aliases;
+ string *hits=filter(m_indices(selected_aliases),
+ function int (string alname, string start)
+ { return strstr(alname, start) == 0; },
+ str);
if (!sizeof(hits))
{
printf("Du hast kein Alias, das mit \"%s\" anfaengt.\n", str);
return 1;
}
hits=sort_array(hits, #'>);
- for (l=sizeof(hits); l--;)
- hits[l]=sprintf(ALIFORMAT, hits[l], present_alias(aliases[hits[l]]));
+ foreach(string hit: &hits)
+ hit = sprintf((familymode ? FALIFORMAT : ALIFORMAT),
+ hit, present_alias(selected_aliases[hit]));
More("Folgende Aliase beginnen mit \""+str+"\":\n"+implode(hits,"\n"));
}
else // Nix gefunden
@@ -320,7 +357,7 @@
return 1;
}
// Kommandoverb alles bis zum ersten " ".
- commandverb=str[0..pos-1];
+ string commandverb=str[0..pos-1];
if (commandverb=="unalias")
{
write
@@ -334,70 +371,125 @@
return 1;
}
- str=str[pos+1..],tmp=({});
+ // ab hier wird der Expansionstext in ein Array von Strings geparst. Alle
+ // Alias-Argument ($n, $* oder $n*) stehen an der jeweiligen Stelle als
+ // laufender Index im Array. Negative Zahlen stehen fuer $n*, d.h. alle
+ // Argument nach dem genannten.
+ // Bsp: ({"stecke ", 1, " in ", -2 })
+ //TODO: regexplode("teile $1 mit $2* Ich bin jetzt weg, \$ verdienen!","[$][0-9][*]{0,1}",RE_PCRE)
+ str=str[pos+1..];
+ <string|int>* tmp=({}); // Alias-Array
+ int l, num;
while (l=sizeof(str)) {
- pos=0,cont=1;
- while (cont) {
- if (pos<l) {
- if(str[pos]=='\\') {
+ pos=0; // Positionszaehler in str
+ int cont=1; // Statusflag fuer inneres while
+ while (cont)
+ {
+ // innere Schleife: scannt ein Argument und haengt es als Element in
+ // tmp an. Laeuft ueber den String bis Stringende oder & oder $
+ // erreicht wird, dann ist ein Argument vollstaendig und das naechste
+ // faengt an.
+ if (pos<l)
+ {
+ if(str[pos]=='\\') // escapte '\' werden zu einzelnen '\'.
+ {
str=str[0..pos-1]+str[pos+1..];
l--;
- } else {
- if (str[pos]=='&' || str[pos]=='$') {
+ }
+ else
+ {
+ if (str[pos]=='$' || str[pos]=='&') // & ist historisch...
+ { // Argument-Platzhalter gefunden
cont=0;
- if (pos>0) {
+ if (pos>0) { // vorhergehender Textblock vollstaendig, anhaengen
tmp+=({str[0..pos-1]});
}
if (pos==l-1) {
printf("Fehler: %c am Zeilenende\n",str[pos]);
return 1;
}
- if ((num=str[++pos])=='*') {
+ // $* oder $n ? Im Falle von $n landet in num der ASCII-Wert des
+ // Zeichens, von welchem der Wert von '0' abgezogen wird -> num
+ // enthaelt danach 0..9, wenn eine Ziffer angegeben wurde.
+ num=str[++pos]; // naechstes Zeichen holen
+ if (num=='*') {
+ // Argument 1 und pos muss wieder eins zurueck.
num=1;
pos--;
} else {
num-='0';
}
if (num<0 || num>9) {
- printf("Fehler: Nach %c muss Ziffer oder * folgen\n",
+ printf("Fehler: Nach %c muss eine Ziffer oder * folgen\n",
str[pos-1]);
return 1;
}
- if ((str=str[pos+1..])!=""&&str[0]=='*') {
- str=str[1..];
- num=-num;
+ // str nach Argumentkennung weiter verarbeiten.
+ str=str[pos+1..];
+ // Aber fuer den Fall $n* das naechste Zeichen auch untersuchen
+ if (sizeof(str) && str[0]=='*') {
+ str=str[1..]; // auch ueberspringen
+ num = negate(num); // Im Array negiert kodieren
}
tmp+=({num});
}
}
- pos++;
- } else {
- cont=0;
- if (str!="") tmp+=({str});
- str="";
+ ++pos; // naechstes Zeichen im naechste inner while angucken
}
+ // Ende des gesamten Strings erreicht.
+ else
+ {
+ cont=0; // ende inner while
+ // letzten Argumentblock anhaengen
+ if (str!="") tmp+=({str});
+ str=""; // beendet outer while
+ }
+ } // inner while
+ } // outer while
+
+ if (familymode)
+ {
+ int err=FALIASDB->AddOrReplaceFamilyAlias(commandverb, tmp);
+ if (err < 1)
+ {
+ printf("Neues Familienalias konnte nicht definiert werden.\n");
+ if (err==-2)
+ printf("Du hast schon genuegend Aliase definiert!\n");
+ }
+ else
+ {
+ printf("Neues Familienalias: %s\t= %s\n",
+ commandverb, present_alias(tmp));
+ // Alias direkt aktivieren, aber nur falls es keins in diesem Char gibt
+ // (was dann eh schon aktiv ist).
+ if (!member(aliases, commandverb))
+ active_aliases[commandverb] = tmp;
}
}
- if ((!aliases[commandverb]) && (sizeof(aliases)>2000))
- printf("Du hast schon genuegend Aliase definiert!\n");
else
{
- aliases[commandverb]=tmp;
- printf("Neues Alias: %s\t= %s\n",commandverb, present_alias(tmp));
+ if ((!aliases[commandverb]) && (sizeof(aliases)>2000))
+ printf("Du hast schon genuegend Aliase definiert!\n");
+ else
+ {
+ aliases[commandverb]=tmp;
+ active_aliases[commandverb] = tmp;
+ printf("Neues Alias: %s\t= %s\n",commandverb, present_alias(tmp));
+ }
}
return 1;
}
static int unalias(string str) {
- int i, familymode;
- string *als,um;
+ string um;
if (unmodified&&unmodified!="")
um=implode(old_explode(unmodified," ")[1..]," ");
if (um=="") um=0;
if ( !(str=um || _unparsed_args()))
return 0;
+ int familymode;
while(sizeof(str) >= 2 && str[0] == '-')
{
if (str[1] == 'f')
@@ -414,22 +506,40 @@
"willst.",78));
return 1;
}
- if (!member(aliases,str))
+
+ mapping selected_aliases;
+ if (familymode)
+ selected_aliases=FALIASDB->QueryFamilyAlias();
+ else
+ selected_aliases = aliases;
+
+ string *to_delete;
+ // Genau ein Alias gegeben?
+ if (member(selected_aliases,str))
+ to_delete = ({str});
+ else // sonst als RegExp interpretieren
+ to_delete=regexp(m_indices(selected_aliases),("^"+str+"$"));
+
+ if (sizeof(to_delete))
{
- als=regexp(m_indices(aliases),("^"+str+"$"));
- if (!(i=sizeof(als)))
+ foreach(string key : to_delete)
{
- write("So ein Alias hast Du nicht definiert.\n");
- return 1;
+ if (familymode)
+ FALIASDB->DeleteFamilyAlias(key);
+ else
+ m_delete(aliases, key);
+ // auf jeden Fall noch deaktivieren
+ m_delete(active_aliases, key);
}
- for (--i;i>=0;i--)
- m_delete(aliases,als[i]);
- write(break_string(("Du entfernst folgende Aliase: "+
- implode(als," ")+".\n"),75));
- return 1;
+ if (sizeof(to_delete) == 1)
+ write("Du entfernst das Alias \""+ to_delete[0] +"\".\n");
+ else
+ write(break_string(("Du entfernst folgende Aliase: "
+ +CountUp(to_delete) + ".\n"),75));
}
- m_delete(aliases,str);
- write("Du entfernst das Alias \""+str+"\".\n");
+ else
+ write("So ein Alias hast Du nicht definiert.\n");
+
return 1;
}
@@ -637,9 +747,15 @@
string output = "";
string* input = explode(str," ");
int input_size = sizeof(input);
- mixed alias = aliases[input[0]];
+ mixed alias = active_aliases[input[0]];
if (!alias)
return str;
+ // Das Alias ist in ein Array von Strings gespeichert. Alle
+ // Alias-Argument ($n, $* oder $n*) stehen an der jeweiligen Stelle als
+ // laufender Index im Array. An der Stelle werden die Argumente vom Alias
+ // eingefuegt, alle anderen Elemente werden in den output kopiert. Negative
+ // Zahlen stehen fuer $n*, d.h. alle Argument nach dem genannten.
+ // Bsp: ({"stecke ", 1, " in ", -2 })
foreach (mixed a:alias)
{
if (!intp(a))
@@ -648,11 +764,14 @@
{
if (a >= 0)
{
+ // Einzelnes Argument ($n). Argument anstelle von a einfuegen, falls
+ // genug angegeben wurden
if (input_size > a)
output += input[a];
}
else
{
+ // Argumente ab n ($n*). Alle von a bis Ende einfuegen.
a = -a;
if (input_size > a)
output += implode(input[a..]," ");
@@ -814,7 +933,11 @@
int unalias_all()
{
- if (IS_ELDER(this_interactive())) aliases=([]);
+ if (IS_ELDER(this_interactive()))
+ {
+ aliases=([]);
+ merge_family_aliases();
+ }
return 1;
}