excellent

package
v0.4.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 5, 2018 License: AGPL-3.0 Imports: 22 Imported by: 6

Documentation

Index

Constants

View Source
const (
	// BODY - Not in expression
	BODY xToken = iota

	// IDENTIFIER - 'contact.age' in '@contact.age'
	IDENTIFIER

	// EXPRESSION - the body of an expression '1+2' in '@(1+2)'
	EXPRESSION

	// EOF - end of expression
	EOF
)

Variables

View Source
var XFUNCTIONS = map[string]XFunction{
	"and": And,
	"if":  If,
	"or":  Or,

	"array_length": ArrayLength,
	"default":      Default,

	"legacy_add": LegacyAdd,

	"round":      Round,
	"round_up":   RoundUp,
	"round_down": RoundDown,
	"int":        Int,
	"max":        Max,
	"min":        Min,
	"mean":       Mean,
	"mod":        Mod,
	"rand":       Rand,
	"abs":        Abs,

	"format_num": FormatNum,
	"read_code":  ReadCode,

	"to_json":    ToJSON,
	"from_json":  FromJSON,
	"url_encode": URLEncode,

	"char":              Char,
	"code":              Code,
	"split":             Split,
	"join":              Join,
	"title":             Title,
	"word":              Word,
	"remove_first_word": RemoveFirstWord,
	"word_count":        WordCount,
	"word_slice":        WordSlice,
	"field":             Field,
	"clean":             Clean,
	"left":              Left,
	"lower":             Lower,
	"length":            Length,
	"right":             Right,
	"string_length":     Length,
	"repeat":            Repeat,
	"replace":           Replace,
	"upper":             Upper,
	"percent":           Percent,

	"format_date":     FormatDate,
	"parse_date":      ParseDate,
	"date":            Date,
	"date_from_parts": DateFromParts,
	"date_diff":       DateDiff,
	"date_add":        DateAdd,
	"weekday":         Weekday,
	"tz":              TZ,
	"tz_offset":       TZOffset,
	"today":           Today,
	"now":             Now,
	"from_epoch":      FromEpoch,
	"to_epoch":        ToEpoch,

	"format_urn": FormatURN,
}

XFUNCTIONS is our map of functions available in Excellent which aren't tests

View Source
var XFalseResult = XTestResult{}

XFalseResult can be used as a singleton for false result values

View Source
var XTESTS = map[string]XFunction{
	"has_error":          HasError,
	"has_value":          HasValue,
	"has_group":          HasGroup,
	"has_wait_timed_out": HasWaitTimedOut,

	"is_string_eq":    IsStringEQ,
	"has_phrase":      HasPhrase,
	"has_only_phrase": HasOnlyPhrase,
	"has_any_word":    HasAnyWord,
	"has_all_words":   HasAllWords,
	"has_beginning":   HasBeginning,
	"has_text":        HasText,
	"has_pattern":     HasPattern,

	"has_number":         HasNumber,
	"has_number_between": HasNumberBetween,
	"has_number_lt":      HasNumberLT,
	"has_number_lte":     HasNumberLTE,
	"has_number_eq":      HasNumberEQ,
	"has_number_gte":     HasNumberGTE,
	"has_number_gt":      HasNumberGT,

	"has_date":    HasDate,
	"has_date_lt": HasDateLT,
	"has_date_eq": HasDateEQ,
	"has_date_gt": HasDateGT,

	"has_phone": HasPhone,
	"has_email": HasEmail,

	"has_state":    HasState,
	"has_district": HasDistrict,
	"has_ward":     HasWard,
}

XTESTS is our mapping of the excellent test names to their actual functions

Functions

func Abs

func Abs(env utils.Environment, args ...interface{}) interface{}

Abs returns the absolute value of `num`

@(abs(-10)) -> 10
@(abs(10.5)) -> 10.5
@(abs("foo")) -> ERROR

@function abs(num)

func And

func And(env utils.Environment, args ...interface{}) interface{}

And returns whether all the passed in arguments are truthy

@(and(true)) -> true
@(and(true, false, true)) -> false

@function and(tests...)

func ArrayLength

func ArrayLength(env utils.Environment, args ...interface{}) interface{}

ArrayLength returns the number of items in the passed in array

array_length will return an error if it is passed an item which is not an array.

@(array_length(SPLIT("1 2 3", " "))) -> 3
@(array_length("123")) -> ERROR

@function array_length(array)

func Char

func Char(env utils.Environment, args ...interface{}) interface{}

Char returns the rune for the passed in codepoint, `num`, which may be unicode, this is the reverse of code

@(char(33)) -> "!"
@(char(128512)) -> "😀"
@(char("foo")) -> ERROR

@function char(num)

func Clean

func Clean(env utils.Environment, args ...interface{}) interface{}

