I am trying to teach myself how to write custom macros in Twine, and decided to start with something a bit simpler than
this problem here, so I figured a case macro might be quite handy as there doesn't appear to be anything built into Twine for this.
Using the code posted by TheMadExile
here, I decided to try and adapt it, and I do appear to have something that seems to work for pieces of text.
Code:
Upper : <<changecase "upper">>tHisIsAtEsT<<endchangecase>>
Lower : <<changecase "lower">>tHisIsAtEsT<<endchangecase>>
Proper : <<changecase "proper">>tHisIsAtEsT<<endchangecase>>
Incorrect use: <<changecase>>tHisIsAtEsT<<endchangecase>>
Script:
//casemacro allows user to change text case to uppercase, lowercase or proper/titlecase.
//usage examples:
// <<changecase "upper">>text<<endchangecase>>
// <<changecase "lower">>text<<endchangecase>>
// <<changecase "proper">>text<<endchangecase>>
version.extensions["caseMacro"] = { major: 1, minor: 0, revision: 0 };
macros["changecase"] =
{
handler: function(place, macroName, params, parser)
{
if (params.length === 0)
{
throwError(place, "<<" + macroName + ">>: Please specify case type i.e. upper, lower or proper");
return;
}
// process the contents of the container macro
var openTag = macroName
, closeTag = "end" + macroName
, start = parser.source.indexOf(">>", parser.matchStart) + 2
, end = -1
, tagBegin = start
, tagEnd = start
, opened = 1;
while ((tagBegin = parser.source.indexOf("<<", tagEnd)) !== -1
&& (tagEnd = parser.source.indexOf(">>", tagBegin)) !== -1)
{
var tagName = parser.source.slice(tagBegin + 2, tagEnd)
, tagDelim = tagName.search(/\s/);
if (tagDelim !== -1)
{
tagName = tagName.slice(0, tagDelim);
}
tagEnd += 2;
switch (tagName)
{
case closeTag:
opened--;
break;
case openTag:
opened++;
break;
}
if (opened === 0)
{
end = tagBegin;
break;
}
}
// if we successfully found an end tag for the macro
if (end !== -1)
{
parser.nextMatch = tagEnd;
this.n = params[0];
if (this.n === "upper") //changes the spanned text with uppercase text
{
this.m = parser.source.slice(start, end);
this.f = this.m.toUpperCase();
}
else if (this.n === "lower") //changes the spanned text with lowercase text
{
this.m = parser.source.slice(start, end);
this.f = this.m.toLowerCase();
}
else if (this.n === "proper") //changes the spanned text with proper/titlecase text - note currently this only works for the first word in a sentence.
{
this.m = parser.source.slice(start, end);
this.f = this.m.slice(0,1).toUpperCase() + this.m.slice(1).toLowerCase();
}
new Wikifier(place, this.f);
}
else
{
throwError(place, "<<" + macroName + ">>: cannot find a matching close tag");
}
},
};
macros["endchangecase"] = { handler: function () {} };
Now, the thing is, this doesn't seem to play well with a <<print $variable>> nested between the start and end tags, with Twine returning a Macro not found: Print error if I try to nest it. The original code this was adapted from seems to have a <<print>> macro nested within the start and end tags, so I presumed that it should work. So, I guess I'm wondering why it doesn't, because really, this changecase macro would come in handy mainly for use with variables (for instance, if you wish to use title case on a variable because it comes at the end of the sentence, or you have an NPC shouting the characters player defined name). I know these can be achieved with javascript, but I know it'd come in handy for me to have a case macro like this just so I don't have to remember what the correct piece of javascript is all the time.
As always, any help or advice is much appreciated!
Comments
Obviously I'm still very new to this, so just trying to study as many examples as custom macros as I can to get an idea of how they can be built/used.