github.com/purpleclay/gitz@v0.8.2-0.20240515052600-43f80eea2fe1/parser.go (about) 1 package git 2 3 import ( 4 "strings" 5 "unicode" 6 ) 7 8 type parser func(string) (string, []string) 9 10 type combinator func(string) (string, string) 11 12 func separatedPair(first, sep, second combinator) parser { 13 return func(s string) (string, []string) { 14 out := make([]string, 0, 2) 15 str, ret := first(s) 16 out = append(out, ret) 17 str, _ = sep(str) 18 str, ret = second(str) 19 out = append(out, ret) 20 21 return str, out 22 } 23 } 24 25 func tag(tag string) combinator { 26 return func(s string) (string, string) { 27 if strings.HasPrefix(s, tag) { 28 return s[len(tag):], tag 29 } 30 return s, "" 31 } 32 } 33 34 func ws() combinator { 35 return func(s string) (string, string) { 36 for i, c := range s { 37 if !unicode.IsSpace(c) { 38 return s[i:], s[:i] 39 } 40 } 41 return s, "" 42 } 43 } 44 45 func until(delim string) combinator { 46 return func(s string) (string, string) { 47 if i := strings.Index(s, delim); i > -1 { 48 return s[i:], s[:i] 49 } 50 return s, "" 51 } 52 } 53 54 func line() combinator { 55 return func(s string) (string, string) { 56 if i := strings.Index(s, "\n"); i > 0 { 57 j := i 58 if j > 1 && s[j-1] == '\r' { 59 j = j - 1 60 } 61 62 if len(s) == i { 63 return "", s[:j] 64 } 65 return s[i+1:], s[:j] 66 } 67 return s, "" 68 } 69 } 70 71 type condition func(string) int 72 73 func alphanumeric(str string) int { 74 for i, b := range str { 75 if unicode.IsLetter(b) || unicode.IsNumber(b) { 76 return i 77 } 78 } 79 return -1 80 } 81 82 func lineEnding(str string) int { 83 for i, b := range str { 84 if b == '\r' || b == '\n' { 85 return i 86 } 87 } 88 return -1 89 } 90 91 func takeUntil(cond condition) combinator { 92 return func(s string) (string, string) { 93 if i := cond(s); i != -1 { 94 return s[i:], s[:i] 95 } 96 return s, s 97 } 98 }