Clean strips any leading or trailing whitespace from `string“

@(clean("\nfoo\t")) -> "foo"
@(clean(" bar")) -> "bar"
@(clean(123)) -> "123"

@function clean(string)

func Code

func Code(env utils.Environment, args ...interface{}) interface{}

Code returns the numeric code for the first character in `string`, it is the inverse of char

@(code("a")) -> "97"
@(code("abc")) -> "97"
@(code("😀")) -> "128512"
@(code("")) -> "ERROR"
@(code("15")) -> "49"
@(code(15)) -> "49"

@function code(string)

func Date

func Date(env utils.Environment, args ...interface{}) interface{}

Date turns `string` into a date according to the environment's settings

date will return an error if it is unable to convert the string to a date.

@(date("1979-07-18")) -> 1979-07-18T00:00:00.000000Z
@(date("2010 05 10")) -> 2010-05-10T00:00:00.000000Z
@(date("NOT DATE")) -> ERROR

@function date(string)

func DateAdd

func DateAdd(env utils.Environment, args ...interface{}) interface{}

DateAdd calculates the date value arrived at by adding `offset` number of `unit` to the `date`

Valid durations are "y" for years, "M" for months, "w" for weeks, "d" for days, h" for hour, "m" for minutes, "s" for seconds

@(date_add("2017-01-15", 5, "d")) -> 2017-01-20T00:00:00.000000Z
@(date_add("2017-01-15 10:45", 30, "m")) -> 2017-01-15T11:15:00.000000Z

@function date_add(date, offset, unit)

func DateDiff

func DateDiff(env utils.Environment, args ...interface{}) interface{}

DateDiff returns the integer duration between `date1` and `date2` in the `unit` specified.

Valid durations are "y" for years, "M" for months, "w" for weeks, "d" for days, h" for hour, "m" for minutes, "s" for seconds

@(date_diff("2017-01-17", "2017-01-15", "d")) -> 2
@(date_diff("2017-01-17 10:50", "2017-01-17 12:30", "h")) -> -1
@(date_diff("2017-01-17", "2015-12-17", "y")) -> 2

@function date_diff(date1, date2, unit)

func DateFromParts

func DateFromParts(env utils.Environment, args ...interface{}) interface{}

DateFromParts converts the passed in `year`, `month“ and `day`

@(date_from_parts(2017, 1, 15)) -> 2017-01-15T00:00:00.000000Z
@(date_from_parts(2017, 2, 31)) -> 2017-03-03T00:00:00.000000Z
@(date_from_parts(2017, 13, 15)) -> ERROR

@function date_from_parts(year, month, day)

func Default

func Default(env utils.Environment, args ...interface{}) interface{}

Default takes two arguments, returning `test` if not an error or nil, otherwise returning `default`

@(default(undeclared.var, "default_value")) -> default_value
@(default("10", "20")) -> 10
@(default(date("invalid-date"), "today")) -> today

@function default(test, default)

func EvaluateExpression

func EvaluateExpression(env utils.Environment, resolver utils.VariableResolver, template string) (interface{}, error)

EvaluateExpression evalutes the passed in template, returning the raw value it evaluates to

func EvaluateTemplate

func EvaluateTemplate(env utils.Environment, resolver utils.VariableResolver, template string) (interface{}, error)

EvaluateTemplate tries to evaluate the passed in template into an object, this only works if the template is a single identifier or expression, ie: "@contact" or "@(first(contact.urns))". In cases which are not a single identifier or expression, we return the stringified value

func EvaluateTemplateAsString

func EvaluateTemplateAsString(env utils.Environment, resolver utils.VariableResolver, template string, urlEncode bool) (string, error)

EvaluateTemplateAsString evaluates the passed in template returning the string value of its execution

func Field

func Field(env utils.Environment, args ...interface{}) interface{}

Field splits `string` based on the passed in `delimiter` and returns the field at `offset`. When splitting with a space, the delimiter is considered to be all whitespace. (first field is 0)

@(field("a,b,c", 1, ",")) -> "b"
@(field("a,,b,c", 1, ",")) -> ""
@(field("a   b c", 1, " ")) -> "b"
@(field("a		b	c	d", 1, "	")) -> ""
@(field("a\t\tb\tc\td", 1, " ")) -> ""
@(field("a,b,c", "foo", ",")) -> ERROR

@function field(string, offset, delimeter)

func FormatDate

func FormatDate(env utils.Environment, args ...interface{}) interface{}

FormatDate turns `date` into a string according to the `format` specified and in the optional `timezone`.

The format string can consist of the following characters. The characters ' ', ':', ',', 'T', 'Z', '-' and '_' are ignored. Any other character is an error.

* `d` - day of month, 1-31 * `dd` - day of month, zero padded 0-31 * `fff` - thousandths of a second * `h` - hour of the day 1-12 * `hh` - hour of the day 01-12 * `H` - hour of the day 1-23 * `HH` - hour of the day 01-23 * `K` - hour and minute offset from UTC, or Z for UTC * `m` - minute 0-59 * `mm` - minute 00-59 * `M` - month 1-12 * `MM` - month 01-12 * `s` - second 0-59 * `ss` - second 00-59 * `tt` - am or pm * `TT` - AM or PM * `yy` - last two digits of year 0-99 * `yyyy` - four digits of your 0000-9999 * `zzz` - hour and minute offset from UTC

Timezone should be a location name as specified in the IANA Time Zone database, such as "America/Guayaquil" or "America/Los_Angeles". If not specified the timezone of your environment will be used. An error will be returned if the timezone is not recognized.

@(format_date("1979-07-18T00:00:00.000000Z", "yyyy-MM-dd")) -> 1979-07-18
@(format_date("2010-05-10T19:50:00.000000Z", "yyyy M dd HH:mm")) -> 2010 5 10 19:50
@(format_date("2010-05-10T19:50:00.000000Z", "yyyy-MM-dd HH:mm TT", "America/Los_Angeles")) -> 2010-05-10 12:50 PM
@(format_date("NOT DATE", "yyyy-mm-dd")) -> ERROR

@function format_date(date, format [,timezone])

func FormatNum

func FormatNum(env utils.Environment, args ...interface{}) interface{}

FormatNum returns `num` formatted with the passed in number of decimal `places` and optional `commas` dividing thousands separators

@(format_num(31337, 2, true)) -> "31,337.00"
@(format_num(31337, 0, false)) -> "31337"
@(format_num("foo", 2, false)) -> ERROR

@function format_num(num, places, commas)

func FormatURN added in v0.4.7

func FormatURN(env utils.Environment, args ...interface{}) interface{}

FormatURN turns `urn` into a human friendly string

@(format_urn("tel:+250781234567")) -> 0781 234 567
@(format_urn("twitter:134252511151#billy_bob")) -> billy_bob
@(format_urn(contact.urns)) -> (206) 555-1212
@(format_urn(contact.urns.1)) -> foo@bar.com
@(format_urn(contact.urns.mailto)) -> foo@bar.com
@(format_urn(contact.urns.mailto.0)) -> foo@bar.com
@(format_urn(contact.urns.telegram)) -> ""
@(format_urn("NOT URN")) -> ERROR

@function format_urn(urn)

func FromEpoch

func FromEpoch(env utils.Environment, args ...interface{}) interface{}

FromEpoch returns a new date created from `num` which represents number of nanoseconds since January 1st, 1970 GMT

@(from_epoch(1497286619000000000)) -> 2017-06-12T16:56:59.000000Z

@function from_epoch(num)

func FromJSON

func FromJSON(env utils.Environment, args ...interface{}) interface{}

FromJSON tries to parse `string` as JSON, returning a fragment you can index into

If the passed in value is not JSON, then an error is returned

@(from_json("[1,2,3,4]").2) -> 3
@(from_json("invalid json")) -> ERROR

@function from_json(string)

func HasAllWords

func HasAllWords(env utils.Environment, args ...interface{}) interface{}

HasAllWords tests whether all the `words` are contained in `string`

The words can be in any order and may appear more than once.

@(has_all_words("the quick brown FOX", "the fox")) -> true
@(has_all_words("the quick brown FOX", "the fox").match) -> "the FOX"
@(has_all_words("the quick brown fox", "red fox")) -> false

@test has_all_words(string, words)

func HasAnyWord

func HasAnyWord(env utils.Environment, args ...interface{}) interface{}

HasAnyWord tests whether any of the `words` are contained in the `string`

Only one of the words needs to match and it may appear more than once.

@(has_any_word("The Quick Brown Fox", "fox quick")) -> true
@(has_any_word("The Quick Brown Fox", "red fox")) -> true
@(has_any_word("The Quick Brown Fox", "red fox").match) -> "Fox"

@test has_any_word(string, words)

func HasBeginning

func HasBeginning(env utils.Environment, args ...interface{}) interface{}

HasBeginning tests whether `string` starts with `beginning`

Both strings are trimmed of surrounding whitespace, but otherwise matching is strict without any tokenization.

@(has_beginning("The Quick Brown", "the quick")) -> true
@(has_beginning("The Quick Brown", "the quick").match) -> "The Quick"
@(has_beginning("The Quick Brown", "the   quick")) -> false
@(has_beginning("The Quick Brown", "quick brown")) -> false

@test has_beginning(string, beginning)

func HasDate

func HasDate(env utils.Environment, args ...interface{}) interface{}

HasDate tests whether `string` contains a date formatted according to our environment

@(has_date("the date is 2017-01-15")) -> true
@(has_date("the date is 2017-01-15").match) -> 2017-01-15T00:00:00.000000Z
@(has_date("there is no date here, just a year 2017")) -> false

@test has_date(string)

func HasDateEQ

func HasDateEQ(env utils.Environment, args ...interface{}) interface{}

HasDateEQ tests whether `string` a date equal to `date`

@(has_date_eq("the date is 2017-01-15", "2017-01-15")) -> true
@(has_date_eq("the date is 2017-01-15", "2017-01-15").match) -> 2017-01-15T00:00:00.000000Z
@(has_date_eq("the date is 2017-01-15 15:00", "2017-01-15")) -> false
@(has_date_eq("there is no date here, just a year 2017", "2017-06-01")) -> false
@(has_date_eq("there is no date here, just a year 2017", "not date")) -> ERROR

@test has_date_eq(string, date)

func HasDateGT

func HasDateGT(env utils.Environment, args ...interface{}) interface{}

HasDateGT tests whether `string` a date after the date `min`

@(has_date_gt("the date is 2017-01-15", "2017-01-01")) -> true
@(has_date_gt("the date is 2017-01-15", "2017-01-01").match) -> 2017-01-15T00:00:00.000000Z
@(has_date_gt("the date is 2017-01-15", "2017-03-15")) -> false
@(has_date_gt("there is no date here, just a year 2017", "2017-06-01")) -> false
@(has_date_gt("there is no date here, just a year 2017", "not date")) -> ERROR

@test has_date_gt(string, min)

func HasDateLT

func HasDateLT(env utils.Environment, args ...interface{}) interface{}

HasDateLT tests whether `value` contains a date before the date `max`

@(has_date_lt("the date is 2017-01-15", "2017-06-01")) -> true
@(has_date_lt("the date is 2017-01-15", "2017-06-01").match) -> 2017-01-15T00:00:00.000000Z
@(has_date_lt("there is no date here, just a year 2017", "2017-06-01")) -> false
@(has_date_lt("there is no date here, just a year 2017", "not date")) -> ERROR

@test has_date_lt(string, max)

func HasDistrict added in v0.4.0

func HasDistrict(env utils.Environment, args ...interface{}) interface{}

HasDistrict tests whether a district name is contained in the `string`. If `state` is also provided then the returned district must be within that state.

@(has_district("Gasabo", "Kigali")) -> true
@(has_district("I live in Gasabo", "Kigali")) -> true
@(has_district("Gasabo", "Boston")) -> false
@(has_district("Gasabo")) -> true

@test has_district(string, state)

func HasEmail

func HasEmail(env utils.Environment, args ...interface{}) interface{}

HasEmail tests whether an email is contained in `string`

@(has_email("my email is foo@bar.com, please respond")) -> true
@(has_email("my email is foo@bar.com, please respond").match) -> "foo@bar.com"
@(has_email("i'm not sharing my email")) -> false

@test has_email(string)

func HasError

func HasError(env utils.Environment, args ...interface{}) interface{}

HasError returns whether `value` is an error

Note that `contact.fields` and `run.results` are considered dynamic, so it is not an error to try to retrieve a value from fields or results which don't exist, rather these return an empty value.

@(has_error(date("foo"))) -> true
@(has_error(run.not.existing)) -> true
@(has_error(contact.fields.unset)) -> false
@(has_error("hello")) -> false

@test has_error(value)

func HasGroup

func HasGroup(env utils.Environment, args ...interface{}) interface{}

HasGroup returns whether the `contact` is part of group with the passed in UUID

@(has_group(contact, "97fe7029-3a15-4005-b0c7-277b884fc1d5")) -> true

@test has_group(contact)

func HasNumber

func HasNumber(env utils.Environment, args ...interface{}) interface{}

HasNumber tests whether `string` contains a number

@(has_number("the number is 42")) -> true
@(has_number("the number is 42").match) -> 42
@(has_number("the number is forty two")) -> false

@test has_number(string)

func HasNumberBetween

func HasNumberBetween(env utils.Environment, args ...interface{}) interface{}

HasNumberBetween tests whether `string` contains a number between `min` and `max` inclusive

@(has_number_between("the number is 42", 40, 44)) -> true
@(has_number_between("the number is 42", 40, 44).match) -> 42
@(has_number_between("the number is 42", 50, 60)) -> false
@(has_number_between("the number is not there", 50, 60)) -> false
@(has_number_between("the number is not there", "foo", 60)) -> ERROR

@test has_number_between(string, min, max)

func HasNumberEQ

func HasNumberEQ(env utils.Environment, args ...interface{}) interface{}

HasNumberEQ tests whether `strung` contains a number equal to the `value`

@(has_number_eq("the number is 42", 42)) -> true
@(has_number_eq("the number is 42", 42).match) -> 42
@(has_number_eq("the number is 42", 40)) -> false
@(has_number_eq("the number is not there", 40)) -> false
@(has_number_eq("the number is not there", "foo")) -> ERROR

@test has_number_eq(string, value)

func HasNumberGT

func HasNumberGT(env utils.Environment, args ...interface{}) interface{}

HasNumberGT tests whether `string` contains a number greater than `min`

@(has_number_gt("the number is 42", 40)) -> true
@(has_number_gt("the number is 42", 40).match) -> 42
@(has_number_gt("the number is 42", 42)) -> false
@(has_number_gt("the number is not there", 40)) -> false
@(has_number_gt("the number is not there", "foo")) -> ERROR

@test has_number_gt(string, min)

func HasNumberGTE

func HasNumberGTE(env utils.Environment, args ...interface{}) interface{}

HasNumberGTE tests whether `string` contains a number greater than or equal to `min`

@(has_number_gte("the number is 42", 42)) -> true
@(has_number_gte("the number is 42", 42).match) -> 42
@(has_number_gte("the number is 42", 45)) -> false
@(has_number_gte("the number is not there", 40)) -> false
@(has_number_gte("the number is not there", "foo")) -> ERROR

@test has_number_gte(string, min)

func HasNumberLT

func HasNumberLT(env utils.Environment, args ...interface{}) interface{}

HasNumberLT tests whether `string` contains a number less than `max`

@(has_number_lt("the number is 42", 44)) -> true
@(has_number_lt("the number is 42", 44).match) -> 42
@(has_number_lt("the number is 42", 40)) -> false
@(has_number_lt("the number is not there", 40)) -> false
@(has_number_lt("the number is not there", "foo")) -> ERROR

@test has_number_lt(string, max)

func HasNumberLTE

func HasNumberLTE(env utils.Environment, args ...interface{}) interface{}

HasNumberLTE tests whether `value` contains a number less than or equal to `max`

@(has_number_lte("the number is 42", 42)) -> true
@(has_number_lte("the number is 42", 44).match) -> 42
@(has_number_lte("the number is 42", 40)) -> false
@(has_number_lte("the number is not there", 40)) -> false
@(has_number_lte("the number is not there", "foo")) -> ERROR

@test has_number_lte(string, max)

func HasOnlyPhrase

func HasOnlyPhrase(env utils.Environment, args ...interface{}) interface{}

HasOnlyPhrase tests whether the `string` contains only `phrase`

The phrase must be the only text in the string to match

@(has_only_phrase("The Quick Brown Fox", "quick brown")) -> false
@(has_only_phrase("Quick Brown", "quick brown")) -> true
@(has_only_phrase("Quick Brown", "quick brown").match) -> "Quick Brown"
@(has_only_phrase("The Quick Brown Fox", "red fox")) -> false

@test has_only_phrase(string, phrase)

func HasPattern added in v0.4.0

func HasPattern(env utils.Environment, args ...interface{}) interface{}

HasPattern tests whether `string` matches the regex `pattern`

Both strings are trimmed of surrounding whitespace and matching is case-insensitive.

@(has_pattern("Sell cheese please", "buy (\w+)")) -> false
@(has_pattern("Buy cheese please", "buy (\w+)")) -> true
@(has_pattern("Buy cheese please", "buy (\w+)").match) -> "Buy cheese"
@(has_pattern("Buy cheese please", "buy (\w+)").match.groups[0]) -> "Buy cheese"
@(has_pattern("Buy cheese please", "buy (\w+)").match.groups[1]) -> "cheese"

