def complete_message(buf):
    """returns msg,buf_remaining or None,buf"""
    lines = buf.split('\r\n')
    if len(lines) <= 1:
        return None, buf
    nargs_raw = lines.pop(0)
    assert nargs_raw[0] == '*'
    nargs = int(nargs_raw[1:])
    args = []
    while len(lines) >= 2:
        if lines[0][0] == '+':
            args.append(lines.pop(0))
        elif lines[0][0] == ':':
            args.append(int(lines.pop(0)[1:]))
        elif lines[0][0] == '$':
            if len(lines) < 3:
                return None, buf
            slen, s = int(lines[0][1:]), lines[1]
            if slen != len(s):
                raise ValueError('length mismatch %s %r' % (slen, s))
            lines = lines[2:]
            args.append(s)
        else:
            raise ValueError('expected initial code in %r' % lines)
    if len(args) == nargs:
        return args, '\r\n'.join(lines)
    else:
        return None, buf
