github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/core/elvish/util/strings.go (about) 1 package util 2 3 import ( 4 "errors" 5 "strings" 6 ) 7 8 // ErrIndexOutOfRange is returned when out-of-range errors occur. 9 var ErrIndexOutOfRange = errors.New("substring out of range") 10 11 // FindContext takes a position in a text and finds its line number, 12 // corresponding line and column numbers. Line and column numbers are counted 13 // from 0. Used in diagnostic messages. 14 func FindContext(text string, pos int) (lineno, colno int, line string) { 15 var i, linestart int 16 var r rune 17 for i, r = range text { 18 if i == pos { 19 break 20 } 21 if r == '\n' { 22 lineno++ 23 linestart = i + 1 24 colno = 0 25 } else { 26 colno++ 27 } 28 } 29 line = strings.SplitN(text[linestart:], "\n", 2)[0] 30 return 31 } 32 33 // FindFirstEOL returns the index of the first '\n'. When there is no '\n', the 34 // length of s is returned. 35 func FindFirstEOL(s string) int { 36 eol := strings.IndexRune(s, '\n') 37 if eol == -1 { 38 eol = len(s) 39 } 40 return eol 41 } 42 43 // FindLastSOL returns an index just after the last '\n'. 44 func FindLastSOL(s string) int { 45 return strings.LastIndex(s, "\n") + 1 46 } 47 48 // SubstringByRune returns the range of the i-th rune (inclusive) through the 49 // j-th rune (exclusive) in s. 50 func SubstringByRune(s string, low, high int) (string, error) { 51 if low > high || low < 0 || high < 0 { 52 return "", ErrIndexOutOfRange 53 } 54 var bLow, bHigh, j int 55 for i := range s { 56 if j == low { 57 bLow = i 58 } 59 if j == high { 60 bHigh = i 61 } 62 j++ 63 } 64 if j < high { 65 return "", ErrIndexOutOfRange 66 } 67 if low == high { 68 return "", nil 69 } 70 if j == high { 71 bHigh = len(s) 72 } 73 return s[bLow:bHigh], nil 74 } 75 76 // NthRune returns the n-th rune of s. 77 func NthRune(s string, n int) (rune, error) { 78 if n < 0 { 79 return 0, ErrIndexOutOfRange 80 } 81 var j int 82 for _, r := range s { 83 if j == n { 84 return r, nil 85 } 86 j++ 87 } 88 return 0, ErrIndexOutOfRange 89 } 90 91 // MatchSubseq returns whether pattern is a subsequence of s. 92 func MatchSubseq(s, pattern string) bool { 93 for _, p := range pattern { 94 i := strings.IndexRune(s, p) 95 if i == -1 { 96 return false 97 } 98 s = s[i+len(string(p)):] 99 } 100 return true 101 }