@test has_pattern(string, pattern)

func HasPhone

func HasPhone(env utils.Environment, args ...interface{}) interface{}

HasPhone tests whether a phone number (in the passed in `country_code`) is contained in the `string`

@(has_phone("my number is 2067799294", "US")) -> true
@(has_phone("my number is 206 779 9294", "US").match) -> "+12067799294"
@(has_phone("my number is none of your business", "US")) -> false

@test has_phone(string, country_code)

func HasPhrase

func HasPhrase(env utils.Environment, args ...interface{}) interface{}

HasPhrase tests whether `phrase` is contained in `string`

The words in the test phrase must appear in the same order with no other words in between.

@(has_phrase("the quick brown fox", "brown fox")) -> true
@(has_phrase("the Quick Brown fox", "quick fox")) -> false
@(has_phrase("the.quick.brown.fox", "the quick").match) -> "the quick"

@test has_phrase(string, phrase)

func HasState added in v0.4.0

func HasState(env utils.Environment, args ...interface{}) interface{}

HasState tests whether a state name is contained in the `string`

@(has_state("Kigali")) -> true
@(has_state("Boston")) -> false
@(has_state("¡Kigali!")) -> true
@(has_state("I live in Kigali")) -> true

@test has_state(string)

func HasText

func HasText(env utils.Environment, args ...interface{}) interface{}

HasText tests whether there the string has any characters in it

@(has_text("quick brown")) -> true
@(has_text("quick brown").match) -> "quick brown"
@(has_text("")) -> false
@(has_text(" \n")) -> false
@(has_text(123)) -> true

@test has_text(string)

func HasValue

func HasValue(env utils.Environment, args ...interface{}) interface{}

HasValue returns whether `value` is non-nil and not an error

Note that `contact.fields` and `run.results` are considered dynamic, so it is not an error to try to retrieve a value from fields or results which don't exist, rather these return an empty value.

@(has_value(date("foo"))) -> false
@(has_value(not.existing)) -> false
@(has_value(contact.fields.unset)) -> false
@(has_value("hello")) -> true

@test has_value(value)

func HasWaitTimedOut added in v0.4.0

func HasWaitTimedOut(env utils.Environment, args ...interface{}) interface{}

HasWaitTimedOut returns whether the last wait timed out.

@(has_wait_timed_out(run)) -> false

@test has_wait_timed_out(run)

func HasWard added in v0.4.0

func HasWard(env utils.Environment, args ...interface{}) interface{}

HasWard tests whether a ward name is contained in the `string`

@(has_ward("Gisozi", "Gasabo", "Kigali")) -> true
@(has_ward("I live in Gisozi", "Gasabo", "Kigali")) -> true
@(has_ward("Gisozi", "Gasabo", "Brooklyn")) -> false
@(has_ward("Gisozi", "Brooklyn", "Kigali")) -> false
@(has_ward("Brooklyn", "Gasabo", "Kigali")) -> false
@(has_ward("Gasabo")) -> false
@(has_ward("Gisozi")) -> true

@test has_ward(string, district, state)

func If

func If(env utils.Environment, args ...interface{}) interface{}

If evaluates the `test` argument, and if truthy returns `true_value`, if not returning `false_value`

If the first argument is an error that error is returned

@(if(1 = 1, "foo", "bar")) -> "foo"
@(if("foo" > "bar", "foo", "bar")) -> ERROR

@function if(test, true_value, false_value)

func Int

func Int(env utils.Environment, args ...interface{}) interface{}

Int takes `num` and returns the integer value (floored)

@(int(12.14)) -> 12
@(int(12.9)) -> 12
@(int("foo")) -> ERROR

@function int(num)

func IsStringEQ added in v0.4.0

func IsStringEQ(env utils.Environment, args ...interface{}) interface{}

IsStringEQ returns whether two strings are equal (case sensitive). In the case that they are, it will return the string as the match.

@(is_string_eq("foo", "foo")) -> true
@(is_string_eq("foo", "FOO")) -> false
@(is_string_eq("foo", "bar")) -> false
@(is_string_eq("foo", " foo ")) -> false
@(is_string_eq(run.status, "completed")) -> true
@(is_string_eq(child.status, "expired")) -> false
@(is_string_eq(webhook.status, "success")) -> true
@(is_string_eq(webhook.status, "connection_error")) -> false

@test is_string_eq(run)

func Join

func Join(env utils.Environment, args ...interface{}) interface{}

Join joins the passed in `array` of strings with the passed in `delimeter`

@(join(split("a.b.c", "."), " ")) -> "a b c"

@function join(array, delimeter)

func Left

func Left(env utils.Environment, args ...interface{}) interface{}

Left returns the `len` most left characters of the passed in `string`

@(left("hello", 2)) -> "he"
@(left("hello", 7)) -> "hello"
@(left("😀😃😄😁", 2)) -> "😀😃"
@(left("hello", -1)) -> ERROR

@function left(string, len)

func LegacyAdd

func LegacyAdd(env utils.Environment, args ...interface{}) interface{}

LegacyAdd simulates our old + operator, which operated differently based on whether one of the parameters was a date or not. If one is a date, then the other side is expected to be an integer with a number of days to add to the date, otherwise a normal decimal addition is attempted.

func Length

func Length(env utils.Environment, args ...interface{}) interface{}

Length returns the number of unicode characters in `string`

