Hello, my contribution to the tbamud code, syntax highlighting will help many new and old builders better understand the scripts.
Feel free to use, share and improve the code.
The only problem I see is in the social commands, should identify and color only if the social is the beginning of the line, is currently coloring anywhere in the command.
+++ file: dg_olc.c, in function: void trigedit_parse(struct descriptor_data *d, char *arg)
+++ file: dg_olc.c, add the following lines before function: void trigedit_parse(struct descriptor_data *d, char *arg)
Code:
/****************************************************************************************
DG Scripts Code Syntax Highlighting
Created by Victor Almeida (aka Stoneheart) in Brazil
from BrMUD:Tormenta www.tormenta.com.br (mudbrasil@gmail.com)
License: Attribution 4.0 International (CC BY 4.0)
http://creativecommons.org/licenses/by/4.0/
You are free to:
Share — copy and redistribute the material in any medium or format
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and indicate
if changes were made. You may do so in any reasonable manner, but not in any way that
suggests the licensor endorses you or your use.
*****************************************************************************************/
// Change a string for another without memory bugs
char *str_replace(const char *string, const char *substr, const char *replacement) {
char *tok = NULL;
char *newstr = NULL;
char *oldstr = NULL;
char *head = NULL;
// if either substr or replacement is NULL, duplicate string a let caller handle it
if (substr == NULL || replacement == NULL) {
return strdup (string);
}
newstr = strdup (string);
head = newstr;
while ((tok = strstr(head, substr))) {
oldstr = newstr;
newstr = malloc(strlen(oldstr) - strlen(substr) + strlen (replacement) + 1);
// Failed to alloc mem, free old string and return NULL
if (newstr == NULL) {
free (oldstr);
return NULL;
}
memcpy (newstr, oldstr, tok - oldstr);
memcpy (newstr + (tok - oldstr), replacement, strlen (replacement));
memcpy (newstr + (tok - oldstr) + strlen(replacement), tok + strlen (substr), strlen (oldstr) - strlen (substr) - (tok - oldstr));
memset (newstr + strlen (oldstr) - strlen(substr) + strlen (replacement) , 0, 1 );
// move back head right after the last replacement
head = newstr + (tok - oldstr) + strlen( replacement);
free (oldstr);
}
return newstr;
}
// You can easily change the color code (\tn) to the old one (@n or &n)
#define SYNTAX_TERMS 49
const char *syntax_color_replacement[SYNTAX_TERMS][2] =
{
// script logic (10)
{ "if", "\tcif\tn" }, // 0
{ "elseif", "\tcelseif\tn" },
{ "else", "\tcelse\tn" },
{ "end", "\tcend\tn" },
{ "switch", "\tcswitch\tn" },
{ "case", "\tccase\tY" },
{ "default", "\tcdefault\tn" },
{ "break", "\tcbreak\tn" },
{ "while", "\tcwhile\tn" },
{ "done", "\tcdone\tn" },
// commands (15)
{ "eval ", "\tceval\tY " }, //10
{ "nop ", "\tcnop\tY " },
{ "extract ", "\tcextract\tY " },
{ "dg_letter ", "\tcdg_letter\tY " },
{ "makeuid ", "\tcmakeuid\tY " },
{ "dg_cast ", "\tcdg_cast\tY " },
{ "dg_affect ", "\tcdg_affect\tY " },
{ "global ", "\tcglobal\tY " },
{ "context ", "\tccontext\tY " },
{ "remote ", "\tcremot\tce\tY " },
{ "rdelete ", "\tcrdelete\tY " }, // 20
{ "set ", "\tcset\tY " },
{ "unset ", "\tcunset\tY " },
{ "attach ", "\tcattach\tY " },
{ "detach ", "\tcdetach\tY " },
// stopping (3)
{ "wait", "\trwait" },
{ "return", "\trreturn" },
{ "halt", "\trhalt" },
// operands (12)
{ "||", "\tc||\tY" },
{ "&&", "\tc&&\tY" },
{ "==", "\tc==\tY" }, // 30
{ "!=", "\tc!=\tY" },
{ "<=", "\tc<=\tY" },
{ ">=", "\tc>=\tY" },
{ "< ", "\tc< \tY" },
{ "> ", "\tc> \tY" },
{ "/=", "\tc/=\tY" },
{ "!", "\tc!\tn" },
{ "(", "\tc(\tY" },
{ ")", "\tc)\tn" },
// corrective (4)
{ "\tc!\tn=", "\tc!=\tY" }, // 40
{ "%s\tcend\tn%", "\tm%\tosend%\tn" },
{ "%\tc)", "\tm%\tc)" },
{ ")\tn%", ")\tm%"},
// variables (5)
{ "% ", "\tm%\tn " },
{ "%,", "\tm%\tn," },
{ "%.", "\tm%\tn." },
{ "%:", "\tm%\tn:" },
{ "%", "\tm%\to" } // 48
};
// Here you can include more commands usually used in your triggers
#define COMMAND_TERMS 35
const char *command_color_replacement[COMMAND_TERMS][2] =
{
// Mob specific commands (25)
{ "marena", "\tcmarena\tn" }, // 0
{ "masound", "\tcmasound\tn" },
{ "mkill", "\tcmkill\tn" },
{ "mjunk", "\tcmjunk\tn" },
{ "mdamage", "\tcmdamage\tn" },
{ "mdoor", "\tcmdoor\tn" },
{ "mecho", "\tcmecho\tn" },
{ "mrecho", "\tcmrecho\tn" },
{ "mechoaround", "\tcmechoaround\tn" },
{ "msend", "\tcmsend\tn" },
{ "mload", "\tcmload\tn" }, // 10
{ "mpurge", "\tcmpurge\tn" },
{ "mgoto", "\tcmgoto\tn" },
{ "mteleport", "\tcmteleport\tn" },
{ "mforce", "\tcmforce\tn" },
{ "mhunt", "\tcmhunt\tn" },
{ "mremember", "\tcmremember\tn" },
{ "mforget", "\tcmforget\tn" },
{ "mtransform", "\tcmtransform\tn" },
{ "mzoneecho", "\tcmzoneecho\tn" },
{ "mfollow", "\tcmfollow\tn" }, // 20
{ "mquest", "\tcmquest\tn" },
{ "malign", "\tcmalign\tn" },
{ "mcast", "\tcmcast\tn" },
{ "mdismiss", "\tcmdismiss\tn" },
// common commands (10)
{ "drop ", "\tcdrop \tn" },
{ "emote ", "\tcemote \tn" },
{ "give ", "\tcgive \tn" },
{ "say ", "\tcsay \tn" },
{ "tell ", "\tctell \tn" },
{ "unlock ", "\tcunlock \tn" }, // 30
{ "lock ", "\tclock \tn" },
{ "open ", "\tcopen \tn" },
{ "close ", "\tcclose \tn" },
{ "junk ", "\tcjunk \tn" } // 34
};
void script_syntax_highlighting(struct descriptor_data *d, char *string)
{
ACMD(do_action);
char buffer[MAX_STRING_LENGTH] = "";
char *newlist, *curtok;
int i;
// Parse script text line by line
newlist = strdup(string);
for (curtok = strtok(newlist, "\r\n"); curtok; curtok = strtok(NULL, "\r\n")) {
char *line = strdup(curtok);
bool comment = FALSE;
// Find if is a comment
for (i=0;i <= strlen(line);i++) {
// skip initial spaces
if (strncmp(&line[i], " ", 1) == 0) {
continue;
}
// is a comment, highlight
if (strncmp(&line[i], "*", 1) == 0) {
line = str_replace(line, "*", "\tg*");
comment = TRUE;
break;
}
// not a comment
else {
comment = FALSE;
break;
}
}
// Highlight lines
if (!comment) {
// Syntax replacement
for (i=0;i <= SYNTAX_TERMS;i++) {
line = str_replace(line, syntax_color_replacement[i][0], syntax_color_replacement[i][1]);
}
// Commands replacement
for (i=0;i <= COMMAND_TERMS;i++) {
line = str_replace(line, command_color_replacement[i][0], command_color_replacement[i][1]);
}
// Socials replacement (experimental)
int cmd;
for (cmd = 0; *complete_cmd_info[cmd].command != '\n'; cmd++) {
if (complete_cmd_info[cmd].command_pointer == do_action) {
char replace_social[MAX_INPUT_LENGTH];
sprintf(replace_social, "\tc%s\tn", complete_cmd_info[cmd].command);
line = str_replace(line, complete_cmd_info[cmd].command, replace_social);
}
}
}
sprintf(buffer, "%s%s\tn\r\n", buffer, line);
}
page_string(d, buffer, TRUE);
}
/****************************************************************************************/