├── README.md ├── config └── config.go ├── example.conf.yaml ├── gui ├── history.go └── window.go ├── main.go ├── redis.png ├── redis ├── client.go ├── cluster_client.go └── simple_client.go └── vendor ├── github.com ├── BurntSushi │ └── toml │ │ ├── COMPATIBLE │ │ ├── COPYING │ │ ├── Makefile │ │ ├── README.md │ │ ├── decode.go │ │ ├── decode_meta.go │ │ ├── doc.go │ │ ├── encode.go │ │ ├── encoding_types.go │ │ ├── encoding_types_1.1.go │ │ ├── lex.go │ │ ├── parse.go │ │ ├── session.vim │ │ ├── type_check.go │ │ └── type_fields.go ├── garyburd │ └── redigo │ │ ├── LICENSE │ │ ├── internal │ │ └── commandinfo.go │ │ └── redis │ │ ├── conn.go │ │ ├── doc.go │ │ ├── go16.go │ │ ├── go17.go │ │ ├── go18.go │ │ ├── log.go │ │ ├── pool.go │ │ ├── pool17.go │ │ ├── pubsub.go │ │ ├── redis.go │ │ ├── reply.go │ │ ├── scan.go │ │ └── script.go ├── jinzhu │ └── configor │ │ ├── README.md │ │ ├── configor.go │ │ ├── unmarshal_json_1_10.go │ │ ├── unmarshal_json_1_9.go │ │ ├── utils.go │ │ └── wercker.yml ├── jroimartin │ └── gocui │ │ ├── AUTHORS │ │ ├── LICENSE │ │ ├── README.md │ │ ├── attribute.go │ │ ├── doc.go │ │ ├── edit.go │ │ ├── escape.go │ │ ├── gui.go │ │ ├── keybinding.go │ │ └── view.go ├── mattn │ └── go-runewidth │ │ ├── LICENSE │ │ ├── README.mkd │ │ ├── go.mod │ │ ├── runewidth.go │ │ ├── runewidth_appengine.go │ │ ├── runewidth_js.go │ │ ├── runewidth_posix.go │ │ └── runewidth_windows.go ├── nsf │ └── termbox-go │ │ ├── AUTHORS │ │ ├── LICENSE │ │ ├── README.md │ │ ├── api.go │ │ ├── api_common.go │ │ ├── api_windows.go │ │ ├── collect_terminfo.py │ │ ├── escwait.go │ │ ├── escwait_darwin.go │ │ ├── syscalls.go │ │ ├── syscalls_darwin.go │ │ ├── syscalls_darwin_amd64.go │ │ ├── syscalls_dragonfly.go │ │ ├── syscalls_freebsd.go │ │ ├── syscalls_linux.go │ │ ├── syscalls_netbsd.go │ │ ├── syscalls_openbsd.go │ │ ├── syscalls_windows.go │ │ ├── termbox.go │ │ ├── termbox_common.go │ │ ├── termbox_windows.go │ │ ├── terminfo.go │ │ └── terminfo_builtin.go └── wuxibin89 │ └── redis-go-cluster │ ├── LICENSE │ ├── README.md │ ├── batch.go │ ├── cluster.go │ ├── crc16.go │ ├── doc.go │ ├── multi.go │ ├── node.go │ └── reply.go ├── gopkg.in └── yaml.v2 │ ├── LICENSE │ ├── LICENSE.libyaml │ ├── NOTICE │ ├── README.md │ ├── apic.go │ ├── decode.go │ ├── emitterc.go │ ├── encode.go │ ├── go.mod │ ├── parserc.go │ ├── readerc.go │ ├── resolve.go │ ├── scannerc.go │ ├── sorter.go │ ├── writerc.go │ ├── yaml.go │ ├── yamlh.go │ └── yamlprivateh.go └── vendor.json /README.md: -------------------------------------------------------------------------------- 1 | # lazyredis 2 | 3 | 基于[gocui](https://github.com/jroimartin/gocui)实现的redis命令行客户端,灵感来源于[lazydocker](https://github.com/jesseduffield/lazydocker) 4 | 5 | ![](/redis.png) 6 | 7 | 8 | 9 | 10 | ## 欢迎打赏 11 | 12 | 走过路过的大佬,如果这个项目对您帮助,请往这扔几个铜板 13 | 14 | - BTC: 16L9w2vMn8XSFV7Ytar2LzHEsdDp3w9gM3 15 | - ETH: 0xE00a72aFb1890Bc4d0dcf2561aB26099cACEcD87 16 | - EOS: eosbetkiller 17 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "github.com/jinzhu/configor" 4 | 5 | const DefaultConfigFile = "conf.yml" 6 | 7 | type ( 8 | RedisConfig struct { 9 | Addr []string `yaml:"addr"` 10 | Password string `yaml:"password"` 11 | Db int `yaml:"db"` 12 | } 13 | 14 | AppConfig struct { 15 | Redis RedisConfig `yaml:"redis"` 16 | } 17 | ) 18 | 19 | var Conf AppConfig 20 | 21 | func Load(path string) (*AppConfig, error) { 22 | err := configor.Load(&Conf, path) 23 | return &Conf, err 24 | } 25 | -------------------------------------------------------------------------------- /example.conf.yaml: -------------------------------------------------------------------------------- 1 | redis: 2 | addr: 3 | - 10.50.0.180:15011 4 | password: Lclclc123 5 | db: 3 -------------------------------------------------------------------------------- /gui/history.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | type History struct { 4 | list []string 5 | index int 6 | } 7 | 8 | func (h *History) Add(str string) { 9 | h.list = append(h.list, str) 10 | h.index = len(h.list) 11 | } 12 | 13 | func (h *History) Prev() string { 14 | if len(h.list) == 0 { 15 | return "" 16 | } 17 | h.index = (h.index - 1 + len(h.list)) % len(h.list) 18 | cmd := h.list[h.index] 19 | return cmd 20 | } 21 | 22 | func (h *History) Next() string { 23 | if len(h.list) == 0 { 24 | return "" 25 | } 26 | h.index = (h.index + 1) % len(h.list) 27 | cmd := h.list[h.index] 28 | return cmd 29 | } -------------------------------------------------------------------------------- /gui/window.go: -------------------------------------------------------------------------------- 1 | package gui 2 | 3 | import ( 4 | "fmt" 5 | "github.com/jroimartin/gocui" 6 | "github.com/liyue201/lazyredis/config" 7 | "github.com/liyue201/lazyredis/redis" 8 | "log" 9 | "strings" 10 | ) 11 | 12 | const ( 13 | topView = "top" 14 | midleView = "midle" 15 | BottomView = "bottom" 16 | ) 17 | 18 | type Window struct { 19 | g *gocui.Gui 20 | redisCli redis.Client 21 | history History 22 | } 23 | 24 | func NewWindow() *Window { 25 | g, err := gocui.NewGui(gocui.OutputNormal) 26 | if err != nil { 27 | panic(err.Error()) 28 | } 29 | w := &Window{g: g} 30 | 31 | g.Cursor = true 32 | g.Highlight = true 33 | g.SelFgColor = gocui.ColorGreen 34 | g.SetManager(w) 35 | w.keybindings() 36 | 37 | return w 38 | } 39 | 40 | func (w *Window) SetRedisClient(cli redis.Client) { 41 | w.redisCli = cli 42 | } 43 | 44 | func (w *Window) Close() { 45 | w.g.Close() 46 | } 47 | 48 | func (w *Window) Run() { 49 | if err := w.g.MainLoop(); err != nil && err != gocui.ErrQuit { 50 | fmt.Println(err) 51 | } 52 | } 53 | 54 | func (w *Window) Layout(g *gocui.Gui) error { 55 | maxX, maxY := g.Size() 56 | if v, err := g.SetView(topView, 1, 1, maxX-1, 3); err != nil { 57 | if err != gocui.ErrUnknownView { 58 | return err 59 | } 60 | v.Wrap = true 61 | v.Title = "db" 62 | fmt.Fprintln(v, fmt.Sprintf("%v", config.Conf.Redis.Addr)) 63 | } 64 | 65 | if v, err := g.SetView(midleView, 1, 4, maxX-1, 12); err != nil { 66 | if err != gocui.ErrUnknownView { 67 | return err 68 | } 69 | v.Title = "cmd" 70 | v.Editable = true 71 | w.writeArrow(v) 72 | 73 | if _, err = g.SetCurrentView(midleView); err != nil { 74 | return err 75 | } 76 | } 77 | if v, err := g.SetView(BottomView, 1, 13, maxX-1, maxY-1); err != nil { 78 | if err != gocui.ErrUnknownView { 79 | return err 80 | } 81 | v.Wrap = true 82 | v.Title = "output" 83 | } 84 | return nil 85 | } 86 | 87 | func (w *Window) keybindings() error { 88 | if err := w.g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, w.nextView); err != nil { 89 | log.Panicln(err) 90 | } 91 | if err := w.g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, w.quit); err != nil { 92 | return err 93 | } 94 | if err := w.g.SetKeybinding(midleView, gocui.KeyEnter, gocui.ModNone, w.execCmd); err != nil { 95 | return err 96 | } 97 | if err := w.g.SetKeybinding(midleView, gocui.KeyArrowUp, gocui.ModNone, w.preCmd); err != nil { 98 | return err 99 | } 100 | if err := w.g.SetKeybinding(midleView, gocui.KeyArrowDown, gocui.ModNone, w.nextCmd); err != nil { 101 | return err 102 | } 103 | if err := w.g.SetKeybinding(midleView, gocui.KeyBackspace, gocui.ModNone, w.onKeyBackspace); err != nil { 104 | return err 105 | } 106 | if err := w.g.SetKeybinding(midleView, gocui.KeyBackspace2, gocui.ModNone, w.onKeyBackspace); err != nil { 107 | return err 108 | } 109 | 110 | if err := w.g.SetKeybinding(midleView, gocui.KeyArrowLeft, gocui.ModNone, w.onKeyArrowLeft); err != nil { 111 | return err 112 | } 113 | 114 | if err := w.g.SetKeybinding(midleView, gocui.KeyArrowRight, gocui.ModNone, w.onKeyArrowRight); err != nil { 115 | return err 116 | } 117 | 118 | keys := []gocui.Key{gocui.KeyDelete } 119 | for _, key := range keys { 120 | w.g.SetKeybinding(midleView, key, gocui.ModNone, w.ignoreKey); 121 | } 122 | if err := w.g.SetKeybinding(BottomView, gocui.KeyArrowDown, gocui.ModNone, w.cursorDown); err != nil { 123 | return err 124 | } 125 | if err := w.g.SetKeybinding(BottomView, gocui.KeyArrowUp, gocui.ModNone, w.cursorUp); err != nil { 126 | return err 127 | } 128 | return nil 129 | } 130 | 131 | func (w *Window) nextView(g *gocui.Gui, v *gocui.View) error { 132 | views := g.Views() 133 | 134 | curViewIdx := 0 135 | for i, v1 := range views { 136 | if v1.Name() == v.Name() { 137 | curViewIdx = i 138 | break 139 | } 140 | } 141 | curView := views[(curViewIdx+1)%len(views)] 142 | 143 | g.SetCurrentView(curView.Name()) 144 | g.SetViewOnTop(curView.Name()) 145 | 146 | return nil 147 | } 148 | 149 | func (w *Window) execCmd(g *gocui.Gui, v *gocui.View) error { 150 | var line string 151 | var err error 152 | 153 | defer func() { 154 | v.EditNewLine() 155 | w.writeArrow(v) 156 | }() 157 | 158 | _, cy := v.Cursor() 159 | if line, err = v.Line(cy); err != nil { 160 | line = "" 161 | return nil 162 | } 163 | v.SetCursor(len(line), cy) 164 | 165 | inputs := "" 166 | splits := strings.Split(line, ">") 167 | if len(splits) > 1 { 168 | inputs = splits[1] 169 | } 170 | if inputs == "" { 171 | return nil 172 | } 173 | 174 | cmd := "" 175 | args := []interface{}{} 176 | 177 | inputSprits := strings.Split(inputs, " ") 178 | for _, item := range inputSprits { 179 | item = strings.TrimSpace(item) 180 | if item == "" { 181 | continue 182 | } 183 | if cmd == "" { 184 | cmd = item 185 | } else { 186 | args = append(args, item) 187 | } 188 | } 189 | 190 | mainView, _ := g.View(BottomView) 191 | mainView.Clear() 192 | mainView.SetCursor(0, 0) 193 | 194 | if w.redisCli == nil { 195 | fmt.Fprintln(mainView, "redis disconnected") 196 | return nil 197 | } 198 | 199 | relpy, err := w.redisCli.Do(cmd, args...) 200 | if err == nil { 201 | str := strings.ReplaceAll(relpy, "\r\n", "\n") 202 | if str != "" { 203 | fmt.Fprintln(mainView, str) 204 | } else { 205 | fmt.Fprintln(mainView, "") 206 | } 207 | } else { 208 | fmt.Fprintln(mainView, err.Error()) 209 | } 210 | w.history.Add(inputs) 211 | return nil 212 | } 213 | 214 | func (w *Window) quit(g *gocui.Gui, v *gocui.View) error { 215 | return gocui.ErrQuit 216 | } 217 | 218 | func (w *Window) cursorDown(g *gocui.Gui, v *gocui.View) error { 219 | if v != nil { 220 | cx, cy := v.Cursor() 221 | if err := v.SetCursor(cx, cy+1); err != nil { 222 | ox, oy := v.Origin() 223 | if err := v.SetOrigin(ox, oy+1); err != nil { 224 | return err 225 | } 226 | } 227 | } 228 | return nil 229 | } 230 | 231 | func (w *Window) cursorUp(g *gocui.Gui, v *gocui.View) error { 232 | if v != nil { 233 | ox, oy := v.Origin() 234 | cx, cy := v.Cursor() 235 | if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 { 236 | if err := v.SetOrigin(ox, oy-1); err != nil { 237 | return err 238 | } 239 | } 240 | } 241 | return nil 242 | } 243 | 244 | func (w *Window) nextCmd(g *gocui.Gui, v *gocui.View) error { 245 | nextCmd := w.history.Next() 246 | if nextCmd == "" { 247 | return nil 248 | } 249 | w.deleteCurrentLine(g, v) 250 | w.writeArrow(v) 251 | w.writeText(v, nextCmd) 252 | return nil 253 | } 254 | 255 | func (w *Window) preCmd(g *gocui.Gui, v *gocui.View) error { 256 | preCmd := w.history.Prev() 257 | if preCmd == "" { 258 | return nil 259 | } 260 | w.deleteCurrentLine(g, v) 261 | w.writeArrow(v) 262 | w.writeText(v, preCmd) 263 | 264 | return nil 265 | } 266 | 267 | func (w *Window) onKeyBackspace(g *gocui.Gui, v *gocui.View) error { 268 | x, _ := v.Cursor() 269 | if x > 1 { 270 | v.EditDelete(true) 271 | } 272 | return nil 273 | } 274 | 275 | func (w *Window) onKeyArrowLeft(g *gocui.Gui, v *gocui.View) error { 276 | x, _ := v.Cursor() 277 | if x > 1 { 278 | v.MoveCursor(-1, 0, true) 279 | } 280 | return nil 281 | } 282 | 283 | func (w *Window) onKeyArrowRight(g *gocui.Gui, v *gocui.View) error { 284 | v.MoveCursor(1, 0, true) 285 | return nil 286 | } 287 | 288 | func (w *Window) writeArrow(v *gocui.View) { 289 | line := fmt.Sprintf(">") 290 | w.writeText(v, line) 291 | } 292 | 293 | func (w *Window) writeText(v *gocui.View, str string) { 294 | runes := []rune(str) 295 | for _, c := range runes { 296 | v.EditWrite(c) 297 | } 298 | } 299 | 300 | func (w *Window) ignoreKey(g *gocui.Gui, v *gocui.View) error { 301 | //do nothing 302 | return nil 303 | } 304 | 305 | func (w *Window) deleteCurrentLine(g *gocui.Gui, v *gocui.View) error { 306 | _, y := v.Cursor() 307 | line, _ := v.Line(y) 308 | n := len(line) 309 | v.SetCursor(n, y) 310 | 311 | for i := 0; i < n; i++ { 312 | v.EditDelete(true) 313 | } 314 | return nil 315 | } -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The gocui Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "flag" 9 | "strings" 10 | 11 | "github.com/liyue201/lazyredis/config" 12 | "github.com/liyue201/lazyredis/gui" 13 | "github.com/liyue201/lazyredis/redis" 14 | ) 15 | 16 | var ( 17 | addr = flag.String("addr", "localhost:6379", "redis address") 18 | pass = flag.String("pass", "", "redis password") 19 | db = flag.Int("db", 0, "redis database") 20 | cfgFile = flag.String("conf", "", "yaml config file") 21 | ) 22 | 23 | func main() { 24 | flag.Parse() 25 | 26 | redisAddrs := strings.Split(*addr, ",") 27 | 28 | if *cfgFile != "" { 29 | conf, err := config.Load(*cfgFile) 30 | if err != nil { 31 | panic(err.Error()) 32 | } 33 | 34 | redisAddrs = conf.Redis.Addr 35 | *pass = conf.Redis.Password 36 | *db = conf.Redis.Db 37 | } 38 | 39 | redisCli, err := redis.NewRedisClient(redisAddrs, *pass, *db) 40 | if err != nil { 41 | panic(err.Error()) 42 | } 43 | defer redisCli.Close() 44 | 45 | w := gui.NewWindow() 46 | w.SetRedisClient(redisCli) 47 | 48 | w.Run() 49 | w.Close() 50 | } 51 | -------------------------------------------------------------------------------- /redis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liyue201/lazyredis/71ae584fb3dd636c3def578843da202011088828/redis.png -------------------------------------------------------------------------------- /redis/client.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "encoding/hex" 5 | "errors" 6 | "fmt" 7 | redigo "github.com/garyburd/redigo/redis" 8 | "github.com/wuxibin89/redis-go-cluster" 9 | ) 10 | 11 | type Client interface { 12 | Do(cmd string, args ...interface{}) (string, error) 13 | Close() error 14 | } 15 | 16 | func NewRedisClient(addr [] string, password string, db int) (Client, error) { 17 | if len(addr) == 0 { 18 | return nil, errors.New("addr is empty") 19 | } 20 | if len(addr) > 1 { 21 | return NewClusterClient(&redis.Options{StartNodes: addr}) 22 | } 23 | return NewSimpleClient(addr[0], redigo.DialPassword(password), redigo.DialDatabase(db)) 24 | } 25 | 26 | func replyText(reply interface{}) string { 27 | if n, err := redigo.Int(reply, nil); err == nil { 28 | return fmt.Sprintf("%d", n) 29 | } 30 | if n, err := redigo.Int64(reply, nil); err == nil { 31 | return fmt.Sprintf("%d", n) 32 | } 33 | if n, err := redigo.Uint64(reply, nil); err == nil { 34 | return fmt.Sprintf("%d", n) 35 | } 36 | if n, err := redigo.Float64(reply, nil); err == nil { 37 | return fmt.Sprintf("%f", n) 38 | } 39 | if str, err := redigo.String(reply, nil); err == nil { 40 | return str 41 | } 42 | if bys, err := redigo.Bytes(reply, nil); err == nil { 43 | return hex.EncodeToString(bys) 44 | } 45 | if b, err := redigo.Bool(reply, nil); err == nil { 46 | if b { 47 | return "true" 48 | } 49 | return "false" 50 | } 51 | if values, err := redigo.Values(reply, nil); err == nil { 52 | str := "" 53 | for _, v := range values { 54 | if str != "" { 55 | str += "\n" 56 | } 57 | str += replyText(v) 58 | } 59 | return str 60 | } 61 | if floats, err := redigo.Float64s(reply, nil); err == nil { 62 | str := "" 63 | for _, v := range floats { 64 | if str != "" { 65 | str += "\n" 66 | } 67 | str += fmt.Sprintf("%s", v) 68 | } 69 | return str 70 | } 71 | 72 | if strs, err := redigo.Strings(reply, nil); err == nil { 73 | str := "" 74 | for _, v := range strs { 75 | if str != "" { 76 | str += "\n" 77 | } 78 | str += v 79 | } 80 | return str 81 | } 82 | 83 | if byteSlids, err := redigo.ByteSlices(reply, nil); err == nil { 84 | str := "" 85 | for _, v := range byteSlids { 86 | if str != "" { 87 | str += "\n" 88 | } 89 | str += hex.EncodeToString(v) 90 | } 91 | return str 92 | } 93 | 94 | if ints, err := redigo.Int64s(reply, nil); err == nil { 95 | str := "" 96 | for _, v := range ints { 97 | if str != "" { 98 | str += "\n" 99 | } 100 | str += fmt.Sprintf("%d", v) 101 | } 102 | return str 103 | } 104 | if ints, err := redigo.Ints(reply, nil); err == nil { 105 | str := "" 106 | for _, v := range ints { 107 | if str != "" { 108 | str += "\n" 109 | } 110 | str += fmt.Sprintf("%d", v) 111 | } 112 | return str 113 | } 114 | 115 | if mps, err := redigo.StringMap(reply, nil); err == nil { 116 | str := "" 117 | for k, v := range mps { 118 | if str != "" { 119 | str += "\n" 120 | } 121 | str += fmt.Sprintf("%s %s", k, v) 122 | } 123 | return str 124 | } 125 | 126 | if mps, err := redigo.IntMap(reply, nil); err == nil { 127 | str := "" 128 | for k, v := range mps { 129 | if str != "" { 130 | str += "\n" 131 | } 132 | str += fmt.Sprintf("%s %d", k, v) 133 | } 134 | return str 135 | } 136 | 137 | if mps, err := redigo.Int64Map(reply, nil); err == nil { 138 | str := "" 139 | for k, v := range mps { 140 | if str != "" { 141 | str += "\n" 142 | } 143 | str += fmt.Sprintf("%s %d", k, v) 144 | } 145 | return str 146 | } 147 | 148 | if pos, err := redigo.Positions(reply, nil); err == nil { 149 | str := "" 150 | for _, v := range pos { 151 | if str != "" { 152 | str += "\n" 153 | } 154 | str += fmt.Sprintf("%f %f", v[0], v[1]) 155 | } 156 | return str 157 | } 158 | return "" 159 | } 160 | -------------------------------------------------------------------------------- /redis/cluster_client.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "github.com/wuxibin89/redis-go-cluster" 4 | 5 | type ClusterClient struct { 6 | cluster *redis.Cluster 7 | } 8 | 9 | func NewClusterClient(opts *redis.Options) (Client, error) { 10 | cluster, err := redis.NewCluster(opts) 11 | return &ClusterClient{cluster: cluster}, err 12 | } 13 | 14 | func (c *ClusterClient) Do(cmd string, args ...interface{}) (string, error) { 15 | reply, err := c.cluster.Do(cmd, args...) 16 | if err != nil { 17 | return "", err 18 | } 19 | return replyText(reply), nil 20 | } 21 | 22 | func (c *ClusterClient) Close() error { 23 | c.cluster.Close() 24 | return nil 25 | } 26 | -------------------------------------------------------------------------------- /redis/simple_client.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import "github.com/garyburd/redigo/redis" 4 | 5 | type SimpleClient struct { 6 | conn redis.Conn 7 | } 8 | 9 | func NewSimpleClient(addr string, opts ...redis.DialOption) (Client, error) { 10 | c, err := redis.Dial("tcp", addr, opts...) 11 | return &SimpleClient{conn: c}, err 12 | } 13 | 14 | func (c *SimpleClient) Do(cmd string, args ...interface{}) (string, error) { 15 | reply, err := c.conn.Do(cmd, args...) 16 | if err != nil { 17 | return "", err 18 | } 19 | return replyText(reply), nil 20 | } 21 | 22 | func (c *SimpleClient) Close() error { 23 | return c.conn.Close() 24 | } 25 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/COMPATIBLE: -------------------------------------------------------------------------------- 1 | Compatible with TOML version 2 | [v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md) 3 | 4 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/COPYING: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 TOML authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/Makefile: -------------------------------------------------------------------------------- 1 | install: 2 | go install ./... 3 | 4 | test: install 5 | go test -v 6 | toml-test toml-test-decoder 7 | toml-test -encoder toml-test-encoder 8 | 9 | fmt: 10 | gofmt -w *.go */*.go 11 | colcheck *.go */*.go 12 | 13 | tags: 14 | find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS 15 | 16 | push: 17 | git push origin master 18 | git push github master 19 | 20 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/README.md: -------------------------------------------------------------------------------- 1 | ## TOML parser and encoder for Go with reflection 2 | 3 | TOML stands for Tom's Obvious, Minimal Language. This Go package provides a 4 | reflection interface similar to Go's standard library `json` and `xml` 5 | packages. This package also supports the `encoding.TextUnmarshaler` and 6 | `encoding.TextMarshaler` interfaces so that you can define custom data 7 | representations. (There is an example of this below.) 8 | 9 | Spec: https://github.com/toml-lang/toml 10 | 11 | Compatible with TOML version 12 | [v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) 13 | 14 | Documentation: https://godoc.org/github.com/BurntSushi/toml 15 | 16 | Installation: 17 | 18 | ```bash 19 | go get github.com/BurntSushi/toml 20 | ``` 21 | 22 | Try the toml validator: 23 | 24 | ```bash 25 | go get github.com/BurntSushi/toml/cmd/tomlv 26 | tomlv some-toml-file.toml 27 | ``` 28 | 29 | [![Build Status](https://travis-ci.org/BurntSushi/toml.svg?branch=master)](https://travis-ci.org/BurntSushi/toml) [![GoDoc](https://godoc.org/github.com/BurntSushi/toml?status.svg)](https://godoc.org/github.com/BurntSushi/toml) 30 | 31 | ### Testing 32 | 33 | This package passes all tests in 34 | [toml-test](https://github.com/BurntSushi/toml-test) for both the decoder 35 | and the encoder. 36 | 37 | ### Examples 38 | 39 | This package works similarly to how the Go standard library handles `XML` 40 | and `JSON`. Namely, data is loaded into Go values via reflection. 41 | 42 | For the simplest example, consider some TOML file as just a list of keys 43 | and values: 44 | 45 | ```toml 46 | Age = 25 47 | Cats = [ "Cauchy", "Plato" ] 48 | Pi = 3.14 49 | Perfection = [ 6, 28, 496, 8128 ] 50 | DOB = 1987-07-05T05:45:00Z 51 | ``` 52 | 53 | Which could be defined in Go as: 54 | 55 | ```go 56 | type Config struct { 57 | Age int 58 | Cats []string 59 | Pi float64 60 | Perfection []int 61 | DOB time.Time // requires `import time` 62 | } 63 | ``` 64 | 65 | And then decoded with: 66 | 67 | ```go 68 | var conf Config 69 | if _, err := toml.Decode(tomlData, &conf); err != nil { 70 | // handle error 71 | } 72 | ``` 73 | 74 | You can also use struct tags if your struct field name doesn't map to a TOML 75 | key value directly: 76 | 77 | ```toml 78 | some_key_NAME = "wat" 79 | ``` 80 | 81 | ```go 82 | type TOML struct { 83 | ObscureKey string `toml:"some_key_NAME"` 84 | } 85 | ``` 86 | 87 | ### Using the `encoding.TextUnmarshaler` interface 88 | 89 | Here's an example that automatically parses duration strings into 90 | `time.Duration` values: 91 | 92 | ```toml 93 | [[song]] 94 | name = "Thunder Road" 95 | duration = "4m49s" 96 | 97 | [[song]] 98 | name = "Stairway to Heaven" 99 | duration = "8m03s" 100 | ``` 101 | 102 | Which can be decoded with: 103 | 104 | ```go 105 | type song struct { 106 | Name string 107 | Duration duration 108 | } 109 | type songs struct { 110 | Song []song 111 | } 112 | var favorites songs 113 | if _, err := toml.Decode(blob, &favorites); err != nil { 114 | log.Fatal(err) 115 | } 116 | 117 | for _, s := range favorites.Song { 118 | fmt.Printf("%s (%s)\n", s.Name, s.Duration) 119 | } 120 | ``` 121 | 122 | And you'll also need a `duration` type that satisfies the 123 | `encoding.TextUnmarshaler` interface: 124 | 125 | ```go 126 | type duration struct { 127 | time.Duration 128 | } 129 | 130 | func (d *duration) UnmarshalText(text []byte) error { 131 | var err error 132 | d.Duration, err = time.ParseDuration(string(text)) 133 | return err 134 | } 135 | ``` 136 | 137 | ### More complex usage 138 | 139 | Here's an example of how to load the example from the official spec page: 140 | 141 | ```toml 142 | # This is a TOML document. Boom. 143 | 144 | title = "TOML Example" 145 | 146 | [owner] 147 | name = "Tom Preston-Werner" 148 | organization = "GitHub" 149 | bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." 150 | dob = 1979-05-27T07:32:00Z # First class dates? Why not? 151 | 152 | [database] 153 | server = "192.168.1.1" 154 | ports = [ 8001, 8001, 8002 ] 155 | connection_max = 5000 156 | enabled = true 157 | 158 | [servers] 159 | 160 | # You can indent as you please. Tabs or spaces. TOML don't care. 161 | [servers.alpha] 162 | ip = "10.0.0.1" 163 | dc = "eqdc10" 164 | 165 | [servers.beta] 166 | ip = "10.0.0.2" 167 | dc = "eqdc10" 168 | 169 | [clients] 170 | data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it 171 | 172 | # Line breaks are OK when inside arrays 173 | hosts = [ 174 | "alpha", 175 | "omega" 176 | ] 177 | ``` 178 | 179 | And the corresponding Go types are: 180 | 181 | ```go 182 | type tomlConfig struct { 183 | Title string 184 | Owner ownerInfo 185 | DB database `toml:"database"` 186 | Servers map[string]server 187 | Clients clients 188 | } 189 | 190 | type ownerInfo struct { 191 | Name string 192 | Org string `toml:"organization"` 193 | Bio string 194 | DOB time.Time 195 | } 196 | 197 | type database struct { 198 | Server string 199 | Ports []int 200 | ConnMax int `toml:"connection_max"` 201 | Enabled bool 202 | } 203 | 204 | type server struct { 205 | IP string 206 | DC string 207 | } 208 | 209 | type clients struct { 210 | Data [][]interface{} 211 | Hosts []string 212 | } 213 | ``` 214 | 215 | Note that a case insensitive match will be tried if an exact match can't be 216 | found. 217 | 218 | A working example of the above can be found in `_examples/example.{go,toml}`. 219 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/decode_meta.go: -------------------------------------------------------------------------------- 1 | package toml 2 | 3 | import "strings" 4 | 5 | // MetaData allows access to meta information about TOML data that may not 6 | // be inferrable via reflection. In particular, whether a key has been defined 7 | // and the TOML type of a key. 8 | type MetaData struct { 9 | mapping map[string]interface{} 10 | types map[string]tomlType 11 | keys []Key 12 | decoded map[string]bool 13 | context Key // Used only during decoding. 14 | } 15 | 16 | // IsDefined returns true if the key given exists in the TOML data. The key 17 | // should be specified hierarchially. e.g., 18 | // 19 | // // access the TOML key 'a.b.c' 20 | // IsDefined("a", "b", "c") 21 | // 22 | // IsDefined will return false if an empty key given. Keys are case sensitive. 23 | func (md *MetaData) IsDefined(key ...string) bool { 24 | if len(key) == 0 { 25 | return false 26 | } 27 | 28 | var hash map[string]interface{} 29 | var ok bool 30 | var hashOrVal interface{} = md.mapping 31 | for _, k := range key { 32 | if hash, ok = hashOrVal.(map[string]interface{}); !ok { 33 | return false 34 | } 35 | if hashOrVal, ok = hash[k]; !ok { 36 | return false 37 | } 38 | } 39 | return true 40 | } 41 | 42 | // Type returns a string representation of the type of the key specified. 43 | // 44 | // Type will return the empty string if given an empty key or a key that 45 | // does not exist. Keys are case sensitive. 46 | func (md *MetaData) Type(key ...string) string { 47 | fullkey := strings.Join(key, ".") 48 | if typ, ok := md.types[fullkey]; ok { 49 | return typ.typeString() 50 | } 51 | return "" 52 | } 53 | 54 | // Key is the type of any TOML key, including key groups. Use (MetaData).Keys 55 | // to get values of this type. 56 | type Key []string 57 | 58 | func (k Key) String() string { 59 | return strings.Join(k, ".") 60 | } 61 | 62 | func (k Key) maybeQuotedAll() string { 63 | var ss []string 64 | for i := range k { 65 | ss = append(ss, k.maybeQuoted(i)) 66 | } 67 | return strings.Join(ss, ".") 68 | } 69 | 70 | func (k Key) maybeQuoted(i int) string { 71 | quote := false 72 | for _, c := range k[i] { 73 | if !isBareKeyChar(c) { 74 | quote = true 75 | break 76 | } 77 | } 78 | if quote { 79 | return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\"" 80 | } 81 | return k[i] 82 | } 83 | 84 | func (k Key) add(piece string) Key { 85 | newKey := make(Key, len(k)+1) 86 | copy(newKey, k) 87 | newKey[len(k)] = piece 88 | return newKey 89 | } 90 | 91 | // Keys returns a slice of every key in the TOML data, including key groups. 92 | // Each key is itself a slice, where the first element is the top of the 93 | // hierarchy and the last is the most specific. 94 | // 95 | // The list will have the same order as the keys appeared in the TOML data. 96 | // 97 | // All keys returned are non-empty. 98 | func (md *MetaData) Keys() []Key { 99 | return md.keys 100 | } 101 | 102 | // Undecoded returns all keys that have not been decoded in the order in which 103 | // they appear in the original TOML document. 104 | // 105 | // This includes keys that haven't been decoded because of a Primitive value. 106 | // Once the Primitive value is decoded, the keys will be considered decoded. 107 | // 108 | // Also note that decoding into an empty interface will result in no decoding, 109 | // and so no keys will be considered decoded. 110 | // 111 | // In this sense, the Undecoded keys correspond to keys in the TOML document 112 | // that do not have a concrete type in your representation. 113 | func (md *MetaData) Undecoded() []Key { 114 | undecoded := make([]Key, 0, len(md.keys)) 115 | for _, key := range md.keys { 116 | if !md.decoded[key.String()] { 117 | undecoded = append(undecoded, key) 118 | } 119 | } 120 | return undecoded 121 | } 122 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package toml provides facilities for decoding and encoding TOML configuration 3 | files via reflection. There is also support for delaying decoding with 4 | the Primitive type, and querying the set of keys in a TOML document with the 5 | MetaData type. 6 | 7 | The specification implemented: https://github.com/toml-lang/toml 8 | 9 | The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify 10 | whether a file is a valid TOML document. It can also be used to print the 11 | type of each key in a TOML document. 12 | 13 | Testing 14 | 15 | There are two important types of tests used for this package. The first is 16 | contained inside '*_test.go' files and uses the standard Go unit testing 17 | framework. These tests are primarily devoted to holistically testing the 18 | decoder and encoder. 19 | 20 | The second type of testing is used to verify the implementation's adherence 21 | to the TOML specification. These tests have been factored into their own 22 | project: https://github.com/BurntSushi/toml-test 23 | 24 | The reason the tests are in a separate project is so that they can be used by 25 | any implementation of TOML. Namely, it is language agnostic. 26 | */ 27 | package toml 28 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/encoding_types.go: -------------------------------------------------------------------------------- 1 | // +build go1.2 2 | 3 | package toml 4 | 5 | // In order to support Go 1.1, we define our own TextMarshaler and 6 | // TextUnmarshaler types. For Go 1.2+, we just alias them with the 7 | // standard library interfaces. 8 | 9 | import ( 10 | "encoding" 11 | ) 12 | 13 | // TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here 14 | // so that Go 1.1 can be supported. 15 | type TextMarshaler encoding.TextMarshaler 16 | 17 | // TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined 18 | // here so that Go 1.1 can be supported. 19 | type TextUnmarshaler encoding.TextUnmarshaler 20 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/encoding_types_1.1.go: -------------------------------------------------------------------------------- 1 | // +build !go1.2 2 | 3 | package toml 4 | 5 | // These interfaces were introduced in Go 1.2, so we add them manually when 6 | // compiling for Go 1.1. 7 | 8 | // TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here 9 | // so that Go 1.1 can be supported. 10 | type TextMarshaler interface { 11 | MarshalText() (text []byte, err error) 12 | } 13 | 14 | // TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined 15 | // here so that Go 1.1 can be supported. 16 | type TextUnmarshaler interface { 17 | UnmarshalText(text []byte) error 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/session.vim: -------------------------------------------------------------------------------- 1 | au BufWritePost *.go silent!make tags > /dev/null 2>&1 2 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/type_check.go: -------------------------------------------------------------------------------- 1 | package toml 2 | 3 | // tomlType represents any Go type that corresponds to a TOML type. 4 | // While the first draft of the TOML spec has a simplistic type system that 5 | // probably doesn't need this level of sophistication, we seem to be militating 6 | // toward adding real composite types. 7 | type tomlType interface { 8 | typeString() string 9 | } 10 | 11 | // typeEqual accepts any two types and returns true if they are equal. 12 | func typeEqual(t1, t2 tomlType) bool { 13 | if t1 == nil || t2 == nil { 14 | return false 15 | } 16 | return t1.typeString() == t2.typeString() 17 | } 18 | 19 | func typeIsHash(t tomlType) bool { 20 | return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash) 21 | } 22 | 23 | type tomlBaseType string 24 | 25 | func (btype tomlBaseType) typeString() string { 26 | return string(btype) 27 | } 28 | 29 | func (btype tomlBaseType) String() string { 30 | return btype.typeString() 31 | } 32 | 33 | var ( 34 | tomlInteger tomlBaseType = "Integer" 35 | tomlFloat tomlBaseType = "Float" 36 | tomlDatetime tomlBaseType = "Datetime" 37 | tomlString tomlBaseType = "String" 38 | tomlBool tomlBaseType = "Bool" 39 | tomlArray tomlBaseType = "Array" 40 | tomlHash tomlBaseType = "Hash" 41 | tomlArrayHash tomlBaseType = "ArrayHash" 42 | ) 43 | 44 | // typeOfPrimitive returns a tomlType of any primitive value in TOML. 45 | // Primitive values are: Integer, Float, Datetime, String and Bool. 46 | // 47 | // Passing a lexer item other than the following will cause a BUG message 48 | // to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime. 49 | func (p *parser) typeOfPrimitive(lexItem item) tomlType { 50 | switch lexItem.typ { 51 | case itemInteger: 52 | return tomlInteger 53 | case itemFloat: 54 | return tomlFloat 55 | case itemDatetime: 56 | return tomlDatetime 57 | case itemString: 58 | return tomlString 59 | case itemMultilineString: 60 | return tomlString 61 | case itemRawString: 62 | return tomlString 63 | case itemRawMultilineString: 64 | return tomlString 65 | case itemBool: 66 | return tomlBool 67 | } 68 | p.bug("Cannot infer primitive type of lex item '%s'.", lexItem) 69 | panic("unreachable") 70 | } 71 | 72 | // typeOfArray returns a tomlType for an array given a list of types of its 73 | // values. 74 | // 75 | // In the current spec, if an array is homogeneous, then its type is always 76 | // "Array". If the array is not homogeneous, an error is generated. 77 | func (p *parser) typeOfArray(types []tomlType) tomlType { 78 | // Empty arrays are cool. 79 | if len(types) == 0 { 80 | return tomlArray 81 | } 82 | 83 | theType := types[0] 84 | for _, t := range types[1:] { 85 | if !typeEqual(theType, t) { 86 | p.panicf("Array contains values of type '%s' and '%s', but "+ 87 | "arrays must be homogeneous.", theType, t) 88 | } 89 | } 90 | return tomlArray 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/BurntSushi/toml/type_fields.go: -------------------------------------------------------------------------------- 1 | package toml 2 | 3 | // Struct field handling is adapted from code in encoding/json: 4 | // 5 | // Copyright 2010 The Go Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style 7 | // license that can be found in the Go distribution. 8 | 9 | import ( 10 | "reflect" 11 | "sort" 12 | "sync" 13 | ) 14 | 15 | // A field represents a single field found in a struct. 16 | type field struct { 17 | name string // the name of the field (`toml` tag included) 18 | tag bool // whether field has a `toml` tag 19 | index []int // represents the depth of an anonymous field 20 | typ reflect.Type // the type of the field 21 | } 22 | 23 | // byName sorts field by name, breaking ties with depth, 24 | // then breaking ties with "name came from toml tag", then 25 | // breaking ties with index sequence. 26 | type byName []field 27 | 28 | func (x byName) Len() int { return len(x) } 29 | 30 | func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 31 | 32 | func (x byName) Less(i, j int) bool { 33 | if x[i].name != x[j].name { 34 | return x[i].name < x[j].name 35 | } 36 | if len(x[i].index) != len(x[j].index) { 37 | return len(x[i].index) < len(x[j].index) 38 | } 39 | if x[i].tag != x[j].tag { 40 | return x[i].tag 41 | } 42 | return byIndex(x).Less(i, j) 43 | } 44 | 45 | // byIndex sorts field by index sequence. 46 | type byIndex []field 47 | 48 | func (x byIndex) Len() int { return len(x) } 49 | 50 | func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 51 | 52 | func (x byIndex) Less(i, j int) bool { 53 | for k, xik := range x[i].index { 54 | if k >= len(x[j].index) { 55 | return false 56 | } 57 | if xik != x[j].index[k] { 58 | return xik < x[j].index[k] 59 | } 60 | } 61 | return len(x[i].index) < len(x[j].index) 62 | } 63 | 64 | // typeFields returns a list of fields that TOML should recognize for the given 65 | // type. The algorithm is breadth-first search over the set of structs to 66 | // include - the top struct and then any reachable anonymous structs. 67 | func typeFields(t reflect.Type) []field { 68 | // Anonymous fields to explore at the current level and the next. 69 | current := []field{} 70 | next := []field{{typ: t}} 71 | 72 | // Count of queued names for current level and the next. 73 | count := map[reflect.Type]int{} 74 | nextCount := map[reflect.Type]int{} 75 | 76 | // Types already visited at an earlier level. 77 | visited := map[reflect.Type]bool{} 78 | 79 | // Fields found. 80 | var fields []field 81 | 82 | for len(next) > 0 { 83 | current, next = next, current[:0] 84 | count, nextCount = nextCount, map[reflect.Type]int{} 85 | 86 | for _, f := range current { 87 | if visited[f.typ] { 88 | continue 89 | } 90 | visited[f.typ] = true 91 | 92 | // Scan f.typ for fields to include. 93 | for i := 0; i < f.typ.NumField(); i++ { 94 | sf := f.typ.Field(i) 95 | if sf.PkgPath != "" && !sf.Anonymous { // unexported 96 | continue 97 | } 98 | opts := getOptions(sf.Tag) 99 | if opts.skip { 100 | continue 101 | } 102 | index := make([]int, len(f.index)+1) 103 | copy(index, f.index) 104 | index[len(f.index)] = i 105 | 106 | ft := sf.Type 107 | if ft.Name() == "" && ft.Kind() == reflect.Ptr { 108 | // Follow pointer. 109 | ft = ft.Elem() 110 | } 111 | 112 | // Record found field and index sequence. 113 | if opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { 114 | tagged := opts.name != "" 115 | name := opts.name 116 | if name == "" { 117 | name = sf.Name 118 | } 119 | fields = append(fields, field{name, tagged, index, ft}) 120 | if count[f.typ] > 1 { 121 | // If there were multiple instances, add a second, 122 | // so that the annihilation code will see a duplicate. 123 | // It only cares about the distinction between 1 or 2, 124 | // so don't bother generating any more copies. 125 | fields = append(fields, fields[len(fields)-1]) 126 | } 127 | continue 128 | } 129 | 130 | // Record new anonymous struct to explore in next round. 131 | nextCount[ft]++ 132 | if nextCount[ft] == 1 { 133 | f := field{name: ft.Name(), index: index, typ: ft} 134 | next = append(next, f) 135 | } 136 | } 137 | } 138 | } 139 | 140 | sort.Sort(byName(fields)) 141 | 142 | // Delete all fields that are hidden by the Go rules for embedded fields, 143 | // except that fields with TOML tags are promoted. 144 | 145 | // The fields are sorted in primary order of name, secondary order 146 | // of field index length. Loop over names; for each name, delete 147 | // hidden fields by choosing the one dominant field that survives. 148 | out := fields[:0] 149 | for advance, i := 0, 0; i < len(fields); i += advance { 150 | // One iteration per name. 151 | // Find the sequence of fields with the name of this first field. 152 | fi := fields[i] 153 | name := fi.name 154 | for advance = 1; i+advance < len(fields); advance++ { 155 | fj := fields[i+advance] 156 | if fj.name != name { 157 | break 158 | } 159 | } 160 | if advance == 1 { // Only one field with this name 161 | out = append(out, fi) 162 | continue 163 | } 164 | dominant, ok := dominantField(fields[i : i+advance]) 165 | if ok { 166 | out = append(out, dominant) 167 | } 168 | } 169 | 170 | fields = out 171 | sort.Sort(byIndex(fields)) 172 | 173 | return fields 174 | } 175 | 176 | // dominantField looks through the fields, all of which are known to 177 | // have the same name, to find the single field that dominates the 178 | // others using Go's embedding rules, modified by the presence of 179 | // TOML tags. If there are multiple top-level fields, the boolean 180 | // will be false: This condition is an error in Go and we skip all 181 | // the fields. 182 | func dominantField(fields []field) (field, bool) { 183 | // The fields are sorted in increasing index-length order. The winner 184 | // must therefore be one with the shortest index length. Drop all 185 | // longer entries, which is easy: just truncate the slice. 186 | length := len(fields[0].index) 187 | tagged := -1 // Index of first tagged field. 188 | for i, f := range fields { 189 | if len(f.index) > length { 190 | fields = fields[:i] 191 | break 192 | } 193 | if f.tag { 194 | if tagged >= 0 { 195 | // Multiple tagged fields at the same level: conflict. 196 | // Return no field. 197 | return field{}, false 198 | } 199 | tagged = i 200 | } 201 | } 202 | if tagged >= 0 { 203 | return fields[tagged], true 204 | } 205 | // All remaining fields have the same length. If there's more than one, 206 | // we have a conflict (two fields named "X" at the same level) and we 207 | // return no field. 208 | if len(fields) > 1 { 209 | return field{}, false 210 | } 211 | return fields[0], true 212 | } 213 | 214 | var fieldCache struct { 215 | sync.RWMutex 216 | m map[reflect.Type][]field 217 | } 218 | 219 | // cachedTypeFields is like typeFields but uses a cache to avoid repeated work. 220 | func cachedTypeFields(t reflect.Type) []field { 221 | fieldCache.RLock() 222 | f := fieldCache.m[t] 223 | fieldCache.RUnlock() 224 | if f != nil { 225 | return f 226 | } 227 | 228 | // Compute fields without lock. 229 | // Might duplicate effort but won't hold other computations back. 230 | f = typeFields(t) 231 | if f == nil { 232 | f = []field{} 233 | } 234 | 235 | fieldCache.Lock() 236 | if fieldCache.m == nil { 237 | fieldCache.m = map[reflect.Type][]field{} 238 | } 239 | fieldCache.m[t] = f 240 | fieldCache.Unlock() 241 | return f 242 | } 243 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/internal/commandinfo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package internal // import "github.com/garyburd/redigo/internal" 16 | 17 | import ( 18 | "strings" 19 | ) 20 | 21 | const ( 22 | WatchState = 1 << iota 23 | MultiState 24 | SubscribeState 25 | MonitorState 26 | ) 27 | 28 | type CommandInfo struct { 29 | Set, Clear int 30 | } 31 | 32 | var commandInfos = map[string]CommandInfo{ 33 | "WATCH": {Set: WatchState}, 34 | "UNWATCH": {Clear: WatchState}, 35 | "MULTI": {Set: MultiState}, 36 | "EXEC": {Clear: WatchState | MultiState}, 37 | "DISCARD": {Clear: WatchState | MultiState}, 38 | "PSUBSCRIBE": {Set: SubscribeState}, 39 | "SUBSCRIBE": {Set: SubscribeState}, 40 | "MONITOR": {Set: MonitorState}, 41 | } 42 | 43 | func init() { 44 | for n, ci := range commandInfos { 45 | commandInfos[strings.ToLower(n)] = ci 46 | } 47 | } 48 | 49 | func LookupCommandInfo(commandName string) CommandInfo { 50 | if ci, ok := commandInfos[commandName]; ok { 51 | return ci 52 | } 53 | return commandInfos[strings.ToUpper(commandName)] 54 | } 55 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | // Package redis is a client for the Redis database. 16 | // 17 | // The Redigo FAQ (https://github.com/garyburd/redigo/wiki/FAQ) contains more 18 | // documentation about this package. 19 | // 20 | // Connections 21 | // 22 | // The Conn interface is the primary interface for working with Redis. 23 | // Applications create connections by calling the Dial, DialWithTimeout or 24 | // NewConn functions. In the future, functions will be added for creating 25 | // sharded and other types of connections. 26 | // 27 | // The application must call the connection Close method when the application 28 | // is done with the connection. 29 | // 30 | // Executing Commands 31 | // 32 | // The Conn interface has a generic method for executing Redis commands: 33 | // 34 | // Do(commandName string, args ...interface{}) (reply interface{}, err error) 35 | // 36 | // The Redis command reference (http://redis.io/commands) lists the available 37 | // commands. An example of using the Redis APPEND command is: 38 | // 39 | // n, err := conn.Do("APPEND", "key", "value") 40 | // 41 | // The Do method converts command arguments to bulk strings for transmission 42 | // to the server as follows: 43 | // 44 | // Go Type Conversion 45 | // []byte Sent as is 46 | // string Sent as is 47 | // int, int64 strconv.FormatInt(v) 48 | // float64 strconv.FormatFloat(v, 'g', -1, 64) 49 | // bool true -> "1", false -> "0" 50 | // nil "" 51 | // all other types fmt.Fprint(w, v) 52 | // 53 | // Redis command reply types are represented using the following Go types: 54 | // 55 | // Redis type Go type 56 | // error redis.Error 57 | // integer int64 58 | // simple string string 59 | // bulk string []byte or nil if value not present. 60 | // array []interface{} or nil if value not present. 61 | // 62 | // Use type assertions or the reply helper functions to convert from 63 | // interface{} to the specific Go type for the command result. 64 | // 65 | // Pipelining 66 | // 67 | // Connections support pipelining using the Send, Flush and Receive methods. 68 | // 69 | // Send(commandName string, args ...interface{}) error 70 | // Flush() error 71 | // Receive() (reply interface{}, err error) 72 | // 73 | // Send writes the command to the connection's output buffer. Flush flushes the 74 | // connection's output buffer to the server. Receive reads a single reply from 75 | // the server. The following example shows a simple pipeline. 76 | // 77 | // c.Send("SET", "foo", "bar") 78 | // c.Send("GET", "foo") 79 | // c.Flush() 80 | // c.Receive() // reply from SET 81 | // v, err = c.Receive() // reply from GET 82 | // 83 | // The Do method combines the functionality of the Send, Flush and Receive 84 | // methods. The Do method starts by writing the command and flushing the output 85 | // buffer. Next, the Do method receives all pending replies including the reply 86 | // for the command just sent by Do. If any of the received replies is an error, 87 | // then Do returns the error. If there are no errors, then Do returns the last 88 | // reply. If the command argument to the Do method is "", then the Do method 89 | // will flush the output buffer and receive pending replies without sending a 90 | // command. 91 | // 92 | // Use the Send and Do methods to implement pipelined transactions. 93 | // 94 | // c.Send("MULTI") 95 | // c.Send("INCR", "foo") 96 | // c.Send("INCR", "bar") 97 | // r, err := c.Do("EXEC") 98 | // fmt.Println(r) // prints [1, 1] 99 | // 100 | // Concurrency 101 | // 102 | // Connections support one concurrent caller to the Receive method and one 103 | // concurrent caller to the Send and Flush methods. No other concurrency is 104 | // supported including concurrent calls to the Do method. 105 | // 106 | // For full concurrent access to Redis, use the thread-safe Pool to get, use 107 | // and release a connection from within a goroutine. Connections returned from 108 | // a Pool have the concurrency restrictions described in the previous 109 | // paragraph. 110 | // 111 | // Publish and Subscribe 112 | // 113 | // Use the Send, Flush and Receive methods to implement Pub/Sub subscribers. 114 | // 115 | // c.Send("SUBSCRIBE", "example") 116 | // c.Flush() 117 | // for { 118 | // reply, err := c.Receive() 119 | // if err != nil { 120 | // return err 121 | // } 122 | // // process pushed message 123 | // } 124 | // 125 | // The PubSubConn type wraps a Conn with convenience methods for implementing 126 | // subscribers. The Subscribe, PSubscribe, Unsubscribe and PUnsubscribe methods 127 | // send and flush a subscription management command. The receive method 128 | // converts a pushed message to convenient types for use in a type switch. 129 | // 130 | // psc := redis.PubSubConn{Conn: c} 131 | // psc.Subscribe("example") 132 | // for { 133 | // switch v := psc.Receive().(type) { 134 | // case redis.Message: 135 | // fmt.Printf("%s: message: %s\n", v.Channel, v.Data) 136 | // case redis.Subscription: 137 | // fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count) 138 | // case error: 139 | // return v 140 | // } 141 | // } 142 | // 143 | // Reply Helpers 144 | // 145 | // The Bool, Int, Bytes, String, Strings and Values functions convert a reply 146 | // to a value of a specific type. To allow convenient wrapping of calls to the 147 | // connection Do and Receive methods, the functions take a second argument of 148 | // type error. If the error is non-nil, then the helper function returns the 149 | // error. If the error is nil, the function converts the reply to the specified 150 | // type: 151 | // 152 | // exists, err := redis.Bool(c.Do("EXISTS", "foo")) 153 | // if err != nil { 154 | // // handle error return from c.Do or type conversion error. 155 | // } 156 | // 157 | // The Scan function converts elements of a array reply to Go types: 158 | // 159 | // var value1 int 160 | // var value2 string 161 | // reply, err := redis.Values(c.Do("MGET", "key1", "key2")) 162 | // if err != nil { 163 | // // handle error 164 | // } 165 | // if _, err := redis.Scan(reply, &value1, &value2); err != nil { 166 | // // handle error 167 | // } 168 | // 169 | // Errors 170 | // 171 | // Connection methods return error replies from the server as type redis.Error. 172 | // 173 | // Call the connection Err() method to determine if the connection encountered 174 | // non-recoverable error such as a network error or protocol parsing error. If 175 | // Err() returns a non-nil value, then the connection is not usable and should 176 | // be closed. 177 | package redis // import "github.com/garyburd/redigo/redis" 178 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/go16.go: -------------------------------------------------------------------------------- 1 | // +build !go1.7 2 | 3 | package redis 4 | 5 | import "crypto/tls" 6 | 7 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 8 | return &tls.Config{ 9 | Rand: cfg.Rand, 10 | Time: cfg.Time, 11 | Certificates: cfg.Certificates, 12 | NameToCertificate: cfg.NameToCertificate, 13 | GetCertificate: cfg.GetCertificate, 14 | RootCAs: cfg.RootCAs, 15 | NextProtos: cfg.NextProtos, 16 | ServerName: cfg.ServerName, 17 | ClientAuth: cfg.ClientAuth, 18 | ClientCAs: cfg.ClientCAs, 19 | InsecureSkipVerify: cfg.InsecureSkipVerify, 20 | CipherSuites: cfg.CipherSuites, 21 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 22 | ClientSessionCache: cfg.ClientSessionCache, 23 | MinVersion: cfg.MinVersion, 24 | MaxVersion: cfg.MaxVersion, 25 | CurvePreferences: cfg.CurvePreferences, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/go17.go: -------------------------------------------------------------------------------- 1 | // +build go1.7,!go1.8 2 | 3 | package redis 4 | 5 | import "crypto/tls" 6 | 7 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 8 | return &tls.Config{ 9 | Rand: cfg.Rand, 10 | Time: cfg.Time, 11 | Certificates: cfg.Certificates, 12 | NameToCertificate: cfg.NameToCertificate, 13 | GetCertificate: cfg.GetCertificate, 14 | RootCAs: cfg.RootCAs, 15 | NextProtos: cfg.NextProtos, 16 | ServerName: cfg.ServerName, 17 | ClientAuth: cfg.ClientAuth, 18 | ClientCAs: cfg.ClientCAs, 19 | InsecureSkipVerify: cfg.InsecureSkipVerify, 20 | CipherSuites: cfg.CipherSuites, 21 | PreferServerCipherSuites: cfg.PreferServerCipherSuites, 22 | ClientSessionCache: cfg.ClientSessionCache, 23 | MinVersion: cfg.MinVersion, 24 | MaxVersion: cfg.MaxVersion, 25 | CurvePreferences: cfg.CurvePreferences, 26 | DynamicRecordSizingDisabled: cfg.DynamicRecordSizingDisabled, 27 | Renegotiation: cfg.Renegotiation, 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/go18.go: -------------------------------------------------------------------------------- 1 | // +build go1.8 2 | 3 | package redis 4 | 5 | import "crypto/tls" 6 | 7 | func cloneTLSConfig(cfg *tls.Config) *tls.Config { 8 | return cfg.Clone() 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "bytes" 19 | "fmt" 20 | "log" 21 | "time" 22 | ) 23 | 24 | var ( 25 | _ ConnWithTimeout = (*loggingConn)(nil) 26 | ) 27 | 28 | // NewLoggingConn returns a logging wrapper around a connection. 29 | func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn { 30 | if prefix != "" { 31 | prefix = prefix + "." 32 | } 33 | return &loggingConn{conn, logger, prefix} 34 | } 35 | 36 | type loggingConn struct { 37 | Conn 38 | logger *log.Logger 39 | prefix string 40 | } 41 | 42 | func (c *loggingConn) Close() error { 43 | err := c.Conn.Close() 44 | var buf bytes.Buffer 45 | fmt.Fprintf(&buf, "%sClose() -> (%v)", c.prefix, err) 46 | c.logger.Output(2, buf.String()) 47 | return err 48 | } 49 | 50 | func (c *loggingConn) printValue(buf *bytes.Buffer, v interface{}) { 51 | const chop = 32 52 | switch v := v.(type) { 53 | case []byte: 54 | if len(v) > chop { 55 | fmt.Fprintf(buf, "%q...", v[:chop]) 56 | } else { 57 | fmt.Fprintf(buf, "%q", v) 58 | } 59 | case string: 60 | if len(v) > chop { 61 | fmt.Fprintf(buf, "%q...", v[:chop]) 62 | } else { 63 | fmt.Fprintf(buf, "%q", v) 64 | } 65 | case []interface{}: 66 | if len(v) == 0 { 67 | buf.WriteString("[]") 68 | } else { 69 | sep := "[" 70 | fin := "]" 71 | if len(v) > chop { 72 | v = v[:chop] 73 | fin = "...]" 74 | } 75 | for _, vv := range v { 76 | buf.WriteString(sep) 77 | c.printValue(buf, vv) 78 | sep = ", " 79 | } 80 | buf.WriteString(fin) 81 | } 82 | default: 83 | fmt.Fprint(buf, v) 84 | } 85 | } 86 | 87 | func (c *loggingConn) print(method, commandName string, args []interface{}, reply interface{}, err error) { 88 | var buf bytes.Buffer 89 | fmt.Fprintf(&buf, "%s%s(", c.prefix, method) 90 | if method != "Receive" { 91 | buf.WriteString(commandName) 92 | for _, arg := range args { 93 | buf.WriteString(", ") 94 | c.printValue(&buf, arg) 95 | } 96 | } 97 | buf.WriteString(") -> (") 98 | if method != "Send" { 99 | c.printValue(&buf, reply) 100 | buf.WriteString(", ") 101 | } 102 | fmt.Fprintf(&buf, "%v)", err) 103 | c.logger.Output(3, buf.String()) 104 | } 105 | 106 | func (c *loggingConn) Do(commandName string, args ...interface{}) (interface{}, error) { 107 | reply, err := c.Conn.Do(commandName, args...) 108 | c.print("Do", commandName, args, reply, err) 109 | return reply, err 110 | } 111 | 112 | func (c *loggingConn) DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (interface{}, error) { 113 | reply, err := DoWithTimeout(c.Conn, timeout, commandName, args...) 114 | c.print("DoWithTimeout", commandName, args, reply, err) 115 | return reply, err 116 | } 117 | 118 | func (c *loggingConn) Send(commandName string, args ...interface{}) error { 119 | err := c.Conn.Send(commandName, args...) 120 | c.print("Send", commandName, args, nil, err) 121 | return err 122 | } 123 | 124 | func (c *loggingConn) Receive() (interface{}, error) { 125 | reply, err := c.Conn.Receive() 126 | c.print("Receive", "", nil, reply, err) 127 | return reply, err 128 | } 129 | 130 | func (c *loggingConn) ReceiveWithTimeout(timeout time.Duration) (interface{}, error) { 131 | reply, err := ReceiveWithTimeout(c.Conn, timeout) 132 | c.print("ReceiveWithTimeout", "", nil, reply, err) 133 | return reply, err 134 | } 135 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/pool17.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | // +build go1.7 16 | 17 | package redis 18 | 19 | import "context" 20 | 21 | // GetContext gets a connection using the provided context. 22 | // 23 | // The provided Context must be non-nil. If the context expires before the 24 | // connection is complete, an error is returned. Any expiration on the context 25 | // will not affect the returned connection. 26 | // 27 | // If the function completes without error, then the application must close the 28 | // returned connection. 29 | func (p *Pool) GetContext(ctx context.Context) (Conn, error) { 30 | pc, err := p.get(ctx) 31 | if err != nil { 32 | return errorConn{err}, err 33 | } 34 | return &activeConn{p: p, pc: pc}, nil 35 | } 36 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/pubsub.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "errors" 19 | "time" 20 | ) 21 | 22 | // Subscription represents a subscribe or unsubscribe notification. 23 | type Subscription struct { 24 | // Kind is "subscribe", "unsubscribe", "psubscribe" or "punsubscribe" 25 | Kind string 26 | 27 | // The channel that was changed. 28 | Channel string 29 | 30 | // The current number of subscriptions for connection. 31 | Count int 32 | } 33 | 34 | // Message represents a message notification. 35 | type Message struct { 36 | // The originating channel. 37 | Channel string 38 | 39 | // The message data. 40 | Data []byte 41 | } 42 | 43 | // PMessage represents a pmessage notification. 44 | type PMessage struct { 45 | // The matched pattern. 46 | Pattern string 47 | 48 | // The originating channel. 49 | Channel string 50 | 51 | // The message data. 52 | Data []byte 53 | } 54 | 55 | // Pong represents a pubsub pong notification. 56 | type Pong struct { 57 | Data string 58 | } 59 | 60 | // PubSubConn wraps a Conn with convenience methods for subscribers. 61 | type PubSubConn struct { 62 | Conn Conn 63 | } 64 | 65 | // Close closes the connection. 66 | func (c PubSubConn) Close() error { 67 | return c.Conn.Close() 68 | } 69 | 70 | // Subscribe subscribes the connection to the specified channels. 71 | func (c PubSubConn) Subscribe(channel ...interface{}) error { 72 | c.Conn.Send("SUBSCRIBE", channel...) 73 | return c.Conn.Flush() 74 | } 75 | 76 | // PSubscribe subscribes the connection to the given patterns. 77 | func (c PubSubConn) PSubscribe(channel ...interface{}) error { 78 | c.Conn.Send("PSUBSCRIBE", channel...) 79 | return c.Conn.Flush() 80 | } 81 | 82 | // Unsubscribe unsubscribes the connection from the given channels, or from all 83 | // of them if none is given. 84 | func (c PubSubConn) Unsubscribe(channel ...interface{}) error { 85 | c.Conn.Send("UNSUBSCRIBE", channel...) 86 | return c.Conn.Flush() 87 | } 88 | 89 | // PUnsubscribe unsubscribes the connection from the given patterns, or from all 90 | // of them if none is given. 91 | func (c PubSubConn) PUnsubscribe(channel ...interface{}) error { 92 | c.Conn.Send("PUNSUBSCRIBE", channel...) 93 | return c.Conn.Flush() 94 | } 95 | 96 | // Ping sends a PING to the server with the specified data. 97 | // 98 | // The connection must be subscribed to at least one channel or pattern when 99 | // calling this method. 100 | func (c PubSubConn) Ping(data string) error { 101 | c.Conn.Send("PING", data) 102 | return c.Conn.Flush() 103 | } 104 | 105 | // Receive returns a pushed message as a Subscription, Message, PMessage, Pong 106 | // or error. The return value is intended to be used directly in a type switch 107 | // as illustrated in the PubSubConn example. 108 | func (c PubSubConn) Receive() interface{} { 109 | return c.receiveInternal(c.Conn.Receive()) 110 | } 111 | 112 | // ReceiveWithTimeout is like Receive, but it allows the application to 113 | // override the connection's default timeout. 114 | func (c PubSubConn) ReceiveWithTimeout(timeout time.Duration) interface{} { 115 | return c.receiveInternal(ReceiveWithTimeout(c.Conn, timeout)) 116 | } 117 | 118 | func (c PubSubConn) receiveInternal(replyArg interface{}, errArg error) interface{} { 119 | reply, err := Values(replyArg, errArg) 120 | if err != nil { 121 | return err 122 | } 123 | 124 | var kind string 125 | reply, err = Scan(reply, &kind) 126 | if err != nil { 127 | return err 128 | } 129 | 130 | switch kind { 131 | case "message": 132 | var m Message 133 | if _, err := Scan(reply, &m.Channel, &m.Data); err != nil { 134 | return err 135 | } 136 | return m 137 | case "pmessage": 138 | var pm PMessage 139 | if _, err := Scan(reply, &pm.Pattern, &pm.Channel, &pm.Data); err != nil { 140 | return err 141 | } 142 | return pm 143 | case "subscribe", "psubscribe", "unsubscribe", "punsubscribe": 144 | s := Subscription{Kind: kind} 145 | if _, err := Scan(reply, &s.Channel, &s.Count); err != nil { 146 | return err 147 | } 148 | return s 149 | case "pong": 150 | var p Pong 151 | if _, err := Scan(reply, &p.Data); err != nil { 152 | return err 153 | } 154 | return p 155 | } 156 | return errors.New("redigo: unknown pubsub notification") 157 | } 158 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/redis.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "errors" 19 | "time" 20 | ) 21 | 22 | // Error represents an error returned in a command reply. 23 | type Error string 24 | 25 | func (err Error) Error() string { return string(err) } 26 | 27 | // Conn represents a connection to a Redis server. 28 | type Conn interface { 29 | // Close closes the connection. 30 | Close() error 31 | 32 | // Err returns a non-nil value when the connection is not usable. 33 | Err() error 34 | 35 | // Do sends a command to the server and returns the received reply. 36 | Do(commandName string, args ...interface{}) (reply interface{}, err error) 37 | 38 | // Send writes the command to the client's output buffer. 39 | Send(commandName string, args ...interface{}) error 40 | 41 | // Flush flushes the output buffer to the Redis server. 42 | Flush() error 43 | 44 | // Receive receives a single reply from the Redis server 45 | Receive() (reply interface{}, err error) 46 | } 47 | 48 | // Argument is the interface implemented by an object which wants to control how 49 | // the object is converted to Redis bulk strings. 50 | type Argument interface { 51 | // RedisArg returns a value to be encoded as a bulk string per the 52 | // conversions listed in the section 'Executing Commands'. 53 | // Implementations should typically return a []byte or string. 54 | RedisArg() interface{} 55 | } 56 | 57 | // Scanner is implemented by an object which wants to control its value is 58 | // interpreted when read from Redis. 59 | type Scanner interface { 60 | // RedisScan assigns a value from a Redis value. The argument src is one of 61 | // the reply types listed in the section `Executing Commands`. 62 | // 63 | // An error should be returned if the value cannot be stored without 64 | // loss of information. 65 | RedisScan(src interface{}) error 66 | } 67 | 68 | // ConnWithTimeout is an optional interface that allows the caller to override 69 | // a connection's default read timeout. This interface is useful for executing 70 | // the BLPOP, BRPOP, BRPOPLPUSH, XREAD and other commands that block at the 71 | // server. 72 | // 73 | // A connection's default read timeout is set with the DialReadTimeout dial 74 | // option. Applications should rely on the default timeout for commands that do 75 | // not block at the server. 76 | // 77 | // All of the Conn implementations in this package satisfy the ConnWithTimeout 78 | // interface. 79 | // 80 | // Use the DoWithTimeout and ReceiveWithTimeout helper functions to simplify 81 | // use of this interface. 82 | type ConnWithTimeout interface { 83 | Conn 84 | 85 | // Do sends a command to the server and returns the received reply. 86 | // The timeout overrides the read timeout set when dialing the 87 | // connection. 88 | DoWithTimeout(timeout time.Duration, commandName string, args ...interface{}) (reply interface{}, err error) 89 | 90 | // Receive receives a single reply from the Redis server. The timeout 91 | // overrides the read timeout set when dialing the connection. 92 | ReceiveWithTimeout(timeout time.Duration) (reply interface{}, err error) 93 | } 94 | 95 | var errTimeoutNotSupported = errors.New("redis: connection does not support ConnWithTimeout") 96 | 97 | // DoWithTimeout executes a Redis command with the specified read timeout. If 98 | // the connection does not satisfy the ConnWithTimeout interface, then an error 99 | // is returned. 100 | func DoWithTimeout(c Conn, timeout time.Duration, cmd string, args ...interface{}) (interface{}, error) { 101 | cwt, ok := c.(ConnWithTimeout) 102 | if !ok { 103 | return nil, errTimeoutNotSupported 104 | } 105 | return cwt.DoWithTimeout(timeout, cmd, args...) 106 | } 107 | 108 | // ReceiveWithTimeout receives a reply with the specified read timeout. If the 109 | // connection does not satisfy the ConnWithTimeout interface, then an error is 110 | // returned. 111 | func ReceiveWithTimeout(c Conn, timeout time.Duration) (interface{}, error) { 112 | cwt, ok := c.(ConnWithTimeout) 113 | if !ok { 114 | return nil, errTimeoutNotSupported 115 | } 116 | return cwt.ReceiveWithTimeout(timeout) 117 | } 118 | -------------------------------------------------------------------------------- /vendor/github.com/garyburd/redigo/redis/script.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Gary Burd 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "crypto/sha1" 19 | "encoding/hex" 20 | "io" 21 | "strings" 22 | ) 23 | 24 | // Script encapsulates the source, hash and key count for a Lua script. See 25 | // http://redis.io/commands/eval for information on scripts in Redis. 26 | type Script struct { 27 | keyCount int 28 | src string 29 | hash string 30 | } 31 | 32 | // NewScript returns a new script object. If keyCount is greater than or equal 33 | // to zero, then the count is automatically inserted in the EVAL command 34 | // argument list. If keyCount is less than zero, then the application supplies 35 | // the count as the first value in the keysAndArgs argument to the Do, Send and 36 | // SendHash methods. 37 | func NewScript(keyCount int, src string) *Script { 38 | h := sha1.New() 39 | io.WriteString(h, src) 40 | return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))} 41 | } 42 | 43 | func (s *Script) args(spec string, keysAndArgs []interface{}) []interface{} { 44 | var args []interface{} 45 | if s.keyCount < 0 { 46 | args = make([]interface{}, 1+len(keysAndArgs)) 47 | args[0] = spec 48 | copy(args[1:], keysAndArgs) 49 | } else { 50 | args = make([]interface{}, 2+len(keysAndArgs)) 51 | args[0] = spec 52 | args[1] = s.keyCount 53 | copy(args[2:], keysAndArgs) 54 | } 55 | return args 56 | } 57 | 58 | // Hash returns the script hash. 59 | func (s *Script) Hash() string { 60 | return s.hash 61 | } 62 | 63 | // Do evaluates the script. Under the covers, Do optimistically evaluates the 64 | // script using the EVALSHA command. If the command fails because the script is 65 | // not loaded, then Do evaluates the script using the EVAL command (thus 66 | // causing the script to load). 67 | func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) { 68 | v, err := c.Do("EVALSHA", s.args(s.hash, keysAndArgs)...) 69 | if e, ok := err.(Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") { 70 | v, err = c.Do("EVAL", s.args(s.src, keysAndArgs)...) 71 | } 72 | return v, err 73 | } 74 | 75 | // SendHash evaluates the script without waiting for the reply. The script is 76 | // evaluated with the EVALSHA command. The application must ensure that the 77 | // script is loaded by a previous call to Send, Do or Load methods. 78 | func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error { 79 | return c.Send("EVALSHA", s.args(s.hash, keysAndArgs)...) 80 | } 81 | 82 | // Send evaluates the script without waiting for the reply. 83 | func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error { 84 | return c.Send("EVAL", s.args(s.src, keysAndArgs)...) 85 | } 86 | 87 | // Load loads the script without evaluating it. 88 | func (s *Script) Load(c Conn) error { 89 | _, err := c.Do("SCRIPT", "LOAD", s.src) 90 | return err 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/configor/README.md: -------------------------------------------------------------------------------- 1 | # Configor 2 | 3 | Golang Configuration tool that support YAML, JSON, TOML, Shell Environment 4 | 5 | [![wercker status](https://app.wercker.com/status/9ebd3684ff8998501af5aac38a79a380/s/master "wercker status")](https://app.wercker.com/project/byKey/9ebd3684ff8998501af5aac38a79a380) 6 | 7 | ## Usage 8 | 9 | ```go 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "github.com/jinzhu/configor" 15 | ) 16 | 17 | var Config = struct { 18 | APPName string `default:"app name"` 19 | 20 | DB struct { 21 | Name string 22 | User string `default:"root"` 23 | Password string `required:"true" env:"DBPassword"` 24 | Port uint `default:"3306"` 25 | } 26 | 27 | Contacts []struct { 28 | Name string 29 | Email string `required:"true"` 30 | } 31 | }{} 32 | 33 | func main() { 34 | configor.Load(&Config, "config.yml") 35 | fmt.Printf("config: %#v", Config) 36 | } 37 | ``` 38 | 39 | With configuration file *config.yml*: 40 | 41 | ```yaml 42 | appname: test 43 | 44 | db: 45 | name: test 46 | user: test 47 | password: test 48 | port: 1234 49 | 50 | contacts: 51 | - name: i test 52 | email: test@test.com 53 | ``` 54 | 55 | ## Debug Mode & Verbose Mode 56 | 57 | Debug/Verbose mode is helpful when debuging your application, `debug mode` will let you know how `configor` loaded your configurations, like from which file, shell env, `verbose mode` will tell you even more, like those shell environments `configor` tried to load. 58 | 59 | ```go 60 | // Enable debug mode or set env `CONFIGOR_DEBUG_MODE` to true when running your application 61 | configor.New(&configor.Config{Debug: true}).Load(&Config, "config.json") 62 | 63 | // Enable verbose mode or set env `CONFIGOR_VERBOSE_MODE` to true when running your application 64 | configor.New(&configor.Config{Verbose: true}).Load(&Config, "config.json") 65 | ``` 66 | 67 | # Advanced Usage 68 | 69 | * Load mutiple configurations 70 | 71 | ```go 72 | // Earlier configurations have higher priority 73 | configor.Load(&Config, "application.yml", "database.json") 74 | ``` 75 | 76 | * Return error on unmatched keys 77 | 78 | Return an error on finding keys in the config file that do not match any fields in the config struct. 79 | In the example below, an error will be returned if config.toml contains keys that do not match any fields in the ConfigStruct struct. 80 | If ErrorOnUnmatchedKeys is not set, it defaults to false. 81 | 82 | Note that for json files, setting ErrorOnUnmatchedKeys to true will have an effect only if using go 1.10 or later. 83 | 84 | ```go 85 | err := configor.New(&configor.Config{ErrorOnUnmatchedKeys: true}).Load(&ConfigStruct, "config.toml") 86 | ``` 87 | 88 | * Load configuration by environment 89 | 90 | Use `CONFIGOR_ENV` to set environment, if `CONFIGOR_ENV` not set, environment will be `development` by default, and it will be `test` when running tests with `go test` 91 | 92 | ```go 93 | // config.go 94 | configor.Load(&Config, "config.json") 95 | 96 | $ go run config.go 97 | // Will load `config.json`, `config.development.json` if it exists 98 | // `config.development.json` will overwrite `config.json`'s configuration 99 | // You could use this to share same configuration across different environments 100 | 101 | $ CONFIGOR_ENV=production go run config.go 102 | // Will load `config.json`, `config.production.json` if it exists 103 | // `config.production.json` will overwrite `config.json`'s configuration 104 | 105 | $ go test 106 | // Will load `config.json`, `config.test.json` if it exists 107 | // `config.test.json` will overwrite `config.json`'s configuration 108 | 109 | $ CONFIGOR_ENV=production go test 110 | // Will load `config.json`, `config.production.json` if it exists 111 | // `config.production.json` will overwrite `config.json`'s configuration 112 | ``` 113 | 114 | ```go 115 | // Set environment by config 116 | configor.New(&configor.Config{Environment: "production"}).Load(&Config, "config.json") 117 | ``` 118 | 119 | * Example Configuration 120 | 121 | ```go 122 | // config.go 123 | configor.Load(&Config, "config.yml") 124 | 125 | $ go run config.go 126 | // Will load `config.example.yml` automatically if `config.yml` not found and print warning message 127 | ``` 128 | 129 | * Load From Shell Environment 130 | 131 | ```go 132 | $ CONFIGOR_APPNAME="hello world" CONFIGOR_DB_NAME="hello world" go run config.go 133 | // Load configuration from shell environment, it's name is {{prefix}}_FieldName 134 | ``` 135 | 136 | ```go 137 | // You could overwrite the prefix with environment CONFIGOR_ENV_PREFIX, for example: 138 | $ CONFIGOR_ENV_PREFIX="WEB" WEB_APPNAME="hello world" WEB_DB_NAME="hello world" go run config.go 139 | 140 | // Set prefix by config 141 | configor.New(&configor.Config{ENVPrefix: "WEB"}).Load(&Config, "config.json") 142 | ``` 143 | 144 | * Anonymous Struct 145 | 146 | Add the `anonymous:"true"` tag to an anonymous, embedded struct to NOT include the struct name in the environment 147 | variable of any contained fields. For example: 148 | 149 | ```go 150 | type Details struct { 151 | Description string 152 | } 153 | 154 | type Config struct { 155 | Details `anonymous:"true"` 156 | } 157 | ``` 158 | 159 | With the `anonymous:"true"` tag specified, the environment variable for the `Description` field is `CONFIGOR_DESCRIPTION`. 160 | Without the `anonymous:"true"`tag specified, then environment variable would include the embedded struct name and be `CONFIGOR_DETAILS_DESCRIPTION`. 161 | 162 | * With flags 163 | 164 | ```go 165 | func main() { 166 | config := flag.String("file", "config.yml", "configuration file") 167 | flag.StringVar(&Config.APPName, "name", "", "app name") 168 | flag.StringVar(&Config.DB.Name, "db-name", "", "database name") 169 | flag.StringVar(&Config.DB.User, "db-user", "root", "database user") 170 | flag.Parse() 171 | 172 | os.Setenv("CONFIGOR_ENV_PREFIX", "-") 173 | configor.Load(&Config, *config) 174 | // configor.Load(&Config) // only load configurations from shell env & flag 175 | } 176 | ``` 177 | 178 | ## Contributing 179 | 180 | You can help to make the project better, check out [http://gorm.io/contribute.html](http://gorm.io/contribute.html) for things you can do. 181 | 182 | ## Author 183 | 184 | **jinzhu** 185 | 186 | * 187 | * 188 | * 189 | 190 | ## License 191 | 192 | Released under the MIT License 193 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/configor/configor.go: -------------------------------------------------------------------------------- 1 | package configor 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "regexp" 7 | ) 8 | 9 | type Configor struct { 10 | *Config 11 | } 12 | 13 | type Config struct { 14 | Environment string 15 | ENVPrefix string 16 | Debug bool 17 | Verbose bool 18 | 19 | // In case of json files, this field will be used only when compiled with 20 | // go 1.10 or later. 21 | // This field will be ignored when compiled with go versions lower than 1.10. 22 | ErrorOnUnmatchedKeys bool 23 | } 24 | 25 | // New initialize a Configor 26 | func New(config *Config) *Configor { 27 | if config == nil { 28 | config = &Config{} 29 | } 30 | 31 | if os.Getenv("CONFIGOR_DEBUG_MODE") != "" { 32 | config.Debug = true 33 | } 34 | 35 | if os.Getenv("CONFIGOR_VERBOSE_MODE") != "" { 36 | config.Verbose = true 37 | } 38 | 39 | return &Configor{Config: config} 40 | } 41 | 42 | var testRegexp = regexp.MustCompile("_test|(\\.test$)") 43 | 44 | // GetEnvironment get environment 45 | func (configor *Configor) GetEnvironment() string { 46 | if configor.Environment == "" { 47 | if env := os.Getenv("CONFIGOR_ENV"); env != "" { 48 | return env 49 | } 50 | 51 | if testRegexp.MatchString(os.Args[0]) { 52 | return "test" 53 | } 54 | 55 | return "development" 56 | } 57 | return configor.Environment 58 | } 59 | 60 | // GetErrorOnUnmatchedKeys returns a boolean indicating if an error should be 61 | // thrown if there are keys in the config file that do not correspond to the 62 | // config struct 63 | func (configor *Configor) GetErrorOnUnmatchedKeys() bool { 64 | return configor.ErrorOnUnmatchedKeys 65 | } 66 | 67 | // Load will unmarshal configurations to struct from files that you provide 68 | func (configor *Configor) Load(config interface{}, files ...string) error { 69 | defer func() { 70 | if configor.Config.Debug || configor.Config.Verbose { 71 | fmt.Printf("Configuration:\n %#v\n", config) 72 | } 73 | }() 74 | 75 | for _, file := range configor.getConfigurationFiles(files...) { 76 | if configor.Config.Debug || configor.Config.Verbose { 77 | fmt.Printf("Loading configurations from file '%v'...\n", file) 78 | } 79 | if err := processFile(config, file, configor.GetErrorOnUnmatchedKeys()); err != nil { 80 | return err 81 | } 82 | } 83 | 84 | prefix := configor.getENVPrefix(config) 85 | if prefix == "-" { 86 | return configor.processTags(config) 87 | } 88 | return configor.processTags(config, prefix) 89 | } 90 | 91 | // ENV return environment 92 | func ENV() string { 93 | return New(nil).GetEnvironment() 94 | } 95 | 96 | // Load will unmarshal configurations to struct from files that you provide 97 | func Load(config interface{}, files ...string) error { 98 | return New(nil).Load(config, files...) 99 | } 100 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/configor/unmarshal_json_1_10.go: -------------------------------------------------------------------------------- 1 | // +build go1.10 2 | 3 | package configor 4 | 5 | import ( 6 | "encoding/json" 7 | "io" 8 | "strings" 9 | ) 10 | 11 | // unmarshalJSON unmarshals the given data into the config interface. 12 | // If the errorOnUnmatchedKeys boolean is true, an error will be returned if there 13 | // are keys in the data that do not match fields in the config interface. 14 | func unmarshalJSON(data []byte, config interface{}, errorOnUnmatchedKeys bool) error { 15 | reader := strings.NewReader(string(data)) 16 | decoder := json.NewDecoder(reader) 17 | 18 | if errorOnUnmatchedKeys { 19 | decoder.DisallowUnknownFields() 20 | } 21 | 22 | err := decoder.Decode(config) 23 | if err != nil && err != io.EOF { 24 | return err 25 | } 26 | return nil 27 | 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/configor/unmarshal_json_1_9.go: -------------------------------------------------------------------------------- 1 | // +build !go1.10 2 | 3 | package configor 4 | 5 | import ( 6 | "encoding/json" 7 | ) 8 | 9 | // unmarshalJSON unmarshals the given data into the config interface. 10 | // The errorOnUnmatchedKeys boolean is ignored since the json library only has 11 | // support for that feature from go 1.10 onwards. 12 | // If there are any keys in the data that do not match fields in the config 13 | // interface, they will be silently ignored. 14 | func unmarshalJSON(data []byte, config interface{}, errorOnUnmatchedKeys bool) error { 15 | 16 | return json.Unmarshal(data, &config) 17 | 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/configor/utils.go: -------------------------------------------------------------------------------- 1 | package configor 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "path" 9 | "reflect" 10 | "strings" 11 | 12 | "github.com/BurntSushi/toml" 13 | yaml "gopkg.in/yaml.v2" 14 | ) 15 | 16 | // UnmatchedTomlKeysError errors are returned by the Load function when 17 | // ErrorOnUnmatchedKeys is set to true and there are unmatched keys in the input 18 | // toml config file. The string returned by Error() contains the names of the 19 | // missing keys. 20 | type UnmatchedTomlKeysError struct { 21 | Keys []toml.Key 22 | } 23 | 24 | func (e *UnmatchedTomlKeysError) Error() string { 25 | return fmt.Sprintf("There are keys in the config file that do not match any field in the given struct: %v", e.Keys) 26 | } 27 | 28 | func (configor *Configor) getENVPrefix(config interface{}) string { 29 | if configor.Config.ENVPrefix == "" { 30 | if prefix := os.Getenv("CONFIGOR_ENV_PREFIX"); prefix != "" { 31 | return prefix 32 | } 33 | return "Configor" 34 | } 35 | return configor.Config.ENVPrefix 36 | } 37 | 38 | func getConfigurationFileWithENVPrefix(file, env string) (string, error) { 39 | var ( 40 | envFile string 41 | extname = path.Ext(file) 42 | ) 43 | 44 | if extname == "" { 45 | envFile = fmt.Sprintf("%v.%v", file, env) 46 | } else { 47 | envFile = fmt.Sprintf("%v.%v%v", strings.TrimSuffix(file, extname), env, extname) 48 | } 49 | 50 | if fileInfo, err := os.Stat(envFile); err == nil && fileInfo.Mode().IsRegular() { 51 | return envFile, nil 52 | } 53 | return "", fmt.Errorf("failed to find file %v", file) 54 | } 55 | 56 | func (configor *Configor) getConfigurationFiles(files ...string) []string { 57 | var results []string 58 | 59 | if configor.Config.Debug || configor.Config.Verbose { 60 | fmt.Printf("Current environment: '%v'\n", configor.GetEnvironment()) 61 | } 62 | 63 | for i := len(files) - 1; i >= 0; i-- { 64 | foundFile := false 65 | file := files[i] 66 | 67 | // check configuration 68 | if fileInfo, err := os.Stat(file); err == nil && fileInfo.Mode().IsRegular() { 69 | foundFile = true 70 | results = append(results, file) 71 | } 72 | 73 | // check configuration with env 74 | if file, err := getConfigurationFileWithENVPrefix(file, configor.GetEnvironment()); err == nil { 75 | foundFile = true 76 | results = append(results, file) 77 | } 78 | 79 | // check example configuration 80 | if !foundFile { 81 | if example, err := getConfigurationFileWithENVPrefix(file, "example"); err == nil { 82 | fmt.Printf("Failed to find configuration %v, using example file %v\n", file, example) 83 | results = append(results, example) 84 | } else { 85 | fmt.Printf("Failed to find configuration %v\n", file) 86 | } 87 | } 88 | } 89 | return results 90 | } 91 | 92 | func processFile(config interface{}, file string, errorOnUnmatchedKeys bool) error { 93 | data, err := ioutil.ReadFile(file) 94 | if err != nil { 95 | return err 96 | } 97 | 98 | switch { 99 | case strings.HasSuffix(file, ".yaml") || strings.HasSuffix(file, ".yml"): 100 | if errorOnUnmatchedKeys { 101 | return yaml.UnmarshalStrict(data, config) 102 | } 103 | return yaml.Unmarshal(data, config) 104 | case strings.HasSuffix(file, ".toml"): 105 | return unmarshalToml(data, config, errorOnUnmatchedKeys) 106 | case strings.HasSuffix(file, ".json"): 107 | return unmarshalJSON(data, config, errorOnUnmatchedKeys) 108 | default: 109 | 110 | if err := unmarshalToml(data, config, errorOnUnmatchedKeys); err == nil { 111 | return nil 112 | } else if errUnmatchedKeys, ok := err.(*UnmatchedTomlKeysError); ok { 113 | return errUnmatchedKeys 114 | } 115 | 116 | if err := unmarshalJSON(data, config, errorOnUnmatchedKeys); err == nil { 117 | return nil 118 | } else if strings.Contains(err.Error(), "json: unknown field") { 119 | return err 120 | } 121 | 122 | var yamlError error 123 | if errorOnUnmatchedKeys { 124 | yamlError = yaml.UnmarshalStrict(data, config) 125 | } else { 126 | yamlError = yaml.Unmarshal(data, config) 127 | } 128 | 129 | if yamlError == nil { 130 | return nil 131 | } else if yErr, ok := yamlError.(*yaml.TypeError); ok { 132 | return yErr 133 | } 134 | 135 | return errors.New("failed to decode config") 136 | } 137 | } 138 | 139 | // GetStringTomlKeys returns a string array of the names of the keys that are passed in as args 140 | func GetStringTomlKeys(list []toml.Key) []string { 141 | arr := make([]string, len(list)) 142 | 143 | for index, key := range list { 144 | arr[index] = key.String() 145 | } 146 | return arr 147 | } 148 | 149 | func unmarshalToml(data []byte, config interface{}, errorOnUnmatchedKeys bool) error { 150 | metadata, err := toml.Decode(string(data), config) 151 | if err == nil && len(metadata.Undecoded()) > 0 && errorOnUnmatchedKeys { 152 | return &UnmatchedTomlKeysError{Keys: metadata.Undecoded()} 153 | } 154 | return err 155 | } 156 | 157 | func getPrefixForStruct(prefixes []string, fieldStruct *reflect.StructField) []string { 158 | if fieldStruct.Anonymous && fieldStruct.Tag.Get("anonymous") == "true" { 159 | return prefixes 160 | } 161 | return append(prefixes, fieldStruct.Name) 162 | } 163 | 164 | func (configor *Configor) processTags(config interface{}, prefixes ...string) error { 165 | configValue := reflect.Indirect(reflect.ValueOf(config)) 166 | if configValue.Kind() != reflect.Struct { 167 | return errors.New("invalid config, should be struct") 168 | } 169 | 170 | configType := configValue.Type() 171 | for i := 0; i < configType.NumField(); i++ { 172 | var ( 173 | envNames []string 174 | fieldStruct = configType.Field(i) 175 | field = configValue.Field(i) 176 | envName = fieldStruct.Tag.Get("env") // read configuration from shell env 177 | ) 178 | 179 | if !field.CanAddr() || !field.CanInterface() { 180 | continue 181 | } 182 | 183 | if envName == "" { 184 | envNames = append(envNames, strings.Join(append(prefixes, fieldStruct.Name), "_")) // Configor_DB_Name 185 | envNames = append(envNames, strings.ToUpper(strings.Join(append(prefixes, fieldStruct.Name), "_"))) // CONFIGOR_DB_NAME 186 | } else { 187 | envNames = []string{envName} 188 | } 189 | 190 | if configor.Config.Verbose { 191 | fmt.Printf("Trying to load struct `%v`'s field `%v` from env %v\n", configType.Name(), fieldStruct.Name, strings.Join(envNames, ", ")) 192 | } 193 | 194 | // Load From Shell ENV 195 | for _, env := range envNames { 196 | if value := os.Getenv(env); value != "" { 197 | if configor.Config.Debug || configor.Config.Verbose { 198 | fmt.Printf("Loading configuration for struct `%v`'s field `%v` from env %v...\n", configType.Name(), fieldStruct.Name, env) 199 | } 200 | if err := yaml.Unmarshal([]byte(value), field.Addr().Interface()); err != nil { 201 | return err 202 | } 203 | break 204 | } 205 | } 206 | 207 | if isBlank := reflect.DeepEqual(field.Interface(), reflect.Zero(field.Type()).Interface()); isBlank { 208 | // Set default configuration if blank 209 | if value := fieldStruct.Tag.Get("default"); value != "" { 210 | if err := yaml.Unmarshal([]byte(value), field.Addr().Interface()); err != nil { 211 | return err 212 | } 213 | } else if fieldStruct.Tag.Get("required") == "true" { 214 | // return error if it is required but blank 215 | return errors.New(fieldStruct.Name + " is required, but blank") 216 | } 217 | } 218 | 219 | for field.Kind() == reflect.Ptr { 220 | field = field.Elem() 221 | } 222 | 223 | if field.Kind() == reflect.Struct { 224 | if err := configor.processTags(field.Addr().Interface(), getPrefixForStruct(prefixes, &fieldStruct)...); err != nil { 225 | return err 226 | } 227 | } 228 | 229 | if field.Kind() == reflect.Slice { 230 | for i := 0; i < field.Len(); i++ { 231 | if reflect.Indirect(field.Index(i)).Kind() == reflect.Struct { 232 | if err := configor.processTags(field.Index(i).Addr().Interface(), append(getPrefixForStruct(prefixes, &fieldStruct), fmt.Sprint(i))...); err != nil { 233 | return err 234 | } 235 | } 236 | } 237 | } 238 | } 239 | return nil 240 | } 241 | -------------------------------------------------------------------------------- /vendor/github.com/jinzhu/configor/wercker.yml: -------------------------------------------------------------------------------- 1 | box: golang 2 | 3 | build: 4 | steps: 5 | - setup-go-workspace 6 | 7 | # Gets the dependencies 8 | - script: 9 | name: go get 10 | code: | 11 | go get 12 | 13 | # Build the project 14 | - script: 15 | name: go build 16 | code: | 17 | go build ./... 18 | 19 | # Test the project 20 | - script: 21 | name: go test 22 | code: | 23 | go test ./... 24 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of gocui authors for copyright purposes. 2 | 3 | # Names should be added to this file as 4 | # Name or Organization contribution 5 | # Contribution 6 | # The email address is not required for organizations. 7 | 8 | Roi Martin 9 | Main developer 10 | 11 | Ryan Sullivan 12 | Toggleable view frames 13 | 14 | Matthieu Rakotojaona 15 | Wrapped views 16 | 17 | Harry Lawrence 18 | Basic mouse support 19 | 20 | Danny Tylman 21 | Masked views 22 | 23 | Frederik Deweerdt 24 | Colored fonts 25 | 26 | Henri Koski 27 | Custom current view color 28 | 29 | Dustin Willis Webber 30 | 256-colors output mode support 31 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 The gocui Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright 8 | notice, this list of conditions and the following disclaimer in the 9 | documentation and/or other materials provided with the distribution. 10 | * Neither the name of the gocui Authors nor the names of its contributors 11 | may be used to endorse or promote products derived from this software 12 | without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/README.md: -------------------------------------------------------------------------------- 1 | # GOCUI - Go Console User Interface 2 | 3 | [![GoDoc](https://godoc.org/github.com/jroimartin/gocui?status.svg)](https://godoc.org/github.com/jroimartin/gocui) 4 | 5 | Minimalist Go package aimed at creating Console User Interfaces. 6 | 7 | ## Features 8 | 9 | * Minimalist API. 10 | * Views (the "windows" in the GUI) implement the interface io.ReadWriter. 11 | * Support for overlapping views. 12 | * The GUI can be modified at runtime (concurrent-safe). 13 | * Global and view-level keybindings. 14 | * Mouse support. 15 | * Colored text. 16 | * Customizable edition mode. 17 | * Easy to build reusable widgets, complex layouts... 18 | 19 | ## Installation 20 | 21 | Execute: 22 | 23 | ``` 24 | $ go get github.com/jroimartin/gocui 25 | ``` 26 | 27 | ## Documentation 28 | 29 | Execute: 30 | 31 | ``` 32 | $ go doc github.com/jroimartin/gocui 33 | ``` 34 | 35 | Or visit [godoc.org](https://godoc.org/github.com/jroimartin/gocui) to read it 36 | online. 37 | 38 | ## Example 39 | 40 | ```go 41 | package main 42 | 43 | import ( 44 | "fmt" 45 | "log" 46 | 47 | "github.com/jroimartin/gocui" 48 | ) 49 | 50 | func main() { 51 | g, err := gocui.NewGui(gocui.OutputNormal) 52 | if err != nil { 53 | log.Panicln(err) 54 | } 55 | defer g.Close() 56 | 57 | g.SetManagerFunc(layout) 58 | 59 | if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { 60 | log.Panicln(err) 61 | } 62 | 63 | if err := g.MainLoop(); err != nil && err != gocui.ErrQuit { 64 | log.Panicln(err) 65 | } 66 | } 67 | 68 | func layout(g *gocui.Gui) error { 69 | maxX, maxY := g.Size() 70 | if v, err := g.SetView("hello", maxX/2-7, maxY/2, maxX/2+7, maxY/2+2); err != nil { 71 | if err != gocui.ErrUnknownView { 72 | return err 73 | } 74 | fmt.Fprintln(v, "Hello world!") 75 | } 76 | return nil 77 | } 78 | 79 | func quit(g *gocui.Gui, v *gocui.View) error { 80 | return gocui.ErrQuit 81 | } 82 | ``` 83 | 84 | ## Screenshots 85 | 86 | ![r2cui](https://cloud.githubusercontent.com/assets/1223476/19418932/63645052-93ce-11e6-867c-da5e97e37237.png) 87 | 88 | ![_examples/demo.go](https://cloud.githubusercontent.com/assets/1223476/5992750/720b84f0-aa36-11e4-88ec-296fa3247b52.png) 89 | 90 | ![_examples/dynamic.go](https://cloud.githubusercontent.com/assets/1223476/5992751/76ad5cc2-aa36-11e4-8204-6a90269db827.png) 91 | 92 | ## Projects using gocui 93 | 94 | * [komanda-cli](https://github.com/mephux/komanda-cli): IRC Client For Developers. 95 | * [vuls](https://github.com/future-architect/vuls): Agentless vulnerability scanner for Linux/FreeBSD. 96 | * [wuzz](https://github.com/asciimoo/wuzz): Interactive cli tool for HTTP inspection. 97 | * [httplab](https://github.com/gchaincl/httplab): Interactive web server. 98 | * [domainr](https://github.com/MichaelThessel/domainr): Tool that checks the availability of domains based on keywords. 99 | * [gotime](https://github.com/nanohard/gotime): Time tracker for projects and tasks. 100 | * [claws](https://github.com/thehowl/claws): Interactive command line client for testing websockets. 101 | * [terminews](http://github.com/antavelos/terminews): Terminal based RSS reader. 102 | * [diagram](https://github.com/esimov/diagram): Tool to convert ascii arts into hand drawn diagrams. 103 | * [pody](https://github.com/JulienBreux/pody): CLI app to manage Pods in a Kubernetes cluster. 104 | * [kubexp](https://github.com/alitari/kubexp): Kubernetes client. 105 | * [kcli](https://github.com/cswank/kcli): Tool for inspecting kafka topics/partitions/messages. 106 | * [fac](https://github.com/mkchoi212/fac): git merge conflict resolver 107 | * [jsonui](https://github.com/gulyasm/jsonui): Interactive JSON explorer for your terminal. 108 | * [cointop](https://github.com/miguelmota/cointop): Interactive terminal based UI application for tracking cryptocurrencies. 109 | 110 | Note: if your project is not listed here, let us know! :) 111 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/attribute.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The gocui Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gocui 6 | 7 | import "github.com/nsf/termbox-go" 8 | 9 | // Attribute represents a terminal attribute, like color, font style, etc. They 10 | // can be combined using bitwise OR (|). Note that it is not possible to 11 | // combine multiple color attributes. 12 | type Attribute termbox.Attribute 13 | 14 | // Color attributes. 15 | const ( 16 | ColorDefault Attribute = Attribute(termbox.ColorDefault) 17 | ColorBlack = Attribute(termbox.ColorBlack) 18 | ColorRed = Attribute(termbox.ColorRed) 19 | ColorGreen = Attribute(termbox.ColorGreen) 20 | ColorYellow = Attribute(termbox.ColorYellow) 21 | ColorBlue = Attribute(termbox.ColorBlue) 22 | ColorMagenta = Attribute(termbox.ColorMagenta) 23 | ColorCyan = Attribute(termbox.ColorCyan) 24 | ColorWhite = Attribute(termbox.ColorWhite) 25 | ) 26 | 27 | // Text style attributes. 28 | const ( 29 | AttrBold Attribute = Attribute(termbox.AttrBold) 30 | AttrUnderline = Attribute(termbox.AttrUnderline) 31 | AttrReverse = Attribute(termbox.AttrReverse) 32 | ) 33 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The gocui Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package gocui allows to create console user interfaces. 7 | 8 | Create a new GUI: 9 | 10 | g, err := gocui.NewGui(gocui.OutputNormal) 11 | if err != nil { 12 | // handle error 13 | } 14 | defer g.Close() 15 | 16 | // Set GUI managers and key bindings 17 | // ... 18 | 19 | if err := g.MainLoop(); err != nil && err != gocui.ErrQuit { 20 | // handle error 21 | } 22 | 23 | Set GUI managers: 24 | 25 | g.SetManager(mgr1, mgr2) 26 | 27 | Managers are in charge of GUI's layout and can be used to build widgets. On 28 | each iteration of the GUI's main loop, the Layout function of each configured 29 | manager is executed. Managers are used to set-up and update the application's 30 | main views, being possible to freely change them during execution. Also, it is 31 | important to mention that a main loop iteration is executed on each reported 32 | event (key-press, mouse event, window resize, etc). 33 | 34 | GUIs are composed by Views, you can think of it as buffers. Views implement the 35 | io.ReadWriter interface, so you can just write to them if you want to modify 36 | their content. The same is valid for reading. 37 | 38 | Create and initialize a view with absolute coordinates: 39 | 40 | if v, err := g.SetView("viewname", 2, 2, 22, 7); err != nil { 41 | if err != gocui.ErrUnknownView { 42 | // handle error 43 | } 44 | fmt.Fprintln(v, "This is a new view") 45 | // ... 46 | } 47 | 48 | Views can also be created using relative coordinates: 49 | 50 | maxX, maxY := g.Size() 51 | if v, err := g.SetView("viewname", maxX/2-30, maxY/2, maxX/2+30, maxY/2+2); err != nil { 52 | // ... 53 | } 54 | 55 | Configure keybindings: 56 | 57 | if err := g.SetKeybinding("viewname", gocui.KeyEnter, gocui.ModNone, fcn); err != nil { 58 | // handle error 59 | } 60 | 61 | gocui implements full mouse support that can be enabled with: 62 | 63 | g.Mouse = true 64 | 65 | Mouse events are handled like any other keybinding: 66 | 67 | if err := g.SetKeybinding("viewname", gocui.MouseLeft, gocui.ModNone, fcn); err != nil { 68 | // handle error 69 | } 70 | 71 | IMPORTANT: Views can only be created, destroyed or updated in three ways: from 72 | the Layout function within managers, from keybinding callbacks or via 73 | *Gui.Update(). The reason for this is that it allows gocui to be 74 | concurrent-safe. So, if you want to update your GUI from a goroutine, you must 75 | use *Gui.Update(). For example: 76 | 77 | g.Update(func(g *gocui.Gui) error { 78 | v, err := g.View("viewname") 79 | if err != nil { 80 | // handle error 81 | } 82 | v.Clear() 83 | fmt.Fprintln(v, "Writing from different goroutines") 84 | return nil 85 | }) 86 | 87 | By default, gocui provides a basic edition mode. This mode can be extended 88 | and customized creating a new Editor and assigning it to *View.Editor: 89 | 90 | type Editor interface { 91 | Edit(v *View, key Key, ch rune, mod Modifier) 92 | } 93 | 94 | DefaultEditor can be taken as example to create your own custom Editor: 95 | 96 | var DefaultEditor Editor = EditorFunc(simpleEditor) 97 | 98 | func simpleEditor(v *View, key Key, ch rune, mod Modifier) { 99 | switch { 100 | case ch != 0 && mod == 0: 101 | v.EditWrite(ch) 102 | case key == KeySpace: 103 | v.EditWrite(' ') 104 | case key == KeyBackspace || key == KeyBackspace2: 105 | v.EditDelete(true) 106 | // ... 107 | } 108 | } 109 | 110 | Colored text: 111 | 112 | Views allow to add colored text using ANSI colors. For example: 113 | 114 | fmt.Fprintln(v, "\x1b[0;31mHello world") 115 | 116 | For more information, see the examples in folder "_examples/". 117 | */ 118 | package gocui 119 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/edit.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The gocui Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gocui 6 | 7 | import "errors" 8 | 9 | const maxInt = int(^uint(0) >> 1) 10 | 11 | // Editor interface must be satisfied by gocui editors. 12 | type Editor interface { 13 | Edit(v *View, key Key, ch rune, mod Modifier) 14 | } 15 | 16 | // The EditorFunc type is an adapter to allow the use of ordinary functions as 17 | // Editors. If f is a function with the appropriate signature, EditorFunc(f) 18 | // is an Editor object that calls f. 19 | type EditorFunc func(v *View, key Key, ch rune, mod Modifier) 20 | 21 | // Edit calls f(v, key, ch, mod) 22 | func (f EditorFunc) Edit(v *View, key Key, ch rune, mod Modifier) { 23 | f(v, key, ch, mod) 24 | } 25 | 26 | // DefaultEditor is the default editor. 27 | var DefaultEditor Editor = EditorFunc(simpleEditor) 28 | 29 | // simpleEditor is used as the default gocui editor. 30 | func simpleEditor(v *View, key Key, ch rune, mod Modifier) { 31 | switch { 32 | case ch != 0 && mod == 0: 33 | v.EditWrite(ch) 34 | case key == KeySpace: 35 | v.EditWrite(' ') 36 | case key == KeyBackspace || key == KeyBackspace2: 37 | v.EditDelete(true) 38 | case key == KeyDelete: 39 | v.EditDelete(false) 40 | case key == KeyInsert: 41 | v.Overwrite = !v.Overwrite 42 | case key == KeyEnter: 43 | v.EditNewLine() 44 | case key == KeyArrowDown: 45 | v.MoveCursor(0, 1, false) 46 | case key == KeyArrowUp: 47 | v.MoveCursor(0, -1, false) 48 | case key == KeyArrowLeft: 49 | v.MoveCursor(-1, 0, false) 50 | case key == KeyArrowRight: 51 | v.MoveCursor(1, 0, false) 52 | } 53 | } 54 | 55 | // EditWrite writes a rune at the cursor position. 56 | func (v *View) EditWrite(ch rune) { 57 | v.writeRune(v.cx, v.cy, ch) 58 | v.MoveCursor(1, 0, true) 59 | } 60 | 61 | // EditDelete deletes a rune at the cursor position. back determines the 62 | // direction. 63 | func (v *View) EditDelete(back bool) { 64 | x, y := v.ox+v.cx, v.oy+v.cy 65 | if y < 0 { 66 | return 67 | } else if y >= len(v.viewLines) { 68 | v.MoveCursor(-1, 0, true) 69 | return 70 | } 71 | 72 | maxX, _ := v.Size() 73 | if back { 74 | if x == 0 { // start of the line 75 | if y < 1 { 76 | return 77 | } 78 | 79 | var maxPrevWidth int 80 | if v.Wrap { 81 | maxPrevWidth = maxX 82 | } else { 83 | maxPrevWidth = maxInt 84 | } 85 | 86 | if v.viewLines[y].linesX == 0 { // regular line 87 | v.mergeLines(v.cy - 1) 88 | if len(v.viewLines[y-1].line) < maxPrevWidth { 89 | v.MoveCursor(-1, 0, true) 90 | } 91 | } else { // wrapped line 92 | v.deleteRune(len(v.viewLines[y-1].line)-1, v.cy-1) 93 | v.MoveCursor(-1, 0, true) 94 | } 95 | } else { // middle/end of the line 96 | v.deleteRune(v.cx-1, v.cy) 97 | v.MoveCursor(-1, 0, true) 98 | } 99 | } else { 100 | if x == len(v.viewLines[y].line) { // end of the line 101 | v.mergeLines(v.cy) 102 | } else { // start/middle of the line 103 | v.deleteRune(v.cx, v.cy) 104 | } 105 | } 106 | } 107 | 108 | // EditNewLine inserts a new line under the cursor. 109 | func (v *View) EditNewLine() { 110 | v.breakLine(v.cx, v.cy) 111 | v.ox = 0 112 | v.cx = 0 113 | v.MoveCursor(0, 1, true) 114 | } 115 | 116 | // MoveCursor moves the cursor taking into account the width of the line/view, 117 | // displacing the origin if necessary. 118 | func (v *View) MoveCursor(dx, dy int, writeMode bool) { 119 | maxX, maxY := v.Size() 120 | cx, cy := v.cx+dx, v.cy+dy 121 | x, y := v.ox+cx, v.oy+cy 122 | 123 | var curLineWidth, prevLineWidth int 124 | // get the width of the current line 125 | if writeMode { 126 | if v.Wrap { 127 | curLineWidth = maxX - 1 128 | } else { 129 | curLineWidth = maxInt 130 | } 131 | } else { 132 | if y >= 0 && y < len(v.viewLines) { 133 | curLineWidth = len(v.viewLines[y].line) 134 | if v.Wrap && curLineWidth >= maxX { 135 | curLineWidth = maxX - 1 136 | } 137 | } else { 138 | curLineWidth = 0 139 | } 140 | } 141 | // get the width of the previous line 142 | if y-1 >= 0 && y-1 < len(v.viewLines) { 143 | prevLineWidth = len(v.viewLines[y-1].line) 144 | } else { 145 | prevLineWidth = 0 146 | } 147 | 148 | // adjust cursor's x position and view's x origin 149 | if x > curLineWidth { // move to next line 150 | if dx > 0 { // horizontal movement 151 | cy++ 152 | if writeMode || v.oy+cy < len(v.viewLines) { 153 | if !v.Wrap { 154 | v.ox = 0 155 | } 156 | v.cx = 0 157 | } 158 | } else { // vertical movement 159 | if curLineWidth > 0 { // move cursor to the EOL 160 | if v.Wrap { 161 | v.cx = curLineWidth 162 | } else { 163 | ncx := curLineWidth - v.ox 164 | if ncx < 0 { 165 | v.ox += ncx 166 | if v.ox < 0 { 167 | v.ox = 0 168 | } 169 | v.cx = 0 170 | } else { 171 | v.cx = ncx 172 | } 173 | } 174 | } else { 175 | if writeMode || v.oy+cy < len(v.viewLines) { 176 | if !v.Wrap { 177 | v.ox = 0 178 | } 179 | v.cx = 0 180 | } 181 | } 182 | } 183 | } else if cx < 0 { 184 | if !v.Wrap && v.ox > 0 { // move origin to the left 185 | v.ox += cx 186 | v.cx = 0 187 | } else { // move to previous line 188 | cy-- 189 | if prevLineWidth > 0 { 190 | if !v.Wrap { // set origin so the EOL is visible 191 | nox := prevLineWidth - maxX + 1 192 | if nox < 0 { 193 | v.ox = 0 194 | } else { 195 | v.ox = nox 196 | } 197 | } 198 | v.cx = prevLineWidth 199 | } else { 200 | if !v.Wrap { 201 | v.ox = 0 202 | } 203 | v.cx = 0 204 | } 205 | } 206 | } else { // stay on the same line 207 | if v.Wrap { 208 | v.cx = cx 209 | } else { 210 | if cx >= maxX { 211 | v.ox += cx - maxX + 1 212 | v.cx = maxX 213 | } else { 214 | v.cx = cx 215 | } 216 | } 217 | } 218 | 219 | // adjust cursor's y position and view's y origin 220 | if cy < 0 { 221 | if v.oy > 0 { 222 | v.oy-- 223 | } 224 | } else if writeMode || v.oy+cy < len(v.viewLines) { 225 | if cy >= maxY { 226 | v.oy++ 227 | } else { 228 | v.cy = cy 229 | } 230 | } 231 | } 232 | 233 | // writeRune writes a rune into the view's internal buffer, at the 234 | // position corresponding to the point (x, y). The length of the internal 235 | // buffer is increased if the point is out of bounds. Overwrite mode is 236 | // governed by the value of View.overwrite. 237 | func (v *View) writeRune(x, y int, ch rune) error { 238 | v.tainted = true 239 | 240 | x, y, err := v.realPosition(x, y) 241 | if err != nil { 242 | return err 243 | } 244 | 245 | if x < 0 || y < 0 { 246 | return errors.New("invalid point") 247 | } 248 | 249 | if y >= len(v.lines) { 250 | s := make([][]cell, y-len(v.lines)+1) 251 | v.lines = append(v.lines, s...) 252 | } 253 | 254 | olen := len(v.lines[y]) 255 | 256 | var s []cell 257 | if x >= len(v.lines[y]) { 258 | s = make([]cell, x-len(v.lines[y])+1) 259 | } else if !v.Overwrite { 260 | s = make([]cell, 1) 261 | } 262 | v.lines[y] = append(v.lines[y], s...) 263 | 264 | if !v.Overwrite || (v.Overwrite && x >= olen-1) { 265 | copy(v.lines[y][x+1:], v.lines[y][x:]) 266 | } 267 | v.lines[y][x] = cell{ 268 | fgColor: v.FgColor, 269 | bgColor: v.BgColor, 270 | chr: ch, 271 | } 272 | 273 | return nil 274 | } 275 | 276 | // deleteRune removes a rune from the view's internal buffer, at the 277 | // position corresponding to the point (x, y). 278 | func (v *View) deleteRune(x, y int) error { 279 | v.tainted = true 280 | 281 | x, y, err := v.realPosition(x, y) 282 | if err != nil { 283 | return err 284 | } 285 | 286 | if x < 0 || y < 0 || y >= len(v.lines) || x >= len(v.lines[y]) { 287 | return errors.New("invalid point") 288 | } 289 | v.lines[y] = append(v.lines[y][:x], v.lines[y][x+1:]...) 290 | return nil 291 | } 292 | 293 | // mergeLines merges the lines "y" and "y+1" if possible. 294 | func (v *View) mergeLines(y int) error { 295 | v.tainted = true 296 | 297 | _, y, err := v.realPosition(0, y) 298 | if err != nil { 299 | return err 300 | } 301 | 302 | if y < 0 || y >= len(v.lines) { 303 | return errors.New("invalid point") 304 | } 305 | 306 | if y < len(v.lines)-1 { // otherwise we don't need to merge anything 307 | v.lines[y] = append(v.lines[y], v.lines[y+1]...) 308 | v.lines = append(v.lines[:y+1], v.lines[y+2:]...) 309 | } 310 | return nil 311 | } 312 | 313 | // breakLine breaks a line of the internal buffer at the position corresponding 314 | // to the point (x, y). 315 | func (v *View) breakLine(x, y int) error { 316 | v.tainted = true 317 | 318 | x, y, err := v.realPosition(x, y) 319 | if err != nil { 320 | return err 321 | } 322 | 323 | if y < 0 || y >= len(v.lines) { 324 | return errors.New("invalid point") 325 | } 326 | 327 | var left, right []cell 328 | if x < len(v.lines[y]) { // break line 329 | left = make([]cell, len(v.lines[y][:x])) 330 | copy(left, v.lines[y][:x]) 331 | right = make([]cell, len(v.lines[y][x:])) 332 | copy(right, v.lines[y][x:]) 333 | } else { // new empty line 334 | left = v.lines[y] 335 | } 336 | 337 | lines := make([][]cell, len(v.lines)+1) 338 | lines[y] = left 339 | lines[y+1] = right 340 | copy(lines, v.lines[:y]) 341 | copy(lines[y+2:], v.lines[y+1:]) 342 | v.lines = lines 343 | return nil 344 | } 345 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/escape.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The gocui Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gocui 6 | 7 | import ( 8 | "errors" 9 | "strconv" 10 | ) 11 | 12 | type escapeInterpreter struct { 13 | state escapeState 14 | curch rune 15 | csiParam []string 16 | curFgColor, curBgColor Attribute 17 | mode OutputMode 18 | } 19 | 20 | type escapeState int 21 | 22 | const ( 23 | stateNone escapeState = iota 24 | stateEscape 25 | stateCSI 26 | stateParams 27 | ) 28 | 29 | var ( 30 | errNotCSI = errors.New("Not a CSI escape sequence") 31 | errCSIParseError = errors.New("CSI escape sequence parsing error") 32 | errCSITooLong = errors.New("CSI escape sequence is too long") 33 | ) 34 | 35 | // runes in case of error will output the non-parsed runes as a string. 36 | func (ei *escapeInterpreter) runes() []rune { 37 | switch ei.state { 38 | case stateNone: 39 | return []rune{0x1b} 40 | case stateEscape: 41 | return []rune{0x1b, ei.curch} 42 | case stateCSI: 43 | return []rune{0x1b, '[', ei.curch} 44 | case stateParams: 45 | ret := []rune{0x1b, '['} 46 | for _, s := range ei.csiParam { 47 | ret = append(ret, []rune(s)...) 48 | ret = append(ret, ';') 49 | } 50 | return append(ret, ei.curch) 51 | } 52 | return nil 53 | } 54 | 55 | // newEscapeInterpreter returns an escapeInterpreter that will be able to parse 56 | // terminal escape sequences. 57 | func newEscapeInterpreter(mode OutputMode) *escapeInterpreter { 58 | ei := &escapeInterpreter{ 59 | state: stateNone, 60 | curFgColor: ColorDefault, 61 | curBgColor: ColorDefault, 62 | mode: mode, 63 | } 64 | return ei 65 | } 66 | 67 | // reset sets the escapeInterpreter in initial state. 68 | func (ei *escapeInterpreter) reset() { 69 | ei.state = stateNone 70 | ei.curFgColor = ColorDefault 71 | ei.curBgColor = ColorDefault 72 | ei.csiParam = nil 73 | } 74 | 75 | // parseOne parses a rune. If isEscape is true, it means that the rune is part 76 | // of an escape sequence, and as such should not be printed verbatim. Otherwise, 77 | // it's not an escape sequence. 78 | func (ei *escapeInterpreter) parseOne(ch rune) (isEscape bool, err error) { 79 | // Sanity checks 80 | if len(ei.csiParam) > 20 { 81 | return false, errCSITooLong 82 | } 83 | if len(ei.csiParam) > 0 && len(ei.csiParam[len(ei.csiParam)-1]) > 255 { 84 | return false, errCSITooLong 85 | } 86 | 87 | ei.curch = ch 88 | 89 | switch ei.state { 90 | case stateNone: 91 | if ch == 0x1b { 92 | ei.state = stateEscape 93 | return true, nil 94 | } 95 | return false, nil 96 | case stateEscape: 97 | if ch == '[' { 98 | ei.state = stateCSI 99 | return true, nil 100 | } 101 | return false, errNotCSI 102 | case stateCSI: 103 | switch { 104 | case ch >= '0' && ch <= '9': 105 | ei.csiParam = append(ei.csiParam, "") 106 | case ch == 'm': 107 | ei.csiParam = append(ei.csiParam, "0") 108 | default: 109 | return false, errCSIParseError 110 | } 111 | ei.state = stateParams 112 | fallthrough 113 | case stateParams: 114 | switch { 115 | case ch >= '0' && ch <= '9': 116 | ei.csiParam[len(ei.csiParam)-1] += string(ch) 117 | return true, nil 118 | case ch == ';': 119 | ei.csiParam = append(ei.csiParam, "") 120 | return true, nil 121 | case ch == 'm': 122 | var err error 123 | switch ei.mode { 124 | case OutputNormal: 125 | err = ei.outputNormal() 126 | case Output256: 127 | err = ei.output256() 128 | } 129 | if err != nil { 130 | return false, errCSIParseError 131 | } 132 | 133 | ei.state = stateNone 134 | ei.csiParam = nil 135 | return true, nil 136 | default: 137 | return false, errCSIParseError 138 | } 139 | } 140 | return false, nil 141 | } 142 | 143 | // outputNormal provides 8 different colors: 144 | // black, red, green, yellow, blue, magenta, cyan, white 145 | func (ei *escapeInterpreter) outputNormal() error { 146 | for _, param := range ei.csiParam { 147 | p, err := strconv.Atoi(param) 148 | if err != nil { 149 | return errCSIParseError 150 | } 151 | 152 | switch { 153 | case p >= 30 && p <= 37: 154 | ei.curFgColor = Attribute(p - 30 + 1) 155 | case p == 39: 156 | ei.curFgColor = ColorDefault 157 | case p >= 40 && p <= 47: 158 | ei.curBgColor = Attribute(p - 40 + 1) 159 | case p == 49: 160 | ei.curBgColor = ColorDefault 161 | case p == 1: 162 | ei.curFgColor |= AttrBold 163 | case p == 4: 164 | ei.curFgColor |= AttrUnderline 165 | case p == 7: 166 | ei.curFgColor |= AttrReverse 167 | case p == 0: 168 | ei.curFgColor = ColorDefault 169 | ei.curBgColor = ColorDefault 170 | } 171 | } 172 | 173 | return nil 174 | } 175 | 176 | // output256 allows you to leverage the 256-colors terminal mode: 177 | // 0x01 - 0x08: the 8 colors as in OutputNormal 178 | // 0x09 - 0x10: Color* | AttrBold 179 | // 0x11 - 0xe8: 216 different colors 180 | // 0xe9 - 0x1ff: 24 different shades of grey 181 | func (ei *escapeInterpreter) output256() error { 182 | if len(ei.csiParam) < 3 { 183 | return ei.outputNormal() 184 | } 185 | 186 | mode, err := strconv.Atoi(ei.csiParam[1]) 187 | if err != nil { 188 | return errCSIParseError 189 | } 190 | if mode != 5 { 191 | return ei.outputNormal() 192 | } 193 | 194 | fgbg, err := strconv.Atoi(ei.csiParam[0]) 195 | if err != nil { 196 | return errCSIParseError 197 | } 198 | color, err := strconv.Atoi(ei.csiParam[2]) 199 | if err != nil { 200 | return errCSIParseError 201 | } 202 | 203 | switch fgbg { 204 | case 38: 205 | ei.curFgColor = Attribute(color + 1) 206 | 207 | for _, param := range ei.csiParam[3:] { 208 | p, err := strconv.Atoi(param) 209 | if err != nil { 210 | return errCSIParseError 211 | } 212 | 213 | switch { 214 | case p == 1: 215 | ei.curFgColor |= AttrBold 216 | case p == 4: 217 | ei.curFgColor |= AttrUnderline 218 | case p == 7: 219 | ei.curFgColor |= AttrReverse 220 | } 221 | } 222 | case 48: 223 | ei.curBgColor = Attribute(color + 1) 224 | default: 225 | return errCSIParseError 226 | } 227 | 228 | return nil 229 | } 230 | -------------------------------------------------------------------------------- /vendor/github.com/jroimartin/gocui/keybinding.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The gocui Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gocui 6 | 7 | import "github.com/nsf/termbox-go" 8 | 9 | // Keybidings are used to link a given key-press event with a handler. 10 | type keybinding struct { 11 | viewName string 12 | key Key 13 | ch rune 14 | mod Modifier 15 | handler func(*Gui, *View) error 16 | } 17 | 18 | // newKeybinding returns a new Keybinding object. 19 | func newKeybinding(viewname string, key Key, ch rune, mod Modifier, handler func(*Gui, *View) error) (kb *keybinding) { 20 | kb = &keybinding{ 21 | viewName: viewname, 22 | key: key, 23 | ch: ch, 24 | mod: mod, 25 | handler: handler, 26 | } 27 | return kb 28 | } 29 | 30 | // matchKeypress returns if the keybinding matches the keypress. 31 | func (kb *keybinding) matchKeypress(key Key, ch rune, mod Modifier) bool { 32 | return kb.key == key && kb.ch == ch && kb.mod == mod 33 | } 34 | 35 | // matchView returns if the keybinding matches the current view. 36 | func (kb *keybinding) matchView(v *View) bool { 37 | if kb.viewName == "" { 38 | return true 39 | } 40 | return v != nil && kb.viewName == v.name 41 | } 42 | 43 | // Key represents special keys or keys combinations. 44 | type Key termbox.Key 45 | 46 | // Special keys. 47 | const ( 48 | KeyF1 Key = Key(termbox.KeyF1) 49 | KeyF2 = Key(termbox.KeyF2) 50 | KeyF3 = Key(termbox.KeyF3) 51 | KeyF4 = Key(termbox.KeyF4) 52 | KeyF5 = Key(termbox.KeyF5) 53 | KeyF6 = Key(termbox.KeyF6) 54 | KeyF7 = Key(termbox.KeyF7) 55 | KeyF8 = Key(termbox.KeyF8) 56 | KeyF9 = Key(termbox.KeyF9) 57 | KeyF10 = Key(termbox.KeyF10) 58 | KeyF11 = Key(termbox.KeyF11) 59 | KeyF12 = Key(termbox.KeyF12) 60 | KeyInsert = Key(termbox.KeyInsert) 61 | KeyDelete = Key(termbox.KeyDelete) 62 | KeyHome = Key(termbox.KeyHome) 63 | KeyEnd = Key(termbox.KeyEnd) 64 | KeyPgup = Key(termbox.KeyPgup) 65 | KeyPgdn = Key(termbox.KeyPgdn) 66 | KeyArrowUp = Key(termbox.KeyArrowUp) 67 | KeyArrowDown = Key(termbox.KeyArrowDown) 68 | KeyArrowLeft = Key(termbox.KeyArrowLeft) 69 | KeyArrowRight = Key(termbox.KeyArrowRight) 70 | 71 | MouseLeft = Key(termbox.MouseLeft) 72 | MouseMiddle = Key(termbox.MouseMiddle) 73 | MouseRight = Key(termbox.MouseRight) 74 | MouseRelease = Key(termbox.MouseRelease) 75 | MouseWheelUp = Key(termbox.MouseWheelUp) 76 | MouseWheelDown = Key(termbox.MouseWheelDown) 77 | ) 78 | 79 | // Keys combinations. 80 | const ( 81 | KeyCtrlTilde Key = Key(termbox.KeyCtrlTilde) 82 | KeyCtrl2 = Key(termbox.KeyCtrl2) 83 | KeyCtrlSpace = Key(termbox.KeyCtrlSpace) 84 | KeyCtrlA = Key(termbox.KeyCtrlA) 85 | KeyCtrlB = Key(termbox.KeyCtrlB) 86 | KeyCtrlC = Key(termbox.KeyCtrlC) 87 | KeyCtrlD = Key(termbox.KeyCtrlD) 88 | KeyCtrlE = Key(termbox.KeyCtrlE) 89 | KeyCtrlF = Key(termbox.KeyCtrlF) 90 | KeyCtrlG = Key(termbox.KeyCtrlG) 91 | KeyBackspace = Key(termbox.KeyBackspace) 92 | KeyCtrlH = Key(termbox.KeyCtrlH) 93 | KeyTab = Key(termbox.KeyTab) 94 | KeyCtrlI = Key(termbox.KeyCtrlI) 95 | KeyCtrlJ = Key(termbox.KeyCtrlJ) 96 | KeyCtrlK = Key(termbox.KeyCtrlK) 97 | KeyCtrlL = Key(termbox.KeyCtrlL) 98 | KeyEnter = Key(termbox.KeyEnter) 99 | KeyCtrlM = Key(termbox.KeyCtrlM) 100 | KeyCtrlN = Key(termbox.KeyCtrlN) 101 | KeyCtrlO = Key(termbox.KeyCtrlO) 102 | KeyCtrlP = Key(termbox.KeyCtrlP) 103 | KeyCtrlQ = Key(termbox.KeyCtrlQ) 104 | KeyCtrlR = Key(termbox.KeyCtrlR) 105 | KeyCtrlS = Key(termbox.KeyCtrlS) 106 | KeyCtrlT = Key(termbox.KeyCtrlT) 107 | KeyCtrlU = Key(termbox.KeyCtrlU) 108 | KeyCtrlV = Key(termbox.KeyCtrlV) 109 | KeyCtrlW = Key(termbox.KeyCtrlW) 110 | KeyCtrlX = Key(termbox.KeyCtrlX) 111 | KeyCtrlY = Key(termbox.KeyCtrlY) 112 | KeyCtrlZ = Key(termbox.KeyCtrlZ) 113 | KeyEsc = Key(termbox.KeyEsc) 114 | KeyCtrlLsqBracket = Key(termbox.KeyCtrlLsqBracket) 115 | KeyCtrl3 = Key(termbox.KeyCtrl3) 116 | KeyCtrl4 = Key(termbox.KeyCtrl4) 117 | KeyCtrlBackslash = Key(termbox.KeyCtrlBackslash) 118 | KeyCtrl5 = Key(termbox.KeyCtrl5) 119 | KeyCtrlRsqBracket = Key(termbox.KeyCtrlRsqBracket) 120 | KeyCtrl6 = Key(termbox.KeyCtrl6) 121 | KeyCtrl7 = Key(termbox.KeyCtrl7) 122 | KeyCtrlSlash = Key(termbox.KeyCtrlSlash) 123 | KeyCtrlUnderscore = Key(termbox.KeyCtrlUnderscore) 124 | KeySpace = Key(termbox.KeySpace) 125 | KeyBackspace2 = Key(termbox.KeyBackspace2) 126 | KeyCtrl8 = Key(termbox.KeyCtrl8) 127 | ) 128 | 129 | // Modifier allows to define special keys combinations. They can be used 130 | // in combination with Keys or Runes when a new keybinding is defined. 131 | type Modifier termbox.Modifier 132 | 133 | // Modifiers. 134 | const ( 135 | ModNone Modifier = Modifier(0) 136 | ModAlt = Modifier(termbox.ModAlt) 137 | ) 138 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yasuhiro Matsumoto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/README.mkd: -------------------------------------------------------------------------------- 1 | go-runewidth 2 | ============ 3 | 4 | [![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) 5 | [![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) 6 | [![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) 7 | [![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) 8 | 9 | Provides functions to get fixed width of the character or string. 10 | 11 | Usage 12 | ----- 13 | 14 | ```go 15 | runewidth.StringWidth("つのだ☆HIRO") == 12 16 | ``` 17 | 18 | 19 | Author 20 | ------ 21 | 22 | Yasuhiro Matsumoto 23 | 24 | License 25 | ------- 26 | 27 | under the MIT License: http://mattn.mit-license.org/2013 28 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mattn/go-runewidth 2 | 3 | go 1.9 4 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_appengine.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package runewidth 4 | 5 | // IsEastAsian return true if the current locale is CJK 6 | func IsEastAsian() bool { 7 | return false 8 | } 9 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_js.go: -------------------------------------------------------------------------------- 1 | // +build js 2 | // +build !appengine 3 | 4 | package runewidth 5 | 6 | func IsEastAsian() bool { 7 | // TODO: Implement this for the web. Detect east asian in a compatible way, and return true. 8 | return false 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | // +build !js 3 | // +build !appengine 4 | 5 | package runewidth 6 | 7 | import ( 8 | "os" 9 | "regexp" 10 | "strings" 11 | ) 12 | 13 | var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) 14 | 15 | var mblenTable = map[string]int{ 16 | "utf-8": 6, 17 | "utf8": 6, 18 | "jis": 8, 19 | "eucjp": 3, 20 | "euckr": 2, 21 | "euccn": 2, 22 | "sjis": 2, 23 | "cp932": 2, 24 | "cp51932": 2, 25 | "cp936": 2, 26 | "cp949": 2, 27 | "cp950": 2, 28 | "big5": 2, 29 | "gbk": 2, 30 | "gb2312": 2, 31 | } 32 | 33 | func isEastAsian(locale string) bool { 34 | charset := strings.ToLower(locale) 35 | r := reLoc.FindStringSubmatch(locale) 36 | if len(r) == 2 { 37 | charset = strings.ToLower(r[1]) 38 | } 39 | 40 | if strings.HasSuffix(charset, "@cjk_narrow") { 41 | return false 42 | } 43 | 44 | for pos, b := range []byte(charset) { 45 | if b == '@' { 46 | charset = charset[:pos] 47 | break 48 | } 49 | } 50 | max := 1 51 | if m, ok := mblenTable[charset]; ok { 52 | max = m 53 | } 54 | if max > 1 && (charset[0] != 'u' || 55 | strings.HasPrefix(locale, "ja") || 56 | strings.HasPrefix(locale, "ko") || 57 | strings.HasPrefix(locale, "zh")) { 58 | return true 59 | } 60 | return false 61 | } 62 | 63 | // IsEastAsian return true if the current locale is CJK 64 | func IsEastAsian() bool { 65 | locale := os.Getenv("LC_CTYPE") 66 | if locale == "" { 67 | locale = os.Getenv("LANG") 68 | } 69 | 70 | // ignore C locale 71 | if locale == "POSIX" || locale == "C" { 72 | return false 73 | } 74 | if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { 75 | return false 76 | } 77 | 78 | return isEastAsian(locale) 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/mattn/go-runewidth/runewidth_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | // +build !appengine 3 | 4 | package runewidth 5 | 6 | import ( 7 | "syscall" 8 | ) 9 | 10 | var ( 11 | kernel32 = syscall.NewLazyDLL("kernel32") 12 | procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") 13 | ) 14 | 15 | // IsEastAsian return true if the current locale is CJK 16 | func IsEastAsian() bool { 17 | r1, _, _ := procGetConsoleOutputCP.Call() 18 | if r1 == 0 { 19 | return false 20 | } 21 | 22 | switch int(r1) { 23 | case 932, 51932, 936, 949, 950: 24 | return true 25 | } 26 | 27 | return false 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/AUTHORS: -------------------------------------------------------------------------------- 1 | # Please keep this file sorted. 2 | 3 | Georg Reinke 4 | nsf 5 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 termbox-go authors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/README.md: -------------------------------------------------------------------------------- 1 | [![GoDoc](https://godoc.org/github.com/nsf/termbox-go?status.svg)](http://godoc.org/github.com/nsf/termbox-go) 2 | 3 | ## IMPORTANT 4 | 5 | This library is somewhat not maintained anymore. But I'm glad that it did what I wanted the most. It moved people away from "ncurses" mindset and these days we see both re-implementations of termbox API in various languages and even possibly better libs with similar API design. If you're looking for a Go lib that provides terminal-based user interface facilities, I've heard that https://github.com/gdamore/tcell is good (never used it myself). Also for more complicated interfaces and/or computer games I recommend you to consider using HTML-based UI. Having said that, termbox still somewhat works. In fact I'm writing this line of text right now in godit (which is a text editor written using termbox-go). So, be aware. Good luck and have a nice day. 6 | 7 | ## Termbox 8 | Termbox is a library that provides a minimalistic API which allows the programmer to write text-based user interfaces. The library is crossplatform and has both terminal-based implementations on *nix operating systems and a winapi console based implementation for windows operating systems. The basic idea is an abstraction of the greatest common subset of features available on all major terminals and other terminal-like APIs in a minimalistic fashion. Small API means it is easy to implement, test, maintain and learn it, that's what makes the termbox a distinct library in its area. 9 | 10 | ### Installation 11 | Install and update this go package with `go get -u github.com/nsf/termbox-go` 12 | 13 | ### Examples 14 | For examples of what can be done take a look at demos in the _demos directory. You can try them with go run: `go run _demos/keyboard.go` 15 | 16 | There are also some interesting projects using termbox-go: 17 | - [godit](https://github.com/nsf/godit) is an emacsish lightweight text editor written using termbox. 18 | - [gotetris](https://github.com/jjinux/gotetris) is an implementation of Tetris. 19 | - [sokoban-go](https://github.com/rn2dy/sokoban-go) is an implementation of sokoban game. 20 | - [hecate](https://github.com/evanmiller/hecate) is a hex editor designed by Satan. 21 | - [httopd](https://github.com/verdverm/httopd) is top for httpd logs. 22 | - [mop](https://github.com/mop-tracker/mop) is stock market tracker for hackers. 23 | - [termui](https://github.com/gizak/termui) is a terminal dashboard. 24 | - [termdash](https://github.com/mum4k/termdash) is a terminal dashboard. 25 | - [termloop](https://github.com/JoelOtter/termloop) is a terminal game engine. 26 | - [xterm-color-chart](https://github.com/kutuluk/xterm-color-chart) is a XTerm 256 color chart. 27 | - [gocui](https://github.com/jroimartin/gocui) is a minimalist Go library aimed at creating console user interfaces. 28 | - [dry](https://github.com/moncho/dry) is an interactive cli to manage Docker containers. 29 | - [pxl](https://github.com/ichinaski/pxl) displays images in the terminal. 30 | - [snake-game](https://github.com/DyegoCosta/snake-game) is an implementation of the Snake game. 31 | - [gone](https://github.com/guillaumebreton/gone) is a CLI pomodoro® timer. 32 | - [Spoof.go](https://github.com/sabey/spoofgo) controllable movement spoofing from the cli 33 | - [lf](https://github.com/gokcehan/lf) is a terminal file manager 34 | - [rat](https://github.com/ericfreese/rat) lets you compose shell commands to build terminal applications. 35 | - [httplab](https://github.com/gchaincl/httplab) An interactive web server. 36 | - [tetris](https://github.com/MichaelS11/tetris) Go Tetris with AI option 37 | - [wot](https://github.com/kyu-suke/wot) Wait time during command is completed. 38 | - [2048-go](https://github.com/1984weed/2048-go) is 2048 in Go 39 | - [jv](https://github.com/maxzender/jv) helps you view JSON on the command-line. 40 | - [pinger](https://github.com/hirose31/pinger) helps you to monitor numerous hosts using ICMP ECHO_REQUEST. 41 | - [vixl44](https://github.com/sebashwa/vixl44) lets you create pixel art inside your terminal using vim movements 42 | - [zterm](https://github.com/varunrau/zterm) is a typing game inspired by http://zty.pe/ 43 | - [gotypist](https://github.com/pb-/gotypist) is a fun touch-typing tutor following Steve Yegge's method. 44 | - [cointop](https://github.com/miguelmota/cointop) is an interactive terminal based UI application for tracking cryptocurrencies. 45 | - [pexpo](https://github.com/nnao45/pexpo) is a terminal sending ping tool written in Go. 46 | - [jid](https://github.com/simeji/jid) is an interactive JSON drill down tool using filtering queries like jq. 47 | - [nonograminGo](https://github.com/N0RM4L15T/nonograminGo) is a nonogram(aka. picross) in Go 48 | 49 | ### API reference 50 | [godoc.org/github.com/nsf/termbox-go](http://godoc.org/github.com/nsf/termbox-go) 51 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/api_common.go: -------------------------------------------------------------------------------- 1 | // termbox is a library for creating cross-platform text-based interfaces 2 | package termbox 3 | 4 | // public API, common OS agnostic part 5 | 6 | type ( 7 | InputMode int 8 | OutputMode int 9 | EventType uint8 10 | Modifier uint8 11 | Key uint16 12 | Attribute uint16 13 | ) 14 | 15 | // This type represents a termbox event. The 'Mod', 'Key' and 'Ch' fields are 16 | // valid if 'Type' is EventKey. The 'Width' and 'Height' fields are valid if 17 | // 'Type' is EventResize. The 'Err' field is valid if 'Type' is EventError. 18 | type Event struct { 19 | Type EventType // one of Event* constants 20 | Mod Modifier // one of Mod* constants or 0 21 | Key Key // one of Key* constants, invalid if 'Ch' is not 0 22 | Ch rune // a unicode character 23 | Width int // width of the screen 24 | Height int // height of the screen 25 | Err error // error in case if input failed 26 | MouseX int // x coord of mouse 27 | MouseY int // y coord of mouse 28 | N int // number of bytes written when getting a raw event 29 | } 30 | 31 | // A cell, single conceptual entity on the screen. The screen is basically a 2d 32 | // array of cells. 'Ch' is a unicode character, 'Fg' and 'Bg' are foreground 33 | // and background attributes respectively. 34 | type Cell struct { 35 | Ch rune 36 | Fg Attribute 37 | Bg Attribute 38 | } 39 | 40 | // To know if termbox has been initialized or not 41 | var ( 42 | IsInit bool = false 43 | ) 44 | 45 | // Key constants, see Event.Key field. 46 | const ( 47 | KeyF1 Key = 0xFFFF - iota 48 | KeyF2 49 | KeyF3 50 | KeyF4 51 | KeyF5 52 | KeyF6 53 | KeyF7 54 | KeyF8 55 | KeyF9 56 | KeyF10 57 | KeyF11 58 | KeyF12 59 | KeyInsert 60 | KeyDelete 61 | KeyHome 62 | KeyEnd 63 | KeyPgup 64 | KeyPgdn 65 | KeyArrowUp 66 | KeyArrowDown 67 | KeyArrowLeft 68 | KeyArrowRight 69 | key_min // see terminfo 70 | MouseLeft 71 | MouseMiddle 72 | MouseRight 73 | MouseRelease 74 | MouseWheelUp 75 | MouseWheelDown 76 | ) 77 | 78 | const ( 79 | KeyCtrlTilde Key = 0x00 80 | KeyCtrl2 Key = 0x00 81 | KeyCtrlSpace Key = 0x00 82 | KeyCtrlA Key = 0x01 83 | KeyCtrlB Key = 0x02 84 | KeyCtrlC Key = 0x03 85 | KeyCtrlD Key = 0x04 86 | KeyCtrlE Key = 0x05 87 | KeyCtrlF Key = 0x06 88 | KeyCtrlG Key = 0x07 89 | KeyBackspace Key = 0x08 90 | KeyCtrlH Key = 0x08 91 | KeyTab Key = 0x09 92 | KeyCtrlI Key = 0x09 93 | KeyCtrlJ Key = 0x0A 94 | KeyCtrlK Key = 0x0B 95 | KeyCtrlL Key = 0x0C 96 | KeyEnter Key = 0x0D 97 | KeyCtrlM Key = 0x0D 98 | KeyCtrlN Key = 0x0E 99 | KeyCtrlO Key = 0x0F 100 | KeyCtrlP Key = 0x10 101 | KeyCtrlQ Key = 0x11 102 | KeyCtrlR Key = 0x12 103 | KeyCtrlS Key = 0x13 104 | KeyCtrlT Key = 0x14 105 | KeyCtrlU Key = 0x15 106 | KeyCtrlV Key = 0x16 107 | KeyCtrlW Key = 0x17 108 | KeyCtrlX Key = 0x18 109 | KeyCtrlY Key = 0x19 110 | KeyCtrlZ Key = 0x1A 111 | KeyEsc Key = 0x1B 112 | KeyCtrlLsqBracket Key = 0x1B 113 | KeyCtrl3 Key = 0x1B 114 | KeyCtrl4 Key = 0x1C 115 | KeyCtrlBackslash Key = 0x1C 116 | KeyCtrl5 Key = 0x1D 117 | KeyCtrlRsqBracket Key = 0x1D 118 | KeyCtrl6 Key = 0x1E 119 | KeyCtrl7 Key = 0x1F 120 | KeyCtrlSlash Key = 0x1F 121 | KeyCtrlUnderscore Key = 0x1F 122 | KeySpace Key = 0x20 123 | KeyBackspace2 Key = 0x7F 124 | KeyCtrl8 Key = 0x7F 125 | ) 126 | 127 | // Alt modifier constant, see Event.Mod field and SetInputMode function. 128 | const ( 129 | ModAlt Modifier = 1 << iota 130 | ModMotion 131 | ) 132 | 133 | // Cell colors, you can combine a color with multiple attributes using bitwise 134 | // OR ('|'). 135 | const ( 136 | ColorDefault Attribute = iota 137 | ColorBlack 138 | ColorRed 139 | ColorGreen 140 | ColorYellow 141 | ColorBlue 142 | ColorMagenta 143 | ColorCyan 144 | ColorWhite 145 | ) 146 | 147 | // Cell attributes, it is possible to use multiple attributes by combining them 148 | // using bitwise OR ('|'). Although, colors cannot be combined. But you can 149 | // combine attributes and a single color. 150 | // 151 | // It's worth mentioning that some platforms don't support certain attributes. 152 | // For example windows console doesn't support AttrUnderline. And on some 153 | // terminals applying AttrBold to background may result in blinking text. Use 154 | // them with caution and test your code on various terminals. 155 | const ( 156 | AttrBold Attribute = 1 << (iota + 9) 157 | AttrUnderline 158 | AttrReverse 159 | ) 160 | 161 | // Input mode. See SetInputMode function. 162 | const ( 163 | InputEsc InputMode = 1 << iota 164 | InputAlt 165 | InputMouse 166 | InputCurrent InputMode = 0 167 | ) 168 | 169 | // Output mode. See SetOutputMode function. 170 | const ( 171 | OutputCurrent OutputMode = iota 172 | OutputNormal 173 | Output256 174 | Output216 175 | OutputGrayscale 176 | ) 177 | 178 | // Event type. See Event.Type field. 179 | const ( 180 | EventKey EventType = iota 181 | EventResize 182 | EventMouse 183 | EventError 184 | EventInterrupt 185 | EventRaw 186 | EventNone 187 | ) 188 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/api_windows.go: -------------------------------------------------------------------------------- 1 | package termbox 2 | 3 | import ( 4 | "syscall" 5 | ) 6 | 7 | // public API 8 | 9 | // Initializes termbox library. This function should be called before any other functions. 10 | // After successful initialization, the library must be finalized using 'Close' function. 11 | // 12 | // Example usage: 13 | // err := termbox.Init() 14 | // if err != nil { 15 | // panic(err) 16 | // } 17 | // defer termbox.Close() 18 | func Init() error { 19 | var err error 20 | 21 | interrupt, err = create_event() 22 | if err != nil { 23 | return err 24 | } 25 | 26 | in, err = syscall.Open("CONIN$", syscall.O_RDWR, 0) 27 | if err != nil { 28 | return err 29 | } 30 | out, err = syscall.Open("CONOUT$", syscall.O_RDWR, 0) 31 | if err != nil { 32 | return err 33 | } 34 | 35 | err = get_console_mode(in, &orig_mode) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | err = set_console_mode(in, enable_window_input) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | orig_size, orig_window = get_term_size(out) 46 | win_size := get_win_size(out) 47 | 48 | err = set_console_screen_buffer_size(out, win_size) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | err = fix_win_size(out, win_size) 54 | if err != nil { 55 | return err 56 | } 57 | 58 | err = get_console_cursor_info(out, &orig_cursor_info) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | show_cursor(false) 64 | term_size, _ = get_term_size(out) 65 | back_buffer.init(int(term_size.x), int(term_size.y)) 66 | front_buffer.init(int(term_size.x), int(term_size.y)) 67 | back_buffer.clear() 68 | front_buffer.clear() 69 | clear() 70 | 71 | diffbuf = make([]diff_msg, 0, 32) 72 | 73 | go input_event_producer() 74 | IsInit = true 75 | return nil 76 | } 77 | 78 | // Finalizes termbox library, should be called after successful initialization 79 | // when termbox's functionality isn't required anymore. 80 | func Close() { 81 | // we ignore errors here, because we can't really do anything about them 82 | Clear(0, 0) 83 | Flush() 84 | 85 | // stop event producer 86 | cancel_comm <- true 87 | set_event(interrupt) 88 | select { 89 | case <-input_comm: 90 | default: 91 | } 92 | <-cancel_done_comm 93 | 94 | set_console_screen_buffer_size(out, orig_size) 95 | set_console_window_info(out, &orig_window) 96 | set_console_cursor_info(out, &orig_cursor_info) 97 | set_console_cursor_position(out, coord{}) 98 | set_console_mode(in, orig_mode) 99 | syscall.Close(in) 100 | syscall.Close(out) 101 | syscall.Close(interrupt) 102 | IsInit = false 103 | } 104 | 105 | // Interrupt an in-progress call to PollEvent by causing it to return 106 | // EventInterrupt. Note that this function will block until the PollEvent 107 | // function has successfully been interrupted. 108 | func Interrupt() { 109 | interrupt_comm <- struct{}{} 110 | } 111 | 112 | // Synchronizes the internal back buffer with the terminal. 113 | func Flush() error { 114 | update_size_maybe() 115 | prepare_diff_messages() 116 | for _, diff := range diffbuf { 117 | r := small_rect{ 118 | left: 0, 119 | top: diff.pos, 120 | right: term_size.x - 1, 121 | bottom: diff.pos + diff.lines - 1, 122 | } 123 | write_console_output(out, diff.chars, r) 124 | } 125 | if !is_cursor_hidden(cursor_x, cursor_y) { 126 | move_cursor(cursor_x, cursor_y) 127 | } 128 | return nil 129 | } 130 | 131 | // Sets the position of the cursor. See also HideCursor(). 132 | func SetCursor(x, y int) { 133 | if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) { 134 | show_cursor(true) 135 | } 136 | 137 | if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) { 138 | show_cursor(false) 139 | } 140 | 141 | cursor_x, cursor_y = x, y 142 | if !is_cursor_hidden(cursor_x, cursor_y) { 143 | move_cursor(cursor_x, cursor_y) 144 | } 145 | } 146 | 147 | // The shortcut for SetCursor(-1, -1). 148 | func HideCursor() { 149 | SetCursor(cursor_hidden, cursor_hidden) 150 | } 151 | 152 | // Changes cell's parameters in the internal back buffer at the specified 153 | // position. 154 | func SetCell(x, y int, ch rune, fg, bg Attribute) { 155 | if x < 0 || x >= back_buffer.width { 156 | return 157 | } 158 | if y < 0 || y >= back_buffer.height { 159 | return 160 | } 161 | 162 | back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg} 163 | } 164 | 165 | // Returns a slice into the termbox's back buffer. You can get its dimensions 166 | // using 'Size' function. The slice remains valid as long as no 'Clear' or 167 | // 'Flush' function calls were made after call to this function. 168 | func CellBuffer() []Cell { 169 | return back_buffer.cells 170 | } 171 | 172 | // Wait for an event and return it. This is a blocking function call. 173 | func PollEvent() Event { 174 | select { 175 | case ev := <-input_comm: 176 | return ev 177 | case <-interrupt_comm: 178 | return Event{Type: EventInterrupt} 179 | } 180 | } 181 | 182 | // Returns the size of the internal back buffer (which is mostly the same as 183 | // console's window size in characters). But it doesn't always match the size 184 | // of the console window, after the console size has changed, the internal back 185 | // buffer will get in sync only after Clear or Flush function calls. 186 | func Size() (int, int) { 187 | return int(term_size.x), int(term_size.y) 188 | } 189 | 190 | // Clears the internal back buffer. 191 | func Clear(fg, bg Attribute) error { 192 | foreground, background = fg, bg 193 | update_size_maybe() 194 | back_buffer.clear() 195 | return nil 196 | } 197 | 198 | // Sets termbox input mode. Termbox has two input modes: 199 | // 200 | // 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match 201 | // any known sequence. ESC means KeyEsc. This is the default input mode. 202 | // 203 | // 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match 204 | // any known sequence. ESC enables ModAlt modifier for the next keyboard event. 205 | // 206 | // Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will 207 | // enable mouse button press/release and drag events. 208 | // 209 | // If 'mode' is InputCurrent, returns the current input mode. See also Input* 210 | // constants. 211 | func SetInputMode(mode InputMode) InputMode { 212 | if mode == InputCurrent { 213 | return input_mode 214 | } 215 | if mode&InputMouse != 0 { 216 | err := set_console_mode(in, enable_window_input|enable_mouse_input|enable_extended_flags) 217 | if err != nil { 218 | panic(err) 219 | } 220 | } else { 221 | err := set_console_mode(in, enable_window_input) 222 | if err != nil { 223 | panic(err) 224 | } 225 | } 226 | 227 | input_mode = mode 228 | return input_mode 229 | } 230 | 231 | // Sets the termbox output mode. 232 | // 233 | // Windows console does not support extra colour modes, 234 | // so this will always set and return OutputNormal. 235 | func SetOutputMode(mode OutputMode) OutputMode { 236 | return OutputNormal 237 | } 238 | 239 | // Sync comes handy when something causes desync between termbox's understanding 240 | // of a terminal buffer and the reality. Such as a third party process. Sync 241 | // forces a complete resync between the termbox and a terminal, it may not be 242 | // visually pretty though. At the moment on Windows it does nothing. 243 | func Sync() error { 244 | return nil 245 | } 246 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/collect_terminfo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, os, subprocess 4 | 5 | def escaped(s): 6 | return repr(s)[1:-1] 7 | 8 | def tput(term, name): 9 | try: 10 | return subprocess.check_output(['tput', '-T%s' % term, name]).decode() 11 | except subprocess.CalledProcessError as e: 12 | return e.output.decode() 13 | 14 | 15 | def w(s): 16 | if s == None: 17 | return 18 | sys.stdout.write(s) 19 | 20 | terminals = { 21 | 'xterm' : 'xterm', 22 | 'rxvt-256color' : 'rxvt_256color', 23 | 'rxvt-unicode' : 'rxvt_unicode', 24 | 'linux' : 'linux', 25 | 'Eterm' : 'eterm', 26 | 'screen' : 'screen' 27 | } 28 | 29 | keys = [ 30 | "F1", "kf1", 31 | "F2", "kf2", 32 | "F3", "kf3", 33 | "F4", "kf4", 34 | "F5", "kf5", 35 | "F6", "kf6", 36 | "F7", "kf7", 37 | "F8", "kf8", 38 | "F9", "kf9", 39 | "F10", "kf10", 40 | "F11", "kf11", 41 | "F12", "kf12", 42 | "INSERT", "kich1", 43 | "DELETE", "kdch1", 44 | "HOME", "khome", 45 | "END", "kend", 46 | "PGUP", "kpp", 47 | "PGDN", "knp", 48 | "KEY_UP", "kcuu1", 49 | "KEY_DOWN", "kcud1", 50 | "KEY_LEFT", "kcub1", 51 | "KEY_RIGHT", "kcuf1" 52 | ] 53 | 54 | funcs = [ 55 | "T_ENTER_CA", "smcup", 56 | "T_EXIT_CA", "rmcup", 57 | "T_SHOW_CURSOR", "cnorm", 58 | "T_HIDE_CURSOR", "civis", 59 | "T_CLEAR_SCREEN", "clear", 60 | "T_SGR0", "sgr0", 61 | "T_UNDERLINE", "smul", 62 | "T_BOLD", "bold", 63 | "T_BLINK", "blink", 64 | "T_REVERSE", "rev", 65 | "T_ENTER_KEYPAD", "smkx", 66 | "T_EXIT_KEYPAD", "rmkx" 67 | ] 68 | 69 | def iter_pairs(iterable): 70 | iterable = iter(iterable) 71 | while True: 72 | yield (next(iterable), next(iterable)) 73 | 74 | def do_term(term, nick): 75 | w("// %s\n" % term) 76 | w("var %s_keys = []string{\n\t" % nick) 77 | for k, v in iter_pairs(keys): 78 | w('"') 79 | w(escaped(tput(term, v))) 80 | w('",') 81 | w("\n}\n") 82 | w("var %s_funcs = []string{\n\t" % nick) 83 | for k,v in iter_pairs(funcs): 84 | w('"') 85 | if v == "sgr": 86 | w("\\033[3%d;4%dm") 87 | elif v == "cup": 88 | w("\\033[%d;%dH") 89 | else: 90 | w(escaped(tput(term, v))) 91 | w('", ') 92 | w("\n}\n\n") 93 | 94 | def do_terms(d): 95 | w("var terms = []struct {\n") 96 | w("\tname string\n") 97 | w("\tkeys []string\n") 98 | w("\tfuncs []string\n") 99 | w("}{\n") 100 | for k, v in d.items(): 101 | w('\t{"%s", %s_keys, %s_funcs},\n' % (k, v, v)) 102 | w("}\n\n") 103 | 104 | w("// +build !windows\n\npackage termbox\n\n") 105 | 106 | for k,v in terminals.items(): 107 | do_term(k, v) 108 | 109 | do_terms(terminals) 110 | 111 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/escwait.go: -------------------------------------------------------------------------------- 1 | // +build !darwin 2 | 3 | package termbox 4 | 5 | // On all systems other than macOS, disable behavior which will wait before 6 | // deciding that the escape key was pressed, to account for partially send 7 | // escape sequences, especially with regard to lengthy mouse sequences. 8 | // See https://github.com/nsf/termbox-go/issues/132 9 | func enable_wait_for_escape_sequence() bool { 10 | return false 11 | } 12 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/escwait_darwin.go: -------------------------------------------------------------------------------- 1 | package termbox 2 | 3 | // On macOS, enable behavior which will wait before deciding that the escape 4 | // key was pressed, to account for partially send escape sequences, especially 5 | // with regard to lengthy mouse sequences. 6 | // See https://github.com/nsf/termbox-go/issues/132 7 | func enable_wait_for_escape_sequence() bool { 8 | return true 9 | } 10 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package termbox 4 | 5 | /* 6 | #include 7 | #include 8 | */ 9 | import "C" 10 | 11 | type syscall_Termios C.struct_termios 12 | 13 | const ( 14 | syscall_IGNBRK = C.IGNBRK 15 | syscall_BRKINT = C.BRKINT 16 | syscall_PARMRK = C.PARMRK 17 | syscall_ISTRIP = C.ISTRIP 18 | syscall_INLCR = C.INLCR 19 | syscall_IGNCR = C.IGNCR 20 | syscall_ICRNL = C.ICRNL 21 | syscall_IXON = C.IXON 22 | syscall_OPOST = C.OPOST 23 | syscall_ECHO = C.ECHO 24 | syscall_ECHONL = C.ECHONL 25 | syscall_ICANON = C.ICANON 26 | syscall_ISIG = C.ISIG 27 | syscall_IEXTEN = C.IEXTEN 28 | syscall_CSIZE = C.CSIZE 29 | syscall_PARENB = C.PARENB 30 | syscall_CS8 = C.CS8 31 | syscall_VMIN = C.VMIN 32 | syscall_VTIME = C.VTIME 33 | 34 | // on darwin change these to (on *bsd too?): 35 | // C.TIOCGETA 36 | // C.TIOCSETA 37 | syscall_TCGETS = C.TCGETS 38 | syscall_TCSETS = C.TCSETS 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_darwin.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | // +build !amd64 5 | 6 | package termbox 7 | 8 | type syscall_Termios struct { 9 | Iflag uint32 10 | Oflag uint32 11 | Cflag uint32 12 | Lflag uint32 13 | Cc [20]uint8 14 | Ispeed uint32 15 | Ospeed uint32 16 | } 17 | 18 | const ( 19 | syscall_IGNBRK = 0x1 20 | syscall_BRKINT = 0x2 21 | syscall_PARMRK = 0x8 22 | syscall_ISTRIP = 0x20 23 | syscall_INLCR = 0x40 24 | syscall_IGNCR = 0x80 25 | syscall_ICRNL = 0x100 26 | syscall_IXON = 0x200 27 | syscall_OPOST = 0x1 28 | syscall_ECHO = 0x8 29 | syscall_ECHONL = 0x10 30 | syscall_ICANON = 0x100 31 | syscall_ISIG = 0x80 32 | syscall_IEXTEN = 0x400 33 | syscall_CSIZE = 0x300 34 | syscall_PARENB = 0x1000 35 | syscall_CS8 = 0x300 36 | syscall_VMIN = 0x10 37 | syscall_VTIME = 0x11 38 | 39 | syscall_TCGETS = 0x402c7413 40 | syscall_TCSETS = 0x802c7414 41 | ) 42 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_darwin_amd64.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint64 8 | Oflag uint64 9 | Cflag uint64 10 | Lflag uint64 11 | Cc [20]uint8 12 | Pad_cgo_0 [4]byte 13 | Ispeed uint64 14 | Ospeed uint64 15 | } 16 | 17 | const ( 18 | syscall_IGNBRK = 0x1 19 | syscall_BRKINT = 0x2 20 | syscall_PARMRK = 0x8 21 | syscall_ISTRIP = 0x20 22 | syscall_INLCR = 0x40 23 | syscall_IGNCR = 0x80 24 | syscall_ICRNL = 0x100 25 | syscall_IXON = 0x200 26 | syscall_OPOST = 0x1 27 | syscall_ECHO = 0x8 28 | syscall_ECHONL = 0x10 29 | syscall_ICANON = 0x100 30 | syscall_ISIG = 0x80 31 | syscall_IEXTEN = 0x400 32 | syscall_CSIZE = 0x300 33 | syscall_PARENB = 0x1000 34 | syscall_CS8 = 0x300 35 | syscall_VMIN = 0x10 36 | syscall_VTIME = 0x11 37 | 38 | syscall_TCGETS = 0x40487413 39 | syscall_TCSETS = 0x80487414 40 | ) 41 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_dragonfly.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed uint32 13 | Ospeed uint32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_freebsd.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed uint32 13 | Ospeed uint32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_linux.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | import "syscall" 7 | 8 | type syscall_Termios syscall.Termios 9 | 10 | const ( 11 | syscall_IGNBRK = syscall.IGNBRK 12 | syscall_BRKINT = syscall.BRKINT 13 | syscall_PARMRK = syscall.PARMRK 14 | syscall_ISTRIP = syscall.ISTRIP 15 | syscall_INLCR = syscall.INLCR 16 | syscall_IGNCR = syscall.IGNCR 17 | syscall_ICRNL = syscall.ICRNL 18 | syscall_IXON = syscall.IXON 19 | syscall_OPOST = syscall.OPOST 20 | syscall_ECHO = syscall.ECHO 21 | syscall_ECHONL = syscall.ECHONL 22 | syscall_ICANON = syscall.ICANON 23 | syscall_ISIG = syscall.ISIG 24 | syscall_IEXTEN = syscall.IEXTEN 25 | syscall_CSIZE = syscall.CSIZE 26 | syscall_PARENB = syscall.PARENB 27 | syscall_CS8 = syscall.CS8 28 | syscall_VMIN = syscall.VMIN 29 | syscall_VTIME = syscall.VTIME 30 | 31 | syscall_TCGETS = syscall.TCGETS 32 | syscall_TCSETS = syscall.TCSETS 33 | ) 34 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_netbsd.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed int32 13 | Ospeed int32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_openbsd.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs syscalls.go 3 | 4 | package termbox 5 | 6 | type syscall_Termios struct { 7 | Iflag uint32 8 | Oflag uint32 9 | Cflag uint32 10 | Lflag uint32 11 | Cc [20]uint8 12 | Ispeed int32 13 | Ospeed int32 14 | } 15 | 16 | const ( 17 | syscall_IGNBRK = 0x1 18 | syscall_BRKINT = 0x2 19 | syscall_PARMRK = 0x8 20 | syscall_ISTRIP = 0x20 21 | syscall_INLCR = 0x40 22 | syscall_IGNCR = 0x80 23 | syscall_ICRNL = 0x100 24 | syscall_IXON = 0x200 25 | syscall_OPOST = 0x1 26 | syscall_ECHO = 0x8 27 | syscall_ECHONL = 0x10 28 | syscall_ICANON = 0x100 29 | syscall_ISIG = 0x80 30 | syscall_IEXTEN = 0x400 31 | syscall_CSIZE = 0x300 32 | syscall_PARENB = 0x1000 33 | syscall_CS8 = 0x300 34 | syscall_VMIN = 0x10 35 | syscall_VTIME = 0x11 36 | 37 | syscall_TCGETS = 0x402c7413 38 | syscall_TCSETS = 0x802c7414 39 | ) 40 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/syscalls_windows.go: -------------------------------------------------------------------------------- 1 | // Created by cgo -godefs - DO NOT EDIT 2 | // cgo -godefs -- -DUNICODE syscalls.go 3 | 4 | package termbox 5 | 6 | const ( 7 | foreground_blue = 0x1 8 | foreground_green = 0x2 9 | foreground_red = 0x4 10 | foreground_intensity = 0x8 11 | background_blue = 0x10 12 | background_green = 0x20 13 | background_red = 0x40 14 | background_intensity = 0x80 15 | std_input_handle = -0xa 16 | std_output_handle = -0xb 17 | key_event = 0x1 18 | mouse_event = 0x2 19 | window_buffer_size_event = 0x4 20 | enable_window_input = 0x8 21 | enable_mouse_input = 0x10 22 | enable_extended_flags = 0x80 23 | 24 | vk_f1 = 0x70 25 | vk_f2 = 0x71 26 | vk_f3 = 0x72 27 | vk_f4 = 0x73 28 | vk_f5 = 0x74 29 | vk_f6 = 0x75 30 | vk_f7 = 0x76 31 | vk_f8 = 0x77 32 | vk_f9 = 0x78 33 | vk_f10 = 0x79 34 | vk_f11 = 0x7a 35 | vk_f12 = 0x7b 36 | vk_insert = 0x2d 37 | vk_delete = 0x2e 38 | vk_home = 0x24 39 | vk_end = 0x23 40 | vk_pgup = 0x21 41 | vk_pgdn = 0x22 42 | vk_arrow_up = 0x26 43 | vk_arrow_down = 0x28 44 | vk_arrow_left = 0x25 45 | vk_arrow_right = 0x27 46 | vk_backspace = 0x8 47 | vk_tab = 0x9 48 | vk_enter = 0xd 49 | vk_esc = 0x1b 50 | vk_space = 0x20 51 | 52 | left_alt_pressed = 0x2 53 | left_ctrl_pressed = 0x8 54 | right_alt_pressed = 0x1 55 | right_ctrl_pressed = 0x4 56 | shift_pressed = 0x10 57 | 58 | generic_read = 0x80000000 59 | generic_write = 0x40000000 60 | console_textmode_buffer = 0x1 61 | ) 62 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/termbox_common.go: -------------------------------------------------------------------------------- 1 | package termbox 2 | 3 | // private API, common OS agnostic part 4 | 5 | type cellbuf struct { 6 | width int 7 | height int 8 | cells []Cell 9 | } 10 | 11 | func (this *cellbuf) init(width, height int) { 12 | this.width = width 13 | this.height = height 14 | this.cells = make([]Cell, width*height) 15 | } 16 | 17 | func (this *cellbuf) resize(width, height int) { 18 | if this.width == width && this.height == height { 19 | return 20 | } 21 | 22 | oldw := this.width 23 | oldh := this.height 24 | oldcells := this.cells 25 | 26 | this.init(width, height) 27 | this.clear() 28 | 29 | minw, minh := oldw, oldh 30 | 31 | if width < minw { 32 | minw = width 33 | } 34 | if height < minh { 35 | minh = height 36 | } 37 | 38 | for i := 0; i < minh; i++ { 39 | srco, dsto := i*oldw, i*width 40 | src := oldcells[srco : srco+minw] 41 | dst := this.cells[dsto : dsto+minw] 42 | copy(dst, src) 43 | } 44 | } 45 | 46 | func (this *cellbuf) clear() { 47 | for i := range this.cells { 48 | c := &this.cells[i] 49 | c.Ch = ' ' 50 | c.Fg = foreground 51 | c.Bg = background 52 | } 53 | } 54 | 55 | const cursor_hidden = -1 56 | 57 | func is_cursor_hidden(x, y int) bool { 58 | return x == cursor_hidden || y == cursor_hidden 59 | } 60 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/terminfo.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | // This file contains a simple and incomplete implementation of the terminfo 3 | // database. Information was taken from the ncurses manpages term(5) and 4 | // terminfo(5). Currently, only the string capabilities for special keys and for 5 | // functions without parameters are actually used. Colors are still done with 6 | // ANSI escape sequences. Other special features that are not (yet?) supported 7 | // are reading from ~/.terminfo, the TERMINFO_DIRS variable, Berkeley database 8 | // format and extended capabilities. 9 | 10 | package termbox 11 | 12 | import ( 13 | "bytes" 14 | "encoding/binary" 15 | "encoding/hex" 16 | "errors" 17 | "fmt" 18 | "io/ioutil" 19 | "os" 20 | "strings" 21 | ) 22 | 23 | const ( 24 | ti_magic = 0432 25 | ti_header_length = 12 26 | ti_mouse_enter = "\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h" 27 | ti_mouse_leave = "\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l" 28 | ) 29 | 30 | func load_terminfo() ([]byte, error) { 31 | var data []byte 32 | var err error 33 | 34 | term := os.Getenv("TERM") 35 | if term == "" { 36 | return nil, fmt.Errorf("termbox: TERM not set") 37 | } 38 | 39 | // The following behaviour follows the one described in terminfo(5) as 40 | // distributed by ncurses. 41 | 42 | terminfo := os.Getenv("TERMINFO") 43 | if terminfo != "" { 44 | // if TERMINFO is set, no other directory should be searched 45 | return ti_try_path(terminfo) 46 | } 47 | 48 | // next, consider ~/.terminfo 49 | home := os.Getenv("HOME") 50 | if home != "" { 51 | data, err = ti_try_path(home + "/.terminfo") 52 | if err == nil { 53 | return data, nil 54 | } 55 | } 56 | 57 | // next, TERMINFO_DIRS 58 | dirs := os.Getenv("TERMINFO_DIRS") 59 | if dirs != "" { 60 | for _, dir := range strings.Split(dirs, ":") { 61 | if dir == "" { 62 | // "" -> "/usr/share/terminfo" 63 | dir = "/usr/share/terminfo" 64 | } 65 | data, err = ti_try_path(dir) 66 | if err == nil { 67 | return data, nil 68 | } 69 | } 70 | } 71 | 72 | // next, /lib/terminfo 73 | data, err = ti_try_path("/lib/terminfo") 74 | if err == nil { 75 | return data, nil 76 | } 77 | 78 | // fall back to /usr/share/terminfo 79 | return ti_try_path("/usr/share/terminfo") 80 | } 81 | 82 | func ti_try_path(path string) (data []byte, err error) { 83 | // load_terminfo already made sure it is set 84 | term := os.Getenv("TERM") 85 | 86 | // first try, the typical *nix path 87 | terminfo := path + "/" + term[0:1] + "/" + term 88 | data, err = ioutil.ReadFile(terminfo) 89 | if err == nil { 90 | return 91 | } 92 | 93 | // fallback to darwin specific dirs structure 94 | terminfo = path + "/" + hex.EncodeToString([]byte(term[:1])) + "/" + term 95 | data, err = ioutil.ReadFile(terminfo) 96 | return 97 | } 98 | 99 | func setup_term_builtin() error { 100 | name := os.Getenv("TERM") 101 | if name == "" { 102 | return errors.New("termbox: TERM environment variable not set") 103 | } 104 | 105 | for _, t := range terms { 106 | if t.name == name { 107 | keys = t.keys 108 | funcs = t.funcs 109 | return nil 110 | } 111 | } 112 | 113 | compat_table := []struct { 114 | partial string 115 | keys []string 116 | funcs []string 117 | }{ 118 | {"xterm", xterm_keys, xterm_funcs}, 119 | {"rxvt", rxvt_unicode_keys, rxvt_unicode_funcs}, 120 | {"linux", linux_keys, linux_funcs}, 121 | {"Eterm", eterm_keys, eterm_funcs}, 122 | {"screen", screen_keys, screen_funcs}, 123 | // let's assume that 'cygwin' is xterm compatible 124 | {"cygwin", xterm_keys, xterm_funcs}, 125 | {"st", xterm_keys, xterm_funcs}, 126 | } 127 | 128 | // try compatibility variants 129 | for _, it := range compat_table { 130 | if strings.Contains(name, it.partial) { 131 | keys = it.keys 132 | funcs = it.funcs 133 | return nil 134 | } 135 | } 136 | 137 | return errors.New("termbox: unsupported terminal") 138 | } 139 | 140 | func setup_term() (err error) { 141 | var data []byte 142 | var header [6]int16 143 | var str_offset, table_offset int16 144 | 145 | data, err = load_terminfo() 146 | if err != nil { 147 | return setup_term_builtin() 148 | } 149 | 150 | rd := bytes.NewReader(data) 151 | // 0: magic number, 1: size of names section, 2: size of boolean section, 3: 152 | // size of numbers section (in integers), 4: size of the strings section (in 153 | // integers), 5: size of the string table 154 | 155 | err = binary.Read(rd, binary.LittleEndian, header[:]) 156 | if err != nil { 157 | return 158 | } 159 | 160 | number_sec_len := int16(2) 161 | if header[0] == 542 { // doc says it should be octal 0542, but what I see it terminfo files is 542, learn to program please... thank you.. 162 | number_sec_len = 4 163 | } 164 | 165 | if (header[1]+header[2])%2 != 0 { 166 | // old quirk to align everything on word boundaries 167 | header[2] += 1 168 | } 169 | str_offset = ti_header_length + header[1] + header[2] + number_sec_len*header[3] 170 | table_offset = str_offset + 2*header[4] 171 | 172 | keys = make([]string, 0xFFFF-key_min) 173 | for i, _ := range keys { 174 | keys[i], err = ti_read_string(rd, str_offset+2*ti_keys[i], table_offset) 175 | if err != nil { 176 | return 177 | } 178 | } 179 | funcs = make([]string, t_max_funcs) 180 | // the last two entries are reserved for mouse. because the table offset is 181 | // not there, the two entries have to fill in manually 182 | for i, _ := range funcs[:len(funcs)-2] { 183 | funcs[i], err = ti_read_string(rd, str_offset+2*ti_funcs[i], table_offset) 184 | if err != nil { 185 | return 186 | } 187 | } 188 | funcs[t_max_funcs-2] = ti_mouse_enter 189 | funcs[t_max_funcs-1] = ti_mouse_leave 190 | return nil 191 | } 192 | 193 | func ti_read_string(rd *bytes.Reader, str_off, table int16) (string, error) { 194 | var off int16 195 | 196 | _, err := rd.Seek(int64(str_off), 0) 197 | if err != nil { 198 | return "", err 199 | } 200 | err = binary.Read(rd, binary.LittleEndian, &off) 201 | if err != nil { 202 | return "", err 203 | } 204 | _, err = rd.Seek(int64(table+off), 0) 205 | if err != nil { 206 | return "", err 207 | } 208 | var bs []byte 209 | for { 210 | b, err := rd.ReadByte() 211 | if err != nil { 212 | return "", err 213 | } 214 | if b == byte(0x00) { 215 | break 216 | } 217 | bs = append(bs, b) 218 | } 219 | return string(bs), nil 220 | } 221 | 222 | // "Maps" the function constants from termbox.go to the number of the respective 223 | // string capability in the terminfo file. Taken from (ncurses) term.h. 224 | var ti_funcs = []int16{ 225 | 28, 40, 16, 13, 5, 39, 36, 27, 26, 34, 89, 88, 226 | } 227 | 228 | // Same as above for the special keys. 229 | var ti_keys = []int16{ 230 | 66, 68 /* apparently not a typo; 67 is F10 for whatever reason */, 69, 70, 231 | 71, 72, 73, 74, 75, 67, 216, 217, 77, 59, 76, 164, 82, 81, 87, 61, 79, 83, 232 | } 233 | -------------------------------------------------------------------------------- /vendor/github.com/nsf/termbox-go/terminfo_builtin.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package termbox 4 | 5 | // Eterm 6 | var eterm_keys = []string{ 7 | "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 8 | } 9 | var eterm_funcs = []string{ 10 | "\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "", 11 | } 12 | 13 | // screen 14 | var screen_keys = []string{ 15 | "\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC", 16 | } 17 | var screen_funcs = []string{ 18 | "\x1b[?1049h", "\x1b[?1049l", "\x1b[34h\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave, 19 | } 20 | 21 | // xterm 22 | var xterm_keys = []string{ 23 | "\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1bOH", "\x1bOF", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC", 24 | } 25 | var xterm_funcs = []string{ 26 | "\x1b[?1049h", "\x1b[?1049l", "\x1b[?12l\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b(B\x1b[m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave, 27 | } 28 | 29 | // rxvt-unicode 30 | var rxvt_unicode_keys = []string{ 31 | "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 32 | } 33 | var rxvt_unicode_funcs = []string{ 34 | "\x1b[?1049h", "\x1b[r\x1b[?1049l", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x1b(B", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave, 35 | } 36 | 37 | // linux 38 | var linux_keys = []string{ 39 | "\x1b[[A", "\x1b[[B", "\x1b[[C", "\x1b[[D", "\x1b[[E", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 40 | } 41 | var linux_funcs = []string{ 42 | "", "", "\x1b[?25h\x1b[?0c", "\x1b[?25l\x1b[?1c", "\x1b[H\x1b[J", "\x1b[0;10m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "", 43 | } 44 | 45 | // rxvt-256color 46 | var rxvt_256color_keys = []string{ 47 | "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", 48 | } 49 | var rxvt_256color_funcs = []string{ 50 | "\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave, 51 | } 52 | 53 | var terms = []struct { 54 | name string 55 | keys []string 56 | funcs []string 57 | }{ 58 | {"Eterm", eterm_keys, eterm_funcs}, 59 | {"screen", screen_keys, screen_funcs}, 60 | {"xterm", xterm_keys, xterm_funcs}, 61 | {"rxvt-unicode", rxvt_unicode_keys, rxvt_unicode_funcs}, 62 | {"linux", linux_keys, linux_funcs}, 63 | {"rxvt-256color", rxvt_256color_keys, rxvt_256color_funcs}, 64 | } 65 | -------------------------------------------------------------------------------- /vendor/github.com/wuxibin89/redis-go-cluster/README.md: -------------------------------------------------------------------------------- 1 | # redis-go-cluster 2 | redis-go-cluster is a golang implementation of redis client based on Gary Burd's 3 | [Redigo](https://github.com/garyburd/redigo). It caches slot info at local and 4 | updates it automatically when cluster change. The client manages a connection pool 5 | for each node, uses goroutine to execute as concurrently as possible, which leads 6 | to its high efficiency and low lantency. 7 | 8 | **Supported**: 9 | * Most commands of keys, strings, lists, sets, sorted sets, hashes. 10 | * MGET/MSET 11 | * Pipelining 12 | 13 | **NOT supported**: 14 | * Cluster commands 15 | * Pub/Sub 16 | * Transaction 17 | * Lua script 18 | 19 | ## Documentation 20 | [API Reference](https://godoc.org/github.com/chasex/redis-go-cluster) 21 | 22 | ## Installation 23 | Install redis-go-cluster with go tool: 24 | ``` 25 | go get github.com/chasex/redis-go-cluster 26 | ``` 27 | 28 | ## Usage 29 | To use redis cluster, you need import the package and create a new cluster client 30 | with an options: 31 | ```go 32 | import "github.com/chasex/redis-go-cluster" 33 | 34 | cluster, err := redis.NewCluster( 35 | &redis.Options{ 36 | StartNodes: []string{"127.0.0.1:7000", "127.0.0.1:7001", "127.0.0.1:7002"}, 37 | ConnTimeout: 50 * time.Millisecond, 38 | ReadTimeout: 50 * time.Millisecond, 39 | WriteTimeout: 50 * time.Millisecond, 40 | KeepAlive: 16, 41 | AliveTime: 60 * time.Second, 42 | }) 43 | ``` 44 | 45 | ### Basic 46 | redis-go-cluster has compatible interface to [Redigo](https://github.com/garyburd/redigo), 47 | which uses a print-like API for all redis commands. When executing a command, it need a key 48 | to hash to a slot, then find the corresponding redis node. Do method will choose first 49 | argument in args as the key, so commands which are independent from keys are not supported, 50 | such as SYNC, BGSAVE, RANDOMKEY, etc. 51 | 52 | **RESTRICTION**: Please be sure the first argument in args is key. 53 | 54 | See full redis commands: http://www.redis.io/commands 55 | 56 | ```go 57 | cluster.Do("SET", "foo", "bar") 58 | cluster.Do("INCR", "mycount", 1) 59 | cluster.Do("LPUSH", "mylist", "foo", "bar") 60 | cluster.Do("HMSET", "myhash", "f1", "foo", "f2", "bar") 61 | ``` 62 | You can use help functions to convert reply to int, float, string, etc. 63 | ```go 64 | reply, err := Int(cluster.Do("INCR", "mycount", 1)) 65 | reply, err := String(cluster.Do("GET", "foo")) 66 | reply, err := Strings(cluster.Do("LRANGE", "mylist", 0, -1)) 67 | reply, err := StringMap(cluster.Do("HGETALL", "myhash")) 68 | ``` 69 | Also, you can use Values and Scan to convert replies to multiple values with different types. 70 | ```go 71 | _, err := cluster.Do("MSET", "key1", "foo", "key2", 1024, "key3", 3.14, "key4", "false") 72 | reply, err := Values(cluster.Do("MGET", "key1", "key2", "key3", "key4")) 73 | var val1 string 74 | var val2 int 75 | reply, err = Scan(reply, &val1, &val2) 76 | var val3 float64 77 | reply, err = Scan(reply, &val3) 78 | var val4 bool 79 | reply, err = Scan(reply, &val4) 80 | 81 | ``` 82 | 83 | ### Multi-keys 84 | Mutiple keys command - MGET/MSET are supported using result aggregation. 85 | Processing steps are as follows: 86 | - First, split the keys into multiple nodes according to their hash slot. 87 | - Then, start a goroutine for each node to excute MGET/MSET commands and wait them finish. 88 | - Last, collect and rerange all replies, return back to caller. 89 | 90 | **NOTE**: Since the keys may spread across mutiple node, there's no atomicity gurantee that 91 | all keys will be set at once. It's possible that some keys are set while others are not. 92 | 93 | ### Pipelining 94 | Pipelining is supported through the Batch interface. You can put multiple commands into a 95 | batch as long as it is supported by Do method. RunBatch will split these command to distinct 96 | nodes and start a goroutine for each node. Commands hash to same nodes will be merged and sent 97 | using pipelining. After all commands done, it rearrange results as MGET/MSET do. Result is a 98 | slice of each command's reply, you can use Scan to convert them to other types. 99 | ```go 100 | batch := cluster.NewBatch() 101 | err = batch.Put("LPUSH", "country_list", "France") 102 | err = batch.Put("LPUSH", "country_list", "Italy") 103 | err = batch.Put("LPUSH", "country_list", "Germany") 104 | err = batch.Put("INCRBY", "countries", 3) 105 | err = batch.Put("LRANGE", "country_list", 0, -1) 106 | reply, err = cluster.RunBatch(batch) 107 | 108 | var resp int 109 | for i := 0; i < 4; i++ { 110 | reply, err = redis.Scan(reply, &resp) 111 | } 112 | 113 | countries, err := Strings(reply[0], nil) 114 | ``` 115 | 116 | ## Contact 117 | Bug reports and feature requests are welcome. 118 | If you have any question, please email me wuxibin2012@gmail.com. 119 | 120 | ## License 121 | redis-go-cluster is available under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). 122 | -------------------------------------------------------------------------------- /vendor/github.com/wuxibin89/redis-go-cluster/batch.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Joel Wu 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "fmt" 19 | ) 20 | 21 | // Batch pack multiple commands, which should be supported by Do method. 22 | type Batch struct { 23 | cluster *Cluster 24 | batches []nodeBatch 25 | index []int 26 | } 27 | 28 | type nodeBatch struct { 29 | node *redisNode 30 | cmds []nodeCommand 31 | 32 | err error 33 | done chan int 34 | } 35 | 36 | type nodeCommand struct { 37 | cmd string 38 | args []interface{} 39 | reply interface{} 40 | err error 41 | } 42 | 43 | // NewBatch create a new batch to pack mutiple commands. 44 | func (cluster *Cluster) NewBatch() *Batch { 45 | return &Batch{ 46 | cluster: cluster, 47 | batches: make([]nodeBatch, 0), 48 | index: make([]int, 0), 49 | } 50 | } 51 | 52 | // Put add a redis command to batch, DO NOT put MGET/MSET/MSETNX. 53 | func (batch *Batch) Put(cmd string, args ...interface{}) error { 54 | if len(args) < 1 { 55 | return fmt.Errorf("Put: no key found in args") 56 | } 57 | 58 | if cmd == "MGET" || cmd == "MSET" || cmd == "MSETNX" { 59 | return fmt.Errorf("Put: %s not supported", cmd) 60 | } 61 | 62 | node, err := batch.cluster.getNodeByKey(args[0]) 63 | if err != nil { 64 | return fmt.Errorf("Put: %v", err) 65 | } 66 | 67 | var i int 68 | for i = 0; i < len(batch.batches); i++ { 69 | if batch.batches[i].node == node { 70 | batch.batches[i].cmds = append(batch.batches[i].cmds, 71 | nodeCommand{cmd: cmd, args: args}) 72 | 73 | batch.index = append(batch.index, i) 74 | break 75 | } 76 | } 77 | 78 | if i == len(batch.batches) { 79 | batch.batches = append(batch.batches, 80 | nodeBatch{ 81 | node: node, 82 | cmds: []nodeCommand{{cmd: cmd, args: args}}, 83 | done: make(chan int)}) 84 | batch.index = append(batch.index, i) 85 | } 86 | 87 | return nil 88 | } 89 | 90 | // RunBatch execute commands in batch simutaneously. If multiple commands are 91 | // directed to the same node, they will be merged and sent at once using pipeling. 92 | func (cluster *Cluster) RunBatch(bat *Batch) ([]interface{}, error) { 93 | for i := range bat.batches { 94 | go doBatch(&bat.batches[i]) 95 | } 96 | 97 | for i := range bat.batches { 98 | <-bat.batches[i].done 99 | } 100 | 101 | var replies []interface{} 102 | for _, i := range bat.index { 103 | if bat.batches[i].err != nil { 104 | return nil, bat.batches[i].err 105 | } 106 | 107 | replies = append(replies, bat.batches[i].cmds[0].reply) 108 | bat.batches[i].cmds = bat.batches[i].cmds[1:] 109 | } 110 | 111 | return replies, nil 112 | } 113 | 114 | func doBatch(batch *nodeBatch) { 115 | conn, err := batch.node.getConn() 116 | if err != nil { 117 | batch.err = err 118 | batch.done <- 1 119 | return 120 | } 121 | 122 | for i := range batch.cmds { 123 | conn.send(batch.cmds[i].cmd, batch.cmds[i].args...) 124 | } 125 | 126 | err = conn.flush() 127 | if err != nil { 128 | batch.err = err 129 | conn.shutdown() 130 | batch.done <- 1 131 | return 132 | } 133 | 134 | for i := range batch.cmds { 135 | reply, err := conn.receive() 136 | if err != nil { 137 | batch.err = err 138 | conn.shutdown() 139 | batch.done <- 1 140 | return 141 | } 142 | 143 | batch.cmds[i].reply, batch.cmds[i].err = reply, err 144 | } 145 | 146 | batch.node.releaseConn(conn) 147 | batch.done <- 1 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/wuxibin89/redis-go-cluster/crc16.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2001-2010 Georges Menie (www.menie.org) 3 | * Copyright 2010-2012 Salvatore Sanfilippo (adapted to Redis coding style) 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of the University of California, Berkeley nor the 15 | * names of its contributors may be used to endorse or promote products 16 | * derived from this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY 19 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | 30 | /* CRC16 implementation according to CCITT standards. 31 | * 32 | * Note by @antirez: this is actually the XMODEM CRC 16 algorithm, using the 33 | * following parameters: 34 | * 35 | * Name : "XMODEM", also known as "ZMODEM", "CRC-16/ACORN" 36 | * Width : 16 bit 37 | * Poly : 1021 (That is actually x^16 + x^12 + x^5 + 1) 38 | * Initialization : 0000 39 | * Reflect Input byte : False 40 | * Reflect Output CRC : False 41 | * Xor constant to output CRC : 0000 42 | * Output for "123456789" : 31C3 43 | */ 44 | 45 | package redis 46 | 47 | var crc16tab = [256]uint16{ 48 | 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, 49 | 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, 50 | 0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, 51 | 0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, 52 | 0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, 53 | 0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, 54 | 0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, 55 | 0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, 56 | 0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, 57 | 0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, 58 | 0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, 59 | 0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, 60 | 0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, 61 | 0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, 62 | 0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, 63 | 0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, 64 | 0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, 65 | 0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, 66 | 0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, 67 | 0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, 68 | 0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, 69 | 0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, 70 | 0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, 71 | 0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, 72 | 0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, 73 | 0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, 74 | 0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, 75 | 0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, 76 | 0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, 77 | 0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, 78 | 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, 79 | 0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0, 80 | } 81 | 82 | func crc16(buf string) uint16 { 83 | var crc uint16 84 | for _, n := range buf { 85 | crc = (crc<>uint16(8)) ^ uint16(n))&0x00FF]; 86 | } 87 | return crc 88 | } 89 | -------------------------------------------------------------------------------- /vendor/github.com/wuxibin89/redis-go-cluster/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Joel Wu 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | /* 16 | Package redis implement a pure redis cluster client, meaning it doesn't 17 | support any cluster commands. 18 | 19 | Create a new cluster client with specified options: 20 | 21 | cluster, err := redis.NewCluster( 22 | &redis.Options{ 23 | StartNodes: []string{"127.0.0.1:7000", "127.0.0.1:7001", "127.0.0.1:7002"}, 24 | ConnTimeout: 50 * time.Millisecond, 25 | ReadTimeout: 50 * time.Millisecond, 26 | WriteTimeout: 50 * time.Millisecond, 27 | KeepAlive: 16, 28 | AliveTime: 60 * time.Second, 29 | }) 30 | 31 | For basic usage: 32 | 33 | cluster.Do("SET", "foo", "bar") 34 | cluster.Do("INCR", "mycount", 1) 35 | cluster.Do("LPUSH", "mylist", "foo", "bar") 36 | cluster.Do("HMSET", "myhash", "f1", "foo", "f2", "bar") 37 | 38 | Use convert help functions to convert replies to int, float, string, etc: 39 | 40 | reply, err := Int(cluster.Do("INCR", "mycount", 1)) 41 | reply, err := String(cluster.Do("GET", "foo")) 42 | reply, err := Strings(cluster.Do("LRANGE", "mylist", 0, -1)) 43 | reply, err := StringMap(cluster.Do("HGETALL", "myhash")) 44 | 45 | Use batch interface to pack multiple commands for pipelining: 46 | 47 | batch := cluster.NewBatch() 48 | batch.Put("LPUSH", "country_list", "France") 49 | batch.Put("LPUSH", "country_list", "Italy") 50 | batch.Put("LPUSH", "country_list", "Germany") 51 | batch.Put("INCRBY", "countries", 3) 52 | batch.Put("LRANGE", "country_list", 0, -1) 53 | */ 54 | package redis 55 | -------------------------------------------------------------------------------- /vendor/github.com/wuxibin89/redis-go-cluster/multi.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Joel Wu 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 | // not use this file except in compliance with the License. You may obtain 5 | // a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | // License for the specific language governing permissions and limitations 13 | // under the License. 14 | 15 | package redis 16 | 17 | import ( 18 | "fmt" 19 | ) 20 | 21 | type multiTask struct { 22 | node *redisNode 23 | slot uint16 24 | 25 | cmd string 26 | args []interface{} 27 | 28 | reply interface{} 29 | replies []interface{} 30 | err error 31 | 32 | done chan int 33 | } 34 | 35 | func (cluster *Cluster) multiSet(cmd string, args ...interface{}) (interface{}, error) { 36 | if len(args) & 1 != 0 { 37 | return nil, fmt.Errorf("multiSet: invalid args %v", args) 38 | } 39 | 40 | tasks := make([]*multiTask, 0) 41 | 42 | cluster.rwLock.RLock() 43 | for i := 0; i < len(args); i += 2 { 44 | key, err := key(args[i]) 45 | if err != nil { 46 | cluster.rwLock.RUnlock() 47 | return nil, fmt.Errorf("multiSet: invalid key %v", args[i]) 48 | } 49 | 50 | slot := hash(key) 51 | 52 | var j int 53 | for j = 0; j < len(tasks); j++ { 54 | if tasks[j].slot == slot { 55 | tasks[j].args = append(tasks[j].args, args[i]) // key 56 | tasks[j].args = append(tasks[j].args, args[i+1]) // value 57 | 58 | break 59 | } 60 | } 61 | 62 | if j == len(tasks) { 63 | node := cluster.slots[slot] 64 | if node == nil { 65 | cluster.rwLock.RUnlock() 66 | return nil, fmt.Errorf("multiSet: %s[%d] no node found", key, slot) 67 | } 68 | 69 | task := &multiTask{ 70 | node: node, 71 | slot: slot, 72 | cmd: cmd, 73 | args: []interface{}{args[i], args[i+1]}, 74 | done: make(chan int), 75 | } 76 | tasks = append(tasks, task) 77 | } 78 | } 79 | cluster.rwLock.RUnlock() 80 | 81 | for i := range tasks { 82 | go handleSetTask(tasks[i]) 83 | } 84 | 85 | for i := range tasks { 86 | <-tasks[i].done 87 | } 88 | 89 | for i := range tasks { 90 | _, err := String(tasks[i].reply, tasks[i].err) 91 | if err != nil { 92 | return nil, err 93 | } 94 | } 95 | 96 | return "OK", nil 97 | } 98 | 99 | func (cluster *Cluster) multiGet(cmd string, args ...interface{}) (interface{}, error) { 100 | tasks := make([]*multiTask, 0) 101 | index := make([]*multiTask, len(args)) 102 | 103 | cluster.rwLock.RLock() 104 | for i := 0; i < len(args); i++ { 105 | key, err := key(args[i]) 106 | if err != nil { 107 | cluster.rwLock.RUnlock() 108 | return nil, fmt.Errorf("multiGet: invalid key %v", args[i]) 109 | } 110 | 111 | slot := hash(key) 112 | 113 | var j int 114 | for j = 0; j < len(tasks); j++ { 115 | if tasks[j].slot == slot { 116 | tasks[j].args = append(tasks[j].args, args[i]) // key 117 | index[i] = tasks[j] 118 | 119 | break 120 | } 121 | } 122 | 123 | if j == len(tasks) { 124 | node := cluster.slots[slot] 125 | if node == nil { 126 | cluster.rwLock.RUnlock() 127 | return nil, fmt.Errorf("multiGet: %s[%d] no node found", key, slot) 128 | } 129 | 130 | task := &multiTask{ 131 | node: node, 132 | slot: slot, 133 | cmd: cmd, 134 | args: []interface{}{args[i]}, 135 | done: make(chan int), 136 | } 137 | tasks = append(tasks, task) 138 | index[i] = tasks[j] 139 | } 140 | } 141 | cluster.rwLock.RUnlock() 142 | 143 | for i := range tasks { 144 | go handleGetTask(tasks[i]) 145 | } 146 | 147 | for i := range tasks { 148 | <-tasks[i].done 149 | } 150 | 151 | reply := make([]interface{}, len(args)) 152 | for i := range reply { 153 | if index[i].err != nil { 154 | return nil, index[i].err 155 | } 156 | 157 | if len(index[i].replies) < 0 { 158 | panic("unreachable") 159 | } 160 | 161 | reply[i] = index[i].replies[0] 162 | index[i].replies = index[i].replies[1:] 163 | } 164 | 165 | return reply, nil 166 | } 167 | 168 | func handleSetTask(task *multiTask) { 169 | task.reply, task.err = task.node.do(task.cmd, task.args...) 170 | task.done <- 1 171 | } 172 | 173 | func handleGetTask(task *multiTask) { 174 | task.replies, task.err = Values(task.node.do(task.cmd, task.args...)) 175 | task.done <- 1 176 | } 177 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/LICENSE.libyaml: -------------------------------------------------------------------------------- 1 | The following files were ported to Go from C files of libyaml, and thus 2 | are still covered by their original copyright and license: 3 | 4 | apic.go 5 | emitterc.go 6 | parserc.go 7 | readerc.go 8 | scannerc.go 9 | writerc.go 10 | yamlh.go 11 | yamlprivateh.go 12 | 13 | Copyright (c) 2006 Kirill Simonov 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy of 16 | this software and associated documentation files (the "Software"), to deal in 17 | the Software without restriction, including without limitation the rights to 18 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 19 | of the Software, and to permit persons to whom the Software is furnished to do 20 | so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2011-2016 Canonical Ltd. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/README.md: -------------------------------------------------------------------------------- 1 | # YAML support for the Go language 2 | 3 | Introduction 4 | ------------ 5 | 6 | The yaml package enables Go programs to comfortably encode and decode YAML 7 | values. It was developed within [Canonical](https://www.canonical.com) as 8 | part of the [juju](https://juju.ubuntu.com) project, and is based on a 9 | pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML) 10 | C library to parse and generate YAML data quickly and reliably. 11 | 12 | Compatibility 13 | ------------- 14 | 15 | The yaml package supports most of YAML 1.1 and 1.2, including support for 16 | anchors, tags, map merging, etc. Multi-document unmarshalling is not yet 17 | implemented, and base-60 floats from YAML 1.1 are purposefully not 18 | supported since they're a poor design and are gone in YAML 1.2. 19 | 20 | Installation and usage 21 | ---------------------- 22 | 23 | The import path for the package is *gopkg.in/yaml.v2*. 24 | 25 | To install it, run: 26 | 27 | go get gopkg.in/yaml.v2 28 | 29 | API documentation 30 | ----------------- 31 | 32 | If opened in a browser, the import path itself leads to the API documentation: 33 | 34 | * [https://gopkg.in/yaml.v2](https://gopkg.in/yaml.v2) 35 | 36 | API stability 37 | ------------- 38 | 39 | The package API for yaml v2 will remain stable as described in [gopkg.in](https://gopkg.in). 40 | 41 | 42 | License 43 | ------- 44 | 45 | The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. 46 | 47 | 48 | Example 49 | ------- 50 | 51 | ```Go 52 | package main 53 | 54 | import ( 55 | "fmt" 56 | "log" 57 | 58 | "gopkg.in/yaml.v2" 59 | ) 60 | 61 | var data = ` 62 | a: Easy! 63 | b: 64 | c: 2 65 | d: [3, 4] 66 | ` 67 | 68 | // Note: struct fields must be public in order for unmarshal to 69 | // correctly populate the data. 70 | type T struct { 71 | A string 72 | B struct { 73 | RenamedC int `yaml:"c"` 74 | D []int `yaml:",flow"` 75 | } 76 | } 77 | 78 | func main() { 79 | t := T{} 80 | 81 | err := yaml.Unmarshal([]byte(data), &t) 82 | if err != nil { 83 | log.Fatalf("error: %v", err) 84 | } 85 | fmt.Printf("--- t:\n%v\n\n", t) 86 | 87 | d, err := yaml.Marshal(&t) 88 | if err != nil { 89 | log.Fatalf("error: %v", err) 90 | } 91 | fmt.Printf("--- t dump:\n%s\n\n", string(d)) 92 | 93 | m := make(map[interface{}]interface{}) 94 | 95 | err = yaml.Unmarshal([]byte(data), &m) 96 | if err != nil { 97 | log.Fatalf("error: %v", err) 98 | } 99 | fmt.Printf("--- m:\n%v\n\n", m) 100 | 101 | d, err = yaml.Marshal(&m) 102 | if err != nil { 103 | log.Fatalf("error: %v", err) 104 | } 105 | fmt.Printf("--- m dump:\n%s\n\n", string(d)) 106 | } 107 | ``` 108 | 109 | This example will generate the following output: 110 | 111 | ``` 112 | --- t: 113 | {Easy! {2 [3 4]}} 114 | 115 | --- t dump: 116 | a: Easy! 117 | b: 118 | c: 2 119 | d: [3, 4] 120 | 121 | 122 | --- m: 123 | map[a:Easy! b:map[c:2 d:[3 4]]] 124 | 125 | --- m dump: 126 | a: Easy! 127 | b: 128 | c: 2 129 | d: 130 | - 3 131 | - 4 132 | ``` 133 | 134 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/go.mod: -------------------------------------------------------------------------------- 1 | module "gopkg.in/yaml.v2" 2 | 3 | require ( 4 | "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405 5 | ) 6 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/resolve.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "encoding/base64" 5 | "math" 6 | "regexp" 7 | "strconv" 8 | "strings" 9 | "time" 10 | ) 11 | 12 | type resolveMapItem struct { 13 | value interface{} 14 | tag string 15 | } 16 | 17 | var resolveTable = make([]byte, 256) 18 | var resolveMap = make(map[string]resolveMapItem) 19 | 20 | func init() { 21 | t := resolveTable 22 | t[int('+')] = 'S' // Sign 23 | t[int('-')] = 'S' 24 | for _, c := range "0123456789" { 25 | t[int(c)] = 'D' // Digit 26 | } 27 | for _, c := range "yYnNtTfFoO~" { 28 | t[int(c)] = 'M' // In map 29 | } 30 | t[int('.')] = '.' // Float (potentially in map) 31 | 32 | var resolveMapList = []struct { 33 | v interface{} 34 | tag string 35 | l []string 36 | }{ 37 | {true, yaml_BOOL_TAG, []string{"y", "Y", "yes", "Yes", "YES"}}, 38 | {true, yaml_BOOL_TAG, []string{"true", "True", "TRUE"}}, 39 | {true, yaml_BOOL_TAG, []string{"on", "On", "ON"}}, 40 | {false, yaml_BOOL_TAG, []string{"n", "N", "no", "No", "NO"}}, 41 | {false, yaml_BOOL_TAG, []string{"false", "False", "FALSE"}}, 42 | {false, yaml_BOOL_TAG, []string{"off", "Off", "OFF"}}, 43 | {nil, yaml_NULL_TAG, []string{"", "~", "null", "Null", "NULL"}}, 44 | {math.NaN(), yaml_FLOAT_TAG, []string{".nan", ".NaN", ".NAN"}}, 45 | {math.Inf(+1), yaml_FLOAT_TAG, []string{".inf", ".Inf", ".INF"}}, 46 | {math.Inf(+1), yaml_FLOAT_TAG, []string{"+.inf", "+.Inf", "+.INF"}}, 47 | {math.Inf(-1), yaml_FLOAT_TAG, []string{"-.inf", "-.Inf", "-.INF"}}, 48 | {"<<", yaml_MERGE_TAG, []string{"<<"}}, 49 | } 50 | 51 | m := resolveMap 52 | for _, item := range resolveMapList { 53 | for _, s := range item.l { 54 | m[s] = resolveMapItem{item.v, item.tag} 55 | } 56 | } 57 | } 58 | 59 | const longTagPrefix = "tag:yaml.org,2002:" 60 | 61 | func shortTag(tag string) string { 62 | // TODO This can easily be made faster and produce less garbage. 63 | if strings.HasPrefix(tag, longTagPrefix) { 64 | return "!!" + tag[len(longTagPrefix):] 65 | } 66 | return tag 67 | } 68 | 69 | func longTag(tag string) string { 70 | if strings.HasPrefix(tag, "!!") { 71 | return longTagPrefix + tag[2:] 72 | } 73 | return tag 74 | } 75 | 76 | func resolvableTag(tag string) bool { 77 | switch tag { 78 | case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG: 79 | return true 80 | } 81 | return false 82 | } 83 | 84 | var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`) 85 | 86 | func resolve(tag string, in string) (rtag string, out interface{}) { 87 | if !resolvableTag(tag) { 88 | return tag, in 89 | } 90 | 91 | defer func() { 92 | switch tag { 93 | case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: 94 | return 95 | case yaml_FLOAT_TAG: 96 | if rtag == yaml_INT_TAG { 97 | switch v := out.(type) { 98 | case int64: 99 | rtag = yaml_FLOAT_TAG 100 | out = float64(v) 101 | return 102 | case int: 103 | rtag = yaml_FLOAT_TAG 104 | out = float64(v) 105 | return 106 | } 107 | } 108 | } 109 | failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag)) 110 | }() 111 | 112 | // Any data is accepted as a !!str or !!binary. 113 | // Otherwise, the prefix is enough of a hint about what it might be. 114 | hint := byte('N') 115 | if in != "" { 116 | hint = resolveTable[in[0]] 117 | } 118 | if hint != 0 && tag != yaml_STR_TAG && tag != yaml_BINARY_TAG { 119 | // Handle things we can lookup in a map. 120 | if item, ok := resolveMap[in]; ok { 121 | return item.tag, item.value 122 | } 123 | 124 | // Base 60 floats are a bad idea, were dropped in YAML 1.2, and 125 | // are purposefully unsupported here. They're still quoted on 126 | // the way out for compatibility with other parser, though. 127 | 128 | switch hint { 129 | case 'M': 130 | // We've already checked the map above. 131 | 132 | case '.': 133 | // Not in the map, so maybe a normal float. 134 | floatv, err := strconv.ParseFloat(in, 64) 135 | if err == nil { 136 | return yaml_FLOAT_TAG, floatv 137 | } 138 | 139 | case 'D', 'S': 140 | // Int, float, or timestamp. 141 | // Only try values as a timestamp if the value is unquoted or there's an explicit 142 | // !!timestamp tag. 143 | if tag == "" || tag == yaml_TIMESTAMP_TAG { 144 | t, ok := parseTimestamp(in) 145 | if ok { 146 | return yaml_TIMESTAMP_TAG, t 147 | } 148 | } 149 | 150 | plain := strings.Replace(in, "_", "", -1) 151 | intv, err := strconv.ParseInt(plain, 0, 64) 152 | if err == nil { 153 | if intv == int64(int(intv)) { 154 | return yaml_INT_TAG, int(intv) 155 | } else { 156 | return yaml_INT_TAG, intv 157 | } 158 | } 159 | uintv, err := strconv.ParseUint(plain, 0, 64) 160 | if err == nil { 161 | return yaml_INT_TAG, uintv 162 | } 163 | if yamlStyleFloat.MatchString(plain) { 164 | floatv, err := strconv.ParseFloat(plain, 64) 165 | if err == nil { 166 | return yaml_FLOAT_TAG, floatv 167 | } 168 | } 169 | if strings.HasPrefix(plain, "0b") { 170 | intv, err := strconv.ParseInt(plain[2:], 2, 64) 171 | if err == nil { 172 | if intv == int64(int(intv)) { 173 | return yaml_INT_TAG, int(intv) 174 | } else { 175 | return yaml_INT_TAG, intv 176 | } 177 | } 178 | uintv, err := strconv.ParseUint(plain[2:], 2, 64) 179 | if err == nil { 180 | return yaml_INT_TAG, uintv 181 | } 182 | } else if strings.HasPrefix(plain, "-0b") { 183 | intv, err := strconv.ParseInt("-" + plain[3:], 2, 64) 184 | if err == nil { 185 | if true || intv == int64(int(intv)) { 186 | return yaml_INT_TAG, int(intv) 187 | } else { 188 | return yaml_INT_TAG, intv 189 | } 190 | } 191 | } 192 | default: 193 | panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 194 | } 195 | } 196 | return yaml_STR_TAG, in 197 | } 198 | 199 | // encodeBase64 encodes s as base64 that is broken up into multiple lines 200 | // as appropriate for the resulting length. 201 | func encodeBase64(s string) string { 202 | const lineLen = 70 203 | encLen := base64.StdEncoding.EncodedLen(len(s)) 204 | lines := encLen/lineLen + 1 205 | buf := make([]byte, encLen*2+lines) 206 | in := buf[0:encLen] 207 | out := buf[encLen:] 208 | base64.StdEncoding.Encode(in, []byte(s)) 209 | k := 0 210 | for i := 0; i < len(in); i += lineLen { 211 | j := i + lineLen 212 | if j > len(in) { 213 | j = len(in) 214 | } 215 | k += copy(out[k:], in[i:j]) 216 | if lines > 1 { 217 | out[k] = '\n' 218 | k++ 219 | } 220 | } 221 | return string(out[:k]) 222 | } 223 | 224 | // This is a subset of the formats allowed by the regular expression 225 | // defined at http://yaml.org/type/timestamp.html. 226 | var allowedTimestampFormats = []string{ 227 | "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields. 228 | "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t". 229 | "2006-1-2 15:4:5.999999999", // space separated with no time zone 230 | "2006-1-2", // date only 231 | // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5" 232 | // from the set of examples. 233 | } 234 | 235 | // parseTimestamp parses s as a timestamp string and 236 | // returns the timestamp and reports whether it succeeded. 237 | // Timestamp formats are defined at http://yaml.org/type/timestamp.html 238 | func parseTimestamp(s string) (time.Time, bool) { 239 | // TODO write code to check all the formats supported by 240 | // http://yaml.org/type/timestamp.html instead of using time.Parse. 241 | 242 | // Quick check: all date formats start with YYYY-. 243 | i := 0 244 | for ; i < len(s); i++ { 245 | if c := s[i]; c < '0' || c > '9' { 246 | break 247 | } 248 | } 249 | if i != 4 || i == len(s) || s[i] != '-' { 250 | return time.Time{}, false 251 | } 252 | for _, format := range allowedTimestampFormats { 253 | if t, err := time.Parse(format, s); err == nil { 254 | return t, true 255 | } 256 | } 257 | return time.Time{}, false 258 | } 259 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/sorter.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | import ( 4 | "reflect" 5 | "unicode" 6 | ) 7 | 8 | type keyList []reflect.Value 9 | 10 | func (l keyList) Len() int { return len(l) } 11 | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 12 | func (l keyList) Less(i, j int) bool { 13 | a := l[i] 14 | b := l[j] 15 | ak := a.Kind() 16 | bk := b.Kind() 17 | for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() { 18 | a = a.Elem() 19 | ak = a.Kind() 20 | } 21 | for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() { 22 | b = b.Elem() 23 | bk = b.Kind() 24 | } 25 | af, aok := keyFloat(a) 26 | bf, bok := keyFloat(b) 27 | if aok && bok { 28 | if af != bf { 29 | return af < bf 30 | } 31 | if ak != bk { 32 | return ak < bk 33 | } 34 | return numLess(a, b) 35 | } 36 | if ak != reflect.String || bk != reflect.String { 37 | return ak < bk 38 | } 39 | ar, br := []rune(a.String()), []rune(b.String()) 40 | for i := 0; i < len(ar) && i < len(br); i++ { 41 | if ar[i] == br[i] { 42 | continue 43 | } 44 | al := unicode.IsLetter(ar[i]) 45 | bl := unicode.IsLetter(br[i]) 46 | if al && bl { 47 | return ar[i] < br[i] 48 | } 49 | if al || bl { 50 | return bl 51 | } 52 | var ai, bi int 53 | var an, bn int64 54 | if ar[i] == '0' || br[i] == '0' { 55 | for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- { 56 | if ar[j] != '0' { 57 | an = 1 58 | bn = 1 59 | break 60 | } 61 | } 62 | } 63 | for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ { 64 | an = an*10 + int64(ar[ai]-'0') 65 | } 66 | for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ { 67 | bn = bn*10 + int64(br[bi]-'0') 68 | } 69 | if an != bn { 70 | return an < bn 71 | } 72 | if ai != bi { 73 | return ai < bi 74 | } 75 | return ar[i] < br[i] 76 | } 77 | return len(ar) < len(br) 78 | } 79 | 80 | // keyFloat returns a float value for v if it is a number/bool 81 | // and whether it is a number/bool or not. 82 | func keyFloat(v reflect.Value) (f float64, ok bool) { 83 | switch v.Kind() { 84 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 85 | return float64(v.Int()), true 86 | case reflect.Float32, reflect.Float64: 87 | return v.Float(), true 88 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 89 | return float64(v.Uint()), true 90 | case reflect.Bool: 91 | if v.Bool() { 92 | return 1, true 93 | } 94 | return 0, true 95 | } 96 | return 0, false 97 | } 98 | 99 | // numLess returns whether a < b. 100 | // a and b must necessarily have the same kind. 101 | func numLess(a, b reflect.Value) bool { 102 | switch a.Kind() { 103 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 104 | return a.Int() < b.Int() 105 | case reflect.Float32, reflect.Float64: 106 | return a.Float() < b.Float() 107 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 108 | return a.Uint() < b.Uint() 109 | case reflect.Bool: 110 | return !a.Bool() && b.Bool() 111 | } 112 | panic("not a number") 113 | } 114 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/writerc.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | // Set the writer error and return false. 4 | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem string) bool { 5 | emitter.error = yaml_WRITER_ERROR 6 | emitter.problem = problem 7 | return false 8 | } 9 | 10 | // Flush the output buffer. 11 | func yaml_emitter_flush(emitter *yaml_emitter_t) bool { 12 | if emitter.write_handler == nil { 13 | panic("write handler not set") 14 | } 15 | 16 | // Check if the buffer is empty. 17 | if emitter.buffer_pos == 0 { 18 | return true 19 | } 20 | 21 | if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil { 22 | return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) 23 | } 24 | emitter.buffer_pos = 0 25 | return true 26 | } 27 | -------------------------------------------------------------------------------- /vendor/gopkg.in/yaml.v2/yamlprivateh.go: -------------------------------------------------------------------------------- 1 | package yaml 2 | 3 | const ( 4 | // The size of the input raw buffer. 5 | input_raw_buffer_size = 512 6 | 7 | // The size of the input buffer. 8 | // It should be possible to decode the whole raw buffer. 9 | input_buffer_size = input_raw_buffer_size * 3 10 | 11 | // The size of the output buffer. 12 | output_buffer_size = 128 13 | 14 | // The size of the output raw buffer. 15 | // It should be possible to encode the whole output buffer. 16 | output_raw_buffer_size = (output_buffer_size*2 + 2) 17 | 18 | // The size of other stacks and queues. 19 | initial_stack_size = 16 20 | initial_queue_size = 16 21 | initial_string_size = 16 22 | ) 23 | 24 | // Check if the character at the specified position is an alphabetical 25 | // character, a digit, '_', or '-'. 26 | func is_alpha(b []byte, i int) bool { 27 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'Z' || b[i] >= 'a' && b[i] <= 'z' || b[i] == '_' || b[i] == '-' 28 | } 29 | 30 | // Check if the character at the specified position is a digit. 31 | func is_digit(b []byte, i int) bool { 32 | return b[i] >= '0' && b[i] <= '9' 33 | } 34 | 35 | // Get the value of a digit. 36 | func as_digit(b []byte, i int) int { 37 | return int(b[i]) - '0' 38 | } 39 | 40 | // Check if the character at the specified position is a hex-digit. 41 | func is_hex(b []byte, i int) bool { 42 | return b[i] >= '0' && b[i] <= '9' || b[i] >= 'A' && b[i] <= 'F' || b[i] >= 'a' && b[i] <= 'f' 43 | } 44 | 45 | // Get the value of a hex-digit. 46 | func as_hex(b []byte, i int) int { 47 | bi := b[i] 48 | if bi >= 'A' && bi <= 'F' { 49 | return int(bi) - 'A' + 10 50 | } 51 | if bi >= 'a' && bi <= 'f' { 52 | return int(bi) - 'a' + 10 53 | } 54 | return int(bi) - '0' 55 | } 56 | 57 | // Check if the character is ASCII. 58 | func is_ascii(b []byte, i int) bool { 59 | return b[i] <= 0x7F 60 | } 61 | 62 | // Check if the character at the start of the buffer can be printed unescaped. 63 | func is_printable(b []byte, i int) bool { 64 | return ((b[i] == 0x0A) || // . == #x0A 65 | (b[i] >= 0x20 && b[i] <= 0x7E) || // #x20 <= . <= #x7E 66 | (b[i] == 0xC2 && b[i+1] >= 0xA0) || // #0xA0 <= . <= #xD7FF 67 | (b[i] > 0xC2 && b[i] < 0xED) || 68 | (b[i] == 0xED && b[i+1] < 0xA0) || 69 | (b[i] == 0xEE) || 70 | (b[i] == 0xEF && // #xE000 <= . <= #xFFFD 71 | !(b[i+1] == 0xBB && b[i+2] == 0xBF) && // && . != #xFEFF 72 | !(b[i+1] == 0xBF && (b[i+2] == 0xBE || b[i+2] == 0xBF)))) 73 | } 74 | 75 | // Check if the character at the specified position is NUL. 76 | func is_z(b []byte, i int) bool { 77 | return b[i] == 0x00 78 | } 79 | 80 | // Check if the beginning of the buffer is a BOM. 81 | func is_bom(b []byte, i int) bool { 82 | return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF 83 | } 84 | 85 | // Check if the character at the specified position is space. 86 | func is_space(b []byte, i int) bool { 87 | return b[i] == ' ' 88 | } 89 | 90 | // Check if the character at the specified position is tab. 91 | func is_tab(b []byte, i int) bool { 92 | return b[i] == '\t' 93 | } 94 | 95 | // Check if the character at the specified position is blank (space or tab). 96 | func is_blank(b []byte, i int) bool { 97 | //return is_space(b, i) || is_tab(b, i) 98 | return b[i] == ' ' || b[i] == '\t' 99 | } 100 | 101 | // Check if the character at the specified position is a line break. 102 | func is_break(b []byte, i int) bool { 103 | return (b[i] == '\r' || // CR (#xD) 104 | b[i] == '\n' || // LF (#xA) 105 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 106 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 107 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9) // PS (#x2029) 108 | } 109 | 110 | func is_crlf(b []byte, i int) bool { 111 | return b[i] == '\r' && b[i+1] == '\n' 112 | } 113 | 114 | // Check if the character is a line break or NUL. 115 | func is_breakz(b []byte, i int) bool { 116 | //return is_break(b, i) || is_z(b, i) 117 | return ( // is_break: 118 | b[i] == '\r' || // CR (#xD) 119 | b[i] == '\n' || // LF (#xA) 120 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 121 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 122 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 123 | // is_z: 124 | b[i] == 0) 125 | } 126 | 127 | // Check if the character is a line break, space, or NUL. 128 | func is_spacez(b []byte, i int) bool { 129 | //return is_space(b, i) || is_breakz(b, i) 130 | return ( // is_space: 131 | b[i] == ' ' || 132 | // is_breakz: 133 | b[i] == '\r' || // CR (#xD) 134 | b[i] == '\n' || // LF (#xA) 135 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 136 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 137 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 138 | b[i] == 0) 139 | } 140 | 141 | // Check if the character is a line break, space, tab, or NUL. 142 | func is_blankz(b []byte, i int) bool { 143 | //return is_blank(b, i) || is_breakz(b, i) 144 | return ( // is_blank: 145 | b[i] == ' ' || b[i] == '\t' || 146 | // is_breakz: 147 | b[i] == '\r' || // CR (#xD) 148 | b[i] == '\n' || // LF (#xA) 149 | b[i] == 0xC2 && b[i+1] == 0x85 || // NEL (#x85) 150 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA8 || // LS (#x2028) 151 | b[i] == 0xE2 && b[i+1] == 0x80 && b[i+2] == 0xA9 || // PS (#x2029) 152 | b[i] == 0) 153 | } 154 | 155 | // Determine the width of the character. 156 | func width(b byte) int { 157 | // Don't replace these by a switch without first 158 | // confirming that it is being inlined. 159 | if b&0x80 == 0x00 { 160 | return 1 161 | } 162 | if b&0xE0 == 0xC0 { 163 | return 2 164 | } 165 | if b&0xF0 == 0xE0 { 166 | return 3 167 | } 168 | if b&0xF8 == 0xF0 { 169 | return 4 170 | } 171 | return 0 172 | 173 | } 174 | -------------------------------------------------------------------------------- /vendor/vendor.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": "", 3 | "ignore": "test", 4 | "package": [ 5 | { 6 | "checksumSHA1": "rcoUTEGR7KVr963l6P1rlMaYCzA=", 7 | "path": "github.com/BurntSushi/toml", 8 | "revision": "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005", 9 | "revisionTime": "2018-08-15T10:47:33Z" 10 | }, 11 | { 12 | "checksumSHA1": "6X3O3mfvOyiwV2iAb5GjxARs08c=", 13 | "path": "github.com/garyburd/redigo/internal", 14 | "revision": "569eae59ada904ea8db7a225c2b47165af08735a", 15 | "revisionTime": "2018-04-04T16:07:26Z" 16 | }, 17 | { 18 | "checksumSHA1": "TRsWhl8gX4p8xoErljH/oyNmY5M=", 19 | "path": "github.com/garyburd/redigo/redis", 20 | "revision": "569eae59ada904ea8db7a225c2b47165af08735a", 21 | "revisionTime": "2018-04-04T16:07:26Z" 22 | }, 23 | { 24 | "checksumSHA1": "VNfjqXslphqEz06cae7eLV+r7dI=", 25 | "path": "github.com/jinzhu/configor", 26 | "revision": "4edaf76fe18865e36de734d887f4c01bd05707af", 27 | "revisionTime": "2018-06-14T02:44:15Z" 28 | }, 29 | { 30 | "checksumSHA1": "ZUSmRRRWHR5TuU8ji0+x/guIGGw=", 31 | "path": "github.com/jroimartin/gocui", 32 | "revision": "c055c87ae801372cd74a0839b972db4f7697ae5f", 33 | "revisionTime": "2018-04-11T15:50:10Z" 34 | }, 35 | { 36 | "checksumSHA1": "pXGkKptkpqusf7/ALDaZVJGSpJg=", 37 | "path": "github.com/mattn/go-runewidth", 38 | "revision": "703b5e6b11ae25aeb2af9ebb5d5fdf8fa2575211", 39 | "revisionTime": "2018-12-18T00:06:49Z" 40 | }, 41 | { 42 | "checksumSHA1": "P+gTDDaUGn6I+Y3ZzRR52xSENVg=", 43 | "path": "github.com/nsf/termbox-go", 44 | "revision": "eeb6cd0a176293eeb2c69270d83835972e3567bc", 45 | "revisionTime": "2019-06-24T07:25:49Z" 46 | }, 47 | { 48 | "checksumSHA1": "B7X1DQkP/pDh/fAG3BAlOEScDi4=", 49 | "path": "github.com/wuxibin89/redis-go-cluster", 50 | "revision": "222d81891f1d3fa7cf8b5655020352c3e5b4ec0f", 51 | "revisionTime": "2016-12-07T02:39:22Z" 52 | }, 53 | { 54 | "checksumSHA1": "oNqPrS2edE8peI3ah2INe379k8E=", 55 | "path": "gopkg.in/yaml.v2", 56 | "revision": "51d6538a90f86fe93ac480b35f37b2be17fef232", 57 | "revisionTime": "2018-11-15T11:05:04Z" 58 | } 59 | ], 60 | "rootPath": "github.com/liyue201/lazyredis" 61 | } 62 | --------------------------------------------------------------------------------