elvish/util/strings.go
2016-06-22 01:03:44 +02:00

102 lines
2.0 KiB
Go

package util
import (
"errors"
"strings"
)
// ErrIndexOutOfRange is returned when out-of-range errors occur.
var ErrIndexOutOfRange = errors.New("substring out of range")
// FindContext takes a position in a text and finds its line number,
// corresponding line and column numbers. Line and column numbers are counted
// from 0. Used in diagnostic messages.
func FindContext(text string, pos int) (lineno, colno int, line string) {
var i, linestart int
var r rune
for i, r = range text {
if i == pos {
break
}
if r == '\n' {
lineno++
linestart = i + 1
colno = 0
} else {
colno++
}
}
line = strings.SplitN(text[linestart:], "\n", 2)[0]
return
}
// FindFirstEOL returns the index of the first '\n'. When there is no '\n', the
// length of s is returned.
func FindFirstEOL(s string) int {
eol := strings.IndexRune(s, '\n')
if eol == -1 {
eol = len(s)
}
return eol
}
// FindLastSOL returns an index just after the last '\n'.
func FindLastSOL(s string) int {
return strings.LastIndex(s, "\n") + 1
}
// SubstringByRune returns the range of the i-th rune (inclusive) through the
// j-th rune (exclusive) in s.
func SubstringByRune(s string, low, high int) (string, error) {
if low > high || low < 0 || high < 0 {
return "", ErrIndexOutOfRange
}
var bLow, bHigh, j int
for i := range s {
if j == low {
bLow = i
}
if j == high {
bHigh = i
}
j++
}
if j < high {
return "", ErrIndexOutOfRange
}
if low == high {
return "", nil
}
if j == high {
bHigh = len(s)
}
return s[bLow:bHigh], nil
}
// NthRune returns the n-th rune of s.
func NthRune(s string, n int) (rune, error) {
if n < 0 {
return 0, ErrIndexOutOfRange
}
var j int
for _, r := range s {
if j == n {
return r, nil
}
j++
}
return 0, ErrIndexOutOfRange
}
// MatchSubseq returns whether pattern is a subsequence of s.
func MatchSubseq(s, pattern string) bool {
for _, p := range pattern {
i := strings.IndexRune(s, p)
if i == -1 {
return false
}
s = s[i+len(string(p)):]
}
return true
}