Description: Drop_ply
--- a/ply/README.md
+++ /dev/null
@@ -1,180 +0,0 @@
-# Ply
-Property list pretty-printer powered by `howett.net/plist`.
-
-_verb. work with (a tool, especially one requiring steady, rhythmic movements)._
-
-## Installation
-
-`go get github.com/DHowett/go-plist/ply`
-
-## Usage
-
-```
-  ply [OPTIONS]
-
-Application Options:
-  -c, --convert=<format>    convert the property list to a new format (c=list for list) (pretty)
-  -k, --key=<keypath>       A keypath! (/)
-  -o, --out=<filename>      output filename
-  -I, --indent              indent indentable output formats (xml, openstep, gnustep, json)
-
-Help Options:
-  -h, --help                Show this help message
-```
-
-## Features
-
-### Keypath evaluation
-
-```
-$ ply file.plist
-{
-  x: {
-       y: {
-            z: 1024
-          }
-     }
-}
-$ ply -k x/y/z file.plist
-1024
-```
-
-Keypaths are composed of a number of path expressions:
-
-* `/name` - dictionary key access
-* `[i]` - index array, string, or data
-* `[i:j]` - silce array, string, or data in the range `[i, j)`
-* `!` - parse the data value as a property list and use it as the base of evaluation for further path components
-* `$(subexpression)` - evaluate `subexpression` and paste its value
-
-#### Examples
-
-Given the following property list:
-
-```
-{
-	a = {
-		b = {
-			c = (1, 2, 3);
-			d = hello;
-		};
-		data = <414243>;
-	};
-	sub = <7b0a0974 6869733d 22612064 69637469 6f6e6172 7920696e 73696465 20616e6f 74686572 20706c69 73742122 3b7d>;
-	hello = subexpression;
-}
-```
-
-##### pretty print
-```
-$ ply file.plist
-{
-  a: {
-       b: {
-            c: (
-                 [0]: 1
-                 [1]: 2
-                 [2]: 3
-               )
-            d: hello
-          }
-       data: 00000000  41 42 43                                          |ABC.............|
-     }
-  hello: subexpression
-  sub: 00000000  7b 0a 09 74 68 69 73 3d  22 61 20 64 69 63 74 69  |{..this="a dicti|
-       00000010  6f 6e 61 72 79 20 69 6e  73 69 64 65 20 61 6e 6f  |onary inside ano|
-       00000020  74 68 65 72 20 70 6c 69  73 74 21 22 3b 7d        |ther plist!";}..|
-}
-```
-
-##### consecutive dictionary keys
-```
-$ ply file.plist -k 'a/b/d'
-hello
-```
-
-##### array indexing
-```
-$ ply file.plist -k 'a/b/c[1]'
-2
-```
-
-##### data hexdump
-```
-$ ply file.plist -k 'a/data'
-00000000  41 42 43                                          |ABC.............|
-```
-
-##### data and array slicing
-```
-$ ply file.plist -k 'a/data[2:3]'
-00000000  43                                                |C...............|
-```
-
-```
-$ ply -k 'sub[0:10]' file.plist
-00000000  7b 0a 09 74 68 69 73 3d  22 61                    |{..this="a......|
-```
-
-##### subplist parsing
-```
-$ ply -k 'sub!' file.plist
-{
-  this: a dictionary inside another plist!
-}
-```
-
-##### subplist keypath evaluation
-```
-$ ply -k 'sub!/this' file.plist
-a dictionary inside another plist!
-```
-
-##### subexpression evaluation
-```
-$ ply -k '/$(/a/b/d)' file.plist
-subexpression
-```
-
-### Property list conversion
-
-`-c <format>`, or `-c list` to list them all.
-
-* Binary property list [`bplist`]
-* XML [`xml`]
-* GNUstep [`gnustep`, `gs`]
-* OpenStep [`openstep`, `os`]
-* JSON (for a subset of data types) [`json`]
-* YAML [`yaml`]
-
-#### Notes
-By default, ply will emit the most compact representation it can for a given format. The `-I` flag influences the inclusion of whitespace.
-
-Ply will overwrite the input file unless an output filename is specified with `-o <file>`.
-
-### Property list subsetting
-
-(and subset conversion)
-
-```
-$ ply -k '/a/b' -o file-a-b.plist -c openstep -I file.plist
-$ cat file-a-b.plist
-{
-	c = (
-		1,
-		2,
-		3,
-	);
-	d = hello;
-}
-```
-
-#### Subplist extraction
-
-```
-$ ply -k '/sub!' -o file-sub.plist -c openstep -I file.plist
-$ cat file-sub.plist
-{
-	this = "a dictionary inside another plist!";
-}
-```
--- a/ply/ply.go
+++ /dev/null
@@ -1,396 +0,0 @@
-package main
-
-import (
-	"bufio"
-	"bytes"
-	"encoding/binary"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"io"
-	"os"
-	"path/filepath"
-	"reflect"
-	"strconv"
-	"strings"
-
-	"github.com/jessevdk/go-flags"
-	"gopkg.in/yaml.v1"
-	"howett.net/plist"
-)
-
-//import "github.com/mgutz/ansi"
-
-const (
-	PrettyFormat = 100 + iota
-	JSONFormat
-	YAMLFormat
-	RawFormat
-)
-
-var nameFormatMap = map[string]int{
-	"x":        plist.XMLFormat,
-	"xml":      plist.XMLFormat,
-	"xml1":     plist.XMLFormat,
-	"b":        plist.BinaryFormat,
-	"bin":      plist.BinaryFormat,
-	"binary":   plist.BinaryFormat,
-	"binary1":  plist.BinaryFormat,
-	"o":        plist.OpenStepFormat,
-	"os":       plist.OpenStepFormat,
-	"openstep": plist.OpenStepFormat,
-	"step":     plist.OpenStepFormat,
-	"g":        plist.GNUStepFormat,
-	"gs":       plist.GNUStepFormat,
-	"gnustep":  plist.GNUStepFormat,
-	"pretty":   PrettyFormat,
-	"json":     JSONFormat,
-	"yaml":     YAMLFormat,
-	"r":        RawFormat,
-	"raw":      RawFormat,
-}
-
-var opts struct {
-	Convert string `short:"c" long:"convert" description:"convert the property list to a new format (c=list for list)" default:"pretty" value-name:"<format>"`
-	Keypath string `short:"k" long:"key" description:"A keypath!" default:"/" value-name:"<keypath>"`
-	Output  string `short:"o" long:"out" description:"output filename" default:"" value-name:"<filename>"`
-	Indent  bool   `short:"I" long:"indent" description:"indent indentable output formats (xml, openstep, gnustep, json)"`
-}
-
-func main() {
-	parser := flags.NewParser(&opts, flags.Default)
-	args, err := parser.Parse()
-	if err != nil {
-		parser.WriteHelp(os.Stderr)
-		fmt.Fprintln(os.Stderr, err)
-		return
-	}
-
-	if opts.Convert == "list" {
-		formats := make([]string, len(nameFormatMap))
-		i := 0
-		for k, _ := range nameFormatMap {
-			formats[i] = k
-			i++
-		}
-
-		fmt.Fprintln(os.Stderr, "Supported output formats:")
-		fmt.Fprintln(os.Stderr, strings.Join(formats, ", "))
-		return
-	}
-
-	if len(args) < 1 {
-		parser.WriteHelp(os.Stderr)
-		return
-	}
-
-	filename := args[0]
-
-	keypath := opts.Keypath
-	if len(keypath) == 0 {
-		c := strings.Index(filename, ":")
-		if c > -1 {
-			keypath = filename[c+1:]
-			filename = filename[:c]
-		}
-	}
-
-	file, err := os.Open(filename)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err.Error())
-		return
-	}
-
-	var val interface{}
-	switch strings.ToLower(filepath.Ext(filename)) {
-	case ".json", ".yaml", ".yml":
-		buf := &bytes.Buffer{}
-		io.Copy(buf, file)
-		err = yaml.Unmarshal(buf.Bytes(), &val)
-	default:
-		dec := plist.NewDecoder(file)
-		err = dec.Decode(&val)
-	}
-
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err.Error())
-		return
-	}
-	file.Close()
-
-	convert := strings.ToLower(opts.Convert)
-	format, ok := nameFormatMap[convert]
-	if !ok {
-		fmt.Fprintf(os.Stderr, "unknown output format %s\n", convert)
-		return
-	}
-
-	output := opts.Output
-	newline := false
-	var outputStream io.WriteCloser
-	if format < PrettyFormat && output == "" {
-		// Writing a plist, but no output filename. Save to original.
-		output = filename
-	} else if format >= PrettyFormat && output == "" {
-		// Writing a non-plist, but no output filename: Stdout
-		outputStream = os.Stdout
-		newline = true
-	} else if output == "-" {
-		// - means stdout.
-		outputStream = os.Stdout
-		newline = true
-	}
-
-	if outputStream == nil {
-		outfile, err := os.Create(output)
-		if err != nil {
-			fmt.Fprintln(os.Stderr, err.Error())
-			return
-		}
-		outputStream = outfile
-	}
-
-	keypathContext := &KeypathWalker{}
-	rval, err := keypathContext.WalkKeypath(reflect.ValueOf(val), keypath)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, err.Error())
-		return
-	}
-	val = rval.Interface()
-
-	switch {
-	case format >= 0 && format < PrettyFormat:
-		enc := plist.NewEncoderForFormat(outputStream, format)
-		if opts.Indent {
-			enc.Indent("\t")
-		}
-		err := enc.Encode(val)
-		if err != nil {
-			fmt.Fprintln(os.Stderr, err.Error())
-			return
-		}
-	case format == PrettyFormat:
-		PrettyPrint(outputStream, rval.Interface())
-	case format == JSONFormat:
-		var out []byte
-		var err error
-		if opts.Indent {
-			out, err = json.MarshalIndent(val, "", "\t")
-		} else {
-			out, err = json.Marshal(val)
-		}
-		if err != nil {
-			fmt.Fprintln(os.Stderr, err.Error())
-			return
-		}
-		outputStream.Write(out)
-	case format == YAMLFormat:
-		out, err := yaml.Marshal(val)
-		if err != nil {
-			fmt.Fprintln(os.Stderr, err.Error())
-			return
-		}
-		outputStream.Write(out)
-	case format == RawFormat:
-		newline = false
-		switch rval.Kind() {
-		case reflect.String:
-			outputStream.Write([]byte(val.(string)))
-		case reflect.Slice:
-			if rval.Elem().Kind() == reflect.Uint8 {
-				outputStream.Write(val.([]byte))
-			}
-		default:
-			binary.Write(outputStream, binary.LittleEndian, val)
-		}
-	}
-	if newline {
-		fmt.Fprintf(outputStream, "\n")
-	}
-	outputStream.Close()
-}
-
-type KeypathWalker struct {
-	rootVal *reflect.Value
-	curVal  reflect.Value
-}
-
-func (ctx *KeypathWalker) Split(data []byte, atEOF bool) (advance int, token []byte, err error) {
-	mode, oldmode := 0, 0
-	depth := 0
-	tok, subexpr := "", ""
-	// modes:
-	// 0: normal string, separated by /
-	// 1: array index (reading between [])
-	// 2: found $, looking for ( or nothing
-	// 3: found $(, reading subkey, looking for )
-	// 4: "escape"? unused as yet.
-	if len(data) == 0 && atEOF {
-		return 0, nil, io.EOF
-	}
-each:
-	for _, v := range data {
-		advance++
-		switch {
-		case mode == 4:
-			// Completing an escape sequence.
-			tok += string(v)
-			mode = 0
-			continue each
-		case mode == 0 && v == '/':
-			if tok != "" {
-				break each
-			} else {
-				continue each
-			}
-		case mode == 0 && v == '[':
-			if tok != "" {
-				// We have encountered a [ after text, we want only the text
-				advance-- // We don't want to consume this character.
-				break each
-			} else {
-				tok += string(v)
-				mode = 1
-			}
-		case mode == 1 && v == ']':
-			mode = 0
-			tok += string(v)
-			break each
-		case mode == 0 && v == '!':
-			if tok == "" {
-				tok = "!"
-				break each
-			} else {
-				// We have encountered a ! after text, we want the text
-				advance-- // We don't want to consume this character.
-				break each
-			}
-		case (mode == 0 || mode == 1) && v == '$':
-			oldmode = mode
-			mode = 2
-		case mode == 2:
-			if v == '(' {
-				mode = 3
-				depth++
-				subexpr = ""
-			} else {
-				// We didn't emit the $ to begin with, so we have to do it here.
-				tok += "$" + string(v)
-				mode = 0
-			}
-		case mode == 3 && v == '(':
-			subexpr += string(v)
-			depth++
-		case mode == 3 && v == ')':
-			depth--
-			if depth == 0 {
-				newCtx := &KeypathWalker{rootVal: ctx.rootVal}
-				subexprVal, e := newCtx.WalkKeypath(*ctx.rootVal, subexpr)
-				if e != nil {
-					return 0, nil, errors.New("Dynamic subexpression " + subexpr + " failed: " + e.Error())
-				}
-				if subexprVal.Kind() == reflect.Interface {
-					subexprVal = subexprVal.Elem()
-				}
-				s := ""
-				if subexprVal.Kind() == reflect.String {
-					s = subexprVal.String()
-				} else if subexprVal.Kind() == reflect.Uint64 {
-					s = strconv.Itoa(int(subexprVal.Uint()))
-				} else {
-					return 0, nil, errors.New("Dynamic subexpression " + subexpr + " evaluated to non-string/non-int.")
-				}
-				tok += s
-				mode = oldmode
-			} else {
-				subexpr += string(v)
-			}
-		case mode == 3:
-			subexpr += string(v)
-		default:
-			tok += string(v)
-		}
-
-	}
-	return advance, []byte(tok), nil
-}
-
-func (ctx *KeypathWalker) WalkKeypath(val reflect.Value, keypath string) (reflect.Value, error) {
-	if keypath == "" {
-		return val, nil
-	}
-
-	if ctx.rootVal == nil {
-		ctx.rootVal = &val
-	}
-
-	ctx.curVal = val
-
-	scanner := bufio.NewScanner(strings.NewReader(keypath))
-	scanner.Split(ctx.Split)
-	for scanner.Scan() {
-		token := scanner.Text()
-		if ctx.curVal.Kind() == reflect.Interface {
-			ctx.curVal = ctx.curVal.Elem()
-		}
-
-		switch {
-		case len(token) == 0:
-			continue
-		case token[0] == '[': // array
-			s := token[1 : len(token)-1]
-			if ctx.curVal.Kind() != reflect.Slice && ctx.curVal.Kind() != reflect.String {
-				return reflect.ValueOf(nil), errors.New("keypath attempted to index non-indexable with " + s)
-			}
-
-			colon := strings.Index(s, ":")
-			if colon > -1 {
-				var err error
-				var si, sj int
-				is := s[:colon]
-				js := s[colon+1:]
-				if is != "" {
-					si, err = strconv.Atoi(is)
-					if err != nil {
-						return reflect.ValueOf(nil), err
-					}
-				}
-				if js != "" {
-					sj, err = strconv.Atoi(js)
-					if err != nil {
-						return reflect.ValueOf(nil), err
-					}
-				}
-				if si < 0 || sj > ctx.curVal.Len() {
-					return reflect.ValueOf(nil), errors.New("keypath attempted to index outside of indexable with " + s)
-				}
-				ctx.curVal = ctx.curVal.Slice(si, sj)
-			} else {
-				idx, _ := strconv.Atoi(s)
-				ctx.curVal = ctx.curVal.Index(idx)
-			}
-		case token[0] == '!': // subplist!
-			if ctx.curVal.Kind() != reflect.Slice || ctx.curVal.Type().Elem().Kind() != reflect.Uint8 {
-				return reflect.Value{}, errors.New("Attempted to subplist non-data.")
-			}
-			byt := ctx.curVal.Interface().([]uint8)
-			buf := bytes.NewReader(byt)
-			dec := plist.NewDecoder(buf)
-			var subval interface{}
-			dec.Decode(&subval)
-			ctx.curVal = reflect.ValueOf(subval)
-		default: // just a string
-			if ctx.curVal.Kind() != reflect.Map {
-				return reflect.ValueOf(nil), errors.New("keypath attempted to descend into non-map using key " + token)
-			}
-			if token != "" {
-				ctx.curVal = ctx.curVal.MapIndex(reflect.ValueOf(token))
-			}
-		}
-	}
-	err := scanner.Err()
-	if err != nil {
-		return reflect.ValueOf(nil), err
-	}
-	return ctx.curVal, nil
-}
--- a/ply/prettyprint.go
+++ /dev/null
@@ -1,117 +0,0 @@
-package main
-
-import (
-	"encoding/hex"
-	"fmt"
-	"io"
-	"reflect"
-	"sort"
-	"time"
-)
-
-func PrettyPrint(w io.Writer, val interface{}) {
-	printValue(w, val, "")
-}
-
-func printMap(w io.Writer, tv reflect.Value, depth string) {
-	fmt.Fprintf(w, "{\n")
-	ss := make(sort.StringSlice, tv.Len())
-	i := 0
-	for _, kval := range tv.MapKeys() {
-		if kval.Kind() == reflect.Interface {
-			kval = kval.Elem()
-		}
-
-		if kval.Kind() != reflect.String {
-			continue
-		}
-
-		ss[i] = kval.String()
-		i++
-	}
-	sort.Sort(ss)
-	for _, k := range ss {
-		val := tv.MapIndex(reflect.ValueOf(k))
-		v := val.Interface()
-		nd := depth + "  "
-		for i := 0; i < len(k)+2; i++ {
-			nd += " "
-		}
-		fmt.Fprintf(w, "  %s%s: ", depth, k)
-		printValue(w, v, nd)
-	}
-	fmt.Fprintf(w, "%s}\n", depth)
-}
-
-func printValue(w io.Writer, val interface{}, depth string) {
-	switch tv := val.(type) {
-	case map[interface{}]interface{}:
-		printMap(w, reflect.ValueOf(tv), depth)
-	case map[string]interface{}:
-		printMap(w, reflect.ValueOf(tv), depth)
-	case []interface{}:
-		fmt.Fprintf(w, "(\n")
-		for i, v := range tv {
-			id := fmt.Sprintf("[%d]", i)
-			nd := depth + "  "
-			for i := 0; i < len(id)+2; i++ {
-				nd += " "
-			}
-			fmt.Fprintf(w, "  %s%s: ", depth, id)
-			printValue(w, v, nd)
-		}
-		fmt.Fprintf(w, "%s)\n", depth)
-	case int64, uint64, string, float32, float64, bool, time.Time:
-		fmt.Fprintf(w, "%+v\n", tv)
-	case uint8:
-		fmt.Fprintf(w, "0x%2.02x\n", tv)
-	case []byte:
-		l := len(tv)
-		sxl := l / 16
-		if l%16 > 0 {
-			sxl++
-		}
-		sxl *= 16
-		var buf [4]byte
-		var off [8]byte
-		var asc [16]byte
-		var ol int
-		for i := 0; i < sxl; i++ {
-			if i%16 == 0 {
-				if i > 0 {
-					io.WriteString(w, depth)
-				}
-				buf[0] = byte(i >> 24)
-				buf[1] = byte(i >> 16)
-				buf[2] = byte(i >> 8)
-				buf[3] = byte(i)
-				hex.Encode(off[:], buf[:])
-				io.WriteString(w, string(off[:])+"  ")
-			}
-			if i < l {
-				hex.Encode(off[:], tv[i:i+1])
-				if tv[i] < 32 || tv[i] > 126 {
-					asc[i%16] = '.'
-				} else {
-					asc[i%16] = tv[i]
-				}
-			} else {
-				off[0] = ' '
-				off[1] = ' '
-				asc[i%16] = '.'
-			}
-			off[2] = ' '
-			ol = 3
-			if i%16 == 7 || i%16 == 15 {
-				off[3] = ' '
-				ol = 4
-			}
-			io.WriteString(w, string(off[:ol]))
-			if i%16 == 15 {
-				io.WriteString(w, "|"+string(asc[:])+"|\n")
-			}
-		}
-	default:
-		fmt.Fprintf(w, "%#v\n", val)
-	}
-}
