Files

55 lines
1.5 KiB
Go

package windows
import (
"errors"
"strings"
"unicode/utf8"
)
var ErrInvalidCommandLineArgument = errors.New("Windows command-line argument contains NUL or invalid UTF-8")
// BuildCommandLine constructs the lpCommandLine string for an explicit
// lpApplicationName. It implements the CommandLineToArgvW-compatible escaping
// convention: quotes are escaped by a preceding run of backslashes and trailing
// backslashes inside a quoted argument are doubled.
func BuildCommandLine(arguments []string) (string, error) {
if len(arguments) == 0 {
return "", nil
}
quoted := make([]string, len(arguments))
for index, argument := range arguments {
if strings.IndexByte(argument, 0) >= 0 || !utf8.ValidString(argument) {
return "", ErrInvalidCommandLineArgument
}
quoted[index] = quoteArgument(argument)
}
return strings.Join(quoted, " "), nil
}
func quoteArgument(argument string) string {
if argument != "" && !strings.ContainsAny(argument, " \t\n\v\"") {
return argument
}
var output strings.Builder
output.Grow(len(argument) + 2)
output.WriteByte('"')
backslashes := 0
for _, character := range argument {
switch character {
case '\\':
backslashes++
case '"':
output.WriteString(strings.Repeat("\\", backslashes*2+1))
output.WriteRune(character)
backslashes = 0
default:
output.WriteString(strings.Repeat("\\", backslashes))
output.WriteRune(character)
backslashes = 0
}
}
output.WriteString(strings.Repeat("\\", backslashes*2))
output.WriteByte('"')
return output.String()
}