git-lfs/tools/str_tools.go
brian m. carlson 899168eb50 tools: move ShellQuote to subprocess
In a future commit, we'll be adding some additional shell-related
handling which logically belongs to the subprocess package.  To avoid an
import loop, move the ShellQuote function and its required variable from
the tools package to the subprocess package.  Update the only caller of
this function.

This commit contains no functional change.
2018-09-14 21:50:09 +00:00

123 lines
2.8 KiB
Go

package tools
import (
"regexp"
"strings"
)
var (
// quoteFieldRe greedily matches between matching pairs of '', "", or
// non-word characters.
quoteFieldRe = regexp.MustCompile("'(.*)'|\"(.*)\"|(\\S*)")
)
// QuotedFields is an alternative to strings.Fields (see:
// https://golang.org/pkg/strings#Fields) that respects spaces between matching
// pairs of quotation delimeters.
//
// For instance, the quoted fields of the string "foo bar 'baz etc'" would be:
// []string{"foo", "bar", "baz etc"}
//
// Whereas the same argument given to strings.Fields, would return:
// []string{"foo", "bar", "'baz", "etc'"}
func QuotedFields(s string) []string {
submatches := quoteFieldRe.FindAllStringSubmatch(s, -1)
out := make([]string, 0, len(submatches))
for _, matches := range submatches {
// if a leading or trailing space is found, ignore that
if matches[0] == "" {
continue
}
// otherwise, find the first non-empty match (inside balanced
// quotes, or a space-delimited string)
var str string
for _, m := range matches[1:] {
if len(m) > 0 {
str = m
break
}
}
out = append(out, str)
}
return out
}
// Ljust returns a copied string slice where each element is left justified to
// match the width of the longest element in the set.
func Ljust(strs []string) []string {
llen := len(Longest(strs))
dup := make([]string, len(strs), cap(strs))
copy(dup, strs)
for i, str := range strs {
width := MaxInt(0, llen-len(str))
padding := strings.Repeat(" ", width)
dup[i] = str + padding
}
return dup
}
// Rjust returns a copied string slice where each element is right justified to
// match the width of the longest element in the set.
func Rjust(strs []string) []string {
llen := len(Longest(strs))
dup := make([]string, len(strs), cap(strs))
copy(dup, strs)
for i, str := range strs {
width := MaxInt(0, llen-len(str))
padding := strings.Repeat(" ", width)
dup[i] = padding + str
}
return dup
}
// Longest returns the longest element in the string slice in O(n) time and O(1)
// space. If strs is empty or nil, an empty string will be returned.
func Longest(strs []string) string {
if len(strs) == 0 {
return ""
}
var longest string
var llen int
for _, str := range strs {
if len(str) >= llen {
longest = str
llen = len(longest)
}
}
return longest
}
// Indent returns a string which prepends "\t" TAB characters to the beginning
// of each line in the given string "str".
func Indent(str string) string {
indented := strings.Replace(str, "\n", "\n\t", -1)
if len(indented) > 0 {
indented = "\t" + indented
}
return indented
}
var (
tabRe = regexp.MustCompile(`(?m)^[ \t]+`)
)
// Undent removes all leading tabs in the given string "str", line-wise.
func Undent(str string) string {
return tabRe.ReplaceAllString(str, "")
}