func StringToSlice(str string) (output Table) {
	colSep := regexp.MustCompile(`\s+`)
	return SeparateString(rowSep, colSep, str)
}
StringToSlice takes in a string and returns a 2D slice of its output,
separated on whitespace and newlines
TODO: this should be depreciated by probabalisticSplit
package tabular
import (
	log "github.com/Sirupsen/logrus"
	"regexp"
	"strings"
	"unicode/utf8"
)
var rowSep = regexp.MustCompile(`\n+`)
type Table [][]string
type Column []string
type Row []string
func ToString(table Table) string {
	maxInt := func(slc []int) (max int) {
		for _, i := range slc {
			if i > max {
				max = i
			}
		}
		return max
	}
	longestRow := func(table Table) int {
		if len(table) < 1 {
			return 0
		}
		max := len(table[0])
		for _, row := range table {
			if len(row) > max {
				max = len(row)
			}
		}
		return max
	}
	longestInColumn := func(col Column) int {
		strLengths := func(slc []string) (lengths []int) {
			for _, str := range slc {
				lengths = append(lengths, utf8.RuneCountInString(str))
			}
			return lengths
		}
		return maxInt(strLengths(col))
	}
	columnWidths := func(table Table) []int {
		columnWidths := []int{}
		for _, row := range table {
			for i, item := range row {
				itemLength := utf8.RuneCountInString(item)
				if len(columnWidths) <= i {
					columnWidths = append(columnWidths, itemLength)
				} else if columnWidths[i] < itemLength {
					columnWidths[i] = itemLength
				}
			}
		}
		return columnWidths
	}
	rows := []string{}
	longest := longestRow(table)
	for _, row := range table {
		rowStr := "\n| "
		for i := 0; i < longest; i++ {
			item := ""
			if len(row) > i {
				item = row[i]
			}
			columnWidth := longestInColumn(GetColumn(i, table))
			rowStr = rowStr + padString(item, " ", columnWidth) + " | "
		}
		rows = append(rows, rowStr)
	}
	maxLength := 0
	for _, row := range rows {
		length := utf8.RuneCountInString(row)
		if length > maxLength {
			maxLength = length
		}
	}
	normalDivider := "+"
	headerDivider := "+"
	for _, width := range columnWidths(table) {
		normalDivider += repeatString("-", width) + "--+"
		headerDivider += repeatString("=", width) + "==+"
	}
	separatedRows := []string{}
	for i, row := range rows {
		divider := normalDivider
		if i == 0 {
			divider = headerDivider
		}
		separatedRows = append(separatedRows, row, "\n"+divider)
	}
	return normalDivider + strings.Join(separatedRows, "")
}
func TableEqual(t1 Table, t2 Table) bool {
	if len(t1) != len(t2) {
		return false
	}
	for i := range t1 {
		if !SliceEqual(t1[i], t2[i]) {
			return false
		}
	}
	return true
}
func SeparateString(rowSep *regexp.Regexp, colSep *regexp.Regexp, str string) (output Table) {
	lines := rowSep.Split(str, -1)
	for _, line := range lines {
		rawRow := colSep.Split(line, -1)
		row := []string{}
		for _, cell := range rawRow {
			row = append(row, strings.TrimSpace(cell))
		}
		if len(row) > 0 && HasNonEmpty(row) {
			output = append(output, row)
		}
	}
	return output
}
func SeparateOnAlignment(str string) (table Table) {
	wordAfterIndex := func(i int, str string) string {
		msg := "Couldn't get wordAfterIndex, "
		fatal := false
		switch {
		case i < 0:
			msg += "negative index passed to wordAfterIndex"
			fatal = true
		case len(strings.Fields(str)) < 1:
			msg += "string had only whitespace"
			return ""
		case len(str) < i:
			msg += "string was too short"
			fatal = true
		}
		if msg != "Couldn't get wordAfterIndex, " {
			if fatal {
				log.WithFields(log.Fields{
					"index": i,
					"str":   str,
				}).Fatal(msg + "string was too short")
			}
			log.WithFields(log.Fields{
				"index": i,
				"str":   str,
			}).Warn(msg + "string was too short")
		}
		fields := strings.Fields(str[i:])
		return strings.TrimSpace(fields[0])
	}
	getHeaders := func(str string) []string {
		rows := regexp.MustCompile("\n+").Split(str, -1)
		if len(rows) < 2 {
			log.WithFields(log.Fields{
				"row regexp": rowSep.String(),
				"length":     len(rows),
				"string":     str,
			}).Fatal("Couldn't split table based on headers")
		}
		headers := strings.Fields(rows[0])
		if len(headers) < 1 {
			log.WithFields(log.Fields{
				"string": str,
			}).Fatal("Couldn't get headers of table, row 0 was only whitespace")
		}
		return headers
	}
	rows := regexp.MustCompile("\n+").Split(str, -1)
	headers := getHeaders(str)
	headerIndicies := IndiciesOf(headers, rows[0])
	for i, index := range headerIndicies {
		if index < 0 {
			header := ""
			if len(headers) > i {
				header = headers[i]
			}
			log.WithFields(log.Fields{
				"index":    index,
				"indicies": headerIndicies,
				"header":   header,
				"row":      rows[0],
			}).Fatal("Internal error: negative header index")
		}
	}
	for i, row := range rows {
		table = append(table, []string{})  
		for _, index := range headerIndicies {
			table[i] = append(table[i], wordAfterIndex(index, row))
		}
	}
	return table
}