parent $libraries
object $string
var $root child_index 0
var $root owners [$string, $sys]
var $root fertile 0
var $root inited 1
var $string alphabet "abcdefghijklmnopqrstuvwxyz"
var $string numbers "1234567890"
var $string non_alphanumeric "!@#$%^&*()_+-=~`'{}[]|/?\"\\,.<>;: "
var $root owned [$string]
var $root manager $string
var $root writable [$string]
var $root readable ['parameters, 'methods, 'code]
var $root dbref 'string
method left
arg str, width, [fchar];
// will NOT chop off 'str' if it is longer than width, use pad() for that.
if (fchar)
return str + ((strlen(str) < width) ? pad("", width - strlen(str), fchar[1]) | "");
else
return str + ((strlen(str) < width) ? pad("", width - strlen(str)) | "");
.
method fill
arg n, [args];
var fill, x;
// same as pad("", n, [args]);
fill = [@args, " "][1];
return pad("", n, fill);
.
method center
arg text, len, [args];
var lfill, rfill, textlen, padlen;
// args[1] == string to center
// args[2] == integer of width to center in
// args[3] <op> == what to fill the left|right side with.
// args[4] <op> == what to fill the right side with.
lfill = ((listlen(args) >= 1) && (args[1])) || " ";
rfill = (listlen(args) >= 2) ? args[2] | ((lfill == " ") ? "" | lfill);
textlen = strlen(text);
padlen = (len - textlen) / 2;
if (textlen < len)
return ((.fill(padlen, lfill)) + text) + (rfill ? .fill(padlen, rfill) | "");
else
return (len > 0) ? text | pad(text, len);
.
method trim
arg string, [args];
var rl, chars, type;
// remove leading and trailing characters.
// if args includes a string, it takes that as the strip string.
// args can also include symbols of what edge to trim: 'left 'right (or both)
// left and right defaults on.
rl = [];
while (args) {
type = type(args[1]);
if (type == 'string)
chars = args[1];
else if (type == 'symbol)
rl = [@rl, args[1]];
args = sublist(args, 2);
}
if (!chars)
chars = " ";
if (!rl)
rl = ['left, 'right];
if ('left in rl) {
// strip from left
while (string && ((string[1]) in chars))
string = substr(string, 2);
}
if ('right in rl) {
// strip from right
while (string && ((string[strlen(string)]) in chars))
string = substr(string, 1, strlen(string) - 1);
}
return string;
.
method to_list
arg str, [sep];
var result, list;
// separate a string into a list of strings, breaking wherever 'sep' appears.
// if not provided, sep defaults to a comma.
// One word of warning. sep should not contain an asterisk. If it does,
// this routine will separate the string oddly, most likely losing bits.
if (!str)
return [];
sep = ("*" + (sep ? sep[1] | ",")) + "*";
list = [];
while (1) {
result = match_pattern(sep, str);
if (result) {
list = list + [result[1]];
str = result[2];
} else {
return list + [str];
}
}
.
method right
arg str, width, [fchar];
// will not chop off 'str' if it is longer than width (unlike pad())
if (fchar)
return pad("", width - strlen(str), fill_char[1]) + str;
else
return pad("", width - strlen(str)) + str;
.
method alphabet
return alphabet;
.
method numbers
return numbers;
.
method capitalize
arg string;
// Capitalizes the first character of a word.
return uppercase(string[1]) + substr(string, 2);
.
method is_numeric
arg string;
return toint(string) || (string == "0");
.
method a_or_an
arg string;
if (lowercase(string[1]) in "aeiou")
return "an";
return "a";
.
method strip
arg string, strip;
var new_str, char;
// strips all of "strip" characters from the string
// if "strip" is -1 it will use .non_alphanumeric()
if ((type(string) != 'string) || ((type(strip) != 'string) && (strip != (-1))))
throw(~type, "First argument must be a string, second can be -1");
new_str = "";
if (strip == (-1))
new_str = non_alphanumeric;
for char in [1 .. strlen(string)] {
if (!((string[char]) in strip))
new_str = new_str + (string[char]);
}
return new_str;
.
method non_alphanumeric
return non_alphanumeric;
.
method chop
arg str, len, [end];
// chops string off strlen(end) characters before len and appends len
end = [@end, "..."][1];
if (strlen(str) < len)
return str;
if (strlen(str) < strlen(end))
return str;
return pad(str, len - strlen(end)) + end;
.
method replace
arg string, replace, [char];
var new_str, character;
// replaces 'replace' with the character in 'char'
// if 'replace' is -1 will use .non_alphanumeric();
if ((type(string) != 'string) || ((type(replace) != 'string) && (strip != (-1))))
throw(~type, "First argument must be a string, second can be -1");
char = [@char, " "][1];
new_str = "";
if (replace == (-1))
new_str = non_alphanumeric;
for character in [1 .. strlen(string)] {
if (!((string[character]) in replace))
new_str = new_str + (string[character]);
else
new_str = new_str + char;
}
return new_str;
.
method explode_english_list
arg line, [opts];
var x, output, tmp;
// explodes an english list ("foo, bar and zoo").
line = explode(line, ",");
output = [];
for x in (line) {
x = .trim(x);
if ((| substr(x, 1, 3) |) == "and")
output = [@output, .trim(substr(x, 4))];
else
output = [@output, x];
}
// check the last element, if they didn't specify 'noand
if (!('noand in opts)) {
line = explode(output[listlen(output)]);
tmp = "";
for x in [1 .. listlen(line)] {
if ((line[x]) == "and") {
output = delete(output, listlen(output));
if (tmp)
output = [@output, tmp];
tmp = $list.to_string(sublist(line, x + 1));
if (tmp)
output = [@output, tmp];
// only bother with the first "and"
break;
}
tmp = (tmp + (tmp ? " " | "")) + (line[x]);
}
}
return output;
.
method explode_delimited
arg str, left, right;
var pattern, parsed, matched, match_num, match_result;
// parse str looking for anything surrounded by left and right
// ;$string.explode_delimited("foo%[bar]baz", "%[", "]")
// => [["foo", 1, "baz"], ["bar"]]
pattern = ((("*" + left) + "*") + right) + "*";
parsed = [];
matched = [];
match_num = 0;
while (str) {
match_result = match_pattern(pattern, str);
if (match_result) {
match_num = match_num + 1;
parsed = [@parsed, match_result[1], match_num];
matched = [@matched, match_result[2]];
str = match_result[3];
} else {
parsed = [@parsed, str];
str = "";
}
}
return [parsed, matched];
.
method wrap_line
arg string, length, [stuff];
var output, cutoff, firstline, prefix;
// takes string and wraps it by words, compared to length, returns a list.
prefix = [@stuff, ""][1];
firstline = [@stuff, 0, 0][2];
output = [];
length = length - strlen(prefix);
if (firstline)
string = prefix + string;
while (strlen(string) > length) {
cutoff = .rindex(substr(string, 1, length), " ");
output = [@output, substr(string, 1, cutoff - 1)];
string = prefix + substr(string, cutoff + 1);
}
return [@output, string];
.
method rindex
arg string, index;
var loc, rest;
// returns the first occurance of index starting from the end of the string,
// and moving to the beginning.
loc = index in string;
rest = loc && substr(string, loc + 1);
while (loc && (index in rest)) {
loc = loc + (index in rest);
rest = loc && substr(string, loc + 1);
}
return loc;
.
method match_sub_tag
arg string, tag;
var x, expl, output, match, matches;
// matches a string between 'tag' and " " in a larger string against
// the sender's environment. If a match is found it subs the match.name
// with the string, otherwize it lets it pass through with the tag, ie:
// .match_sub_tag("this test #of something #note or other");
// => "this test #of something Note of sorts or other"
// where the note is in the sender's environment.
expl = .explode_delimited(string + " ", tag, " ");
matches = expl[2];
expl = expl[1];
output = "";
for x in (expl) {
if (type(x) == 'integer) {
match = (| sender().match_environment(matches[x]) |);
if (match)
output = (output + (match.namef())) + " ";
else
output = ((output + tag) + (matches[x])) + " ";
} else {
output = output + x;
}
}
return substr(output, 1, strlen(output) - 1);
.
method search_pat
arg pat, text, [start_at];
var line, match_result, type;
line = 1;
type = (([@start_at, 'pattern, 'pattern][2]) == 'pattern) ? 'match_pattern | 'match_regexp;
if (start_at) {
line = start_at[1];
start_at = [@start_at, 1, 1][2];
match_result = pat.(type)(substr(text[line], line));
if (match_result != 0) {
if (type == 'match_pattern) {
pat = $string.pat_sub(pat, match_result);
return [line, (start_at + pat) in substr(text[line], start_at)];
} else {
return [line, start_at + ((match_result[1])[1])];
}
}
line = line + 1;
}
while (line <= listlen(text)) {
match_result = pat.(type)(text[line]);
if (match_result != 0) {
if (type == 'pattern) {
pat = $string.pat_sub(pat, match_result);
return [line, pat in (text[line])];
} else {
return [line, (match_result[1])[1]];
}
}
line = line + 1;
}
throw(~strnf, "String not found in text.");
.
method pat_sub
arg pat, subs;
var wc_idx;
// wc_idx == wildcard index
while (subs) {
wc_idx = "*" in pat;
if (wc_idx == 1)
pat = (subs[1]) + substr(pat, 2);
else if (wc_idx == strlen(pat))
pat = substr(pat, 1, wc_idx - 1) + (subs[1]);
else
pat = (substr(pat, 1, wc_idx - 1) + (subs[1])) + substr(pat, wc_idx + 1);
subs = delete(subs, 1);
}
return pat;
.
method is_boolean
arg str;
if (match_begin("yes", str) || (match_begin("true", str) || (str == "1")))
return 1;
else if (match_begin("no", str) || (match_begin("false", str) || (str == "0")))
return 0;
else
return -1;
.
method parse_template
arg str;
var index, out;
out = explode(str, " *")[1];
// index = "?" in str;
// if (index) {
// out = uppercase(substr(str, 1, index - 1));
// out = out + "?" + substr(str, index + 1);
// } else {
// out = uppercase(out);
// }
return out;
.
method repeat
arg string, times;
var t, out;
// repeats <string> <times> times
if (type(string) != 'string)
throw(~type, "The first agrument must be a string.");
if ((type(times) != 'integer) || (times < 0))
throw(~type, "The second agrument must be a non-negatiive integer.");
out = "";
for t in [1 .. times]
out = out + string;
return out;
.
method explode
arg [args];
return (> explode(@args) <);
.
method match_template
arg [args];
return (> match_template(@args) <);
.
method find_next
arg str, choices;
var t, first, pos;
//Returns the index of the first string in choices to appear.
//Returns strlen(str) if none are in str.
first = strlen(str) + 1;
for t in (choices) {
pos = t in str;
if (pos && (pos < first))
first = pos;
}
return first;
.
method split_on_next
arg str, choices;
var pos, pre, post;
// splits str around whichever choice appears first.
pos = $string.find_next(str, choices);
pre = (| substr(str, 1, pos - 1) |) || "";
post = (| substr(str, pos + 1) |) || "";
return [pre, (| str[pos] |) || "", post];
.
method explode_template_word
arg template;
var t, x, idx, out, new;
// this only explodes single word templates
template = explode(template, "|");
out = [];
for t in (template) {
idx = "?" in t;
if (idx) {
t = t.strip("?");
new = substr(t, 1, idx - 1);
out = [@out, new];
for x in [idx .. strlen(t)] {
new = new + (t[x]);
out = [@out, new];
}
} else {
out = [@out, t];
}
}
return out;
.
method match_pattern
arg [args];
return (> match_pattern(@args) <);
.
method match_regexp
arg [args];
return (> match_regexp(@args) <);
.
method to_number
arg str;
if (str.is_numeric())
return toint(str);
throw(~type, ("\"" + str) + "\" is not a number.");
.