You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ntool/ncli/cmdline/builder.go

85 lines
1.7 KiB
Go

1 year ago
package cmdline
import (
"git.noahlan.cn/noahlan/ntool/nstr"
"strings"
)
// LineBuilder build command line string.
// codes refer from strings.Builder
type LineBuilder struct {
strings.Builder
}
// NewBuilder create
func NewBuilder(binFile string, args ...string) *LineBuilder {
b := &LineBuilder{}
if binFile != "" {
b.AddArg(binFile)
}
b.AddArray(args)
return b
}
// AddArg to builder
func (b *LineBuilder) AddArg(arg string) {
_, _ = b.WriteString(arg)
}
// AddArgs to builder
func (b *LineBuilder) AddArgs(args ...string) {
b.AddArray(args)
}
// AddArray to builder
func (b *LineBuilder) AddArray(args []string) {
for _, arg := range args {
_, _ = b.WriteString(arg)
}
}
// AddAny args to builder
func (b *LineBuilder) AddAny(args ...any) {
for _, arg := range args {
_, _ = b.WriteString(nstr.SafeString(arg))
}
}
// WriteString arg string to the builder, will auto quote special string.
// refer strconv.Quote()
func (b *LineBuilder) WriteString(a string) (int, error) {
var quote byte
if pos := strings.IndexByte(a, '"'); pos > -1 {
quote = '\''
// fix: a = `--pretty=format:"one two three"`
if pos > 0 && '"' == a[len(a)-1] {
quote = 0
}
} else if pos := strings.IndexByte(a, '\''); pos > -1 {
quote = '"'
// fix: a = "--pretty=format:'one two three'"
if pos > 0 && '\'' == a[len(a)-1] {
quote = 0
}
} else if a == "" || strings.ContainsRune(a, ' ') {
quote = '"'
}
// add sep on not-first write.
if b.Len() != 0 {
_ = b.WriteByte(' ')
}
// no quote char OR not need quote
if quote == 0 {
return b.Builder.WriteString(a)
}
_ = b.WriteByte(quote) // add start quote
n, err := b.Builder.WriteString(a)
_ = b.WriteByte(quote) // add end quote
return n, err
}