Improve logging and error handling
- enable logging by default: debug was a bad name - it's error logging that I just want to hide in tests - don't panic (all the time) - use a logger. this allows us to add more information - like the path of the parsed file!
This commit is contained in:
parent
c23f8cc281
commit
7a8e90f786
5 changed files with 28 additions and 29 deletions
|
@ -4,7 +4,9 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,7 +21,7 @@ type Document struct {
|
||||||
BufferSettings map[string]string
|
BufferSettings map[string]string
|
||||||
DefaultSettings map[string]string
|
DefaultSettings map[string]string
|
||||||
Error error
|
Error error
|
||||||
Debug bool
|
Log *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type Writer interface {
|
type Writer interface {
|
||||||
|
@ -80,6 +82,7 @@ func NewDocument() *Document {
|
||||||
DefaultSettings: map[string]string{
|
DefaultSettings: map[string]string{
|
||||||
"TODO": "TODO | DONE",
|
"TODO": "TODO | DONE",
|
||||||
},
|
},
|
||||||
|
Log: log.New(os.Stderr, "go-org: ", 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +121,12 @@ func (dIn *Document) Parse(input io.Reader) (d *Document) {
|
||||||
|
|
||||||
func (d *Document) SetPath(path string) *Document {
|
func (d *Document) SetPath(path string) *Document {
|
||||||
d.Path = path
|
d.Path = path
|
||||||
|
d.Log.SetPrefix(fmt.Sprintf("%s(%s): ", d.Log.Prefix(), path))
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Document) Silent() *Document {
|
||||||
|
d.Log = log.New(ioutil.Discard, "", 0)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,9 +205,7 @@ func (d *Document) parseOne(i int, stop stopFn) (consumed int, node Node) {
|
||||||
if consumed != 0 {
|
if consumed != 0 {
|
||||||
return consumed, node
|
return consumed, node
|
||||||
}
|
}
|
||||||
if d.Debug {
|
d.Log.Printf("Could not parse token %#v: Falling back to treating it as plain text.", d.tokens[i])
|
||||||
log.Printf("Could not parse token %#v: Falling back to treating it as plain text.", d.tokens[i])
|
|
||||||
}
|
|
||||||
m := plainTextRegexp.FindStringSubmatch(d.tokens[i].matches[0])
|
m := plainTextRegexp.FindStringSubmatch(d.tokens[i].matches[0])
|
||||||
d.tokens[i] = token{"text", len(m[1]), m[2], m}
|
d.tokens[i] = token{"text", len(m[1]), m[2], m}
|
||||||
return d.parseOne(i, stop)
|
return d.parseOne(i, stop)
|
||||||
|
|
20
org/html.go
20
org/html.go
|
@ -16,7 +16,7 @@ type HTMLWriter struct {
|
||||||
HighlightCodeBlock func(source, lang string) string
|
HighlightCodeBlock func(source, lang string) string
|
||||||
FootnotesHeadingTitle string
|
FootnotesHeadingTitle string
|
||||||
htmlEscape bool
|
htmlEscape bool
|
||||||
debug bool
|
log *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
var emphasisTags = map[string][]string{
|
var emphasisTags = map[string][]string{
|
||||||
|
@ -65,7 +65,7 @@ func (w *HTMLWriter) nodesAsString(nodes ...Node) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) before(d *Document) {
|
func (w *HTMLWriter) before(d *Document) {
|
||||||
w.debug = w.debug || d.Debug
|
w.log = d.Log
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *HTMLWriter) after(d *Document) {
|
func (w *HTMLWriter) after(d *Document) {
|
||||||
|
@ -362,7 +362,7 @@ func (w *HTMLWriter) writeNodeWithMeta(n NodeWithMeta) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, attributes := range n.Meta.HTMLAttributes {
|
for _, attributes := range n.Meta.HTMLAttributes {
|
||||||
out = withHTMLAttributes(w.debug, out, attributes...) + "\n"
|
out = w.withHTMLAttributes(out, attributes...) + "\n"
|
||||||
}
|
}
|
||||||
if len(n.Meta.Caption) != 0 {
|
if len(n.Meta.Caption) != 0 {
|
||||||
caption := ""
|
caption := ""
|
||||||
|
@ -414,19 +414,15 @@ func (w *HTMLWriter) writeTableColumns(columns []Column, tag string) {
|
||||||
w.WriteString("</tr>\n")
|
w.WriteString("</tr>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func withHTMLAttributes(debug bool, input string, kvs ...string) string {
|
func (w *HTMLWriter) withHTMLAttributes(input string, kvs ...string) string {
|
||||||
if len(kvs)%2 != 0 {
|
if len(kvs)%2 != 0 {
|
||||||
if debug {
|
w.log.Printf("withHTMLAttributes: Len of kvs must be even: %#v", kvs)
|
||||||
log.Printf("withHTMLAttributes: Len of kvs must be even: %#v", kvs)
|
|
||||||
}
|
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
context := &h.Node{Type: h.ElementNode, Data: "body", DataAtom: atom.Body}
|
context := &h.Node{Type: h.ElementNode, Data: "body", DataAtom: atom.Body}
|
||||||
nodes, err := h.ParseFragment(strings.NewReader(strings.TrimSpace(input)), context)
|
nodes, err := h.ParseFragment(strings.NewReader(strings.TrimSpace(input)), context)
|
||||||
if err != nil || len(nodes) != 1 {
|
if err != nil || len(nodes) != 1 {
|
||||||
if debug {
|
w.log.Printf("withHTMLAttributes: Could not extend attributes of %s: %v (%s)", input, nodes, err)
|
||||||
log.Printf("withHTMLAttributes: Could not extend attributes of %s: %v (%s)", input, nodes, err)
|
|
||||||
}
|
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
out, node := strings.Builder{}, nodes[0]
|
out, node := strings.Builder{}, nodes[0]
|
||||||
|
@ -435,9 +431,7 @@ func withHTMLAttributes(debug bool, input string, kvs ...string) string {
|
||||||
}
|
}
|
||||||
err = h.Render(&out, nodes[0])
|
err = h.Render(&out, nodes[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if debug {
|
w.log.Printf("withHTMLAttributes: Could not extend attributes of %s: %v (%s)", input, node, err)
|
||||||
log.Printf("withHTMLAttributes: Could not extend attributes of %s: %v (%s)", input, node, err)
|
|
||||||
}
|
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
return out.String()
|
return out.String()
|
||||||
|
|
|
@ -9,7 +9,7 @@ func TestHTMLWriter(t *testing.T) {
|
||||||
for _, path := range orgTestFiles() {
|
for _, path := range orgTestFiles() {
|
||||||
expected := fileString(path[:len(path)-len(".org")] + ".html")
|
expected := fileString(path[:len(path)-len(".org")] + ".html")
|
||||||
reader, writer := strings.NewReader(fileString(path)), NewHTMLWriter()
|
reader, writer := strings.NewReader(fileString(path)), NewHTMLWriter()
|
||||||
actual, err := NewDocument().SetPath(path).Parse(reader).Write(writer)
|
actual, err := NewDocument().Silent().SetPath(path).Parse(reader).Write(writer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s\n got error: %s", path, err)
|
t.Errorf("%s\n got error: %s", path, err)
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -2,9 +2,7 @@ package org
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -119,7 +117,10 @@ func parseKeyword(t token) Keyword {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Document) newInclude(k Keyword) (int, Node) {
|
func (d *Document) newInclude(k Keyword) (int, Node) {
|
||||||
resolve := func() Node { panic(fmt.Sprintf("bad include: '#+INCLUDE: %s'", k.Value)) }
|
resolve := func() Node {
|
||||||
|
d.Log.Printf("Bad include %#v", k)
|
||||||
|
return k
|
||||||
|
}
|
||||||
if m := includeFileRegexp.FindStringSubmatch(k.Value); m != nil {
|
if m := includeFileRegexp.FindStringSubmatch(k.Value); m != nil {
|
||||||
path, kind, lang := m[1], m[2], m[3]
|
path, kind, lang := m[1], m[2], m[3]
|
||||||
if !filepath.IsAbs(path) {
|
if !filepath.IsAbs(path) {
|
||||||
|
@ -128,7 +129,8 @@ func (d *Document) newInclude(k Keyword) (int, Node) {
|
||||||
resolve = func() Node {
|
resolve = func() Node {
|
||||||
bs, err := ioutil.ReadFile(path)
|
bs, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("bad include '#+INCLUDE: %s': %s", k.Value, err))
|
d.Log.Printf("Bad include %#v: %s", k, err)
|
||||||
|
return k
|
||||||
}
|
}
|
||||||
return Block{strings.ToUpper(kind), []string{lang}, d.parseRawInline(string(bs))}
|
return Block{strings.ToUpper(kind), []string{lang}, d.parseRawInline(string(bs))}
|
||||||
}
|
}
|
||||||
|
@ -143,16 +145,12 @@ func (d *Document) loadSetupFile(k Keyword) (int, Node) {
|
||||||
}
|
}
|
||||||
bs, err := ioutil.ReadFile(path)
|
bs, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if d.Debug {
|
d.Log.Printf("Bad setup file: %#v: %s", k, err)
|
||||||
log.Printf("Bad setup file: %#v: %s", k, err)
|
|
||||||
}
|
|
||||||
return 1, k
|
return 1, k
|
||||||
}
|
}
|
||||||
setupDocument := NewDocument().Parse(bytes.NewReader(bs))
|
setupDocument := NewDocument().Parse(bytes.NewReader(bs))
|
||||||
if err := setupDocument.Error; err != nil {
|
if err := setupDocument.Error; err != nil {
|
||||||
if d.Debug {
|
d.Log.Printf("Bad setup file: %#v: %s", k, err)
|
||||||
log.Printf("Bad setup file: %#v: %s", k, err)
|
|
||||||
}
|
|
||||||
return 1, k
|
return 1, k
|
||||||
}
|
}
|
||||||
for k, v := range setupDocument.BufferSettings {
|
for k, v := range setupDocument.BufferSettings {
|
||||||
|
|
|
@ -14,7 +14,7 @@ func TestOrgWriter(t *testing.T) {
|
||||||
for _, path := range orgTestFiles() {
|
for _, path := range orgTestFiles() {
|
||||||
expected := fileString(path[:len(path)-len(".org")] + ".pretty_org")
|
expected := fileString(path[:len(path)-len(".org")] + ".pretty_org")
|
||||||
reader, writer := strings.NewReader(fileString(path)), NewOrgWriter()
|
reader, writer := strings.NewReader(fileString(path)), NewOrgWriter()
|
||||||
actual, err := NewDocument().SetPath(path).Parse(reader).Write(writer)
|
actual, err := NewDocument().Silent().SetPath(path).Parse(reader).Write(writer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s\n got error: %s", path, err)
|
t.Errorf("%s\n got error: %s", path, err)
|
||||||
continue
|
continue
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue