Beam: beamsh is a mini-shell which runs processes and communicates with them over beam
Docker-DCO-1.1-Signed-off-by: Solomon Hykes <solomon@docker.com> (github: shykes)
This commit is contained in:
parent
f3671ea62d
commit
358c2f3ca4
1 changed files with 91 additions and 0 deletions
91
beam/examples/beamsh/beamsh.go
Normal file
91
beam/examples/beamsh/beamsh.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"text/scanner"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
s := &scanner.Scanner{}
|
||||
s.Init(os.Stdin)
|
||||
s.Whitespace = 1<<'\t' | 1<<' '
|
||||
//s.Mode = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
|
||||
s.Mode = scanner.ScanStrings | scanner.ScanRawStrings | scanner.ScanIdents
|
||||
expr, err := parse(s, "")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("%d commands:\n", len(expr))
|
||||
for i, cmd := range expr {
|
||||
fmt.Printf("%%%d: %s\n", i, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
type Command struct {
|
||||
Args []string
|
||||
Children []*Command
|
||||
}
|
||||
|
||||
func (cmd *Command) subString(depth int) string {
|
||||
var prefix string
|
||||
for i:=0; i<depth; i++ {
|
||||
prefix += " "
|
||||
}
|
||||
s := prefix + strings.Join(cmd.Args, ", ")
|
||||
if len(cmd.Children) > 0 {
|
||||
s += " {\n"
|
||||
for _, subcmd := range cmd.Children {
|
||||
s += subcmd.subString(depth + 1)
|
||||
}
|
||||
s += prefix + "}"
|
||||
}
|
||||
s += "\n"
|
||||
return s
|
||||
}
|
||||
|
||||
func (cmd *Command) String() string {
|
||||
return cmd.subString(0)
|
||||
}
|
||||
|
||||
func parseArgs(s *scanner.Scanner) ([]string, rune, error) {
|
||||
var args []string
|
||||
tok := s.Scan()
|
||||
for tok != scanner.EOF {
|
||||
text := s.TokenText()
|
||||
//fmt.Printf("--> [%s]\n", text)
|
||||
if text == "{" || text == "}" || text == "\n" || text == "\r" || text == ";" {
|
||||
return args, tok, nil
|
||||
}
|
||||
args = append(args, text)
|
||||
tok = s.Scan()
|
||||
}
|
||||
return args, tok, nil
|
||||
}
|
||||
|
||||
func parse(s *scanner.Scanner, opener string) ([]*Command, error) {
|
||||
var expr []*Command
|
||||
for {
|
||||
args, tok, err := parseArgs(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := &Command{Args: args}
|
||||
if s.TokenText() == "{" {
|
||||
children, err := parse(s, "{")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd.Children = children
|
||||
}
|
||||
if len(cmd.Args) > 0 || len(cmd.Children) > 0 {
|
||||
expr = append(expr, cmd)
|
||||
}
|
||||
if tok == scanner.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
return expr, nil
|
||||
}
|
Loading…
Reference in a new issue