[
  {
    "path": ".gitignore",
    "content": "*.swp\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013 Patrice FERLET (metal3d.org)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "GoVerbalExpressions\n===================\n\n[![Build Status](https://drone.io/github.com/VerbalExpressions/GoVerbalExpressions/status.png)](https://drone.io/github.com/VerbalExpressions/GoVerbalExpressions/latest)\n[![Coverage Status](https://coveralls.io/repos/VerbalExpressions/GoVerbalExpressions/badge.png?branch=master)](https://coveralls.io/r/VerbalExpressions/GoVerbalExpressions?branch=master)\n\nGo VerbalExpressions implementation\n\nVerbalExpression is a concept to help building difficult regular expressions.\n\nSee online doc here: http://godoc.org/github.com/VerbalExpressions/GoVerbalExpressions\n\n\n## Other Implementations\nYou can see an up to date list of all ports on [VerbalExpressions.github.io](http://VerbalExpressions.github.io).\n- [Javascript](https://github.com/jehna/VerbalExpressions)\n- [Ruby](https://github.com/VerbalExpressions/RubyVerbalExpressions)\n- [C#](https://github.com/VerbalExpressions/CSharpVerbalExpressions)\n- [Python](https://github.com/VerbalExpressions/PythonVerbalExpressions)\n- [Java](https://github.com/VerbalExpressions/JavaVerbalExpressions)\n- [PHP](https://github.com/VerbalExpressions/PHPVerbalExpressions)\n- [C++](https://github.com/VerbalExpressions/CppVerbalExpressions)\n- [Haskell](https://github.com/VerbalExpressions/HaskellVerbalExpressions)\n\n\n## Installation\n\nUse this command line:\n    \n    go get github.com/VerbalExpressions/GoVerbalExpressions\n\nThis will install package in your $GOPATH and you will be ready to import it.\n\n## Examples\n\n```go\n\n// import with a nice name\nimport (\n    \"github.com/VerbalExpressions/GoVerbalExpressions\" // imports verbalexpressions package\n    \"fmt\"\n)\n\nfunc main () {\n    v := verbalexpressions.New().\n            StartOfLine().\n            Then(\"http\").\n            Maybe(\"s\").\n            Then( \"://\").\n            Maybe(\"www.\").\n            AnythingBut(\" \").\n            EndOfLine()\n\n    testMe := \"https://www.google.com\"\n    \n    if v.Test(testMe) {\n       fmt.Println(\"You have a valid URL\") \n    } else {\n       fmt.Println(\"URL is incorrect\") \n    }\n}\n\n```\n\n\nWe try to give alias method and/or helpers. For example:\n\n```go\n\n    // s will be \"We have a blue house\"\n    s := verbalexpressions.New().Find(\"red\").Replace(\"We have a red house\", \"blue\")\n\n    // c will be:\n    // [\n    //    [\"http://www.google.com\",  \"http://\", \"www.google.com\"]\n    // ]\n    c := verbalexpressions.New().\n        BeginCapture().\n            Find(\"http\").Maybe(\"s\").Find(\"://\").\n        EndCapture().\n        BeginCapture().\n            Find(\"www.\").Anything().\n        EndCapture().\n        Captures(\"http://www.google.com\")\n\n    // check c[0][1] => http://\n    //       c[0][2] => www.google.com\n\n```\n\n\n"
  },
  {
    "path": "doc.go",
    "content": "/*\nThis is a Go implementation of VerbalExpressions for other languages.\nCheck http://VerbalExpressions.github.io to know the other implementations.\n\nVerbalExperssions is a way to build complex regular expressions with a verbal language.\n\nThe repo name is \"GoVerbalExpressions\" but the real package name is \"verbalexpressions\". So, to import verbalexpressions package, just do:\n\n\timport \"github.com/VerbalExpressions/GoVerbalExpressions\"\n\nThen, use \"verbalexpressions\" as prefix. There is a simple example\n\nUse \"New()\" factory then you can chain calls. Go syntax allows you to set new line after seperators:\n\n\tv := verbalexpressions.New().\n\t\tStartOfLine().\n\t\tFind(\"foo\").\n\t\tWord().\n\t\tAnything().\n\t\tEndOfLine()\n\nThen, you can use \"Test()\" method to check if your string matches expression.\n\nYou may get the regexp.Regexp structure using \"Regex()\" method, then use common methods to split, replace, find submatches and so on... as usual\n\nThere are some helpers that use direct call to the regexp package:\n\n- Replace\n- Captures\n- Test\n\n*/\npackage verbalexpressions\n"
  },
  {
    "path": "example_test.go",
    "content": "package verbalexpressions_test\n\nimport (\n\t\"fmt\"\n\t\"github.com/VerbalExpressions/GoVerbalExpressions\"\n)\n\nfunc ExampleVerbalExpression_Find() {\n\ts := \"foo bar baz\"\n\tv := verbalexpressions.New().Find(\"bar\")\n\tfmt.Println(v.Test(s))\n\t// Output: true\n}\n\nfunc ExampleVerbalExpression_Captures() {\n\ts := `This should get barsystem and whatever...\nAnd there, another barelement to fetch`\n\t// get \"bar\" followed by a word\n\tv := verbalexpressions.New().Anything().\n\t\tBeginCapture().\n\t\tFind(\"bar\").Word().\n\t\tEndCapture()\n\n\tres := v.Captures(s)\n\n\t// walk results\n\tfor _, element := range res {\n\t\t// i reprensent capture count and element is a\n\t\t// slice with captures (0 = global find, 1 = first capture)\n\t\tfmt.Printf(\"Global capture: %s\\n\", element[0])\n\t\tfmt.Printf(\"First capture: %s\\n\", element[1])\n\t}\n\n\t//Output:\n\t//Global capture: This should get barsystem\n\t//First capture: barsystem\n\t//Global capture: And there, another barelement\n\t//First capture: barelement\n\n}\n\nfunc ExampleVerbalExpression_Range() {\n\ts := \"This 1 is 55 a TEST\"\n\tv := verbalexpressions.New().Range(\"a\", \"z\", 0, 9)\n\tres := v.Regex().FindAllString(s, -1)\n\tfmt.Println(res)\n\t//Output: [h i s 1 i s 5 5 a]\n\n}\n\nfunc ExampleVerbalExpression_Any() {\n\n\ts := \"foo1 foo5 foobar\"\n\tv := verbalexpressions.New().Find(\"foo\").Any(\"1234567890\").Regex().FindAllString(s, -1)\n\tfmt.Println(v)\n\t//Output: [foo1 foo5]\n}\n\nfunc ExampleVerbalExpression_Or() {\n\ts := \"This is a foo and a bar there\"\n\tv1 := verbalexpressions.New().Find(\"bar\")\n\tv := verbalexpressions.New().\n\t\tFind(\"foo\").\n\t\tOr(v1)\n\n\tfmt.Println(v.Regex().FindAllString(s, -1))\n\t//Output: [foo bar]\n}\n\nfunc ExampleVerbalExpression_Replace() {\n\n\ts := \"We've got a red house\"\n\tres := verbalexpressions.New().Find(\"red\").Replace(s, \"blue\")\n\tfmt.Println(res)\n\t//Output: We've got a blue house\n}\n\nfunc ExampleVerbalExpression_AnythingBut() {\n\n\ts := \"This is a simple test\"\n\tv := verbalexpressions.New().AnythingBut(\"ie\").Regex().FindAllString(s, -1)\n\tfmt.Println(v)\n\t//Output: [Th s  s a s mpl  t st]\n}\n"
  },
  {
    "path": "helpers.go",
    "content": "package verbalexpressions\n\n/* proxy and helpers to regexp.Regexp functions */\n\n// Test return true if verbalexpressions matches something in string \"s\"\nfunc (v *VerbalExpression) Test(s string) bool {\n\treturn v.Regex().Match([]byte(s))\n}\n\n// Replace alias to regexp.ReplaceAllString. It replace the found expression from\n// string src by string dst\nfunc (v *VerbalExpression) Replace(src string, dst string) string {\n\treturn v.Regex().ReplaceAllString(src, dst)\n}\n\n// Returns a slice of results from captures. If you didn't apply BeginCapture() and EndCapture(), the slices\n// will return slice of []string where []string is length 1, and 0 index is the global capture\nfunc (v *VerbalExpression) Captures(s string) [][]string {\n\titer := 1\n\tif v.flags&GLOBAL != 0 {\n\t\titer = -1\n\t}\n\treturn v.Regex().FindAllStringSubmatch(s, iter)\n}\n"
  },
  {
    "path": "verbalexpressions.go",
    "content": "// Copyright 2013 Patrice FERLET\n// Use of this source code is governed by MIT-style\n// license that can be found in the LICENSE file\npackage verbalexpressions\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype Flag uint\n\nconst (\n\tMULTILINE Flag = 1 << iota\n\tIGNORE_CASE\n\tDOTALL\n\tUNGREEDY\n\tGLOBAL\n)\n\n// VerbalExpression structure to create expression\ntype VerbalExpression struct {\n\texpression string\n\tparts      []string\n\tsuffixes   string\n\tprefixes   string\n\tflags      Flag\n\tcompiled   bool\n\tregexp     *regexp.Regexp\n}\n\n// quote is an alias to regexp.QuoteMeta\nfunc quote(s string) string {\n\treturn regexp.QuoteMeta(s)\n}\n\n// utility function to return only strings\nfunc tostring(i interface{}) string {\n\tvar r string\n\tswitch x := i.(type) {\n\tcase string:\n\t\tr = x\n\tcase uint64:\n\t\tr = strconv.FormatUint(x, 10)\n\tcase int64:\n\t\tr = strconv.FormatInt(x, 10)\n\tcase uint:\n\t\tr = strconv.FormatUint(uint64(x), 10)\n\tcase int:\n\t\tr = strconv.FormatInt(int64(x), 10)\n\tdefault:\n\t\tlog.Panicf(\"Could not convert %v %t\", x, x)\n\t}\n\treturn r\n}\n\n// Instanciate a new VerbalExpression. You should use this method to\n// initalize some internal var.\n//\n// Example:\n//\t\tv := verbalexpression.New().Find(\"foo\")\nfunc New() *VerbalExpression {\n\tr := new(VerbalExpression)\n\tr.flags = MULTILINE | GLOBAL\n\tr.parts = make([]string, 0)\n\treturn r\n}\n\n// append a modifier\nfunc (v *VerbalExpression) addmodifier(f Flag) *VerbalExpression {\n\tv.compiled = false //reinit previous regexp compilation\n\tv.flags |= f\n\treturn v\n}\n\n// remove a modifier\nfunc (v *VerbalExpression) removemodifier(f Flag) *VerbalExpression {\n\tv.compiled = false //reinit previous regexp compilation\n\tv.flags &= ^f\n\treturn v\n}\n\n// append modifiers that are activated\nfunc (v *VerbalExpression) getFlags() string {\n\tflags := \"misU\" // warning, follow Flag const order\n\tresult := []rune{}\n\n\tfor i, flag := range flags {\n\t\tif v.flags&(1<<uint(i)) != 0 {\n\t\t\tresult = append(result, flag)\n\t\t}\n\t}\n\n\treturn string(result)\n}\n\n// add method, append expresions to the internal string that will be parsed\nfunc (v *VerbalExpression) add(s string) *VerbalExpression {\n\tv.compiled = false //reinit previous regexp compilation\n\tv.expression += s\n\treturn v\n}\n\n// Start to capture something, stop with EndCapture()\nfunc (v *VerbalExpression) BeginCapture() *VerbalExpression {\n\tv.suffixes += \")\"\n\treturn v.add(\"(\")\n}\n\n// Stop capturing expresions parts\nfunc (v *VerbalExpression) EndCapture() *VerbalExpression {\n\tv.suffixes = strings.Replace(v.suffixes, \")\", \"\", 1)\n\treturn v.add(\")\")\n}\n\n// Anything will match any char\nfunc (v *VerbalExpression) Anything() *VerbalExpression {\n\treturn v.add(`(?:.*)`)\n}\n\n// AnythingBut will match anything excpeting the given string.\nfunc (v *VerbalExpression) AnythingBut(s string) *VerbalExpression {\n\treturn v.add(`(?:[^` + quote(s) + `]*)`)\n}\n\n// Something matches at least one char\nfunc (v *VerbalExpression) Something() *VerbalExpression {\n\treturn v.add(`(?:.+)`)\n}\n\n// Same as Something but excepting chars given in string \"s\"\nfunc (v *VerbalExpression) SomethingBut(s string) *VerbalExpression {\n\treturn v.add(`(?:[^` + quote(s) + `]+)`)\n}\n\n// EndOfLine tells verbalexpressions to match a end of line.\n// Warning, to check multiple line, you must use SearchOneLine(true)\nfunc (v *VerbalExpression) EndOfLine() *VerbalExpression {\n\tif !strings.HasSuffix(v.suffixes, \"$\") {\n\t\tv.suffixes += \"$\"\n\t}\n\treturn v\n}\n\n// Maybe will search string zero on more times\nfunc (v *VerbalExpression) Maybe(s string) *VerbalExpression {\n\treturn v.add(`(?:` + quote(s) + `)?`)\n}\n\n// StartOfLine seeks the begining of a line. As EndOfLine you should use\n// SearchOneLine(true) to test multiple lines\nfunc (v *VerbalExpression) StartOfLine() *VerbalExpression {\n\tif !strings.HasPrefix(v.prefixes, \"^\") {\n\t\tv.prefixes = `^` + v.prefixes\n\t}\n\treturn v\n}\n\n// Find seeks string. The string MUST be there (unlike Maybe() method)\nfunc (v *VerbalExpression) Find(s string) *VerbalExpression {\n\treturn v.add(`(?:` + quote(s) + `)`)\n}\n\n// Not invert Find, meaning search something excepting \"value\". This\n// is different than SomethingBut or AnythingBut that works with a list of\n// caracters. Note that this method is not exactly the same as PCRE system.\n//\n// While PCRE allows: foo(?!bar)baz, \"foobarrbaz\" matches (note the double r).\n// With our method, this doesn't match. But: \"foobarbaz\" doen't match (so it's ok).\n// And \"fooXXXbaz\" matches also.\nfunc (v *VerbalExpression) Not(value string) *VerbalExpression {\n\t//return v.add(`(?!(` + quote(value) + `))`)\n\t// because Golang doesn't implement ?!\n\t// we create a pseudo negative system...\n\n\trunes := []rune(quote(value))\n\tparts := make([]string, 0)\n\tprev := \"\"\n\tfor _, r := range runes {\n\t\tparts = append(parts, prev+\"[^\"+string(r)+\"]\")\n\t\tprev += string(r)\n\t}\n\n\texp := strings.Join(parts, \"|\")\n\texp = \"(?:\" + exp + \")*?\"\n\treturn v.add(exp)\n}\n\n// Alias to Find()\nfunc (v *VerbalExpression) Then(s string) *VerbalExpression {\n\treturn v.Find(s)\n}\n\n// Any accepts caracters to be matched\nfunc (v *VerbalExpression) Any(s string) *VerbalExpression {\n\treturn v.add(`(?:[` + quote(s) + `])`)\n}\n\n//AnyOf is an alias to Any\nfunc (v *VerbalExpression) AnyOf(s string) *VerbalExpression {\n\treturn v.Any(s)\n}\n\n// LineBreak to find \"\\n\" or \"\\r\\n\"\nfunc (v *VerbalExpression) LineBreak() *VerbalExpression {\n\treturn v.add(`(?:(?:\\n)|(?:\\r\\n))`)\n}\n\n// Alias to LineBreak\nfunc (v *VerbalExpression) Br() *VerbalExpression {\n\treturn v.LineBreak()\n}\n\n// Range accepts an even number of arguments. Each pair of values defines start and end of range.\n// Think like this: Range(from, to [, from, to ...])\nfunc (v *VerbalExpression) Range(args ...interface{}) *VerbalExpression {\n\tif len(args)%2 != 0 {\n\t\tlog.Panicf(\"Range: not even args number\")\n\t}\n\n\tparts := make([]string, 3)\n\tapp := \"\"\n\tfor i := 0; i < len(args); i++ {\n\t\tapp += tostring(args[i])\n\t\tif i%2 != 0 {\n\t\t\tparts = append(parts, quote(app))\n\t\t\tapp = \"\"\n\t\t} else {\n\t\t\tapp += \"-\"\n\t\t}\n\t}\n\treturn v.add(\"[\" + strings.Join(parts, \"\") + \"]\")\n}\n\n// Tab fetch tabulation char (\\t)\nfunc (v *VerbalExpression) Tab() *VerbalExpression {\n\treturn v.add(`\\t+`)\n}\n\n// Word matches any word (containing alpha char)\nfunc (v *VerbalExpression) Word() *VerbalExpression {\n\treturn v.add(`\\w+`)\n}\n\n// Multiply string s expression\n//\n// Multiple(value string [, min int[, max int]])\n//\n// This method accepts 1 to 3 arguments, argument 2 is min, argument 3 is max:\n//\n//\t\t// get \"foo\" at least one time\n//\t\tv.Multiple(\"foo\")\n//\t\tv.Multiple(\"foo\", 1)\n//\n//\t\t// get \"foo\" 0 or more times\n//\t\tv.Multiple(\"foo\", 0)\n//\n//\t\t//get \"foo\" 0 or 1 times\n//\t\tv.Multiple(\"foo\", 0, 1)\n//\n//\t\t// get \"foo\" 0 to 10 times\n//\t\tv.Multiple(\"foo\",0 ,10)\n//\n//\t\t//get \"foo\" at least 10 times\n//\t\tv.Multiple(\"foo\", 10)\n//\n//\t\t//get \"foo\" exactly 10 times\n//\t\tv.Multiple(\"foo\", 10, 10)\n//\n//\t\t//get \"foo\" from 1 to 10 times\n//\t\tv.Multiple(\"foo\", 1, 10)\nfunc (v *VerbalExpression) Multiple(s string, mults ...int) *VerbalExpression {\n\n\tif len(mults) > 2 {\n\t\tpanic(\"Multiple: you can only give 1 or to multipliers, min and max as int\")\n\t}\n\t// fetch multiplier if any\n\tvar min, max int = -1, -1\n\tmult := \"+\"\n\n\tif len(mults) > 0 {\n\t\tmin = mults[0]\n\t\tif len(mults) == 2 {\n\t\t\tmax = mults[1]\n\t\t}\n\t}\n\n\tif min == 0 && max == 1 {\n\t\t// 0 or 1 time\n\t\tmult = \"?\"\n\t}\n\n\tif min == 0 && max == -1 {\n\t\t// 0 or more\n\t\tmult = \"*\"\n\t}\n\n\tif min == 1 && max == -1 {\n\t\t// at least 1 time\n\t\tmult = \"+\"\n\t}\n\n\tif min > 1 && max == -1 {\n\t\t//at least min times\n\t\tmult = fmt.Sprintf(\"{%d,}\", min)\n\t}\n\n\tif max > 1 {\n\t\tif min > 0 {\n\t\t\t// min to max times\n\t\t\tmult = fmt.Sprintf(\"{%d,%d}\", min, max)\n\t\t} else {\n\t\t\t// max times\n\t\t\tmult = fmt.Sprintf(\"{,%d}\", max)\n\t\t}\n\t}\n\n\treturn v.add(\"(?:\" + quote(s) + \")\" + mult)\n}\n\n// Or, chains an alternative VerbalExpression\nfunc (v *VerbalExpression) Or(ve *VerbalExpression) *VerbalExpression {\n\tv.parts = append(v.parts, ve.Regex().String()+\"|\")\n\treturn v\n}\n\n// Add another VerbalExpression to the current.\n// Usefull to concatenate several complex search patterns\nfunc (v *VerbalExpression) And(ve *VerbalExpression) *VerbalExpression {\n\treturn v.add(\"(?:\" + ve.Regex().String() + \")\")\n}\n\n// WithAnyCase asks verbalexpressions to match with or without case sensitivity\nfunc (v *VerbalExpression) WithAnyCase(sensitive bool) *VerbalExpression {\n\tif sensitive {\n\t\treturn v.addmodifier(IGNORE_CASE)\n\t}\n\treturn v.removemodifier(IGNORE_CASE)\n}\n\n// SearchOneLine deactivates \"multiline\" mode if online argument is true\n// Default is false\nfunc (v *VerbalExpression) SearchOneLine(oneline bool) *VerbalExpression {\n\tif !oneline {\n\t\treturn v.addmodifier(MULTILINE)\n\t}\n\treturn v.removemodifier(MULTILINE)\n}\n\n// MatchAllWithDot lets VerbalExpression matching \".\" for everything including \\n, \\r, and so on\nfunc (v *VerbalExpression) MatchAllWithDot(enable bool) *VerbalExpression {\n\tif enable {\n\t\treturn v.addmodifier(DOTALL)\n\t}\n\treturn v.removemodifier(DOTALL)\n}\n\n// Regex returns the regular expression to use to test on string.\nfunc (v *VerbalExpression) Regex() *regexp.Regexp {\n\n\tif !v.compiled {\n\t\tv.regexp = regexp.MustCompile(\n\t\t\tstrings.Join([]string{\n\t\t\t\tstrings.Join(v.parts, \"\"),\n\t\t\t\t`(?` + v.getFlags() + `)`,\n\t\t\t\tv.prefixes,\n\t\t\t\tv.expression,\n\t\t\t\tv.suffixes}, \"\"))\n\t\tv.compiled = true\n\t}\n\treturn v.regexp\n}\n\nfunc (v *VerbalExpression) StopAtFirst(enable bool) *VerbalExpression {\n\tif enable {\n\t\treturn v.removemodifier(GLOBAL)\n\t}\n\n\treturn v.addmodifier(GLOBAL)\n}\n\n/*\nAlready implemented => v\n\nv\tadd\nv\tstartOfLine\nv\tendOfLine\nv\tthen\nv\tfind\nv\tmaybe\nv\tanything\nv\tanythingBut\nv\tsomething\nv\tsomethingBut\nv\treplace\nv\tlineBreak\nv\tbr (shorthand for lineBreak)\nv\ttab\nv\tword\nv\tanyOf\nv\tany (shorthand for anyOf)\nv\trange\nv\twithAnyCase\nv\tstopAtFirst\nv\tsearchOneLine\nv\tmultiple\nv\tor\nv\tbegindCapture\nv\tendCapture\n*/\n"
  },
  {
    "path": "verbalexpressions_test.go",
    "content": "// Copyright 2013 Patrice FERLET\n// Use of this source code is governed by MIT-style\n// license that can be found in the LICENSE file\npackage verbalexpressions\n\nimport \"testing\"\nimport \"strings\"\n\nfunc assertStringEquals(s1, s2 string, t *testing.T) {\n\tif s1 != s2 {\n\t\tt.Errorf(\"%s != %s\", s1, s2)\n\t}\n}\n\nfunc TestChaining(t *testing.T) {\n\n\texp := \"http://www.google.com\"\n\tv := New().StartOfLine().\n\t\tThen(\"http\").\n\t\tMaybe(\"s\").\n\t\tThen(\"://\").\n\t\tMaybe(\"www.\").\n\t\tWord().\n\t\tThen(\".\").\n\t\tWord().\n\t\tMaybe(\"/\").\n\t\tEndOfLine()\n\tif !v.Test(exp) {\n\t\tt.Errorf(\"%v regexp doesn't match %s\", v.Regex(), exp)\n\t}\n}\n\nfunc TestRange(t *testing.T) {\n\n\texp := \"abcdef 123\"\n\n\tv := New().Range(\"a\", \"z\", 0, 9)\n\tif v.Regex().String() != \"(?m)[a-z0-9]\" {\n\t\tt.Errorf(\"%s is not (?m)[a-z0-9]\", v.Regex())\n\t}\n\tif !v.Test(exp) {\n\t\tt.Errorf(\"%v regexp doesn't match %s\", v.Regex(), exp)\n\t}\n\texp = \"ABCDEF\"\n\tif v.Test(exp) {\n\t\tt.Errorf(\"%v regexp should not match %s\", v.Regex(), exp)\n\t}\n\n}\n\nfunc TestPanicOnRangeOddParams(t *testing.T) {\n\n\tdefer func() {\n\t\t// if no panic... the test fails\n\t\tif r := recover(); r == nil {\n\t\t\tt.Errorf(\"Call must panic !\")\n\t\t}\n\t}()\n\n\tNew().Range(\"a\", \"z\", 0, 9, 10)\n}\n\nfunc TestOneLine(t *testing.T) {\n\ts := \"atlanta\\narkansas\\nalabama\\narachnophobia\"\n\n\tv := New().SearchOneLine(true).Find(\"a\").EndOfLine().Regex()\n\tres := v.FindAllStringIndex(s, -1)\n\tif len(res) != 1 {\n\t\tt.Errorf(\"%v should be length 1, %d instead\", res, len(res))\n\t}\n\tif len(res[0]) != 2 {\n\t\tt.Errorf(\"%v should be length 2, %d instead\", res[0], len(res[0]))\n\t}\n\n\tv = New().SearchOneLine(false).Find(\"a\").EndOfLine().Regex()\n\tres = v.FindAllStringIndex(s, -1)\n\tif len(res) != 3 {\n\t\tt.Errorf(\"%v should be length 3, %d instead\", res, len(res))\n\t}\n\tfor _, r := range res {\n\t\tif len(r) != 2 {\n\t\t\tt.Errorf(\"%v should be length 2, %d instead\", r, len(r))\n\t\t}\n\t}\n}\n\nfunc TestAnythingBut(t *testing.T) {\n\n\ts := \"This is a simple test\"\n\tv := New().AnythingBut(\"im\").Regex().FindAllString(s, -1)\n\tfor _, st := range v {\n\t\tif strings.Contains(st, \"i\") {\n\t\t\tt.Errorf(\"%s should not find \\\"i\\\"\", st)\n\t\t}\n\t\tif strings.Contains(st, \"m\") {\n\t\t\tt.Errorf(\"%s should not find \\\"m\\\"\", st)\n\t\t}\n\t}\n}\n\nfunc TestAny(t *testing.T) {\n\n\ts := \"foo1 foo5 foobar\"\n\tv := New().Find(\"foo\").Any(\"1234567890\")\n\tres := v.Regex().FindAllString(s, -1)\n\tif len(res) != 2 {\n\t\tt.Errorf(\"len(res) : %d isn't 2\", len(res))\n\t}\n\t//test alias\n\tv = New().Find(\"foo\").AnyOf(\"1234567890\")\n\tres = v.Regex().FindAllString(s, -1)\n\tif len(res) != 2 {\n\t\tt.Errorf(\"len(res) : %d isn't 2\", len(res))\n\t}\n\n}\n\nfunc TestReplace(t *testing.T) {\n\n\ts := \"foomode barmode themodebaz\"\n\texpect := \"foochanged barchanged thechangedbaz\"\n\n\tv := New().Find(\"mode\")\n\tres := v.Replace(s, \"changed\")\n\n\tif res != expect {\n\t\tt.Errorf(\"Replacement hasn't worked as expected %s != %s\", res, expect)\n\t}\n\n}\n\nfunc TestCaptures(t *testing.T) {\n\n\ts := \"this is a foobarsystem to get bar\"\n\n\tv := New().Anything().Find(\"foo\").Find(\"bar\").Word()\n\tres := v.Regex().FindAllStringSubmatch(s, -1)\n\n\tif len(res[0]) > 1 {\n\t\tt.Errorf(\"%v is not a slice of only one match (globale match)\", res)\n\t}\n\tif res[0][0] != \"this is a foobarsystem\" {\n\t\tt.Errorf(\"global capture \\\"%s\\\" is not \\\"this is a foobarsystem\\\"\", res[0][0])\n\t}\n\n\tv = New().Anything().Find(\"foo\").BeginCapture().Find(\"bar\").Word().EndCapture()\n\tres = v.Regex().FindAllStringSubmatch(s, -1)\n\n\tif len(res) != 1 {\n\t\tt.Errorf(\"%v is not slice length 1\", res)\n\t}\n\n\tif res[0][0] != \"this is a foobarsystem\" {\n\t\tt.Errorf(\"global capture \\\"%s\\\" is not \\\"this is a foobarsystem\\\"\", res[0][0])\n\t}\n\tif res[0][1] != \"barsystem\" {\n\t\tt.Errorf(\"capture %s is not barsystem\", res[0][1])\n\t}\n\n}\n\nfunc TestSeveralCaptures(t *testing.T) {\n\n\ts := `\n\tthis is a foobarsystem that matches my test\n\tAnd there, a new foobartest that should be ok\n`\n\n\tv := New().Anything().Find(\"foo\").\n\t\tBeginCapture().\n\t\tFind(\"bar\").Word().\n\t\tEndCapture().\n\t\tSearchOneLine(false)\n\tres := v.Regex().FindAllStringSubmatch(s, -1)\n\n\tfor i, r := range res {\n\t\tswitch i {\n\t\tcase 0:\n\t\t\tif r[1] != \"barsystem\" {\n\t\t\t\tt.Errorf(\"%s is not \\\"barsystem\\\"\", r[1])\n\t\t\t}\n\t\tcase 1:\n\t\t\tif r[1] != \"bartest\" {\n\t\t\t\tt.Errorf(\"%s is not \\\"bartest\\\"\", r[1])\n\t\t\t}\n\t\tdefault:\n\t\t\tt.Errorf(\"%v is not allowed result\", r)\n\t\t}\n\t}\n\n}\n\nfunc TestCaptureSeveralTimes(t *testing.T) {\n\tv := New().\n\t\tBeginCapture().\n\t\tFind(\"http\"). // find http\n\t\tMaybe(\"s\").   // + s if any\n\t\tFind(\"://\").\n\t\tEndCapture(). // stop, so we will capture http:// and https://\n\t\tBeginCapture().\n\t\tFind(\"www.\").Anything(). // capture url: www.google.com\n\t\tEndCapture()\n\tc := v.Captures(\"http://www.google.com\")\n\n\tif len(c) != 1 {\n\t\tt.Errorf(\"capture length is not 1: %d\", len(c))\n\t}\n\n\tif c[0][1] != \"http://\" {\n\t\tt.Errorf(\"first group should be http://, found: %s\", c[0][1])\n\t}\n\n\tif c[0][2] != \"www.google.com\" {\n\t\tt.Errorf(\"first group should be www.google.com, found: %s\", c[0][2])\n\t}\n\n}\n\nfunc TestCapturingSeveralGroups(t *testing.T) {\n\n\ts := `\n\n<b>test 1</b>\n<b>foo 2</b>\n\n`\n\tv := New().\n\t\tFind(\"<b>\").\n\t\tBeginCapture().\n\t\tWord().\n\t\tEndCapture().\n\t\tAny(\" \").\n\t\tBeginCapture().\n\t\tRange(\"0\", \"9\").\n\t\tEndCapture().\n\t\tFind(\"</b>\")\n\n\tres := v.Captures(s)\n\tif len(res) != 2 {\n\t\tt.Errorf(\"%v is not length 2\", res)\n\t}\n\tfor i, r := range res {\n\t\tswitch i {\n\t\tcase 0:\n\t\t\tif r[1] != \"test\" || r[2] != \"1\" {\n\t\t\t\tt.Errorf(\"%s,%s is not test,1\", r[1], r[2])\n\t\t\t}\n\t\tcase 1:\n\t\t\tif r[1] != \"foo\" || r[2] != \"2\" {\n\t\t\t\tt.Errorf(\"%s,%s is not test,1\", r[1], r[2])\n\t\t\t}\n\t\tdefault:\n\t\t\tt.Errorf(\"%d is not a valid result index for %v\", i, res)\n\t\t}\n\t}\n\n}\n\nfunc TestORMethod(t *testing.T) {\n\n\ts := \"foobarbaz footestbaz foonobaz\"\n\texpected := []string{\"foobarbaz\", \"footestbaz\"}\n\n\tv := New().Find(\"foobarbaz\").Or(New().Find(\"footestbaz\"))\n\tif !v.Test(s) {\n\t\tt.Errorf(\"%s doesn't match %s\", v.Regex(), s)\n\t}\n\tres := []string{}\n\tres = v.Regex().FindAllString(s, -1)\n\n\tif len(res) != 2 {\n\t\tt.Errorf(\"%v is not length 2\", res)\n\t}\n\n\tfor i, r := range res {\n\t\tif r != expected[i] {\n\t\t\tt.Errorf(\"%s is not expected value: %s\", r, expected[i])\n\t\t}\n\t}\n\n}\n\nfunc TestMultipleMethod(t *testing.T) {\n\n\tv := New().Multiple(\"foo\")\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo)+\", t)\n\n\t// it the same... but to cover...\n\tv = New().Multiple(\"foo\", 1)\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo)+\", t)\n\n\tv = New().Multiple(\"foo\", 0)\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo)*\", t)\n\n\tv = New().Multiple(\"foo\", 0, 1)\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo)?\", t)\n\n\tv = New().Multiple(\"foo\", 0, 10)\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo){,10}\", t)\n\n\tv = New().Multiple(\"foo\", 10)\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo){10,}\", t)\n\n\tv = New().Multiple(\"foo\", 10, 10)\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo){10,10}\", t)\n\n\tv = New().Multiple(\"foo\", 1, 10)\n\tassertStringEquals(v.Regex().String(), \"(?m)(?:foo){1,10}\", t)\n\n}\n\nfunc TestPanicMultipleMethod(t *testing.T) {\n\tdefer func() {\n\t\tif r := recover(); r == nil {\n\t\t\tt.Errorf(\"We should have panic here !\")\n\t\t}\n\t}()\n\t_ = New().Multiple(\"foo\", 1, 10, 15)\n}\n\nfunc TestSomethingMethods(t *testing.T) {\n\n\ts := \"abcdefghi\"\n\n\tv := New().Find(\"ab\").Something().Find(\"ef\")\n\tres := v.Regex().FindAllString(s, -1)\n\n\tif res[0] != \"abcdef\" {\n\t\tt.Errorf(\"%v hasn't %s \", res, \"abcdef\")\n\t}\n\n\tv = New().Find(\"ab\").SomethingBut(\"d\")\n\tres = v.Regex().FindAllString(s, -1)\n\tif res[0] != \"abc\" {\n\t\tt.Errorf(\"%v hasn't %s \", res, \"abc\")\n\t}\n\n}\n\nfunc TestAllWithDot(t *testing.T) {\n\n\ts := `\nfoo bar\nbaz\n`\n\tv := New().Find(\"bar\").Anything().Then(\"baz\")\n\tres := v.Test(s)\n\tif res {\n\t\tt.Errorf(\"Error, %s should not match bar.baz\", v.Regex())\n\t}\n\n\tv.MatchAllWithDot(true)\n\tres = v.Test(s)\n\tif !res {\n\t\tt.Errorf(\"Error, %s should match bar.baz\", v.Regex())\n\t}\n\n}\n\nfunc TestWithAnyCase(t *testing.T) {\n\ts := \"A MESSAGE IN CAPS\"\n\n\tv := New().Find(\"message\").WithAnyCase(true)\n\tres := v.Test(s)\n\tif !res {\n\t\tt.Errorf(\"Error, message should match MESSAGE\", v.Regex())\n\t}\n}\n\nfunc TestModifiers(t *testing.T) {\n\tv := New()\n\tassertStringEquals(v.getFlags(), \"m\", t)\n\n\tv.SearchOneLine(true)\n\tassertStringEquals(v.getFlags(), \"\", t)\n\n\tv.SearchOneLine(false)\n\tassertStringEquals(v.getFlags(), \"m\", t)\n\n\tv.WithAnyCase(true)\n\tassertStringEquals(v.getFlags(), \"mi\", t)\n\n\tv.WithAnyCase(false)\n\tassertStringEquals(v.getFlags(), \"m\", t)\n\n\tv.MatchAllWithDot(true)\n\tassertStringEquals(v.getFlags(), \"ms\", t)\n\n\tv.MatchAllWithDot(false)\n\tassertStringEquals(v.getFlags(), \"m\", t)\n\n\tv.flags = 16\n\tassertStringEquals(v.getFlags(), \"\", t)\n}\n\nfunc TestGlobalModifier(t *testing.T) {\n\n\ts := \"aaa aab aba abc\"\n\n\tv := New().BeginCapture().Find(\"aa\").AnythingBut(\" \").EndCapture()\n\n\tres := v.Captures(s)\n\n\tif len(res) != 2 {\n\t\tt.Errorf(\"Initial state, GLOBAL on: %v is not lenght 2\", res)\n\t}\n\n\tv.StopAtFirst(true)\n\tres = v.Captures(s)\n\tif len(res) > 1 {\n\t\tt.Errorf(\"%v is not lenght 1\", res)\n\t}\n\n\tv.StopAtFirst(false)\n\tres = v.Captures(s)\n\tif len(res) != 2 {\n\t\tt.Errorf(\"State 2, GLOBAL reactivated: %v is not lenght 2\", res)\n\t}\n\n}\n\nfunc TestStartEndWithOR(t *testing.T) {\n\ts := `\nfoo\nno\nbar\nbar foo bar\nok\nnot\ntest\nfoo bar foo\nbar\n`\n\t// This is a very hight problem\n\t// This should generate (?m)^(?:foo)$|^(?:bar)$\n\tv := New().\n\t\tStartOfLine().\n\t\tFind(\"foo\").\n\t\tEndOfLine().\n\t\tOr(New().\n\t\tStartOfLine().\n\t\tFind(\"bar\").\n\t\tEndOfLine())\n\n\tt.Log(v.Regex())\n\tres := v.Regex().FindAllStringSubmatch(s, -1)\n\tif len(res) != 3 {\n\t\tt.Errorf(\"%v is not length 3\", res)\n\t}\n\n\t// another possibility\n\tv = New().\n\t\tStartOfLine().\n\t\tFind(\"foo\").\n\t\tEndOfLine().\n\t\tOr(New().Find(\"bar\"))\n\n\tres = v.Regex().FindAllStringSubmatch(s, -1)\n\tif len(res) != 6 {\n\t\tt.Errorf(\"%v is not length 6\", res)\n\t}\n}\n\nfunc TestLineBreak(t *testing.T) {\n\ts := `\nfoo\nbar\nbaz\n`\n\tv := New().Find(\"foo\").LineBreak().Find(\"bar\")\n\tif !v.Test(s) {\n\t\tt.Errorf(\"%v should match %s\", v.Regex(), s)\n\t}\n\n\tv = New().Find(\"foo\").Br().Find(\"bar\")\n\tif !v.Test(s) {\n\t\tt.Errorf(\"%v should match %s\", v.Regex(), s)\n\t}\n}\n\nfunc TestTABMethod(t *testing.T) {\n\ts := \"foo\tbar baz\"\n\tv := New().Find(\"foo\").Tab().Find(\"bar\")\n\tr := v.Test(s)\n\tif !r {\n\t\tt.Errorf(\"%v should match %s\", v.Regex(), s)\n\t}\n}\n\nfunc TestToString(t *testing.T) {\n\n\tres := tostring(int64(15))\n\tif res != \"15\" {\n\t\tt.Errorf(\"%v is not string \\\"15\\\"\", res)\n\t}\n\n\tres = tostring(uint64(15))\n\tif res != \"15\" {\n\t\tt.Errorf(\"%v is not string \\\"15\\\"\", res)\n\t}\n\n\tres = tostring(uint(15))\n\tif res != \"15\" {\n\t\tt.Errorf(\"%v is not string \\\"15\\\"\", res)\n\t}\n\n}\n\nfunc TestToStringMustPanic(t *testing.T) {\n\n\tdefer func() {\n\t\tif r := recover(); r == nil {\n\t\t\tt.Errorf(\"ToString must panic with unsupported types\")\n\t\t}\n\t}()\n\n\ts := make(chan int)\n\t_ = tostring(s)\n\n}\n\nfunc TestNotMethod(t *testing.T) {\n\n\ts := `foobarbaz\nfootestbaz\nfooexceptingbaz\nfoootherokbaz\nfoofoofoo\nfoonotcap\n`\n\n\tv := New().\n\t\tFind(\"foo\").\n\t\tBeginCapture().\n\t\tNot(\"excepting\").\n\t\tEndCapture().\n\t\tThen(\"baz\")\n\tres := v.Captures(s)\n\tt.Log(res)\n\tif len(res) != 3 {\n\t\tt.Errorf(\"%v is not length 3\", res)\n\t}\n\tfor i, r := range res {\n\t\tswitch i {\n\t\tcase 0:\n\t\t\tif r[1] != \"bar\" {\n\t\t\t\tt.Errorf(\"%s is not bar\", r)\n\t\t\t}\n\t\tcase 1:\n\t\t\tif r[1] != \"test\" {\n\t\t\t\tt.Errorf(\"%s is not bar\", r)\n\t\t\t}\n\t\tcase 2:\n\t\t\tif r[1] != \"otherok\" {\n\t\t\t\tt.Errorf(\"%s is not bar\", r)\n\t\t\t}\n\t\t}\n\t}\n\n}\n\nfunc TestAndOrCumulate(t *testing.T) {\n\n\ts := `AB\nBC\nAC\nBB\nCC\nA\nB\nB\nC\nA\nC\nC\nC`\n\n\tv1 := New().Find(\"B\")\n\tt.Log(v1.Regex())\n\tv2 := New().Find(\"c\").WithAnyCase(true).Or(v1) // Find B or C\n\tv := New().Find(\"A\").And(v2)                   // Find A and (B or C)\n\n\tt.Log(v.Regex())\n\tres := v.Regex().FindAllStringSubmatch(s, -1)\n\n\tif len(res) != 2 {\n\t\tt.Errorf(\"%v is not length 2\", res)\n\t}\n\n\tif res[0][0] != \"AB\" {\n\t\tt.Errorf(\"%v is not AB \", res[0][0])\n\t}\n\tif res[1][0] != \"AC\" {\n\t\tt.Errorf(\"%v is not AC \", res[1][0])\n\t}\n\n}\n"
  }
]