remove quit channels
This commit is contained in:
parent
f2b7adba1f
commit
45d7c25206
2 changed files with 44 additions and 63 deletions
38
main.go
38
main.go
|
@ -35,16 +35,15 @@ func writer(out string) (io.Writer, error) {
|
|||
}
|
||||
|
||||
func write(w io.Writer, b []byte) {
|
||||
fmt.Fprintf(w, string(b))
|
||||
fmt.Fprint(w, string(b))
|
||||
}
|
||||
|
||||
type ir struct {
|
||||
r io.Reader
|
||||
quit chan struct{}
|
||||
r io.Reader
|
||||
}
|
||||
|
||||
func NewIr(r io.Reader, quit chan struct{}) *ir {
|
||||
return &ir{r: r, quit: quit}
|
||||
func NewIr(r io.Reader) *ir {
|
||||
return &ir{r: r}
|
||||
}
|
||||
|
||||
func (m *ir) Output() chan []byte {
|
||||
|
@ -54,28 +53,22 @@ func (m *ir) Output() chan []byte {
|
|||
for s.Scan() {
|
||||
data <- s.Bytes()
|
||||
}
|
||||
close(m.quit)
|
||||
close(data)
|
||||
}()
|
||||
return data
|
||||
}
|
||||
|
||||
type ow struct {
|
||||
w io.Writer
|
||||
quit chan struct{}
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func NewOw(w io.Writer, quit chan struct{}) *ow {
|
||||
return &ow{w: w, quit: quit}
|
||||
func NewOw(w io.Writer) *ow {
|
||||
return &ow{w: w}
|
||||
}
|
||||
|
||||
func (m *ow) Input(data chan []byte) {
|
||||
for {
|
||||
select {
|
||||
case <-m.quit:
|
||||
return
|
||||
case b := <-data:
|
||||
write(m.w, b)
|
||||
}
|
||||
for b := range data {
|
||||
write(m.w, b)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,8 +79,6 @@ func main() {
|
|||
flag.StringVar(&out, "out", "", "specify a .gmi (gemtext) file to write to, otherwise stdout (default)")
|
||||
flag.Parse()
|
||||
|
||||
quit := make(chan struct{})
|
||||
|
||||
r, err := reader(in)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err.Error())
|
||||
|
@ -100,10 +91,9 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
source := NewIr(r, quit)
|
||||
sink := NewOw(w, quit)
|
||||
source := NewIr(r)
|
||||
sink := NewOw(w)
|
||||
preproc := NewParser()
|
||||
|
||||
sink.Input(source.Output())
|
||||
|
||||
//NewParser(data, w, quit).Parse()
|
||||
sink.Input(preproc.Parse(source.Output()))
|
||||
}
|
||||
|
|
69
parser.go
69
parser.go
|
@ -1,51 +1,43 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// state function
|
||||
type stateFn func(*fsm, []byte) stateFn
|
||||
|
||||
// state machine
|
||||
type fsm struct {
|
||||
state stateFn
|
||||
buffer []byte
|
||||
out io.Writer
|
||||
quit chan struct{}
|
||||
data <-chan []byte
|
||||
state stateFn
|
||||
out chan []byte
|
||||
|
||||
// if we have a nested state, e.g. a link inside a paragraph
|
||||
returnState stateFn
|
||||
// combining multiple input lines
|
||||
buffer []byte
|
||||
// if we have a termination rule to abide, e.g. implied code fences
|
||||
pending []byte
|
||||
}
|
||||
|
||||
func NewParser(data <-chan []byte, writer io.Writer, quit chan struct{}) *fsm {
|
||||
return &fsm{
|
||||
out: writer,
|
||||
data: data,
|
||||
quit: quit,
|
||||
}
|
||||
func NewParser() *fsm {
|
||||
return &fsm{}
|
||||
}
|
||||
|
||||
func (m *fsm) Parse() {
|
||||
var line []byte
|
||||
for m.state = normal; m.state != nil; {
|
||||
select {
|
||||
case <-m.quit:
|
||||
m.flush()
|
||||
m.state = nil
|
||||
case line = <-m.data:
|
||||
m.state = m.state(m, line)
|
||||
func (m *fsm) Parse(in chan []byte) chan []byte {
|
||||
m.out = make(chan []byte)
|
||||
go func() {
|
||||
for m.state = normal; m.state != nil; {
|
||||
b, ok := <-in
|
||||
if !ok {
|
||||
m.flush()
|
||||
close(m.out)
|
||||
m.state = nil
|
||||
continue
|
||||
}
|
||||
m.state = m.state(m, b)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return m.out
|
||||
}
|
||||
|
||||
func (m *fsm) flush() {
|
||||
if len(m.pending) > 0 {
|
||||
fmt.Fprintf(m.out, string(m.pending)+"\n")
|
||||
m.out <- append(m.pending, '\n')
|
||||
m.pending = m.pending[:0]
|
||||
}
|
||||
}
|
||||
|
@ -74,21 +66,21 @@ func normal(m *fsm, data []byte) stateFn {
|
|||
m.flush()
|
||||
// blank line
|
||||
if isBlank(data) {
|
||||
fmt.Fprintf(m.out, "\n")
|
||||
m.out <- []byte("\n")
|
||||
return normal
|
||||
}
|
||||
// header
|
||||
if isHeader(data) {
|
||||
fmt.Fprintf(m.out, string(data)+"\n")
|
||||
m.out <- append(data, '\n')
|
||||
return normal
|
||||
}
|
||||
if isFence(data) {
|
||||
fmt.Fprintf(m.out, string(data)+"\n")
|
||||
m.out <- append(data, '\n')
|
||||
return fence
|
||||
}
|
||||
if needsFence(data) {
|
||||
fmt.Fprintf(m.out, string("```")+"\n")
|
||||
fmt.Fprintf(m.out, string(data)+"\n")
|
||||
m.out <- []byte("```\n")
|
||||
m.out <- append(data, '\n')
|
||||
m.pending = []byte("```")
|
||||
return toFence
|
||||
}
|
||||
|
@ -99,13 +91,13 @@ func normal(m *fsm, data []byte) stateFn {
|
|||
// TODO
|
||||
// find links
|
||||
// collapse lists
|
||||
fmt.Fprintf(m.out, string(data)+"\n")
|
||||
m.out <- append(data, '\n')
|
||||
|
||||
return normal
|
||||
}
|
||||
|
||||
func fence(m *fsm, data []byte) stateFn {
|
||||
fmt.Fprintf(m.out, string(data)+"\n")
|
||||
m.out <- append(data, '\n')
|
||||
if isFence(data) {
|
||||
return normal
|
||||
}
|
||||
|
@ -113,18 +105,17 @@ func fence(m *fsm, data []byte) stateFn {
|
|||
}
|
||||
|
||||
func toFence(m *fsm, data []byte) stateFn {
|
||||
m.out <- append(data, '\n')
|
||||
if needsFence(data) {
|
||||
fmt.Fprintf(m.out, string(data)+"\n")
|
||||
return toFence
|
||||
}
|
||||
fmt.Fprintf(m.out, string(data)+"\n")
|
||||
return normal
|
||||
}
|
||||
|
||||
func paragraph(m *fsm, data []byte) stateFn {
|
||||
if triggerBreak(data) {
|
||||
m.buffer = append(m.buffer, data...)
|
||||
fmt.Fprintf(m.out, string(m.buffer)+"\n")
|
||||
m.out <- append(m.buffer, '\n')
|
||||
m.buffer = m.buffer[:0]
|
||||
return normal
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue