gomu/anko/anko.go

224 lines
4.5 KiB
Go
Raw Normal View History

2021-02-14 14:35:36 +08:00
package anko
import (
2021-02-14 20:33:24 +08:00
"fmt"
"regexp"
"strings"
2021-02-14 20:33:24 +08:00
"github.com/gdamore/tcell/v2"
2021-02-14 14:35:36 +08:00
"github.com/mattn/anko/core"
"github.com/mattn/anko/env"
_ "github.com/mattn/anko/packages"
2021-02-19 09:45:02 +08:00
"github.com/mattn/anko/parser"
"github.com/mattn/anko/vm"
2021-02-14 14:35:36 +08:00
)
type Anko struct {
env *env.Env
}
2021-02-20 11:18:03 +08:00
func NewAnko() *Anko {
2021-02-15 12:37:05 +08:00
env := core.Import(env.NewEnv())
importToX(env)
2021-02-18 16:06:09 +08:00
t, err := env.Get("typeOf")
if err != nil {
panic(err)
}
k, err := env.Get("kindOf")
if err != nil {
panic(err)
}
env.DeleteGlobal("typeOf")
env.DeleteGlobal("kindOf")
err = env.Define("type_of", t)
if err != nil {
panic(err)
}
err = env.Define("kind_of", k)
if err != nil {
panic(err)
}
2021-02-20 11:18:03 +08:00
return &Anko{env}
2021-02-14 14:35:36 +08:00
}
2021-03-21 16:05:23 +08:00
// DefineGlobal defines new symbol and value to the Anko env.
func (a *Anko) DefineGlobal(symbol string, value interface{}) error {
2021-02-14 14:35:36 +08:00
return a.env.DefineGlobal(symbol, value)
}
2021-03-21 16:05:23 +08:00
func (a *Anko) NewModule(name string) (*Anko, error) {
env, err := a.env.NewModule(name)
if err != nil {
return nil, err
}
return &Anko{env}, nil
}
func (a *Anko) Define(name string, value interface{}) error {
return a.env.Define(name, value)
}
2021-02-14 21:37:31 +08:00
// Set sets new value to existing symbol. Use this when change value under an
2021-02-14 14:35:36 +08:00
// existing symbol.
func (a *Anko) Set(symbol string, value interface{}) error {
return a.env.Set(symbol, value)
}
2021-02-14 21:37:31 +08:00
// Get gets value from anko env, returns error if symbol is not found.
2021-02-14 14:35:36 +08:00
func (a *Anko) Get(symbol string) (interface{}, error) {
return a.env.Get(symbol)
}
2021-02-14 21:37:31 +08:00
// GetInt gets int value from symbol, returns golang default value if not found.
2021-02-14 14:35:36 +08:00
func (a *Anko) GetInt(symbol string) int {
v, err := a.Execute(symbol)
2021-02-14 14:35:36 +08:00
if err != nil {
return 0
}
2021-02-15 21:46:43 +08:00
switch val := v.(type) {
case int:
2021-02-15 21:46:43 +08:00
return val
case int64:
return int(val)
2021-02-14 14:35:36 +08:00
}
2021-02-15 21:46:43 +08:00
return 0
2021-02-14 14:35:36 +08:00
}
2021-02-14 21:37:31 +08:00
// GetString gets string value from symbol, returns golang default value if not
// found.
2021-02-14 14:35:36 +08:00
func (a *Anko) GetString(symbol string) string {
v, err := a.Execute(symbol)
2021-02-14 14:35:36 +08:00
if err != nil {
return ""
}
val, ok := v.(string)
if !ok {
return ""
}
return val
}
2021-02-14 21:37:31 +08:00
// GetBool gets bool value from symbol, returns golang default value if not
// found.
2021-02-14 14:35:36 +08:00
func (a *Anko) GetBool(symbol string) bool {
v, err := a.Execute(symbol)
2021-02-14 14:35:36 +08:00
if err != nil {
return false
}
val, ok := v.(bool)
if !ok {
return false
}
return val
}
2021-02-14 21:37:31 +08:00
// Execute executes anko script.
2021-02-14 14:35:36 +08:00
func (a *Anko) Execute(src string) (interface{}, error) {
2021-02-19 09:45:02 +08:00
parser.EnableErrorVerbose()
stmts, err := parser.ParseSrc(src)
if err != nil {
return nil, err
}
val, err := vm.Run(a.env, nil, stmts)
if err != nil {
if e, ok := err.(*vm.Error); ok {
err = fmt.Errorf("error on line %d column %d: %s\n",
e.Pos.Line, e.Pos.Column, err)
} else if e, ok := err.(*parser.Error); ok {
err = fmt.Errorf("error on line %d column %d: %s\n",
e.Pos.Line, e.Pos.Column, err)
}
return nil, err
}
return val, nil
2021-02-14 14:35:36 +08:00
}
2021-02-14 20:33:24 +08:00
2021-02-14 21:37:31 +08:00
// KeybindExists checks if keybinding is defined.
func (a *Anko) KeybindExists(panel string, eventKey *tcell.EventKey) bool {
var src string
name := eventKey.Name()
if strings.Contains(name, "Ctrl") {
key := extractCtrlRune(name)
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"ctrl_%s\"]",
panel, strings.ToLower(string(key)))
} else if strings.Contains(name, "Alt") {
key := extractAltRune(name)
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"alt_%c\"]", panel, key)
} else if strings.Contains(name, "Rune") {
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"%c\"]", panel, eventKey.Rune())
} else {
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"%s\"]", panel, strings.ToLower(name))
}
2021-02-14 21:37:31 +08:00
val, err := a.Execute(src)
2021-02-14 20:33:24 +08:00
if err != nil {
2021-02-14 21:37:31 +08:00
return false
2021-02-14 20:33:24 +08:00
}
2021-02-14 21:37:31 +08:00
return val != nil
}
2021-02-14 20:33:24 +08:00
2021-02-14 21:37:31 +08:00
// ExecKeybind executes function bounded by the keybinding.
func (a *Anko) ExecKeybind(panel string, eventKey *tcell.EventKey) error {
var src string
name := eventKey.Name()
if strings.Contains(name, "Ctrl") {
key := extractCtrlRune(name)
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"ctrl_%s\"]()",
panel, strings.ToLower(string(key)))
} else if strings.Contains(name, "Alt") {
key := extractAltRune(name)
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"alt_%c\"]()", panel, key)
} else if strings.Contains(name, "Rune") {
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"%c\"]()", panel, eventKey.Rune())
} else {
2021-02-17 17:08:39 +08:00
src = fmt.Sprintf("Keybinds.%s[\"%s\"]()", panel, strings.ToLower(name))
}
_, err := a.Execute(src)
if err != nil {
return err
}
return nil
}
func extractCtrlRune(str string) rune {
re := regexp.MustCompile(`\+(.)$`)
x := re.FindStringSubmatch(str)
return rune(x[0][1])
}
func extractAltRune(str string) rune {
re := regexp.MustCompile(`\[(.)\]`)
x := re.FindStringSubmatch(str)
return rune(x[0][1])
2021-02-14 20:33:24 +08:00
}