117 lines
3.1 KiB
Markdown
117 lines
3.1 KiB
Markdown
# script
|
|
|
|
[](https://codecov.io/gh/posener/script)
|
|
[](http://pkg.go.dev/github.com/posener/script)
|
|
|
|
Package script provides helper functions to write scripts.
|
|
|
|
Inspired by [https://github.com/bitfield/script](https://github.com/bitfield/script), with some improvements:
|
|
|
|
* Output between streamed commands is a stream and not loaded to memory.
|
|
|
|
* Better representation and handling of errors.
|
|
|
|
* Proper incocation, usage and handling of stderr of custom commands.
|
|
|
|
The script chain is represented by a
|
|
[`Stream`](https://godoc.org/github.com/posener/script#Stream) object. While each command in the
|
|
stream is abstracted by the [`Command`](https://godoc.org/github.com/posener/script#Command)
|
|
struct. This library provides basic functionality, but can be extended freely.
|
|
|
|
## Examples
|
|
|
|
### HelloWorld
|
|
|
|
A simple "hello world" example that creats a stream and pipe it to the stdout.
|
|
|
|
```golang
|
|
// Create an "hello world" stream and use the ToStdout method to write it to stdout.
|
|
Echo("hello world").ToStdout()
|
|
```
|
|
|
|
Output:
|
|
|
|
```
|
|
hello world
|
|
```
|
|
|
|
### Iterate
|
|
|
|
An example that shows how to iterate scanned lines.
|
|
|
|
```golang
|
|
// Stream can be any stream, in this case we have echoed 3 lines.
|
|
stream := Echo("first\nsecond\nthird")
|
|
|
|
// To iterate over the stream lines, it is better not to read it into memory and split over the
|
|
// lines, but use the `bufio.Scanner`:
|
|
defer stream.Close()
|
|
scanner := bufio.NewScanner(stream)
|
|
for scanner.Scan() {
|
|
fmt.Println(scanner.Text())
|
|
}
|
|
```
|
|
|
|
Output:
|
|
|
|
```
|
|
first
|
|
second
|
|
third
|
|
```
|
|
|
|
### Through
|
|
|
|
An example that shows how to create custom commands using the `Through` method with a `PipeFn`
|
|
function.
|
|
|
|
```golang
|
|
Echo("1\n2\n3").Through(PipeFn(func(r io.Reader) (io.Reader, error) {
|
|
// Create a command that sums up all numbers in input.
|
|
//
|
|
// In this example we create a reader function such that the whole code will fit into the
|
|
// example function body. A more proper and readable way to do it was to create a new
|
|
// type with a state that implements the `io.Reader` interface.
|
|
|
|
// Use buffered reader to read lines from input.
|
|
buf := bufio.NewReader(r)
|
|
|
|
// Store the sum of all numbers.
|
|
sum := 0
|
|
|
|
// Read function reads the next line and adds it to the sum. If it gets and EOF error, it
|
|
// writes the sum to the output and returns an EOF.
|
|
read := func(b []byte) (int, error) {
|
|
// Read next line from input.
|
|
line, _, err := buf.ReadLine()
|
|
|
|
// if EOF write sum to output.
|
|
if err == io.EOF {
|
|
return copy(b, append([]byte(strconv.Itoa(sum)), '\n')), io.EOF
|
|
}
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// Convert the line to a number and add it to the sum.
|
|
if i, err := strconv.Atoi(string(line)); err == nil {
|
|
sum += i
|
|
}
|
|
|
|
// We don't write anything to output, so we return 0 bytes with no error.
|
|
return 0, nil
|
|
}
|
|
|
|
return readerFn(read), nil
|
|
})).ToStdout()
|
|
```
|
|
|
|
Output:
|
|
|
|
```
|
|
6
|
|
```
|
|
|
|
---
|
|
Readme created from Go doc with [goreadme](https://github.com/posener/goreadme)
|