tabsep.go 3.13 KB
Newer Older
Ma_124's avatar
Ma_124 committed
1 2 3 4 5
package awesomefw

import (
	"fmt"
	"io"
Ma_124's avatar
Ma_124 committed
6
	"regexp"
Ma_124's avatar
Ma_124 committed
7 8 9
	"strings"
)

Ma_124's avatar
Ma_124 committed
10 11 12
var NameUrlDescTabSepPattern = []string{"name", "url", "desc"}
var tabsepRegexp = regexp.MustCompile(`(\s{3}|\t)\s*`)

Ma_124's avatar
Ma_124 committed
13 14 15 16 17 18 19 20 21 22
// Parses the code according to this pattern:
//   <name>\t<url>\t<desc>
//   "literal line
//   'literal without newline
//   " continuation of previous line
//    """
//   block literal
//   which spans over
//   multiple lines
//   """
Ma_124's avatar
Ma_124 committed
23 24
func IFFTabSep(fields []string) *InputFileFormat {
	return &InputFileFormat{parseTabSepLine(fields)}
25
}
Ma_124's avatar
Ma_124 committed
26

Ma_124's avatar
Ma_124 committed
27 28 29 30 31
func parseTabSepLine(fieldDefs []string) func(out io.Writer, l string, outFF *OutputFileFormat, ctx *Ctx) {
	return func(out io.Writer, l string, outFF *OutputFileFormat, ctx *Ctx) {
		if ctx.InFFCtx["tabsep--in-literal"] == nil {
			ctx.InFFCtx["tabsep--in-literal"] = false
		}
Ma_124's avatar
Ma_124 committed
32

Ma_124's avatar
Ma_124 committed
33 34 35 36
		if l == "\"\"\"\n" || l == "\"\"\"\r\n" { // Start literal block
			ctx.InFFCtx["tabsep--in-literal"] = !ctx.InFFCtx["tabsep--in-literal"].(bool)
			return
		}
Ma_124's avatar
Ma_124 committed
37

Ma_124's avatar
Ma_124 committed
38 39 40 41
		if ctx.InFFCtx["tabsep--in-literal"].(bool) {
			outFF.Literal(out, l, ctx)
			return
		}
Ma_124's avatar
Ma_124 committed
42

Ma_124's avatar
Ma_124 committed
43 44 45
		if len(l) == 1 {
			return
		}
Ma_124's avatar
Ma_124 committed
46

Ma_124's avatar
Ma_124 committed
47 48 49 50
		if l[0] == '"' { // Start line literal
			outFF.Literal(out, l[1:], ctx)
			return
		}
Ma_124's avatar
Ma_124 committed
51

Ma_124's avatar
Ma_124 committed
52 53 54 55
		if l[0] == '\'' { // Start line literal without newline
			outFF.Literal(out, strings.TrimLeft(l[1:len(l)-1], "\r\n"), ctx)
			return
		}
Ma_124's avatar
Ma_124 committed
56

Ma_124's avatar
Ma_124 committed
57
		l = l[:len(l)-1]
Ma_124's avatar
Ma_124 committed
58

Ma_124's avatar
Ma_124 committed
59 60 61 62
		fields := tabsepRegexp.Split(l, -1)

		it := &Item{}
		i := 0
Ma_124's avatar
Ma_124 committed
63

Ma_124's avatar
Ma_124 committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
		for _, fieldDef := range fieldDefs {
			if i >= len(fields) {
				panic(fmt.Sprintf("%q: expected <%s>\n", l, fieldDef))
			}

			switch fieldDef {
			case "name":
				it.Name = fields[i]
			case "url":
				it.Url = fields[i]
			case "repo-url":
				it.RepoUrl = fields[i]
			case "desc":
				it.Desc = fields[i]
			default:
				panic(fmt.Sprintf("%q: unknown fieldDef (%q)", l, fieldDef))
			}

			i++
		}

		outFF.Item(out, it, ctx)
	}
Ma_124's avatar
Ma_124 committed
87 88
}

Ma_124's avatar
Ma_124 committed
89 90 91 92 93 94 95 96
// Prints the code according to this pattern:
//   <name>\t<url>\t<desc>
//   "literal line
//   'literal without newline
//   " continuation of previous line
//   "block literal
//   "which spans over
//   "multiple lines
Ma_124's avatar
Ma_124 committed
97
func OFFTabSep(fields []string) *OutputFileFormat {
98 99
	return &OutputFileFormat{
		writeLiteralTabSep,
Ma_124's avatar
Ma_124 committed
100
		writeItemTabSep(fields),
101 102 103
		nil, nil,
	}
}
Ma_124's avatar
Ma_124 committed
104

Ma_124's avatar
Ma_124 committed
105
func writeLiteralTabSep(out io.Writer, l string, _ *Ctx) {
Ma_124's avatar
Ma_124 committed
106 107 108 109 110
	/* TODO TabSep Out
	 * literal blocks
	 * align (once multitab support is added)
	 * multiple `'`s to `"`
	 */
Ma_124's avatar
Ma_124 committed
111
	if l[len(l)-1] == '\n' {
Ma_124's avatar
Ma_124 committed
112 113
		_, _ = out.Write([]byte("\""))
		_, _ = out.Write([]byte(l))
Ma_124's avatar
Ma_124 committed
114
	} else {
Ma_124's avatar
Ma_124 committed
115 116 117
		_, _ = out.Write([]byte("'"))
		_, _ = out.Write([]byte(l))
		_, _ = out.Write([]byte("\n"))
Ma_124's avatar
Ma_124 committed
118 119 120
	}
}

Ma_124's avatar
Ma_124 committed
121 122 123 124 125
func writeItemTabSep(fieldDefs []string) func(out io.Writer, it *Item, _ *Ctx) {
	return func(out io.Writer, it *Item, _ *Ctx) {
		for i, fieldDef := range fieldDefs {
			switch fieldDef {
			case "name":
Ma_124's avatar
Ma_124 committed
126
				_, _ = out.Write([]byte(it.Name))
Ma_124's avatar
Ma_124 committed
127
			case "url":
Ma_124's avatar
Ma_124 committed
128
				_, _ = out.Write([]byte(it.Url))
Ma_124's avatar
Ma_124 committed
129
			case "repo-url":
Ma_124's avatar
Ma_124 committed
130
				_, _ = out.Write([]byte(it.RepoUrl))
Ma_124's avatar
Ma_124 committed
131
			case "desc":
Ma_124's avatar
Ma_124 committed
132
				_, _ = out.Write([]byte(it.Desc))
Ma_124's avatar
Ma_124 committed
133 134 135 136 137
			default:
				panic(fmt.Sprintf("%v: unknown fieldDef (%q)", it, fieldDef))
			}

			if i < len(fieldDefs)-1 {
Ma_124's avatar
Ma_124 committed
138
				_, _ = out.Write([]byte("\t"))
Ma_124's avatar
Ma_124 committed
139 140 141
			}
		}

Ma_124's avatar
Ma_124 committed
142
		_, _ = out.Write([]byte("\n"))
Ma_124's avatar
Ma_124 committed
143
	}
Ma_124's avatar
Ma_124 committed
144
}