func (c *Client) doListen() error {
	dec := c.dec
	for {
		_, err := dec.ReadArrayHeader()
		if err == io.EOF {
			break
		} else if err != nil {
			c.log.Fatalf("Could not decode message slice length: %v", err)
		}
		t, err := dec.ReadInt()
		if err == io.EOF {
			break
		} else if err != nil {
			c.log.Fatalf("Could not decode message type: %v", err)
		}
		switch t {
		case 0:
			reqID, err := dec.ReadUint32()
			if err == io.EOF {
				break
			} else if err != nil {
				c.log.Fatalf("Could not decode request id: %v", err)
			}
			reqMeth, err := dec.ReadString()
			if err == io.EOF {
				break
			} else if err != nil {
				c.log.Fatalf("Could not decode request method name: %v", err)
			}
			newdecoderoptions, err := c.syncProvMap.Get(string(reqMeth))
			if err != nil {
				c.log.Fatalf("Could not find RequestHandler for method [%v]: %v\n", string(reqMeth), err)
			}
			opts := newdecoderoptions.MethodOptions
			expArgs := opts.ArgsLength()
			actArgs, err := dec.ReadArrayHeader()
			if err != nil {
				c.log.Fatalf("Could not decode request method args length: %v", err)
			}
			if expArgs != actArgs {
				c.log.Fatalf("Expected args length %v, but got %v", expArgs, actArgs)
			}
			dre := newdecoderoptions.NewSyncDecoder()
			if opts.Type == FUNCTION {
				err = dre.Args().DecodeMsg(c.dec)
				if err == io.EOF {
					break
				} else if err != nil {
					c.log.Fatalf("Could not decode request method args: %v", err)
				}
			} else {
				c.log.Fatalf("We can't support anything other than functions right now")
			}
			if dre.Params() != nil {
				dre.Params().DecodeParams(opts, dec)
			}
			if opts.Eval {
				dre.Eval().DecodeMsg(dec)
			}
			go func(reqID uint32, dre SyncDecoder) {
				mErr, err := dre.Run()
				if err != nil {
					c.log.Fatalf("Could not run method: %v\n", err)
				}
				err = c.sendResponse(reqID, mErr, dre)
				if err != nil {
					c.log.Fatalf("Could not send response: %v\n", err)
				}
			}(reqID, dre)
		case 1:
			reqID, err := dec.ReadUint32()
			if err == io.EOF {
				break
			} else if err != nil {
				c.log.Fatalf("Could not decode request id: %v", err)
			}
			re, err := dec.ReadIntf()
			if err == io.EOF {
				break
			} else if err != nil {
				c.log.Fatalf("Could not decode response error: %v", err)
			}
			if re != nil {
				re := re.([]interface{})
				errBytes := re[1].([]uint8)
				errString := make([]byte, len(errBytes))
				for i := range errBytes {
					errString[i] = byte(errBytes[i])
				}
				c.log.Fatalf("Got a response error for request %v: %v", reqID, string(errString))
			}
			rh, err := c.respMap.Get(reqID)
			if err == io.EOF {
				break
			} else if err != nil {
				c.log.Fatalf("Could not get response holder for %v: %v", reqID, err)
			}
			res, err := rh.dec()
			if err == io.EOF {
				break
			} else if err != nil {
				c.log.Fatalf("Could not decode response: %v\n", err)
			}
			resp := &response{obj: res, err: nil}
			rh.ch <- resp
		case 2:
			topic, err := dec.ReadString()
			if err == io.EOF {
				break
			} else if err != nil {
				c.log.Fatalf("Could not decode topic: %v", err)
			}
			newdecoderoptions, err := c.asyncProvMap.Get(string(topic))
			if err != nil {
				c.log.Fatalf("Could not find RequestHandler for method [%v]: %v\n", string(topic), err)
			}
			opts := newdecoderoptions.MethodOptions
			expArgs := opts.ArgsLength()
			actArgs, err := dec.ReadArrayHeader()
			if err != nil {
				c.log.Fatalf("Could not decode request method args length: %v", err)
			}
			if expArgs != actArgs {
				c.log.Fatalf("Expected args length %v, but got %v", expArgs, actArgs)
			}
			dr := newdecoderoptions.NewAsyncDecoder()
			if opts.Type == FUNCTION {
				err = dr.Args().DecodeMsg(c.dec)
				if err == io.EOF {
					break
				} else if err != nil {
					c.log.Fatalf("Could not decode request method args: %v", err)
				}
			} else {
				c.log.Fatalf("We can't support anything other than functions right now")
			}
			if dr.Params() != nil {
				dr.Params().DecodeParams(opts, dec)
			}
			if opts.Eval {
				dr.Eval().DecodeMsg(dec)
			}
			go func(dr AsyncDecoder) {
				err = dr.Run()
				if err != nil {
					c.log.Fatalf("Could not run async notification")
				}
			}(dr)
		default:
			c.log.Fatalf("Unexpected type of message: %v\n", t)
		}
	}
	return nil
}
TODO split this beast apart
package neovim
import (
	"io"
	_log "log"
	"net"
	"os"
	"os/exec"
	"sync/atomic"
	"github.com/juju/errors"
	"github.com/myitcv/neovim/apidef"
	"github.com/tinylib/msgp/msgp"
)
func NewUnixClient(im InitMethod, _net string, laddr, raddr *net.UnixAddr, log Logger) (*Client, error) {
	c, err := net.DialUnix(_net, laddr, raddr)
	if err != nil {
		return nil, errors.Annotatef(err, "could not establish connection to Neovim, _net %v, laddr %v, %v", _net, laddr, raddr)
	}
	return NewClient(im, c, log)
}
func NewCmdClient(im InitMethod, c *exec.Cmd, log Logger) (*Client, error) {
	stdin, err := c.StdinPipe()
	if err != nil {
		return nil, errors.Annotatef(err, "could not get a stdin pipe to embedded nvim")
	}
	stdout, err := c.StdoutPipe()
	if err != nil {
		return nil, errors.Annotatef(err, "could not get a stdout pipe to embedded nvim")
	}
	wrap := &StdWrapper{Stdin: stdin, Stdout: stdout}
	found := false
	for i := range c.Args {
		if c.Args[i] == "--embed" {
			found = true
		}
	}
	if !found {
		c.Args = append(c.Args, "--embed", "-N")
	}
	err = c.Start()
	if err != nil {
		return nil, errors.Annotatef(err, "could not start the embedded nvim")
	}
	return NewClient(im, wrap, log)
}
func NewClient(im InitMethod, c io.ReadWriteCloser, log Logger) (*Client, error) {
	if log == nil {
		log = _log.New(os.Stderr, "neovim ", _log.Llongfile|_log.Ldate|_log.Ltime)
	}
	res := &Client{rw: c}
	res.respMap = newRespSyncMap()
	res.syncProvMap = newSyncProvSyncMap()
	res.asyncProvMap = newAsyncProvSyncMap()
	res.dec = msgp.NewReader(c)
	res.enc = msgp.NewWriter(c)
	res.log = log
	res.KillChannel = make(chan struct{})
	err := res.syncProvMap.Put(_MethodInit, NewSyncDecoderOptions{NewSyncDecoder: func() SyncDecoder {
		res := &InitMethodWrapper{InitMethod: im, Client: res, args: &InitMethodArgs{}, results: &InitMethodRetVals{}}
		return res
	}, MethodOptions: &MethodOptions{Type: FUNCTION}})
	if err != nil {
		return nil, errors.Annotatef(err, "Could not add init method handler")
	}
	return res, nil
}
func (c *Client) Run() {
	go c.doListen()
}
func (c *Client) RegisterSyncFunction(m string, d NewSyncDecoder, rangeBased bool, eval bool) error {
	return c.RegisterSyncRequestHandler(m, d, &MethodOptions{
		Type:  FUNCTION,
		Range: rangeBased,
		Eval:  eval,
	})
}
func (c *Client) RegisterAsyncFunction(m string, d NewAsyncDecoder, rangeBased bool, eval bool) error {
	return c.RegisterAsyncRequestHandler(m, d, &MethodOptions{
		Type:  FUNCTION,
		Range: rangeBased,
		Eval:  eval,
	})
}
func (c *Client) RegisterSyncRequestHandler(m string, d NewSyncDecoder, o *MethodOptions) error {
	if m == _MethodInit {
		return errors.Errorf("Cannot register a provider with the protected method %v", _MethodInit)
	}
	err := c.syncProvMap.Put(m, NewSyncDecoderOptions{d, o})
	if err != nil {
		return errors.Annotatef(err, "Could not store RequestHanlder in provider map")
	}
	return nil
}
func (c *Client) RegisterAsyncRequestHandler(m string, d NewAsyncDecoder, o *MethodOptions) error {
	err := c.asyncProvMap.Put(m, NewAsyncDecoderOptions{d, o})
	if err != nil {
		return errors.Annotatef(err, "Could not store RequestHanlder in provider map")
	}
	return nil
}
func (c *Client) Close() error {
	c.lock.Lock()
	defer c.lock.Unlock()
	err := c.rw.Close()
	if err != nil {
		return c.panicOrReturn(errors.Annotatef(err, "Could not cleanly close client"))
	}
	return nil
}