#include <adv3.h>
#include <en_us.h>
/*
* easyListing.t - a TADS 3 extension
* Email:
[email protected]
*
* This extension allows you to print simple lists (or vectors) of objects
* using the message parameter substitution system. It works much like the
* Inform 7 list-printing mechanism.
*
* To print a list with indefinite articles, use "{a/list listName}". To print
* a list with definite articles, use "{the/list listName}". To print a list
* with no articles, use "{list listName}". Remember to register the list with
* the message parameter substitution system first, for instance
* "gMessageParams(listName);".
*
* If you want finer-grained control over what your list looks like, you can
* call "listName.showListWith(whicheverListerYouWantToUse)".
*
* This extension is open source software licensed under the MIT Licence:
*
* Copyright (c) 2013 Emily Boegheim
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Change history:
*
* 0.3
* - renamed extension
* - cleaned up the documentation a bit
* - added licence information
*
* 0.2
* - rewrote some of the code to be more respectful of the library code
*
* 0.1
* - initial version
*/
/* Info on the extension, so it will show up in the list of credits. */
easyListingModuleID: ModuleID
name = 'Easy Listing'
byline = 'by Emily Boegheim'
htmlByline = 'by <a href="mailto:
[email protected]">Emily
Boegheim</a>'
version = '0.3'
;
/*
* Adding methods to show and return lists, and to use the correct grammar
* when referring to a list.
*/
modify Collection
/* A generic method for showing this list with any given Lister. */
showListWith(lister) {
lister.showListAll(self, 0, nil);
}
/*
* Wrapper methods for particular listers - plainLister (uses
* indefinite pronouns), theLister (uses definite pronouns), and
* noArticleLister (uses no pronouns). Instead of printing the lists,
* these methods catch the output and return it. This is for message
* substitution parameters, which require a text value to be returned
* rather than printed.
*/
getAList() {
return mainOutputStream.captureOutput(new function
{showListWith(SimpleLister);});
}
getTheList() {
return mainOutputStream.captureOutput(new function
{showListWith(theLister);});
}
getPlainList() {
return mainOutputStream.captureOutput(new function
{showListWith(noArticleLister);});
}
/*
* Decide whether the list is plural or not. If it has more than one
* object in it, or if the single object in it is plural, the list is
* plural.
*/
isPlural() {
return (length > 1 || (length == 1 && self[1].isPlural));
}
/*
* Methods for generating associated verbs - this is for the message
* parameter substitution system. We'll just delegate to Thing.
*/
verbToBe() { return delegated Thing(); }
verbWas { return delegated Thing(); }
verbToHave { return delegated Thing(); }
verbToDo = delegated Thing()
verbToGo = delegated Thing()
verbToCome = delegated Thing()
verbToLeave = delegated Thing()
verbToSee = delegated Thing()
verbToSay = delegated Thing()
verbMust = delegated Thing()
verbCan = delegated Thing()
verbCannot = delegated Thing()
verbCant = delegated Thing()
verbWill = delegated Thing()
verbWont = delegated Thing()
verbEndingS { return delegated Thing(); }
verbEndingSD = delegated Thing()
verbEndingSEd = delegated Thing()
verbEndingSMessageBuilder_ = delegated Thing()
verbEndingEs { return delegated Thing(); }
verbEndingIes { return delegated Thing(); }
/*
* Methods to return the correct pronouns for the list; again, for the
* message parameter substitution system.
*/
itNom { return (isPlural ? 'they' : (length == 1 ? delegated self[1] : 'it')); }
itObj { return (isPlural ? 'them' : (length == 1 ? delegated self[1] : 'it')); }
itPossAdj { return (isPlural ? 'their' : (length == 1 ? delegated self[1] : 'its')); }
itPossNoun { return (isPlural ? 'theirs' : (length == 1 ? delegated self[1] : 'its')); }
itReflexive
{
return (isPlural ? 'themselves' : (length == 1 ? delegated self[1] : 'itself'));
}
thatNom { return (isPlural ? 'those' : (length == 1 ? delegated self[1] : 'that')); }
thatIsContraction
{
return delegated Thing();
}
thatObj { return (isPlural ? 'those' : (length == 1 ? delegated self[1] : 'that')); }
itIs { return delegated Thing(); }
itIsContraction { return delegated Thing(); }
/*
* The pronoun selector. This will only get called when there is a
* single item in the list and a method has been delegated to that
* item. So we'll delegate this to that single item as well.
*/
pronounSelector = delegated self[1]
/* "dummyName", for the "subj" message parameter substition trick. */
dummyName = ''
;
/* Add new options for choosing which articles to use in a list. */
modify SimpleLister
definiteArticle = ListerCustomFlag(1)
noArticle = ListerCustomFlag(2)
;
/* Modify Thing.showListItem to check which article to use. */
modify Thing
showListItemGen(options, pov, infoTab, stateNameProp)
{
local info;
local st;
local stName;
/* get my visual information from the point of view */
info = infoTab[self];
/* check which article to use */
local nameProp;
if (options & SimpleLister.noArticle)
nameProp = &name;
else if (options & SimpleLister.definiteArticle)
nameProp = &theName;
else
nameProp = &listName;
/* show the item's list name */
say(withVisualSenseInfo(pov, info, nameProp));
/*
* If we have a list state with a name, show it. Note that to
* obtain the state name, we have to pass a list of the objects
* being listed to the stateNameProp method of the state object;
* we're the only object we're showing for this particular
* display list element, so we simply pass a single-element list
* containing 'self'.
*/
if ((st = getStateWithInfo(info, pov)) != nil
&& (stName = st.(stateNameProp)([self])) != nil)
{
/* we have a state with a name - show it */
gLibMessages.showListState(stName);
}
}
;
/* The theLister prints a simple list with definite articles. */
theLister: SimpleLister
showList(pov, parent, lst, options, indent, infoTab, parentGroup) {
options = options | definiteArticle;
inherited(pov, parent, lst, options, indent, infoTab, parentGroup);
}
;
/* The noArticleLister prints a simple list with no articles. */
noArticleLister: SimpleLister
showList(pov, parent, lst, options, indent, infoTab, parentGroup) {
options = options | noArticle;
inherited(pov, parent, lst, options, indent, infoTab, parentGroup);
}
;
/* Add the new message parameters to the message builder. */
modify langMessageBuilder
paramList_ = static inherited() + [
['list', &getPlainList, nil, nil, nil],
['the/list', &getTheList, nil, nil, nil],
['a/list', &getAList, nil, nil, nil]
]
;