@(length("Hello")) -> 5
@(length("😀😃😄😁")) -> 4
@(length(1234)) -> 4

@function length(string)

func Lower

func Lower(env utils.Environment, args ...interface{}) interface{}

Lower lowercases the passed in `string`

@(lower("HellO")) -> "hello"
@(lower("hello")) -> "hello"
@(lower("123")) -> "123"
@(lower("😀")) -> "😀"

@function lower(string)

func Max

func Max(env utils.Environment, args ...interface{}) interface{}

Max takes a list of `values` and returns the greatest of them

@(max(1, 2)) -> 2
@(max(1, -1, 10)) -> 10
@(max(1, 10, "foo")) -> ERROR

@function max(values...)

func Mean

func Mean(env utils.Environment, args ...interface{}) interface{}

Mean takes a list of `values` and returns the arithmetic mean of them

@(mean(1, 2)) -> 1.5
@(mean(1, 2, 6)) -> 3
@(mean(1, "foo")) -> ERROR

@function mean(values)

func MigrateTemplate added in v0.4.0

func MigrateTemplate(template string) (string, error)

MigrateTemplate will take a legacy expression and translate it to the new syntax

func Min

func Min(env utils.Environment, args ...interface{}) interface{}

Min takes a list of `values` and returns the smallest of them

@(min(1, 2)) -> 1
@(min(2, 2, -10)) -> -10
@(min(1, 2, "foo")) -> ERROR

@function min(values)

func Mod

func Mod(env utils.Environment, args ...interface{}) interface{}

Mod returns the remainder of the division of `divident` by `divisor`

@(mod(5, 2)) -> 1
@(mod(4, 2)) -> 0
@(mod(5, "foo")) -> ERROR

@function mod(dividend, divisor)

func Now

func Now(env utils.Environment, args ...interface{}) interface{}

Now returns the current date and time in the environment timezone

@(now()) -> 2017-01-20T15:35:65.153654Z

@function now()

func Or

func Or(env utils.Environment, args ...interface{}) interface{}

Or returns whether if any of the passed in arguments are truthy

@(or(true)) -> true
@(or(true, false, true)) -> true

@function or(tests...)

func ParseDate

func ParseDate(env utils.Environment, args ...interface{}) interface{}

ParseDate turns `string` into a date according to the `format` and optional `timezone` specified

The format string can consist of the following characters. The characters ' ', ':', ',', 'T', 'Z', '-' and '_' are ignored. Any other character is an error.

* `d` - day of month, 1-31 * `dd` - day of month, zero padded 0-31 * `fff` - thousandths of a second * `h` - hour of the day 1-12 * `hh` - hour of the day 01-12 * `H` - hour of the day 1-23 * `HH` - hour of the day 01-23 * `K` - hour and minute offset from UTC, or Z for UTC * `m` - minute 0-59 * `mm` - minute 00-59 * `M` - month 1-12 * `MM` - month 01-12 * `s` - second 0-59 * `ss` - second 00-59 * `tt` - am or pm * `TT` - AM or PM * `yy` - last two digits of year 0-99 * `yyyy` - four digits of your 0000-9999 * `zzz` - hour and minute offset from UTC

Timezone should be a location name as specified in the IANA Time Zone database, such as "America/Guayaquil" or "America/Los_Angeles". If not specified the timezone of your environment will be used. An error will be returned if the timezone is not recognized.

parse_date will return an error if it is unable to convert the string to a date.

@(parse_date("1979-07-18", "yyyy-MM-dd")) -> 1979-07-18T00:00:00.000000Z
@(parse_date("2010 5 10", "yyyy M dd")) -> 2010-05-10T00:00:00.000000Z
@(parse_date("2010 5 10 12:50", "yyyy M dd HH:mm", "America/Los_Angeles")) -> 2010-05-10T12:50:00.000000-07:00
@(parse_date("NOT DATE", "yyyy-mm-dd")) -> ERROR

@function parse_date(string, format [,timezone])

func Percent

func Percent(env utils.Environment, args ...interface{}) interface{}

Percent converts `num` to a string represented as a percentage

@(percent(0.54234)) -> "54%"
@(percent(1.2)) -> "120%"
@(percent("foo")) -> ERROR

@function percent(num)

func Rand

func Rand(env utils.Environment, args ...interface{}) interface{}

Rand returns either a single random decimal between 0-1 or a random integer between `floor` and `ceiling` (inclusive)

@(rand()) == 0.5152
@(rand(1, 5)) == 3

@function rand(floor, ceiling)

func ReadCode

func ReadCode(env utils.Environment, args ...interface{}) interface{}

ReadCode converts `code` into something that can be read by IVR systems

ReadCode will split the numbers such as they are easier to understand. This includes splitting in 3s or 4s if appropriate.

@(read_code("1234")) -> "1 2 3 4"
@(read_code("abc")) -> "a b c"
@(read_code("abcdef")) -> "a b c , d e f"

@function read_code(code)

func RemoveFirstWord

func RemoveFirstWord(env utils.Environment, args ...interface{}) interface{}

RemoveFirstWord removes the 1st word of `string`

@(remove_first_word("foo bar")) -> "bar"

@function remove_first_word(string)

func Repeat

func Repeat(env utils.Environment, args ...interface{}) interface{}

Repeat return `string` repeated `count` number of times

@(repeat("*", 8)) -> "********"
@(repeat("*", "foo")) -> ERROR

@function repeat(string, count)

func Replace

func Replace(env utils.Environment, args ...interface{}) interface{}

Replace replaces all occurrences of `needle` with `replacement` in `string`

@(replace("foo bar", "foo", "zap")) -> "zap bar"
@(replace("foo bar", "baz", "zap")) -> "foo bar"

@function replace(string, needle, replacement)

func Right(env utils.Environment, args ...interface{}) interface{}

Right returns the `len` most right characters of the passed in `string`

@(right("hello", 2)) -> "lo"
@(right("hello", 7)) -> "hello"
@(right("😀😃😄😁", 2)) -> "😄😁"
@(right("hello", -1)) -> ERROR

@function right(string, len)

func Round

func Round(env utils.Environment, args ...interface{}) interface{}

Round rounds `num` to the corresponding number of `places`

@(round(12.141, 2)) -> 12.14
@(round("notnum", 2)) -> ERROR

@function round(num, places)

func RoundDown

func RoundDown(env utils.Environment, args ...interface{}) interface{}

RoundDown rounds `num` down to the nearest integer value

@(round_down(12.141)) -> 12
@(round_down(12.9)) -> 12
@(round_down("foo")) -> ERROR

@function round_down(num)

func RoundUp

func RoundUp(env utils.Environment, args ...interface{}) interface{}

RoundUp rounds `num` up to the nearest integer value, also good at fighting weeds

@(round_up(12.141)) -> 13
@(round_up(12)) -> 12
@(round_up("foo")) -> ERROR

@function round_up(num)

func Split

func Split(env utils.Environment, args ...interface{}) interface{}

Split splits `string` based on the passed in `delimeter`

Empty values are removed from the returned list

@(split("a b c", " ")) -> "a, b, c"
@(split("a", " ")) -> "a"
@(split("abc..d", ".")) -> "abc, d"
@(split("a.b.c.", ".")) -> "a, b, c"
@(split("a && b && c", " && ")) -> "a, b, c"

@function split(string, delimeter)

func TZ

func TZ(env utils.Environment, args ...interface{}) interface{}

