Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom lists - Fix issue #16 #17

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,27 @@ Sentencer.configure({
// the list of adjectives to use. Again, Sentencer comes with one!
adjectiveList: [],

// additional lists that generate actions for the template engine to use.
customLists: [
{
// add action for animal
key: "animal",
values: ["dog", "cat", "elephant"],
// if named, add action for articlize
articlize: "an_animal",
// if named, add action for pluralize
pluralize: "animals"
},
{
key: "band",
values: ["The Beatles", "The Who", "Styx"],
// no key or empty value, don't articlize
articlize: "",
// no key or empty value, don't pluralize
pluralize: ""
}
],

// additional actions for the template engine to use.
// you can also redefine the preset actions here if you need to.
// See the "Add your own actions" section below.
Expand Down Expand Up @@ -145,6 +166,29 @@ console.log( Sentencer.make("I can count to {{ number(8, 10) }}.")
// "I can count to 8."
```

### Add your own custom lists
When configuring `Sentencer` you can provide your own custom lists, which are converted to "actions". The `key` sets the name of the action and the `values` the list of values where one is selected when the action is called. You can also specify a name for the `articlize` and/or `pluralize` actions. These names are referenced within a sentence template.

Here is an example of an animal list that includes options to prefix with an article or to make it plural.

```javascript
var Sentencer = require('sentencer');

Sentencer.configure({
customLists: [
{
key: "animal",
values: ["dog", "cat", "elephant"],
articlize: "an_animal",
pluralize: "animals"
}
],
});

console.log( Sentencer.make("I saw {{ an_animal }}, 1 {{ animal }}, and 2 {{ animals }}.")
// "I saw an elephant, 1 dog, and 2 cats."
```

### Where are the verbs?

Verb pluralization, singularization, and tense modification are difficult computer science problems. `Sentencer` doesn't aim to solve those problems, however _present tense_ verb pluralization/singularization is an experimental feature of [`natural`](https://github.com/NaturalNode/natural) and could be integrated if necessary.
Expand Down
36 changes: 29 additions & 7 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,47 @@ function Sentencer() {
return randy.choice(self._nouns);
},
a_noun: function() {
return articles.articlize( self.actions.noun() );
return articles.articlize(self.actions.noun());
},
nouns: function() {
return nounInflector.pluralize( randy.choice(self._nouns) );
return nounInflector.pluralize(randy.choice(self._nouns));
},
adjective: function() {
return randy.choice(self._adjectives);
},
an_adjective: function() {
return articles.articlize( self.actions.adjective() );
return articles.articlize(self.actions.adjective());
}
};

// function definitions
self._func_normal = function(values) {
return randy.choice(values);
}
self._func_articlize = function(name) {
return articles.articlize( self.actions[name]() );
}
self._func_pluralize = function(values) {
return nounInflector.pluralize( randy.choice(values) );
}

self.configure = function(options) {
// merge actions
self.actions = _.merge(self.actions, options.actions || {});
self.actions = _.merge(self.actions, options.actions || {});
// overwrite nouns and adjectives if we got some
self._nouns = options.nounList || self._nouns;
self._adjectives = options.adjectiveList || self._adjectives;
self._nouns = options.nounList || self._nouns;
self._adjectives = options.adjectiveList || self._adjectives;
self._customLists = options.customLists || [];

self._customLists.forEach(item => {
self.actions[item.key] = self._func_normal.bind(null, item.values);
if (item.articlize) {
self.actions[item.articlize] = self._func_articlize.bind(null, item.key);
}
if (item.pluralize) {
self.actions[item.pluralize] = self._func_pluralize.bind(null, item.values);
}
});
};

self.use = function(options) {
Expand Down Expand Up @@ -70,7 +92,7 @@ Sentencer.prototype.make = function(template) {
var actionContents = action.match(/\((.+?)\)/);
actionContents = actionContents && actionContents[1];

if (actionExists && actionContents) {
if(actionExists && actionContents) {
try {
var args = _.map(actionContents.split(','), maybeCastToNumber);
result = self.actions[actionName].apply(null, args);
Expand Down
41 changes: 30 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 45 additions & 9 deletions tests/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,32 +65,53 @@ describe('Sentencer:', function() {
assert(Sentencer.make);
});

it('should merge a new custom list', function() {
Sentencer.configure({
customLists: [
{
key: "animal",
values: ["dog", "cat", "elephant"],
articlize: "an_animal", // if named, add action that calls articlize
pluralize: "animals" // if named, add action that calls pluralize
}
]
});

assert(Sentencer.actions.animal);
assert(Sentencer.actions.an_animal);
assert(Sentencer.actions.animals);

assert.notEqual(["dog", "cat", "elephant"].indexOf(Sentencer.actions.animal()), -1, "missing animal");
assert.notEqual(["a dog", "a cat", "an elephant"].indexOf(Sentencer.actions.an_animal()), -1, "missing an_animal");
assert.notEqual(["dogs", "cats", "elephants"].indexOf(Sentencer.actions.animals()), -1, "missing animals");
});

});

describe('Templating', function() {

describe('# Default Actions', function() {

it('{{ noun }}', function(){ assert(Sentencer.make('{{ noun }}')); });
it('{{ a_noun }}', function(){ assert(Sentencer.make('{{ a_noun }}')); });
it('{{ nouns }}', function(){ assert(Sentencer.make('{{ nouns }}')); });
it('{{ adjective }}', function(){ assert(Sentencer.make('{{ adjective }}')); });
it('{{ an_adjective }}', function(){ assert(Sentencer.make('{{ an_adjective }}')); });
it('{{ noun }}', function() { assert(Sentencer.make('{{ noun }}')); });
it('{{ a_noun }}', function() { assert(Sentencer.make('{{ a_noun }}')); });
it('{{ nouns }}', function() { assert(Sentencer.make('{{ nouns }}')); });
it('{{ adjective }}', function() { assert(Sentencer.make('{{ adjective }}')); });
it('{{ an_adjective }}', function() { assert(Sentencer.make('{{ an_adjective }}')); });

});

describe('# Custom Actions', function() {

it('{{ firstNewAction }}', function(){
it('{{ firstNewAction }}', function() {
assert.equal(Sentencer.make('{{ firstNewAction }}'), 'hello');
});

it('{{ secondNewAction }}', function(){
it('{{ secondNewAction }}', function() {
assert.equal(Sentencer.make('{{ secondNewAction }}'), 'hello again');
});

it('should return {{ action }} if it does not exist', function(){
assert.equal( Sentencer.make('{{ nonexistant thing }}'), '{{ nonexistant thing }}');
it('should return {{ action }} if it does not exist', function() {
assert.equal(Sentencer.make('{{ nonexistant thing }}'), '{{ nonexistant thing }}');
});

});
Expand Down Expand Up @@ -151,6 +172,21 @@ describe('Sentencer:', function() {

});

describe('# Custom Lists', function() {

it('{{ animal }}', function() {
assert.notEqual(["dog", "cat", "elephant"].indexOf(Sentencer.make('{{ animal }}')), -1, "missing animal");
});

it('{{ an_animal }}', function() {
assert.notEqual(["a dog", "a cat", "an elephant"].indexOf(Sentencer.make('{{ an_animal }}')), -1, "missing an_animal");
});

it('{{ animals }}', function() {
assert.notEqual(["dogs", "cats", "elephants"].indexOf(Sentencer.make('{{ animals }}')), -1, "missing animals");
});

});
});

describe('Test Print', function() {
Expand Down