go-ml.dev/pkg/base@v0.0.0-20200610162856-60c38abac71b/fu/pattern.go (about)

     1  package fu
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  /*
     9  	123textE + *textE -> *TEXT => 123TEXT
    10  	123textE + 123text* -> TEXT* => TEXTE
    11  	123textE + *text* -> *TEXT* => 123TEXTE
    12  	123textE + 123*E -> 55*5 => 55text5
    13  
    14  */
    15  
    16  func makesubst(subst string) func(string) string {
    17  	counter := AtomicCounter{1}
    18  	j := strings.Index(subst, "*")
    19  	if j < 0 {
    20  		return func(v string) string {
    21  			if len(v) == 0 {
    22  				return subst
    23  			}
    24  			return subst + fmt.Sprint(counter.PostInc())
    25  		}
    26  	}
    27  	if j == 0 {
    28  		return func(v string) string { return v + subst[1:] }
    29  	}
    30  	if j == len(subst)-1 {
    31  		return func(v string) string { return subst[:j] + v }
    32  	}
    33  	return func(v string) string {
    34  		return subst[:j] + v + subst[j+1:]
    35  	}
    36  }
    37  
    38  func Starsub(pattern, subst string) func(string) (string, bool) {
    39  	j := strings.Index(pattern, "*")
    40  	if j < 0 {
    41  		return func(v string) (string, bool) {
    42  			if v == pattern {
    43  				return subst, true
    44  			}
    45  			return pattern, false
    46  		}
    47  	}
    48  	if j == 0 {
    49  		right := pattern[1:]
    50  		if right[len(right)-1] == '*' {
    51  			center := right[:len(right)-1]
    52  			if subst[0] != '*' && subst[len(subst)-1] != '*' {
    53  				panic("substitution must be like *blablabla*")
    54  			}
    55  			subst = subst[1 : len(subst)-1]
    56  			return func(v string) (string, bool) {
    57  				if k := strings.Index(v, center); k > 0 {
    58  					return v[:k] + subst + v[k+len(center):], true
    59  				}
    60  				return v, false
    61  			}
    62  		}
    63  		f := makesubst(subst)
    64  		return func(v string) (string, bool) {
    65  			if strings.HasSuffix(v, right) {
    66  				return f(v[:len(v)-len(right)]), true
    67  			}
    68  			return v, false
    69  		}
    70  	}
    71  	if j == len(pattern)-1 {
    72  		left := pattern[:j]
    73  		f := makesubst(subst)
    74  		return func(v string) (string, bool) {
    75  			if strings.HasPrefix(v, left) {
    76  				return f(v[len(left):]), true
    77  			}
    78  			return v, false
    79  		}
    80  	}
    81  	// 	123textE + 123*E -> 55*5 => 55text5
    82  	left := pattern[:j]
    83  	right := pattern[j+1:]
    84  	f := makesubst(subst)
    85  	return func(v string) (string, bool) {
    86  		if len(v) > len(left)+len(right) && strings.HasPrefix(v, left) && strings.HasSuffix(v, right) {
    87  			return f(v[len(left) : len(v)-len(right)]), true
    88  		}
    89  		return v, false
    90  	}
    91  }
    92  
    93  func Pattern(pattern string) func(string) bool {
    94  	l := len(pattern)
    95  	j := strings.Index(pattern, "*")
    96  	if j < 0 {
    97  		return func(name string) bool { return name == pattern }
    98  	}
    99  	if j == 0 {
   100  		p := pattern[1:]
   101  		if p[len(p)-1] == '*' {
   102  			p := p[:len(p)-1]
   103  			return func(v string) bool {
   104  				k := strings.Index(v, p)
   105  				return k > 0 && k < len(v)-1
   106  			}
   107  		}
   108  		return func(name string) bool {
   109  			return strings.HasSuffix(name, p)
   110  		}
   111  	}
   112  	if j == l-1 {
   113  		p := pattern[:j]
   114  		return func(name string) bool {
   115  			return strings.HasPrefix(name, p)
   116  		}
   117  	}
   118  	left := pattern[:j]
   119  	right := pattern[j+1:]
   120  	return func(name string) bool {
   121  		return len(name) >= l &&
   122  			strings.HasPrefix(name, left) &&
   123  			strings.HasSuffix(name, right)
   124  	}
   125  }