TZ returns the timezone for `date“

If not timezone information is present in the date, then the environment's timezone will be returned

@(tz("2017-01-15 02:15:18PM UTC")) -> "UTC"
@(tz("2017-01-15 02:15:18PM")) -> "UTC"
@(tz("2017-01-15")) -> "UTC"
@(tz("foo")) -> ERROR

@function tz(date)

func TZOffset

func TZOffset(env utils.Environment, args ...interface{}) interface{}

TZOffset returns the offset for the timezone as a string +/- HHMM for `date`

If no timezone information is present in the date, then the environment's timezone offset will be returned

@(tz_offset("2017-01-15 02:15:18PM UTC")) -> "+0000"
@(tz_offset("2017-01-15 02:15:18PM")) -> "+0000"
@(tz_offset("2017-01-15")) -> "+0000"
@(tz_offset("foo")) -> ERROR

@function tz_offset(date)

func Title

func Title(env utils.Environment, args ...interface{}) interface{}

Title titlecases the passed in `string`, capitalizing each word

@(title("foo")) -> "Foo"
@(title("ryan lewis")) -> "Ryan Lewis"
@(title(123)) -> "123"

@function title(string)

func ToEpoch

func ToEpoch(env utils.Environment, args ...interface{}) interface{}

ToEpoch converts `date` to the number of nanoseconds since January 1st, 1970 GMT

@(to_epoch("2017-06-12T16:56:59.000000Z")) -> 1497286619000000000

@function to_epoch(date)

func ToJSON

func ToJSON(env utils.Environment, args ...interface{}) interface{}

ToJSON tries to return a JSON representation of `value`. An error is returned if there is no JSON representation of that object.

@(to_json("string")) -> "string"
@(to_json(10)) -> 10
@(to_json(contact.uuid)) -> "ce2b5142-453b-4e43-868e-abdafafaa878"
@(to_json(now())) -> "2017-05-10T12:50:00.000000-07:00"

@function to_json(value)

func Today

func Today(env utils.Environment, args ...interface{}) interface{}

Today returns the current date in the current timezone, time is set to midnight in the environment timezone

@(today()) -> 2017-01-20T00:00:00.000000Z

@function today()

func URLEncode

func URLEncode(env utils.Environment, args ...interface{}) interface{}

URLEncode URL encodes `string` for use in a URL parameter

@(url_encode("two words")) -> two+words
@(url_encode(10)) -> 10

@function url_encode(string)

func Upper

func Upper(env utils.Environment, args ...interface{}) interface{}

Upper uppercases all characters in the passed `string`

@(upper("Asdf")) -> "ASDF"
@(upper(123)) -> "123"

@function upper(string)

func Weekday

func Weekday(env utils.Environment, args ...interface{}) interface{}

Weekday returns the day of the week for `date`, 0 is sunday, 1 is monday..

@(weekday("2017-01-15")) -> 0
@(weekday("foo")) -> ERROR

@function weekday(date)

func Word

func Word(env utils.Environment, args ...interface{}) interface{}

Word returns the word at the passed in `offset` for the passed in `string`, 1 indexed

@(word("foo bar", 1)) -> "foo"
@(word("foo.bar", 1)) -> "foo"
@(word("one two.three", 3)) -> "three"

@function word(string, offset)

func WordCount

func WordCount(env utils.Environment, args ...interface{}) interface{}

WordCount returns the number of words in `string`

@(word_count("foo bar")) -> 2
@(word_count(10)) -> 1
@(word_count("")) -> 0
@(word_count("😀😃😄😁")) -> 4

@function word_count(string)

func WordSlice

func WordSlice(env utils.Environment, args ...interface{}) interface{}

WordSlice extracts a substring from `string` spanning from `start` up to but not-including `end`. (first word is 1)

@(word_slice("foo bar", 1, 1)) -> "foo"
@(word_slice("foo bar", 1, 3)) -> "foo bar"
@(word_slice("foo bar", 3, 4)) -> ""

@function word_slice(string, start, end)

Types

type TemplateErrors

type TemplateErrors []error

TemplateErrors represents the list of errors we may have received during execution

func (TemplateErrors) Error

func (e TemplateErrors) Error() string

Error returns a single string describing all the errors encountered

type Visitor

type Visitor struct {
	gen.BaseExcellent2Visitor
	// contains filtered or unexported fields
}

func NewVisitor

func NewVisitor(env utils.Environment, resolver utils.VariableResolver) *Visitor

NewVisitor creates a new Excellent visitor

func (*Visitor) Visit

func (v *Visitor) Visit(tree antlr.ParseTree) interface{}

Visit the top level parse tree

func (*Visitor) VisitAdditionOrSubtraction

func (v *Visitor) VisitAdditionOrSubtraction(ctx *gen.AdditionOrSubtractionContext) interface{}

VisitAdditionOrSubtraction deals with addition and subtraction like 5+5 and 5-3

func (*Visitor) VisitArrayLookup

func (v *Visitor) VisitArrayLookup(ctx *gen.ArrayLookupContext) interface{}

VisitArrayLookup deals with lookups such as foo[5]

func (*Visitor) VisitAtomReference

func (v *Visitor) VisitAtomReference(ctx *gen.AtomReferenceContext) interface{}

VisitAtomReference deals with visiting a single atom in our expression

func (*Visitor) VisitComparison

func (v *Visitor) VisitComparison(ctx *gen.ComparisonContext) interface{}

VisitComparison deals with visiting a comparison between two values, such as 5<3 or 3>5

func (*Visitor) VisitConcatenation

func (v *Visitor) VisitConcatenation(ctx *gen.ConcatenationContext) interface{}

VisitConcatenation deals with string concatenations like "foo" & "bar"

func (*Visitor) VisitContextReference

func (v *Visitor) VisitContextReference(ctx *gen.ContextReferenceContext) interface{}

VisitContextReference deals with references to variables in the context such as "foo"

func (*Visitor) VisitDecimalLiteral

func (v *Visitor) VisitDecimalLiteral(ctx *gen.DecimalLiteralContext) interface{}

VisitDecimalLiteral deals with decimals like 1.5

func (*Visitor) VisitDotLookup

func (v *Visitor) VisitDotLookup(ctx *gen.DotLookupContext) interface{}

VisitDotLookup deals with lookups like foo.0 or foo.bar

func (*Visitor) VisitEquality

func (v *Visitor) VisitEquality(ctx *gen.EqualityContext) interface{}

VisitEquality deals with equality or inequality tests 5 = 5 and 5 != 5

func (*Visitor) VisitExponent

func (v *Visitor) VisitExponent(ctx *gen.ExponentContext) interface{}

VisitExponent deals with exponenets such as 5^5

func (*Visitor) VisitFalse

func (v *Visitor) VisitFalse(ctx *gen.FalseContext) interface{}

VisitFalse deals with the "false" literal

func (*Visitor) VisitFunctionCall

func (v *Visitor) VisitFunctionCall(ctx *gen.FunctionCallContext) interface{}

VisitFunctionCall deals with function calls like TITLE(foo.bar)

func (*Visitor) VisitFunctionParameters

func (v *Visitor) VisitFunctionParameters(ctx *gen.FunctionParametersContext) interface{}

VisitFunctionParameters deals with the parameters to a function call

func (*Visitor) VisitMultiplicationOrDivision

func (v *Visitor) VisitMultiplicationOrDivision(ctx *gen.MultiplicationOrDivisionContext) interface{}

VisitMultiplicationOrDivision deals with division and multiplication such as 5*5 or 5/2

func (*Visitor) VisitNegation

func (v *Visitor) VisitNegation(ctx *gen.NegationContext) interface{}

VisitNegation deals with negations such as -5

func (*Visitor) VisitParentheses

func (v *Visitor) VisitParentheses(ctx *gen.ParenthesesContext) interface{}

VisitParentheses deals with expressions in parentheses such as (1+2)

func (*Visitor) VisitParse

func (v *Visitor) VisitParse(ctx *gen.ParseContext) interface{}

VisitParse handles our top level parser

func (*Visitor) VisitStringLiteral

func (v *Visitor) VisitStringLiteral(ctx *gen.StringLiteralContext) interface{}

VisitStringLiteral deals with string literals such as "asdf"

func (*Visitor) VisitTrue

func (v *Visitor) VisitTrue(ctx *gen.TrueContext) interface{}

VisitTrue deals with the "true" literal

type XFunction

type XFunction func(env utils.Environment, args ...interface{}) interface{}

XFunction defines the interface that Excellent functions must implement

type XTestResult

type XTestResult struct {
	// contains filtered or unexported fields
}

XTestResult encapsulates not only if the test was true but what the match was

func (XTestResult) Default

func (t XTestResult) Default() interface{}

Default satisfies the utils.VariableResolver interface, we always default to whether we matched

func (XTestResult) Match

func (t XTestResult) Match() interface{}

Match returns the item which was matched

func (XTestResult) Matched

func (t XTestResult) Matched() bool

Matched returns whether the test matched

func (XTestResult) Resolve

func (t XTestResult) Resolve(key string) interface{}

Resolve satisfies the utils.VariableResolver interface, users can look up the match or whether we matched

func (XTestResult) String

func (t XTestResult) String() string

String satisfies the utils.VariableResolver interface, we always default to whether we matched

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL