readability

This commit is contained in:
dre 2021-07-05 01:45:42 +08:00
parent c279e77ef8
commit ba528e13fc
5 changed files with 61 additions and 18 deletions

14
main.go
View file

@ -46,7 +46,7 @@ func reader(in string) (io.Reader, error) {
if in != "" { if in != "" {
file, err := os.Open(in) file, err := os.Open(in)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("reader: %w", err)
} }
return file, nil return file, nil
@ -59,7 +59,7 @@ func writer(out string) (io.Writer, error) {
if out != "" { if out != "" {
file, err := os.Create(out) file, err := os.Create(out)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("writer: %w", err)
} }
return file, nil return file, nil
@ -76,14 +76,17 @@ func source(r io.Reader) pipe.Source {
return func() chan pipe.StreamItem { return func() chan pipe.StreamItem {
data := make(chan pipe.StreamItem) data := make(chan pipe.StreamItem)
s := bufio.NewScanner(r) s := bufio.NewScanner(r)
go func() { go func() {
i := 0 i := 0
for s.Scan() { for s.Scan() {
data <- pipe.NewItem(i, s.Bytes()) data <- pipe.NewItem(i, s.Bytes())
i += 1 i++
} }
close(data) close(data)
}() }()
return data return data
} }
} }
@ -115,11 +118,8 @@ func main() {
os.Exit(1) os.Exit(1)
} }
preproc := NewPreproc()
//sink.Input(preproc.Process(source.Output()))
s := pipe.New() s := pipe.New()
s.Use(preproc.Process) s.Use(newPreproc().Process)
s.Use(RemoveFrontMatter) s.Use(RemoveFrontMatter)
s.Use(RemoveComments) s.Use(RemoveComments)
s.Use(FormatHeadings) s.Use(FormatHeadings)

View file

@ -12,12 +12,16 @@ type StreamItem struct {
func NewItem(index int, payload []byte) StreamItem { func NewItem(index int, payload []byte) StreamItem {
var buf bytes.Buffer var buf bytes.Buffer
w := StreamItem{index: index} w := StreamItem{index: index}
if err := gob.NewEncoder(&buf).Encode(payload); err != nil { if err := gob.NewEncoder(&buf).Encode(payload); err != nil {
// assert no broken pipes // assert no broken pipes
panic(err) panic(err)
} }
w.payload = buf.Bytes() w.payload = buf.Bytes()
return w return w
} }
@ -27,7 +31,9 @@ func (w *StreamItem) Index() int {
func (w *StreamItem) Payload() []byte { func (w *StreamItem) Payload() []byte {
var dec []byte var dec []byte
buf := bytes.NewReader(w.payload) buf := bytes.NewReader(w.payload)
if err := gob.NewDecoder(buf).Decode(&dec); err != nil { if err := gob.NewDecoder(buf).Decode(&dec); err != nil {
// assert no broken pipes // assert no broken pipes
panic(err) panic(err)

View file

@ -26,6 +26,7 @@ func chain(nodes []Pipeline, src Connector) Connector {
for i := 1; i < len(nodes); i++ { for i := 1; i < len(nodes); i++ {
c = nodes[i](c) c = nodes[i](c)
} }
return c return c
} }

View file

@ -7,10 +7,10 @@ import (
"github.com/n0x1m/md2gmi/pipe" "github.com/n0x1m/md2gmi/pipe"
) )
// state function // state function.
type stateFn func(*fsm, []byte) stateFn type stateFn func(*fsm, []byte) stateFn
// state machine // state machine.
type fsm struct { type fsm struct {
state stateFn state stateFn
@ -24,12 +24,13 @@ type fsm struct {
pending []byte pending []byte
} }
func NewPreproc() *fsm { func newPreproc() *fsm {
return &fsm{} return &fsm{}
} }
func (m *fsm) Process(in chan pipe.StreamItem) chan pipe.StreamItem { func (m *fsm) Process(in chan pipe.StreamItem) chan pipe.StreamItem {
m.out = make(chan pipe.StreamItem) m.out = make(chan pipe.StreamItem)
go func() { go func() {
for m.state = normal; m.state != nil; { for m.state = normal; m.state != nil; {
b, ok := <-in b, ok := <-in
@ -38,6 +39,7 @@ func (m *fsm) Process(in chan pipe.StreamItem) chan pipe.StreamItem {
m.sync() m.sync()
close(m.out) close(m.out)
m.state = nil m.state = nil
continue continue
} }
@ -45,6 +47,7 @@ func (m *fsm) Process(in chan pipe.StreamItem) chan pipe.StreamItem {
m.sync() m.sync()
} }
}() }()
return m.out return m.out
} }
@ -53,7 +56,7 @@ func (m *fsm) sync() {
m.sendBuffer = append(m.sendBuffer, '\n') m.sendBuffer = append(m.sendBuffer, '\n')
m.out <- pipe.NewItem(m.i, m.sendBuffer) m.out <- pipe.NewItem(m.i, m.sendBuffer)
m.sendBuffer = m.sendBuffer[:0] m.sendBuffer = m.sendBuffer[:0]
m.i += 1 m.i++
} }
} }
@ -84,6 +87,7 @@ func handleList(data []byte) ([]byte, bool) {
if len(sub) > 1 { if len(sub) > 1 {
return bytes.Replace(data, sub[1], []byte("-"), 1), true return bytes.Replace(data, sub[1], []byte("-"), 1), true
} }
return data, false return data, false
} }
@ -99,27 +103,34 @@ func normal(m *fsm, data []byte) stateFn {
if data, isList := handleList(data); isList { if data, isList := handleList(data); isList {
m.blockBuffer = append(data, '\n') m.blockBuffer = append(data, '\n')
m.blockFlush() m.blockFlush()
return normal return normal
} }
if isFence(data) { if isFence(data) {
m.blockBuffer = append(data, '\n') m.blockBuffer = append(data, '\n')
return fence return fence
} }
if needsFence(data) { if needsFence(data) {
m.blockBuffer = append(m.blockBuffer, []byte("```\n")...) m.blockBuffer = append(m.blockBuffer, []byte("```\n")...)
m.blockBuffer = append(m.blockBuffer, append(data[4:], '\n')...) m.blockBuffer = append(m.blockBuffer, append(data[4:], '\n')...)
m.pending = []byte("```\n") m.pending = []byte("```\n")
return toFence return toFence
} }
if isTerminated(data) { if isTerminated(data) {
m.blockBuffer = append(m.blockBuffer, data...) m.blockBuffer = append(m.blockBuffer, data...)
m.blockBuffer = append(m.blockBuffer, ' ') m.blockBuffer = append(m.blockBuffer, ' ')
return paragraph return paragraph
} }
// TODO
// collapse lists
m.blockBuffer = append(m.blockBuffer, append(data, '\n')...) m.blockBuffer = append(m.blockBuffer, append(data, '\n')...)
m.blockFlush() m.blockFlush()
return normal return normal
} }
@ -128,18 +139,23 @@ func fence(m *fsm, data []byte) stateFn {
// second fence returns to normal // second fence returns to normal
if isFence(data) { if isFence(data) {
m.blockFlush() m.blockFlush()
return normal return normal
} }
return fence return fence
} }
func toFence(m *fsm, data []byte) stateFn { func toFence(m *fsm, data []byte) stateFn {
if needsFence(data) { if needsFence(data) {
m.blockBuffer = append(m.blockBuffer, append(data[4:], '\n')...) m.blockBuffer = append(m.blockBuffer, append(data[4:], '\n')...)
return toFence return toFence
} }
m.blockFlush() m.blockFlush()
m.blockBuffer = append(m.blockBuffer, append(data, '\n')...) m.blockBuffer = append(m.blockBuffer, append(data, '\n')...)
return normal return normal
} }
@ -149,9 +165,12 @@ func paragraph(m *fsm, data []byte) stateFn {
m.blockBuffer = bytes.TrimSpace(m.blockBuffer) m.blockBuffer = bytes.TrimSpace(m.blockBuffer)
m.blockBuffer = append(m.blockBuffer, '\n') m.blockBuffer = append(m.blockBuffer, '\n')
m.blockFlush() m.blockFlush()
return normal return normal
} }
m.blockBuffer = append(m.blockBuffer, data...) m.blockBuffer = append(m.blockBuffer, data...)
m.blockBuffer = append(m.blockBuffer, []byte(" ")...) m.blockBuffer = append(m.blockBuffer, []byte(" ")...)
return paragraph return paragraph
} }

27
proc.go
View file

@ -10,28 +10,36 @@ import (
func FormatLinks(in chan pipe.StreamItem) chan pipe.StreamItem { func FormatLinks(in chan pipe.StreamItem) chan pipe.StreamItem {
out := make(chan pipe.StreamItem) out := make(chan pipe.StreamItem)
go func() { go func() {
fenceOn := false fenceOn := false
for b := range in { for b := range in {
data := b.Payload() data := b.Payload()
if isFence(data) { if isFence(data) {
fenceOn = !fenceOn fenceOn = !fenceOn
} }
if fenceOn { if fenceOn {
out <- pipe.NewItem(b.Index(), b.Payload()) out <- pipe.NewItem(b.Index(), b.Payload())
} else {
out <- pipe.NewItem(b.Index(), formatLinks(b.Payload())) continue
} }
out <- pipe.NewItem(b.Index(), formatLinks(b.Payload()))
} }
close(out) close(out)
}() }()
return out return out
} }
func formatLinks(data []byte) []byte { func formatLinks(data []byte) []byte {
// find link name and url // find link name and url
var buffer []byte var buffer []byte
re := regexp.MustCompile(`!?\[([^\]*]*)\]\(([^)]*)\)`) re := regexp.MustCompile(`!?\[([^\]*]*)\]\(([^)]*)\)`)
for i, match := range re.FindAllSubmatch(data, -1) { for i, match := range re.FindAllSubmatch(data, -1) {
replaceWithIndex := append(match[1], fmt.Sprintf("[%d]", i+1)...) replaceWithIndex := append(match[1], fmt.Sprintf("[%d]", i+1)...)
data = bytes.Replace(data, match[0], replaceWithIndex, 1) data = bytes.Replace(data, match[0], replaceWithIndex, 1)
@ -50,43 +58,51 @@ func formatLinks(data []byte) []byte {
func RemoveComments(in chan pipe.StreamItem) chan pipe.StreamItem { func RemoveComments(in chan pipe.StreamItem) chan pipe.StreamItem {
out := make(chan pipe.StreamItem) out := make(chan pipe.StreamItem)
go func() { go func() {
re := regexp.MustCompile(`<!--.*-->`) re := regexp.MustCompile(`<!--.*-->`)
for b := range in { for b := range in {
data := b.Payload() data := b.Payload()
for _, match := range re.FindAllSubmatch(data, -1) { for _, match := range re.FindAllSubmatch(data, -1) {
data = bytes.Replace(data, match[0], []byte(""), 1) data = bytes.Replace(data, match[0], []byte(""), 1)
} }
out <- pipe.NewItem(b.Index(), append(bytes.TrimSpace(data), '\n')) out <- pipe.NewItem(b.Index(), append(bytes.TrimSpace(data), '\n'))
//out <- pipe.NewItem(b.Index(), data)
} }
close(out) close(out)
}() }()
return out return out
} }
func RemoveFrontMatter(in chan pipe.StreamItem) chan pipe.StreamItem { func RemoveFrontMatter(in chan pipe.StreamItem) chan pipe.StreamItem {
out := make(chan pipe.StreamItem) out := make(chan pipe.StreamItem)
go func() { go func() {
re := regexp.MustCompile(`---.*---`) re := regexp.MustCompile(`---.*---`)
for b := range in { for b := range in {
data := b.Payload() data := b.Payload()
for _, match := range re.FindAllSubmatch(data, -1) { for _, match := range re.FindAllSubmatch(data, -1) {
data = bytes.Replace(data, match[0], []byte(""), 1) data = bytes.Replace(data, match[0], []byte(""), 1)
} }
out <- pipe.NewItem(b.Index(), append(bytes.TrimSpace(data), '\n')) out <- pipe.NewItem(b.Index(), append(bytes.TrimSpace(data), '\n'))
//out <- pipe.NewItem(b.Index(), data)
} }
close(out) close(out)
}() }()
return out return out
} }
func FormatHeadings(in chan pipe.StreamItem) chan pipe.StreamItem { func FormatHeadings(in chan pipe.StreamItem) chan pipe.StreamItem {
out := make(chan pipe.StreamItem) out := make(chan pipe.StreamItem)
go func() { go func() {
re := regexp.MustCompile(`^[#]{4,}`) re := regexp.MustCompile(`^[#]{4,}`)
re2 := regexp.MustCompile(`^(#+)[^# ]`) re2 := regexp.MustCompile(`^(#+)[^# ]`)
for b := range in { for b := range in {
// fix up more than 4 levels // fix up more than 4 levels
data := re.ReplaceAll(b.Payload(), []byte("###")) data := re.ReplaceAll(b.Payload(), []byte("###"))
@ -101,9 +117,10 @@ func FormatHeadings(in chan pipe.StreamItem) chan pipe.StreamItem {
} }
// writeback // writeback
out <- pipe.NewItem(b.Index(), data) out <- pipe.NewItem(b.Index(), data)
} }
close(out) close(out)
}() }()
return out return out
} }