execx

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2024 License: MIT Imports: 9 Imported by: 6

README

execx

Provides os/exec.Cmd wrappers.

import (
	"bytes"
	"context"
	"fmt"
	"strings"

	"github.com/berquerant/execx"
)

func main() {
	script := execx.NewScript(
		`echo line1
echo ${line2}
cat -
echo line3 > /dev/stderr`,
		"sh",
	)
	script.Env.Set("line2", "LINE2")

	if err := script.Runner(func(cmd *execx.Cmd) error {
		cmd.Stdin = bytes.NewBufferString("from stdin\n")
		_, err := cmd.Run(
			context.TODO(),
			execx.WithStdoutConsumer(func(x execx.Token) {
				fmt.Printf("1:%s\n", x)
			}),
			execx.WithStderrConsumer(func(x execx.Token) {
				fmt.Printf("2:%s\n", x)
			}),
		)
		return err
	}); err != nil {
		panic(err)
	}

	// Output:
	// 1:line1
	// 1:LINE2
	// 1:from stdin
	// 2:line3
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cmd

type Cmd struct {
	Args  []string
	Stdin io.Reader
	Dir   string
	Env   Env
}

Cmd is an external command.

func New

func New(name string, arg ...string) *Cmd

Create a new Cmd.

Set the current directory to [Cmd.Dir], current environment variables to [Cmd.Env].

func (Cmd) Run

func (c Cmd) Run(ctx context.Context, opt ...Option) (*Result, error)

Run executes the command.

If WithStdoutConsumer set, you can get the standard output of a command without waiting for the command to finish. If WithStderrConsumer set, you can get the standard error of a command without waiting for the command to finish. WithSplitFunc sets the split function for a scanner used in consumers.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"strings"

	"github.com/berquerant/execx"
)

func main() {
	cmd := execx.New("echo", "Hello, ${NAME}!")
	cmd.Env.Set("NAME", "world")
	r, err := cmd.Run(context.TODO())
	if err != nil {
		panic(err)
	}
	fmt.Println(strings.Join(r.ExpandedArgs, " "))
	b, err := io.ReadAll(r.Stdout)
	if err != nil {
		panic(err)
	}
	fmt.Print(string(b))

}
Output:

echo Hello, world!
Hello, world!

type Config

type Config struct {
	StdoutConsumer *ConfigItem[func(Token)]
	StderrConsumer *ConfigItem[func(Token)]
	SplitFunc      *ConfigItem[SplitFunc]
}

func (*Config) Apply

func (s *Config) Apply(opt ...Option)

type ConfigBuilder

type ConfigBuilder struct {
	// contains filtered or unexported fields
}

func NewConfigBuilder

func NewConfigBuilder() *ConfigBuilder

func (*ConfigBuilder) Build

func (s *ConfigBuilder) Build() *Config

func (*ConfigBuilder) SplitFunc added in v0.3.0

func (s *ConfigBuilder) SplitFunc(v SplitFunc) *ConfigBuilder

func (*ConfigBuilder) StderrConsumer

func (s *ConfigBuilder) StderrConsumer(v func(Token)) *ConfigBuilder

func (*ConfigBuilder) StdoutConsumer

func (s *ConfigBuilder) StdoutConsumer(v func(Token)) *ConfigBuilder

type ConfigItem

type ConfigItem[T any] struct {
	// contains filtered or unexported fields
}

func NewConfigItem

func NewConfigItem[T any](defaultValue T) *ConfigItem[T]

func (*ConfigItem[T]) Default

func (s *ConfigItem[T]) Default() T

func (*ConfigItem[T]) Get

func (s *ConfigItem[T]) Get() T

func (*ConfigItem[T]) IsModified

func (s *ConfigItem[T]) IsModified() bool

func (*ConfigItem[T]) Set

func (s *ConfigItem[T]) Set(value T)

type Env

type Env map[string]string

Env represents a set of environment variables.

func EnvFromEnviron

func EnvFromEnviron() Env

EnvFromEnviron creates a new Env from os.Environ.

func EnvFromSlice

func EnvFromSlice(envSlice []string) Env

EnvFromSlice creates a new Env from strings, in the form "key=value".

func NewEnv

func NewEnv() Env

NewEnv creates a new empty Env.

func (Env) Expand

func (e Env) Expand(target string) string

Expand expands environment variables in target.

func (Env) ExpandStrings

func (e Env) ExpandStrings(target []string) []string

ExpandStrings expands environment variables in multiple targets.

func (Env) Get

func (e Env) Get(key string) (string, bool)

func (Env) IntoSlice

func (e Env) IntoSlice() []string

IntoSlice converts into os.Environ format.

func (Env) Merge

func (e Env) Merge(other Env)

func (Env) Set

func (e Env) Set(key, value string)

type Option

type Option func(*Config)

func WithSplitFunc added in v0.3.0

func WithSplitFunc(v SplitFunc) Option

func WithStderrConsumer

func WithStderrConsumer(v func(Token)) Option

func WithStdoutConsumer

func WithStdoutConsumer(v func(Token)) Option

type Result

type Result struct {
	// ExpandedArgs is actual command.
	ExpandedArgs []string
	Stdout       io.Reader
	Stderr       io.Reader
}

Result is Cmd execution result.

type Script

type Script struct {
	// Shell executes Content.
	Shell []string
	// Content is a set of commands.
	Content string
	Env     Env
	// If KeepScriptFile is true, then do not regenerate script files,
	// and not reflect changes in Content and Env when calling Runner.
	KeepScriptFile bool
	// contains filtered or unexported fields
}

Script is an executable script, set of commands.

func NewScript

func NewScript(content string, shell string, arg ...string) *Script

NewScript creates a new Script.

func (*Script) Close added in v0.2.0

func (s *Script) Close() error

Close removes a temporary script file.

func (*Script) Runner

func (s *Script) Runner(f func(*Cmd) error) error

Runner creates a new Cmd and pass it to f.

Example
package main

import (
	"bytes"
	"context"
	"fmt"

	"github.com/berquerant/execx"
)

func main() {
	script := execx.NewScript(
		`echo line1
echo ${line2}
cat -
echo line3 > /dev/stderr`,
		"sh",
	)
	script.Env.Set("line2", "LINE2")

	if err := script.Runner(func(cmd *execx.Cmd) error {
		cmd.Stdin = bytes.NewBufferString("from stdin\n")
		_, err := cmd.Run(
			context.TODO(),
			execx.WithStdoutConsumer(func(x execx.Token) {
				fmt.Printf("1:%s\n", x)
			}),
			execx.WithStderrConsumer(func(x execx.Token) {
				fmt.Printf("2:%s\n", x)
			}),
		)
		return err
	}); err != nil {
		panic(err)
	}

}
Output:

1:line1
1:LINE2
1:from stdin
2:line3

type SplitFunc added in v0.3.0

type SplitFunc = bufio.SplitFunc

type Token added in v0.3.0

type Token interface {
	String() string
	Bytes() []byte
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL