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  }