From 60b733783c5e9f267377d8dbadeb5982e7566418 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 27 Jan 2019 16:39:34 +0100 Subject: [PATCH] allow escaping special characters (*, _, $, [) | fix: append last character when cursor is len-1 after all matches | add transform/markdown/hyperlink format --- clifmt.go | 26 ++++++++++-- internal/transform/color/color.go | 2 +- internal/transform/markdown/bold.go | 2 +- internal/transform/markdown/hyperlink.go | 50 ++++++++++++++++++++++++ internal/transform/markdown/italic.go | 2 +- internal/transform/markdown/markdown.go | 10 ++++- internal/transform/markdown/underline.go | 2 +- 7 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 internal/transform/markdown/hyperlink.go diff --git a/clifmt.go b/clifmt.go index 2054f17..f2c6134 100644 --- a/clifmt.go +++ b/clifmt.go @@ -5,28 +5,48 @@ import ( "git.xdrm.io/go/clifmt/internal/color" colorTransform "git.xdrm.io/go/clifmt/internal/transform/color" mdTransform "git.xdrm.io/go/clifmt/internal/transform/markdown" + "strings" ) var theme = color.DefaultTheme() +var ( + dollarToken = `e4d097183ab04e49f25cb7b0956fb9eb25b90c0316a32cb5afcbcdd9a6692e8d2974919035789d5632b10d799db5b3e5bf8539592c904497f5c356f117ef37382` + asteriskToken = `253c3cd0a904d28abc3e601e3557d59ea69da2616079ceef4987d58d55c9820c83026be92a917ee19a298e613ea0b393cc70d4e55dc614a9afc6a020d8f08f37` + underscoreToken = `2b08e24b7833e90c74ed8e6c27b7b3cd5fe949e0f18b28af813d5f2df863d55f97b0ed7f8fbb26a152eda55ac073331ce11ac10702caca5b3ea4a29f722840b9` + squareBracketToken = `51b06edd58f36003844941916cd3b313979fece55824d89ba02af052a229b2673aafffa541b703472c1a21d8e6a1bb3e844d236fb0e8bf5d62902b24042f4fb5` +) + // Sprintf returns a terminal-colorized output following the coloring format func Sprintf(format string, a ...interface{}) (string, error) { // 1. Pre-process format with 'fmt' formatted := fmt.Sprintf(format, a...) - // 2. Colorize + // 2. Protect escaped characters with tokens + formatted = strings.Replace(formatted, "\\$", dollarToken, -1) + formatted = strings.Replace(formatted, "\\*", asteriskToken, -1) + formatted = strings.Replace(formatted, "\\_", underscoreToken, -1) + formatted = strings.Replace(formatted, "\\[", squareBracketToken, -1) + + // 3. Colorize colorized, err := colorTransform.Transform(formatted, theme) if err != nil { return "", err } - // 3. Markdown format + // 4. Markdown format markdown, err := mdTransform.Transform(colorized) if err != nil { return "", err } - // 3. return final output + // 5. Restore token-protected characters + markdown = strings.Replace(markdown, dollarToken, "$", -1) + markdown = strings.Replace(markdown, asteriskToken, "*", -1) + markdown = strings.Replace(markdown, underscoreToken, "_", -1) + markdown = strings.Replace(markdown, squareBracketToken, "[", -1) + + // 6. return final output return markdown, nil } diff --git a/internal/transform/color/color.go b/internal/transform/color/color.go index ad66299..2595b99 100644 --- a/internal/transform/color/color.go +++ b/internal/transform/color/color.go @@ -83,7 +83,7 @@ func Transform(input string, theme color.Theme) (string, error) { } // 2. Add end of input - if cursor < len(input)-1 { + if cursor < len(input) { output += input[cursor:] } diff --git a/internal/transform/markdown/bold.go b/internal/transform/markdown/bold.go index 1be4c1b..32f8dc8 100644 --- a/internal/transform/markdown/bold.go +++ b/internal/transform/markdown/bold.go @@ -38,7 +38,7 @@ func boldTransform(input string) (string, error) { } // 2. Add end of input - if cursor < len(input)-1 { + if cursor < len(input) { output += input[cursor:] } diff --git a/internal/transform/markdown/hyperlink.go b/internal/transform/markdown/hyperlink.go new file mode 100644 index 0000000..e1f2842 --- /dev/null +++ b/internal/transform/markdown/hyperlink.go @@ -0,0 +1,50 @@ +package markdown + +import ( + "fmt" + "regexp" +) + +var hyperlinkRe = regexp.MustCompile(`(?m)\[([^\[]+)\]\(([^\)]+)\)`) + +// linkify returns the terminal-formatted hyperlink for @url with the text : @label +func linkify(url, label string) string { + return fmt.Sprintf("\x1b]8;;%s\x1b\\%s\x1b]8;;\x1b\\", url, label) +} + +// hyperlinkTransform the @input text using markdown-like syntax : +// - "normal [link label](link url) normal" +func hyperlinkTransform(input string) (string, error) { + output := "" + cursor := int(0) + + // 1. Replace for each match + for _, match := range hyperlinkRe.FindAllStringSubmatchIndex(input, -1) { + + // (1) add gap between input start OR previous match + output += input[cursor:match[0]] + cursor = match[1] + + // (2) extract features + var label, url string + + if match[3]-match[2] > 0 { + label = input[match[2]:match[3]] + } + if match[5]-match[4] > 0 { + url = input[match[4]:match[5]] + } + + // (3) replace with hyperlink + output += linkify(url, label) + } + + // 2. Add end of input + if cursor < len(input) { + output += input[cursor:] + } + + // 3. print final output + return output, nil + +} diff --git a/internal/transform/markdown/italic.go b/internal/transform/markdown/italic.go index f2bec0c..66a0b92 100644 --- a/internal/transform/markdown/italic.go +++ b/internal/transform/markdown/italic.go @@ -38,7 +38,7 @@ func italicTransform(input string) (string, error) { } // 2. Add end of input - if cursor < len(input)-1 { + if cursor < len(input) { output += input[cursor:] } diff --git a/internal/transform/markdown/markdown.go b/internal/transform/markdown/markdown.go index c583a17..94df0c1 100644 --- a/internal/transform/markdown/markdown.go +++ b/internal/transform/markdown/markdown.go @@ -14,11 +14,17 @@ func Transform(input string) (string, error) { return "", err } - // 3. italic + // 3. underline underline, err := underlineTransform(italic) if err != nil { return "", err } - return underline, nil + // 4. hyperlink + hyperlinked, err := hyperlinkTransform(underline) + if err != nil { + return "", err + } + + return hyperlinked, nil } diff --git a/internal/transform/markdown/underline.go b/internal/transform/markdown/underline.go index af2aafb..926669d 100644 --- a/internal/transform/markdown/underline.go +++ b/internal/transform/markdown/underline.go @@ -38,7 +38,7 @@ func underlineTransform(input string) (string, error) { } // 2. Add end of input - if cursor < len(input)-1 { + if cursor < len(input) { output += input[cursor:] }