Initial Commit
This commit is contained in:
commit
e8df2f4afc
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
scpt
|
||||||
|
cmd/scpt/scpt
|
||||||
|
.idea/
|
41
ast.go
Normal file
41
ast.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package scpt
|
||||||
|
|
||||||
|
type AST struct {
|
||||||
|
Commands []*Command `@@*`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Command struct {
|
||||||
|
Vars []*Var `( @@`
|
||||||
|
Calls []*FuncCall `| @@ )`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FuncCall struct {
|
||||||
|
Name string `@Ident`
|
||||||
|
Args []*Arg `@@*`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Arg struct {
|
||||||
|
Key string `"with" @Ident`
|
||||||
|
Value *Value `@@`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Var struct {
|
||||||
|
Key string `"set" @Ident "to"`
|
||||||
|
Value *Value `@@`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Value struct {
|
||||||
|
String *string ` @String`
|
||||||
|
Float *float64 `| @Float`
|
||||||
|
Integer *int64 `| @Int`
|
||||||
|
Bool *Bool `| @("true" | "false")`
|
||||||
|
SubCmd *FuncCall `| "(" @@ ")"`
|
||||||
|
VarVal *string `| "$" @Ident`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bool bool
|
||||||
|
|
||||||
|
func (b *Bool) Capture(values []string) error {
|
||||||
|
*b = values[0] == "true"
|
||||||
|
return nil
|
||||||
|
}
|
8
go.mod
Normal file
8
go.mod
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
module scpt
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/alecthomas/participle v0.7.1
|
||||||
|
github.com/gen2brain/dlgs v0.0.0-20210222160047-2f436553172f
|
||||||
|
)
|
19
go.sum
Normal file
19
go.sum
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
github.com/alecthomas/participle v0.7.1 h1:2bN7reTw//5f0cugJcTOnY/NYZcWQOaajW+BwZB5xWs=
|
||||||
|
github.com/alecthomas/participle v0.7.1/go.mod h1:HfdmEuwvr12HXQN44HPWXR0lHmVolVYe4dyL6lQ3duY=
|
||||||
|
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gen2brain/dlgs v0.0.0-20210222160047-2f436553172f h1:HPKrg4xeWLWOGAJGVJIYXWhVSdy2kaihuoSy7kBP7S4=
|
||||||
|
github.com/gen2brain/dlgs v0.0.0-20210222160047-2f436553172f/go.mod h1:/eFcjDXaU2THSOOqLxOPETIbHETnamk8FA/hMjhg/gU=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20210202160940-bed99a852dfe h1:rcf1P0fm+1l0EjG16p06mYLj9gW9X36KgdHJ/88hS4g=
|
||||||
|
github.com/gopherjs/gopherjs v0.0.0-20210202160940-bed99a852dfe/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
136
scpt.go
Normal file
136
scpt.go
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
package scpt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/alecthomas/participle"
|
||||||
|
"github.com/gen2brain/dlgs"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Vars = map[string]interface{}{}
|
||||||
|
|
||||||
|
type FuncMap map[string]func(map[string]interface{}) (interface{}, error)
|
||||||
|
|
||||||
|
var Funcs = FuncMap{
|
||||||
|
"displaydialog": displayDialog,
|
||||||
|
"doshellscript": doShellScript,
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddFuncs(fnMap FuncMap) {
|
||||||
|
for name, fn := range fnMap {
|
||||||
|
Funcs[name] = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddVars(varMap map[string]interface{}) {
|
||||||
|
for name, val := range varMap {
|
||||||
|
Vars[name] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(r io.Reader) (*AST, error) {
|
||||||
|
parser, err := participle.Build(&AST{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ast := &AST{}
|
||||||
|
err = parser.Parse("", r, ast)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ast, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute(ast AST) {
|
||||||
|
for _, cmd := range ast.Commands {
|
||||||
|
if cmd.Vars != nil {
|
||||||
|
for _, Var := range cmd.Vars {
|
||||||
|
val := ParseValue(Var.Value)
|
||||||
|
if strings.Contains(reflect.TypeOf(val).String(), ".FuncCall") {
|
||||||
|
Call := val.(*FuncCall)
|
||||||
|
Vars[Var.Key], _ = CallFunction(Call)
|
||||||
|
} else {
|
||||||
|
Vars[Var.Key] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if cmd.Calls != nil {
|
||||||
|
for _, Call := range cmd.Calls {
|
||||||
|
_, _ = CallFunction(Call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseValue(val *Value) interface{} {
|
||||||
|
if val.String != nil {
|
||||||
|
return strings.Trim(*val.String, `"`)
|
||||||
|
} else if val.Bool != nil {
|
||||||
|
return *val.Bool
|
||||||
|
} else if val.Float != nil {
|
||||||
|
return *val.Float
|
||||||
|
} else if val.Integer != nil {
|
||||||
|
return *val.Integer
|
||||||
|
} else if val.SubCmd != nil {
|
||||||
|
return val.SubCmd
|
||||||
|
} else if val.VarVal != nil {
|
||||||
|
return Vars[*val.VarVal]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnwrapArgs(args []*Arg) map[string]interface{} {
|
||||||
|
argMap := map[string]interface{}{}
|
||||||
|
for _, arg := range args {
|
||||||
|
argMap[arg.Key] = ParseValue(arg.Value)
|
||||||
|
}
|
||||||
|
return argMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallFunction(call *FuncCall) (interface{}, error) {
|
||||||
|
argMap := UnwrapArgs(call.Args)
|
||||||
|
return Funcs[call.Name](argMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func displayDialog(args map[string]interface{}) (interface{}, error) {
|
||||||
|
title, ok := args["title"]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("title not provided")
|
||||||
|
}
|
||||||
|
text, ok := args["text"]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("text not provided")
|
||||||
|
}
|
||||||
|
switch args["type"] {
|
||||||
|
case "yesno":
|
||||||
|
return dlgs.Question(fmt.Sprint(title), fmt.Sprint(text), true)
|
||||||
|
case "info":
|
||||||
|
return dlgs.Info(fmt.Sprint(title), fmt.Sprint(text))
|
||||||
|
case "error":
|
||||||
|
return dlgs.Error(fmt.Sprint(title), fmt.Sprint(text))
|
||||||
|
case "entry":
|
||||||
|
defaultText, ok := args["default"]
|
||||||
|
if !ok {
|
||||||
|
defaultText = ""
|
||||||
|
}
|
||||||
|
input, _, err := dlgs.Entry(fmt.Sprint(title), fmt.Sprint(text), fmt.Sprint(defaultText))
|
||||||
|
return input, err
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func doShellScript(args map[string]interface{}) (interface{}, error) {
|
||||||
|
script, ok := args["content"].(string)
|
||||||
|
if ok {
|
||||||
|
cmd := exec.Command("sh", "-c", script)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
_ = cmd.Run()
|
||||||
|
return "", nil
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("script not provided")
|
||||||
|
}
|
||||||
|
}
|
5
test.scpt
Normal file
5
test.scpt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
set y to (displaydialog with text "Hello" with title 12 with type "yesno")
|
||||||
|
displaydialog with text "Goodbye" with title 21 with type "error"
|
||||||
|
doshellscript with content "notify-send Test Notification"
|
||||||
|
set g to (displaydialog with text "Test 2" with title 30 with type "entry" with default "text")
|
||||||
|
set x to $g
|
Loading…
Reference in New Issue
Block a user