github.com/tiagovtristao/plz@v13.4.0+incompatible/src/cli/stdin.go (about)

     1  package cli
     2  
     3  import (
     4  	"bufio"
     5  	"os"
     6  	"strings"
     7  )
     8  
     9  var seenStdin = false // Used to track that we don't try to read stdin twice
    10  // ReadStdin reads a sequence of space-delimited words from standard input.
    11  // Words are pushed onto the returned channel asynchronously.
    12  func ReadStdin() <-chan string {
    13  	c := make(chan string)
    14  	if seenStdin {
    15  		log.Fatalf("Repeated - on command line; can't reread stdin.")
    16  	}
    17  	seenStdin = true
    18  	go func() {
    19  		scanner := bufio.NewScanner(os.Stdin)
    20  		scanner.Split(bufio.ScanWords)
    21  		for scanner.Scan() {
    22  			s := strings.TrimSpace(scanner.Text())
    23  			if s != "" {
    24  				c <- s
    25  			}
    26  		}
    27  		if err := scanner.Err(); err != nil {
    28  			log.Fatalf("Error reading stdin: %s", err)
    29  		}
    30  		close(c)
    31  	}()
    32  	return c
    33  }
    34  
    35  // ReadAllStdin reads standard input in its entirety to a slice.
    36  // Since this reads it completely before returning it won't handle a slow input
    37  // very nicely. ReadStdin is therefore preferable when possible.
    38  func ReadAllStdin() []string {
    39  	var ret []string
    40  	for s := range ReadStdin() {
    41  		ret = append(ret, s)
    42  	}
    43  	return ret
    44  }
    45  
    46  // StdinStrings is a type used for flags; it accepts a slice of strings but also
    47  // if it's a single - it reads its contents from stdin.
    48  type StdinStrings []string
    49  
    50  // Get reads stdin if needed and returns the contents of this slice.
    51  func (s StdinStrings) Get() []string {
    52  	if len(s) == 1 && s[0] == "-" {
    53  		return ReadAllStdin()
    54  	} else if ContainsString("-", s) {
    55  		log.Fatalf("Cannot pass - to read stdin along with other arguments.")
    56  	}
    57  	return s
    58  }
    59  
    60  // ContainsString returns true if the given slice contains an individual string.
    61  func ContainsString(needle string, haystack []string) bool {
    62  	for _, straw := range haystack {
    63  		if needle == straw {
    64  			return true
    65  		}
    66  	}
    67  	return false
    68  }