Skip to content

Instantly share code, notes, and snippets.

@hayajo
Last active August 29, 2015 13:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hayajo/9950648 to your computer and use it in GitHub Desktop.
Save hayajo/9950648 to your computer and use it in GitHub Desktop.
ankoを使ってプラグイン機構っぽいのを実装してみた
filter.Add(func(s) {
return strings.ToLower(s)
}, 10)
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"reflect"
"sort"
anko_core "github.com/mattn/anko/builtins"
anko_encoding "github.com/mattn/anko/builtins/encoding"
anko_flag "github.com/mattn/anko/builtins/flag"
anko_io "github.com/mattn/anko/builtins/io"
anko_math "github.com/mattn/anko/builtins/math"
anko_net "github.com/mattn/anko/builtins/net"
anko_os "github.com/mattn/anko/builtins/os"
anko_path "github.com/mattn/anko/builtins/path"
anko_regexp "github.com/mattn/anko/builtins/regexp"
anko_sort "github.com/mattn/anko/builtins/sort"
anko_strings "github.com/mattn/anko/builtins/strings"
anko_term "github.com/mattn/anko/builtins/term"
"github.com/mattn/anko/parser"
"github.com/mattn/anko/vm"
)
type Env vm.Env
func NewEnv() *Env {
env := vm.NewEnv()
anko_core.Import(env)
anko_flag.Import(env)
anko_net.Import(env)
anko_encoding.Import(env)
anko_os.Import(env)
anko_io.Import(env)
anko_math.Import(env)
anko_path.Import(env)
anko_regexp.Import(env)
anko_sort.Import(env)
anko_strings.Import(env)
anko_term.Import(env)
return (*Env)(env)
}
func (env *Env) Define(mod string, name string, i interface{}) {
var m *vm.Env
if mod == "" {
m = (*vm.Env)(env)
} else {
v, err := (*vm.Env)(env).Get(mod)
if err != nil {
m = (*vm.Env)(env).NewModule(mod)
} else {
m, _ = v.Interface().(*vm.Env)
}
}
m.Define(name, reflect.ValueOf(i))
}
type filter struct {
function func(s string) string
priority int64
}
func (f *filter) Apply(s string) string {
return f.function(s)
}
type Filters []*filter
func (f Filters) Len() int {
return len(f)
}
func (f Filters) Less(i, j int) bool {
return f[i].priority < f[j].priority
}
func (f Filters) Swap(i, j int) {
f[i], f[j] = f[j], f[i]
}
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s STRING\n", os.Args[0])
flag.PrintDefaults()
}
}
func main() {
flag.Parse()
if len(os.Args) < 2 {
flag.Usage()
os.Exit(1)
}
filters := make(Filters, 0)
env := NewEnv()
env.Define("filter", "Add", func(f interface{}, prio interface{}) {
filter := &filter{
func(s string) string {
v, _ := f.(vm.Func)(reflect.ValueOf(s))
return v.String()
},
prio.(int64),
}
filters = append(filters, filter)
})
plugins, _ := filepath.Glob("*.ank")
for _, p := range plugins {
stat, err := os.Stat(p)
if err != nil {
log.Println(p, err)
continue
}
if stat.Mode().IsDir() {
continue
}
code, err := ioutil.ReadFile(p)
if err != nil {
log.Println(p, err)
continue
}
scanner := new(parser.Scanner)
scanner.Init(string(code))
stmts, err := parser.Parse(scanner)
if err != nil {
log.Println(p, err)
continue
}
_, err = vm.Run(stmts, (*vm.Env)(env))
if err != nil {
log.Println(p, err)
continue
}
}
str := os.Args[1]
sort.Sort(filters)
for _, f := range filters {
str = f.Apply(str)
}
fmt.Printf("Filtered: \"%s\"\n", str)
}
filter.Add(func(s) {
return strings.Trim(s, " ")
}, 100)
filter.Add(func(s) {
return strings.ToUpper(s)
}, 100)
@hayajo
Copy link
Author

hayajo commented May 1, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment