11 "github.com/mattn/go-runewidth"
14 // Util.go is a collection of utility functions that are used throughout
17 // Count returns the length of a string in runes
18 // This is exactly equivalent to utf8.RuneCountInString(), just less characters
19 func Count(s string) int {
20 return utf8.RuneCountInString(s)
23 // NumOccurences counts the number of occurences of a byte in a string
24 func NumOccurences(s string, c byte) int {
26 for i := 0; i < len(s); i++ {
34 // Spaces returns a string with n spaces
35 func Spaces(n int) string {
37 for i := 0; i < n; i++ {
43 // Min takes the min of two ints
44 func Min(a, b int) int {
51 // Max takes the max of two ints
52 func Max(a, b int) int {
59 // IsWordChar returns whether or not the string is a 'word character'
60 // If it is a unicode character, then it does not match
61 // Word characters are defined as [A-Za-z0-9_]
62 func IsWordChar(str string) bool {
68 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_')
71 // IsWhitespace returns true if the given rune is a space, tab, or newline
72 func IsWhitespace(c rune) bool {
73 return c == ' ' || c == '\t' || c == '\n'
76 // Contains returns whether or not a string array contains a given string
77 func Contains(list []string, a string) bool {
78 for _, b := range list {
86 // Insert makes a simple insert into a string at the given position
87 func Insert(str string, pos int, value string) string {
88 return string([]rune(str)[:pos]) + value + string([]rune(str)[pos:])
91 // GetLeadingWhitespace returns the leading whitespace of the given string
92 func GetLeadingWhitespace(str string) string {
94 for _, c := range str {
95 if c == ' ' || c == '\t' {
104 // IsSpaces checks if a given string is only spaces
105 func IsSpaces(str string) bool {
106 for _, c := range str {
115 // IsSpacesOrTabs checks if a given string contains only spaces and tabs
116 func IsSpacesOrTabs(str string) bool {
117 for _, c := range str {
118 if c != ' ' && c != '\t' {
126 // ParseBool is almost exactly like strconv.ParseBool, except it also accepts 'on' and 'off'
127 // as 'true' and 'false' respectively
128 func ParseBool(str string) (bool, error) {
135 return strconv.ParseBool(str)
138 // EscapePath replaces every path separator in a given path with a %
139 func EscapePath(path string) string {
140 path = filepath.ToSlash(path)
141 return strings.Replace(path, "/", "%", -1)
144 // GetModTime returns the last modification time for a given file
145 // It also returns a boolean if there was a problem accessing the file
146 func GetModTime(path string) (time.Time, bool) {
147 info, err := os.Stat(path)
149 return time.Now(), false
151 return info.ModTime(), true
154 // StringWidth returns the width of a string where tabs count as `tabsize` width
155 func StringWidth(str string, tabsize int) int {
156 sw := runewidth.StringWidth(str)
157 sw += NumOccurences(str, '\t') * (tabsize - 1)
161 // WidthOfLargeRunes searches all the runes in a string and counts up all the widths of runes
162 // that have a width larger than 1 (this also counts tabs as `tabsize` width)
163 func WidthOfLargeRunes(str string, tabsize int) int {
165 for _, ch := range str {
170 w = runewidth.RuneWidth(ch)
179 // RunePos returns the rune index of a given byte index
180 // This could cause problems if the byte index is between code points
181 func runePos(p int, str string) int {
182 return utf8.RuneCountInString(str[:p])
185 func lcs(a, b string) string {
190 for i, r := range arunes {
191 if i >= len(brunes) {
203 func CommonSubstring(arr ...string) string {
206 for _, str := range arr[1:] {
207 commonStr = lcs(commonStr, str)
213 // Abs is a simple absolute value function for ints
214 func Abs(n int) int {