github.com/richardwilkes/toolbox@v1.121.0/cmdline/parse.go (about)

     1  // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the Mozilla Public
     4  // License, version 2.0. If a copy of the MPL was not distributed with
     5  // this file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  //
     7  // This Source Code Form is "Incompatible With Secondary Licenses", as
     8  // defined by the Mozilla Public License, version 2.0.
     9  
    10  package cmdline
    11  
    12  import (
    13  	"fmt"
    14  
    15  	"github.com/richardwilkes/toolbox/errs"
    16  )
    17  
    18  // Parse a command line string into its component parts.
    19  func Parse(command string) ([]string, error) {
    20  	var args []string
    21  	var current []rune
    22  	var lookingForQuote rune
    23  	var escapeNext bool
    24  	for _, ch := range command {
    25  		switch {
    26  		case escapeNext:
    27  			current = append(current, ch)
    28  			escapeNext = false
    29  		case lookingForQuote == ch:
    30  			args = append(args, string(current))
    31  			current = nil
    32  			lookingForQuote = 0
    33  		case lookingForQuote != 0:
    34  			current = append(current, ch)
    35  		case ch == '\\':
    36  			escapeNext = true
    37  		case ch == '"' || ch == '\'':
    38  			lookingForQuote = ch
    39  		case ch == ' ' || ch == '\t':
    40  			if len(current) != 0 {
    41  				args = append(args, string(current))
    42  				current = nil
    43  			}
    44  		default:
    45  			current = append(current, ch)
    46  		}
    47  	}
    48  	if lookingForQuote != 0 {
    49  		return nil, errs.New(fmt.Sprintf("unclosed quote in command line:\n%s", command))
    50  	}
    51  	if len(current) != 0 {
    52  		args = append(args, string(current))
    53  	}
    54  	return args, nil
    55  }