shell/shell.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package shell import ( "context" "fmt" "log" "os" "strings" "j3s.sh/zoa/color" "j3s.sh/zoa/utils" "mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/syntax" ) func Run(r *interp.Runner, script string) { f, err := parseFile(script) if err != nil { log.Fatal(err) } ctx := context.TODO() for _, stmt := range f.Stmts { // 14:8 pos := stmt.Pos() ctx = context.WithValue(ctx, "position", pos) err = r.Run(ctx, stmt) if err != nil { // we yell but keep plowing forward // twirling, twirling color.ZoaYell(fmt.Sprintf("%s:%s: %s", script, pos, err.Error())) } } } func CallHandler(ctx context.Context, args []string) ([]string, error) { script := ctx.Value("script").(string) command := args[0] fmt.Println() // shell tips go here if command == "echo" { color.ZoaSay(`prefer printf over echo! ex: printf '%s\n' "hello world!"`) } fmt.Printf("%s $ %s\n", script, strings.Join(args, " ")) return args, nil } func parseFile(filename string) (*syntax.File, error) { var result = &syntax.File{} f, err := os.Open(filename) if err != nil { return result, err } defer f.Close() result, err = syntax.NewParser().Parse(f, "") return result, err } // ZoaCopy copies a file from src to dst, optionally modifying its mode. // zoaCopy defaults to 0666 for permissions (before umask) func ZoaCopy(src string, dst string, mode os.FileMode) { srcChk, err := utils.ChecksumFile(src) if err != nil { // source file should always exist, return error fmt.Println(err) os.Exit(1) } dstChk, err := utils.ChecksumFile(dst) if err != nil { // dstfile may not exist for a million // reasons, set checksum to blank // to force a mismatch // TODO: why did i do this? revise errors. dstChk = "" } // TODO: templating engine? // - expand vars // - loop support? if srcChk != dstChk { err = utils.Copy(src, dst) if err != nil { fmt.Println(err) os.Exit(1) } } fi, err := os.Lstat(dst) if err != nil { fmt.Println(err) os.Exit(1) } if fi.Mode().Perm() != mode { err = os.Chmod(dst, mode) if err != nil { fmt.Println(err) os.Exit(1) } } }