From 47563c9f39db7f313d9e47e4f25c219fc6238d3c Mon Sep 17 00:00:00 2001 From: clsr Date: Mon, 4 Sep 2017 10:54:12 +0200 Subject: Update CNMfmt to CNM 0.4 --- cnmfmt/cnmfmt.go | 136 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 60 deletions(-) (limited to 'cnmfmt/cnmfmt.go') diff --git a/cnmfmt/cnmfmt.go b/cnmfmt/cnmfmt.go index fa2ec65..1e5b6ee 100644 --- a/cnmfmt/cnmfmt.go +++ b/cnmfmt/cnmfmt.go @@ -9,6 +9,10 @@ import ( "contnet.org/lib/cnm-go" ) +const ( + numFormats = 5 // emphasized, alternate, code, quote, link +) + func init() { cnm.RegisterTextContentParser("fmt", parseTextFmt) } @@ -37,7 +41,7 @@ func ParseParagraph(s string) Text { } switch r { - case '*', '/', '_', '`', '@': + case '*', '_', '`', '"', '@': handleTag(r, &last, &t, &format, &buf, &url) case '\\': @@ -138,13 +142,13 @@ func handleTag(r rune, last *rune, txt *Text, format *Format, buf *bytes.Buffer, buf.Reset() switch r { case '*': - format.Bold = !format.Bold - case '/': - format.Italic = !format.Italic + format.Emphasized = !format.Emphasized case '_': - format.Underline = !format.Underline + format.Alternate = !format.Alternate case '`': - format.Monospace = !format.Monospace + format.Code = !format.Code + case '"': + format.Quote = !format.Quote case '@': format.Link = "" *url = !*url @@ -152,7 +156,7 @@ func handleTag(r rune, last *rune, txt *Text, format *Format, buf *bytes.Buffer, *last = -1 } else { switch *last { - case '*', '/', '_', '`', '@': + case '*', '_', '`', '"', '@': buf.WriteRune(*last) } *last = r @@ -161,7 +165,7 @@ func handleTag(r rune, last *rune, txt *Text, format *Format, buf *bytes.Buffer, // WriteIndent writes the formatted text indented by n tabs. func (t Text) WriteIndent(w io.Writer, n int) error { - var state [5]byte // bold, italic, underline, monospace, link + var state [numFormats]byte si := 0 format := Format{} spans := EscapeSpans(t.Spans) @@ -171,17 +175,17 @@ func (t Text) WriteIndent(w io.Writer, n int) error { for _, f := range order { switch f { case '*': - format.Bold = !format.Bold + format.Emphasized = !format.Emphasized line = append(line, "**") - case '/': - format.Italic = !format.Italic - line = append(line, "//") case '_': - format.Underline = !format.Underline + format.Alternate = !format.Alternate line = append(line, "__") case '`': - format.Monospace = !format.Monospace + format.Code = !format.Code line = append(line, "``") + case '"': + format.Quote = !format.Quote + line = append(line, "\"\"") case '@': if format.Link != "" { line = append(line, "@@") @@ -208,40 +212,41 @@ func tagOrder(state []byte, old, new Format) []byte { ldiff = "1" } diff := Format{ - Bold: old.Bold != new.Bold, - Italic: old.Italic != new.Italic, - Underline: old.Underline != new.Underline, - Monospace: old.Monospace != new.Monospace, - Link: ldiff, + Emphasized: old.Emphasized != new.Emphasized, + Alternate: old.Alternate != new.Alternate, + Code: old.Code != new.Code, + Quote: old.Quote != new.Quote, + Link: ldiff, } - var order [5]byte + // close formats + var order [numFormats]byte oi := 0 for i := len(state) - 1; i >= 0; i-- { switch state[i] { case '*': - if diff.Bold { + if diff.Emphasized { order[oi] = '*' oi++ - diff.Bold = false - } - case '/': - if diff.Italic { - order[oi] = '/' - oi++ - diff.Italic = false + diff.Emphasized = false } case '_': - if diff.Underline { + if diff.Alternate { order[oi] = '_' oi++ - diff.Underline = false + diff.Alternate = false } case '`': - if diff.Monospace { + if diff.Code { order[oi] = '`' oi++ - diff.Monospace = false + diff.Code = false + } + case '"': + if diff.Quote { + order[oi] = '"' + oi++ + diff.Quote = false } case '@': if diff.Link != "" { @@ -252,22 +257,23 @@ func tagOrder(state []byte, old, new Format) []byte { } } - if diff.Bold { + // open formats + if diff.Emphasized { order[oi] = '*' oi++ } - if diff.Italic { - order[oi] = '/' - oi++ - } - if diff.Underline { + if diff.Alternate { order[oi] = '_' oi++ } - if diff.Monospace { + if diff.Code { order[oi] = '`' oi++ } + if diff.Quote { + order[oi] = '"' + oi++ + } if diff.Link != "" { order[oi] = '@' oi++ @@ -277,25 +283,29 @@ func tagOrder(state []byte, old, new Format) []byte { } func cleanupTags(state []byte, order []byte, format Format) int { - var newState [10]byte - copy(newState[:5], state) - copy(newState[5:], order) + var newState [2 * numFormats]byte + + // take care of both state and order + copy(newState[:numFormats], state) + copy(newState[numFormats:], order) + + // remove formats that are off for i := range newState { switch newState[i] { case '*': - if !format.Bold { - newState[i] = 0 - } - case '/': - if !format.Italic { + if !format.Emphasized { newState[i] = 0 } case '_': - if !format.Underline { + if !format.Alternate { newState[i] = 0 } case '`': - if !format.Monospace { + if !format.Code { + newState[i] = 0 + } + case '"': + if !format.Quote { newState[i] = 0 } case '@': @@ -304,6 +314,7 @@ func cleanupTags(state []byte, order []byte, format Format) int { } } } + si := 0 for _, f := range newState { if f > 0 { @@ -311,6 +322,12 @@ func cleanupTags(state []byte, order []byte, format Format) int { si++ } } + + // clean up unused state + for i := si; i < numFormats; i++ { + state[i] = 0 + } + return si } @@ -325,17 +342,17 @@ type Span struct { // Format represents a state of CNMfmt formatting. type Format struct { - // Bold text. - Bold bool + // Emphasized text. + Emphasized bool - // Italic text. - Italic bool + // Text in an alternate voice. + Alternate bool - // Underlined text. - Underline bool + // Text is code. + Code bool - // Monospaced text. - Monospace bool + // Quoted text. + Quote bool // Hyperlink URL (if non-empty). Link string @@ -385,9 +402,9 @@ func EscapeSpans(spans []Span) []Span { var escapeReplacer = strings.NewReplacer( `*`, `\*`, - `/`, `\/`, `_`, `\_`, "`", "\\`", + `"`, `\"`, `@`, `\@`, ) @@ -402,11 +419,10 @@ func Unescape(s string) string { } var unescapeReplacer = strings.NewReplacer( - `\\`, `\\`, `\*`, `*`, - `\/`, `/`, `\_`, `_`, "\\`", "`", + `\"`, `"`, `\@`, `@`, ) -- cgit