Documentation ¶
Index ¶
- Constants
- Variables
- func Abs(env utils.Environment, args ...interface{}) interface{}
- func And(env utils.Environment, args ...interface{}) interface{}
- func ArrayLength(env utils.Environment, args ...interface{}) interface{}
- func Char(env utils.Environment, args ...interface{}) interface{}
- func Clean(env utils.Environment, args ...interface{}) interface{}
- func Code(env utils.Environment, args ...interface{}) interface{}
- func Date(env utils.Environment, args ...interface{}) interface{}
- func DateAdd(env utils.Environment, args ...interface{}) interface{}
- func DateDiff(env utils.Environment, args ...interface{}) interface{}
- func DateFromParts(env utils.Environment, args ...interface{}) interface{}
- func Default(env utils.Environment, args ...interface{}) interface{}
- func EvaluateExpression(env utils.Environment, resolver utils.VariableResolver, template string) (interface{}, error)
- func EvaluateTemplate(env utils.Environment, resolver utils.VariableResolver, template string) (interface{}, error)
- func EvaluateTemplateAsString(env utils.Environment, resolver utils.VariableResolver, template string) (string, error)
- func Field(env utils.Environment, args ...interface{}) interface{}
- func FormatDate(env utils.Environment, args ...interface{}) interface{}
- func FormatNum(env utils.Environment, args ...interface{}) interface{}
- func FromEpoch(env utils.Environment, args ...interface{}) interface{}
- func FromJSON(env utils.Environment, args ...interface{}) interface{}
- func HasAllWords(env utils.Environment, args ...interface{}) interface{}
- func HasAnyWord(env utils.Environment, args ...interface{}) interface{}
- func HasBeginning(env utils.Environment, args ...interface{}) interface{}
- func HasDate(env utils.Environment, args ...interface{}) interface{}
- func HasDateEQ(env utils.Environment, args ...interface{}) interface{}
- func HasDateGT(env utils.Environment, args ...interface{}) interface{}
- func HasDateLT(env utils.Environment, args ...interface{}) interface{}
- func HasEmail(env utils.Environment, args ...interface{}) interface{}
- func HasError(env utils.Environment, args ...interface{}) interface{}
- func HasGroup(env utils.Environment, args ...interface{}) interface{}
- func HasNumber(env utils.Environment, args ...interface{}) interface{}
- func HasNumberBetween(env utils.Environment, args ...interface{}) interface{}
- func HasNumberEQ(env utils.Environment, args ...interface{}) interface{}
- func HasNumberGT(env utils.Environment, args ...interface{}) interface{}
- func HasNumberGTE(env utils.Environment, args ...interface{}) interface{}
- func HasNumberLT(env utils.Environment, args ...interface{}) interface{}
- func HasNumberLTE(env utils.Environment, args ...interface{}) interface{}
- func HasOnlyPhrase(env utils.Environment, args ...interface{}) interface{}
- func HasPhone(env utils.Environment, args ...interface{}) interface{}
- func HasPhrase(env utils.Environment, args ...interface{}) interface{}
- func HasRunStatus(env utils.Environment, args ...interface{}) interface{}
- func HasText(env utils.Environment, args ...interface{}) interface{}
- func HasValue(env utils.Environment, args ...interface{}) interface{}
- func HasWebhookStatus(env utils.Environment, args ...interface{}) interface{}
- func If(env utils.Environment, args ...interface{}) interface{}
- func Int(env utils.Environment, args ...interface{}) interface{}
- func Join(env utils.Environment, args ...interface{}) interface{}
- func Left(env utils.Environment, args ...interface{}) interface{}
- func LegacyAdd(env utils.Environment, args ...interface{}) interface{}
- func Length(env utils.Environment, args ...interface{}) interface{}
- func Lower(env utils.Environment, args ...interface{}) interface{}
- func Max(env utils.Environment, args ...interface{}) interface{}
- func Mean(env utils.Environment, args ...interface{}) interface{}
- func Min(env utils.Environment, args ...interface{}) interface{}
- func Mod(env utils.Environment, args ...interface{}) interface{}
- func Now(env utils.Environment, args ...interface{}) interface{}
- func Or(env utils.Environment, args ...interface{}) interface{}
- func ParseDate(env utils.Environment, args ...interface{}) interface{}
- func Percent(env utils.Environment, args ...interface{}) interface{}
- func Rand(env utils.Environment, args ...interface{}) interface{}
- func ReadCode(env utils.Environment, args ...interface{}) interface{}
- func RemoveFirstWord(env utils.Environment, args ...interface{}) interface{}
- func Repeat(env utils.Environment, args ...interface{}) interface{}
- func Replace(env utils.Environment, args ...interface{}) interface{}
- func Right(env utils.Environment, args ...interface{}) interface{}
- func Round(env utils.Environment, args ...interface{}) interface{}
- func RoundDown(env utils.Environment, args ...interface{}) interface{}
- func RoundUp(env utils.Environment, args ...interface{}) interface{}
- func Split(env utils.Environment, args ...interface{}) interface{}
- func TZ(env utils.Environment, args ...interface{}) interface{}
- func TZOffset(env utils.Environment, args ...interface{}) interface{}
- func Title(env utils.Environment, args ...interface{}) interface{}
- func ToEpoch(env utils.Environment, args ...interface{}) interface{}
- func ToJSON(env utils.Environment, args ...interface{}) interface{}
- func Today(env utils.Environment, args ...interface{}) interface{}
- func TranslateTemplate(template string) (string, error)
- func URLEncode(env utils.Environment, args ...interface{}) interface{}
- func Upper(env utils.Environment, args ...interface{}) interface{}
- func Weekday(env utils.Environment, args ...interface{}) interface{}
- func Word(env utils.Environment, args ...interface{}) interface{}
- func WordCount(env utils.Environment, args ...interface{}) interface{}
- func WordSlice(env utils.Environment, args ...interface{}) interface{}
- type TemplateErrors
- type Visitor
- func (v *Visitor) Visit(tree antlr.ParseTree) interface{}
- func (v *Visitor) VisitAdditionOrSubtraction(ctx *gen.AdditionOrSubtractionContext) interface{}
- func (v *Visitor) VisitArrayLookup(ctx *gen.ArrayLookupContext) interface{}
- func (v *Visitor) VisitAtomReference(ctx *gen.AtomReferenceContext) interface{}
- func (v *Visitor) VisitComparison(ctx *gen.ComparisonContext) interface{}
- func (v *Visitor) VisitConcatenation(ctx *gen.ConcatenationContext) interface{}
- func (v *Visitor) VisitContextReference(ctx *gen.ContextReferenceContext) interface{}
- func (v *Visitor) VisitDecimalLiteral(ctx *gen.DecimalLiteralContext) interface{}
- func (v *Visitor) VisitDotLookup(ctx *gen.DotLookupContext) interface{}
- func (v *Visitor) VisitEquality(ctx *gen.EqualityContext) interface{}
- func (v *Visitor) VisitExponent(ctx *gen.ExponentContext) interface{}
- func (v *Visitor) VisitFalse(ctx *gen.FalseContext) interface{}
- func (v *Visitor) VisitFunctionCall(ctx *gen.FunctionCallContext) interface{}
- func (v *Visitor) VisitFunctionParameters(ctx *gen.FunctionParametersContext) interface{}
- func (v *Visitor) VisitMultiplicationOrDivision(ctx *gen.MultiplicationOrDivisionContext) interface{}
- func (v *Visitor) VisitNegation(ctx *gen.NegationContext) interface{}
- func (v *Visitor) VisitParentheses(ctx *gen.ParenthesesContext) interface{}
- func (v *Visitor) VisitParse(ctx *gen.ParseContext) interface{}
- func (v *Visitor) VisitStringLiteral(ctx *gen.StringLiteralContext) interface{}
- func (v *Visitor) VisitTrue(ctx *gen.TrueContext) interface{}
- type XFunction
- type XTestResult
Constants ¶
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 ¶
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, }
XFUNCTIONS is our map of functions available in Excellent which aren't tests
var XFalseResult = XTestResult{}
XFalseResult can be used as a singleton for false result values
var XTESTS = map[string]XFunction{ "has_error": HasError, "has_value": HasValue, "has_group": HasGroup, "has_run_status": HasRunStatus, "has_webhook_status": HasWebhookStatus, "has_phrase": HasPhrase, "has_only_phrase": HasOnlyPhrase, "has_any_word": HasAnyWord, "has_all_words": HasAllWords, "has_beginning": HasBeginning, "has_text": HasText, "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, }
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) (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 `delimeter` and returns the field at `offset`. (first field is 1)
@(field("a,b,c", 2, ",")) -> "b" @(field("a,b,c", 5, ",")) -> "" @(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 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 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 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 HasRunStatus ¶
func HasRunStatus(env utils.Environment, args ...interface{}) interface{}
HasRunStatus returns whether `run` has the passed in status
Valid run statuses are "A" for active, "C" for complete, "E" for expired and "I" for interrupted
@(has_run_status(run, "C")) -> true @(has_run_status(child, "E")) -> false
@test has_run_status(run)
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 HasWebhookStatus ¶
func HasWebhookStatus(env utils.Environment, args ...interface{}) interface{}
HasWebhookStatus returns whether the passed in webhook response, `response`, has the passed in status
Valid webhook statuses are "S" for success, "F" for a connection failure and "E" for a non-2xx response code.
@(has_webhook_status(webhook, "S")) -> true @(has_webhook_status(webhook, "F")) -> false
@test has_webhook_status(response)
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 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 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 ¶
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 TranslateTemplate ¶
TranslateTemplate will take an old expression and translate it to the new format
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.BaseExcellentVisitor // contains filtered or unexported fields }
func NewVisitor ¶
func NewVisitor(env utils.Environment, resolver utils.VariableResolver) *Visitor
NewVisitor creates a new Excellent visitor
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