Skip to content

Commit

Permalink
feat: optionsValue now uses a similar build pattern as actions
Browse files Browse the repository at this point in the history
  • Loading branch information
aholstenson committed Oct 6, 2019
1 parent 5806f76 commit 4b0dfbf
Showing 2 changed files with 74 additions and 98 deletions.
73 changes: 14 additions & 59 deletions src/values/options.ts
Original file line number Diff line number Diff line change
@@ -3,49 +3,31 @@ import { PhrasesBuilder } from '../resolver/PhrasesBuilder';

import { LanguageSpecificValue, ParsingValue, Value } from './base';
import { ExpressionPart } from '../resolver/expression/ExpressionPart';
import { Phrases } from '../resolver/Phrases';

export interface OptionBuilderOptions {
name?: string;
}

export interface OptionDef<Id extends string, Values extends object> {
id: Id;
phrases: Phrases<Values>;
}

export class OptionsBuilder<CurrentOptions extends object> {
private name: string;
private options: OptionBuilderOptions;
private data: Record<string, OptionData>;
private defs: OptionDef<any, any>[];

constructor(options: OptionBuilderOptions) {
this.name = options.name || 'options';
this.options = options;
this.data = {};
this.defs = [];
}

public option<Id extends string>(id: Id): OptionBuilder<CurrentOptions, Id, {}> {
if(typeof id !== 'string') {
throw new Error('Options require identifiers that are strings');
}

const result: OptionData = {
values: {},
phrases: []
};

const self = this;
return {
value(valueId, type) {
result.values[valueId] = type;
return this as any;
},

phrase(...args) {
result.phrases.push(args);
return this;
},

done() {
self.data[id] = result;
return self as any;
}
};
public add<Id extends string, Values extends object>(options: OptionDef<Id, Values>): OptionsBuilder<CurrentOptions & { [K in Id]: Values }> {
this.defs.push(options);
return this as any;
}

public build() {
@@ -54,23 +36,9 @@ export class OptionsBuilder<CurrentOptions extends object> {
.name(this.name)
.allowPartial();

for(const id of Object.keys(this.data)) {
const option = this.data[id];
const instance = new PhrasesBuilder();

// Transfer all of the values
for(const valueKey of Object.keys(option.values)) {
instance.value(valueKey, option.values[valueKey]);
}

// Transfer the phrases
for(const phrase of option.phrases) {
instance.phrase(...phrase);
}

const parser = instance.build();
parent.add(parser.toGraph(language), v => {
return new Option(id, v[0].values, v[0].expression);
for(const def of this.defs) {
parent.add(def.phrases.toGraph(language), v => {
return new Option(def.id, v[0].values, v[0].expression);
});
}

@@ -92,19 +60,6 @@ export function optionsValue(options: OptionBuilderOptions={}) {
return new OptionsBuilder<{}>(options);
}

export interface OptionBuilder<CurrentOptions, Key extends string, Values extends object> {
value<I extends string, V>(id: I, type: Value<V>): OptionBuilder<CurrentOptions, Key, Values & { [K in I]: V }>;

phrase(...args: string[]): this;

done(): OptionsBuilder<CurrentOptions & { [K in Key]: Values }>;
}

interface OptionData {
values: Record<string, Value<any>>;
phrases: any[];
}

/**
* Options interface, used to access options as they are found in the matched
* expression.
99 changes: 60 additions & 39 deletions test/value-options.test.ts
Original file line number Diff line number Diff line change
@@ -8,9 +8,12 @@ describe('Value: Options', function() {

describe('Standalone option: No values', () => {
const matcher = optionsValue()
.option('deadline')
.phrase('with deadline')
.done()
.add({
id: 'deadline',
phrases: newPhrases()
.phrase('with deadline')
.build()
})
.build()
.matcher(en);

@@ -138,10 +141,13 @@ describe('Value: Options', function() {

describe('Standalone option: With value', () => {
const matcher = optionsValue()
.option('deadline')
.value('deadline', dateIntervalValue())
.phrase('with deadline {deadline}')
.done()
.add({
id: 'deadline',
phrases: newPhrases()
.value('deadline', dateIntervalValue())
.phrase('with deadline {deadline}')
.build()
})
.build()
.matcher(en);

@@ -172,9 +178,12 @@ describe('Value: Options', function() {

describe('Single option - no value', () => {
const queryOptions = optionsValue()
.option('deadline')
.phrase('with deadline')
.done()
.add({
id: 'deadline',
phrases: newPhrases()
.phrase('with deadline')
.build()
})
.build();

const resolver = newPhrases()
@@ -207,15 +216,21 @@ describe('Value: Options', function() {

describe('With values', () => {
const queryOptions = optionsValue()
.option('deadline')
.value('deadline', dateIntervalValue())
.phrase('with deadline {deadline}')
.phrase('deadline {deadline}')
.done()
.option('completed')
.value('completed', dateIntervalValue())
.phrase('completed {completed}')
.done()
.add({
id: 'deadline',
phrases: newPhrases()
.value('deadline', dateIntervalValue())
.phrase('with deadline {deadline}')
.phrase('deadline {deadline}')
.build()
})
.add({
id: 'completed',
phrases: newPhrases()
.value('completed', dateIntervalValue())
.phrase('completed {completed}')
.build()
})
.build();

const resolver = newPhrases()
@@ -268,28 +283,34 @@ describe('Value: Options', function() {
];

const queryOptions = optionsValue()
.option('value')
.value('name', customValue<string>(async function(encounter) {
const text = encounter.text;
if(encounter.partial) {
for(const v of values) {
if(v.indexOf(text) === 0) {
encounter.match(v);
.add({
id: 'value',
phrases: newPhrases()
.value('name', customValue<string>(async function(encounter) {
const text = encounter.text;
if(encounter.partial) {
for(const v of values) {
if(v.indexOf(text) === 0) {
encounter.match(v);
}
}
} else {
if(values.indexOf(text) >= 0) {
encounter.match(text);
}
}
} else {
if(values.indexOf(text) >= 0) {
encounter.match(text);
}
}
}))
.phrase('named {name}')
.done()
.option('completed')
.value('completed', dateIntervalValue())
.phrase('completed {completed}')
.phrase('c {completed}')
.done()
}))
.phrase('named {name}')
.build()
})
.add({
id: 'completed',
phrases: newPhrases()
.value('completed', dateIntervalValue())
.phrase('completed {completed}')
.phrase('c {completed}')
.build()
})
.build();

const resolver = newPhrases()

0 comments on commit 4b0dfbf

Please sign in to comment.