diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..228e701
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+go.sum
+image_generator/typescript
\ No newline at end of file
diff --git a/README.md b/README.md
index d13b694..6214421 100644
--- a/README.md
+++ b/README.md
@@ -44,54 +44,54 @@ Marker has very simple and extensible way to get your strings colorful and brill
#### MatchAll
```go
- aristotleQuote := "The more you know, the more you realize you don't know."
- emphasized := marker.Mark(aristotleQuote, marker.MatchAll("know"), color.New(color.FgRed))
- fmt.Println(emphasized)
+aristotleQuote := "The more you know, the more you realize you don't know."
+emphasized := marker.Mark(aristotleQuote, marker.MatchAll("know"), color.New(color.FgRed))
+fmt.Println(emphasized)
```
#### MatchN
```go
- boringLog := "[INFO] Nobody wants to read pale [INFO] tags."
- brilliantLog := marker.Mark(boringLog, marker.MatchN("[INFO]", 1), color.New(color.FgBlue))
- fmt.Println(brilliantLog)
+boringLog := "[INFO] Nobody wants to read pale [INFO] tags."
+brilliantLog := marker.Mark(boringLog, marker.MatchN("[INFO]", 1), color.New(color.FgBlue))
+fmt.Println(brilliantLog)
```
#### MatchRegexp
```go
- rhyme := "I scream, you all scream, we all scream for ice cream."
- r, _ := regexp.Compile("([a-z]?cream)")
- careAboutCream := marker.Mark(rhyme, marker.MatchRegexp(r), color.New(color.FgYellow))
- fmt.Println(careAboutCream)
+rhyme := "I scream, you all scream, we all scream for ice cream."
+r, _ := regexp.Compile("([a-z]?cream)")
+careAboutCream := marker.Mark(rhyme, marker.MatchRegexp(r), color.New(color.FgYellow))
+fmt.Println(careAboutCream)
```
#### MatchSurrounded
```go
- sentence := "I pull out things surrounded by abcWHOA COLORSdef"
- markedSurrounded := marker.Mark(sentence, marker.MatchSurrounded("abc", "def"), magentaFg)
- fmt.Println(markedSurrounded)
+sentence := "I pull out things surrounded by abcWHOA COLORSdef"
+markedSurrounded := marker.Mark(sentence, marker.MatchSurrounded("abc", "def"), magentaFg)
+fmt.Println(markedSurrounded)
```
#### MatchBracketSurrounded
```go
- sentence = "[INFO] This is what log lines look like"
- markedSurrounded = marker.Mark(sentence, marker.MatchBracketSurrounded(), redFg)
- fmt.Println(markedSurrounded)
+sentence = "[INFO] This is what log lines look like"
+markedSurrounded = marker.Mark(sentence, marker.MatchBracketSurrounded(), redFg)
+fmt.Println(markedSurrounded)
```
#### MatchParensSurrounded
```go
- sentence = "[ERROR] This is what (parens) lines look like"
- markedSurrounded = marker.Mark(sentence, marker.MatchParensSurrounded(), blueFg)
- fmt.Println(markedSurrounded)
+sentence = "[ERROR] This is what (parens) lines look like"
+markedSurrounded = marker.Mark(sentence, marker.MatchParensSurrounded(), blueFg)
+fmt.Println(markedSurrounded)
```
@@ -102,22 +102,70 @@ Marker has very simple and extensible way to get your strings colorful and brill
If you want to mark different patterns in the same string, marker builder is neater way to do this.
```go
- rhyme := "I scream, you all scream, we all scream for ice cream."
- b := &marker.MarkBuilder{}
- r, _ := regexp.Compile("([a-z]?cream)")
+rhyme := "I scream, you all scream, we all scream for ice cream."
+b := &marker.MarkBuilder{}
+r, _ := regexp.Compile("([a-z]?cream)")
- markedWithBuilder := b.SetString(rhyme).
- Mark(marker.MatchN("for ice", 1), color.New(color.FgRed)).
- Mark(marker.MatchAll("all"), color.New(color.FgMagenta)).
- Mark(marker.MatchRegexp(r), color.New(color.FgYellow)).
- Build()
+markedWithBuilder := b.SetString(rhyme).
+ Mark(marker.MatchN("for ice", 1), color.New(color.FgRed)).
+ Mark(marker.MatchAll("all"), color.New(color.FgMagenta)).
+ Mark(marker.MatchRegexp(r), color.New(color.FgYellow)).
+ Build()
- fmt.Println(markedWithBuilder)
+fmt.Println(markedWithBuilder)
```
---
+## Log way
+
+You may want to instrument a logger such that any output coming from it is colorized in the expected manner. `marker` contains functionality which wraps `stdout` or whatever `io.Writer` you wish.
+
+```go
+stdoutMarker := marker.NewStdoutMarker()
+markRules := []marker.MarkRule{
+ {marker.MatchBracketSurrounded(), color.New(color.FgBlue)},
+ {marker.MatchAll("marker"), color.New(color.FgRed)},
+}
+
+stdoutMarker.AddRules(markRules)
+logger := log.New(stdoutMarker, "", 0)
+
+logger.Println("[INFO] marker is working as expected")
+```
+
+
+
+### Customize io.Writer out for log interface
+
+`marker` also allows you to specify the `io.Writer` that you want to send output to. This is useful if the logger is writing to somewhere other than `stdout` like a file.
+
+```go
+f, _ := os.Create("/tmp/awesome.log")
+w := bufio.NewWriter(f)
+
+writeMarker := marker.NewWriteMarker(w)
+
+markRules := []marker.MarkRule{
+ {marker.MatchBracketSurrounded(), blueFg},
+ {marker.MatchAll("marker"), magentaFg},
+}
+
+writeMarker.AddRules(markRules)
+
+logger := log.New(writeMarker, "", 0)
+logger.Println("[INFO] colorful logs even in files, marker to mark them all!")
+
+w.Flush()
+f.Close()
+
+output := catFile("/tmp/awesome.log") // cat /tmp/dat2
+fmt.Print(output)
+```
+
+
+
## Writing your custom Matcher
As you see in above examples, **Mark** function takes an **MatcherFunc** to match the patterns in given string and colorize them.
diff --git a/assets/builder.jpg b/assets/builder.jpg
deleted file mode 100644
index f0f2094..0000000
Binary files a/assets/builder.jpg and /dev/null differ
diff --git a/assets/matchall.jpg b/assets/matchall.jpg
deleted file mode 100644
index 268cee4..0000000
Binary files a/assets/matchall.jpg and /dev/null differ
diff --git a/assets/matchn.jpg b/assets/matchn.jpg
deleted file mode 100644
index b829f8b..0000000
Binary files a/assets/matchn.jpg and /dev/null differ
diff --git a/assets/matchregexp.jpg b/assets/matchregexp.jpg
deleted file mode 100644
index d6ab86a..0000000
Binary files a/assets/matchregexp.jpg and /dev/null differ
diff --git a/assets/png/builder.png b/assets/png/builder.png
index 4de9c99..4a9ed77 100644
Binary files a/assets/png/builder.png and b/assets/png/builder.png differ
diff --git a/assets/png/custom.png b/assets/png/custom.png
index c9f1818..f52f715 100644
Binary files a/assets/png/custom.png and b/assets/png/custom.png differ
diff --git a/assets/png/email.png b/assets/png/email.png
index 2e80f46..9f6eae8 100644
Binary files a/assets/png/email.png and b/assets/png/email.png differ
diff --git a/assets/png/log.png b/assets/png/log.png
new file mode 100644
index 0000000..2032daf
Binary files /dev/null and b/assets/png/log.png differ
diff --git a/assets/png/logtofile.png b/assets/png/logtofile.png
new file mode 100644
index 0000000..56ef851
Binary files /dev/null and b/assets/png/logtofile.png differ
diff --git a/assets/png/matchall.png b/assets/png/matchall.png
index e4d2543..b34c7ef 100644
Binary files a/assets/png/matchall.png and b/assets/png/matchall.png differ
diff --git a/assets/png/matchn.png b/assets/png/matchn.png
index c9f1818..f52f715 100644
Binary files a/assets/png/matchn.png and b/assets/png/matchn.png differ
diff --git a/assets/png/matchregex.png b/assets/png/matchregex.png
index 5b6d0c6..08e852e 100644
Binary files a/assets/png/matchregex.png and b/assets/png/matchregex.png differ
diff --git a/assets/png/matchsurrounded1.png b/assets/png/matchsurrounded1.png
index 59e6ce0..55d24bb 100644
Binary files a/assets/png/matchsurrounded1.png and b/assets/png/matchsurrounded1.png differ
diff --git a/assets/png/matchsurrounded2.png b/assets/png/matchsurrounded2.png
index 06315d6..aa91992 100644
Binary files a/assets/png/matchsurrounded2.png and b/assets/png/matchsurrounded2.png differ
diff --git a/assets/png/matchsurrounded3.png b/assets/png/matchsurrounded3.png
index f4e75f5..3540acd 100644
Binary files a/assets/png/matchsurrounded3.png and b/assets/png/matchsurrounded3.png differ
diff --git a/assets/png/showoff.png b/assets/png/showoff.png
index a03e971..f0dd866 100644
Binary files a/assets/png/showoff.png and b/assets/png/showoff.png differ
diff --git a/assets/showoff.jpg b/assets/showoff.jpg
deleted file mode 100644
index d70f22e..0000000
Binary files a/assets/showoff.jpg and /dev/null differ
diff --git a/assets/surrounded1.png b/assets/surrounded1.png
deleted file mode 100644
index ed0f49b..0000000
Binary files a/assets/surrounded1.png and /dev/null differ
diff --git a/assets/surrounded2.png b/assets/surrounded2.png
deleted file mode 100644
index ebfd707..0000000
Binary files a/assets/surrounded2.png and /dev/null differ
diff --git a/assets/surrounded3.png b/assets/surrounded3.png
deleted file mode 100644
index 5ee3166..0000000
Binary files a/assets/surrounded3.png and /dev/null differ
diff --git a/examples/log/main.go b/examples/log/main.go
new file mode 100644
index 0000000..2abd497
--- /dev/null
+++ b/examples/log/main.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "log"
+
+ "github.com/cyucelen/marker"
+ "github.com/fatih/color"
+)
+
+var (
+ redFg = color.New(color.FgRed)
+ blueFg = color.New(color.FgBlue)
+)
+
+func main() {
+ stdoutMarker := marker.NewStdoutMarker()
+
+ markRules := []marker.MarkRule{
+ {marker.MatchBracketSurrounded(), blueFg},
+ {marker.MatchAll("marker"), redFg},
+ }
+
+ stdoutMarker.AddRules(markRules)
+
+ logger := log.New(stdoutMarker, "", 0)
+ logger.Println("[INFO] marker is working as expected")
+}
diff --git a/examples/logtofile/main.go b/examples/logtofile/main.go
new file mode 100644
index 0000000..43f14a7
--- /dev/null
+++ b/examples/logtofile/main.go
@@ -0,0 +1,52 @@
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+
+ "github.com/cyucelen/marker"
+ "github.com/fatih/color"
+)
+
+var (
+ magentaFg = color.New(color.FgMagenta)
+ blueFg = color.New(color.FgBlue)
+)
+
+func main() {
+ f, _ := os.Create("/tmp/awesome.log")
+ w := bufio.NewWriter(f)
+
+ writeMarker := marker.NewWriteMarker(w)
+
+ markRules := []marker.MarkRule{
+ {marker.MatchBracketSurrounded(), blueFg},
+ {marker.MatchAll("marker"), magentaFg},
+ }
+
+ writeMarker.AddRules(markRules)
+
+ logger := log.New(writeMarker, "", 0)
+ logger.Println("[INFO] colorful logs even in files, marker to mark them all!")
+
+ w.Flush()
+ f.Close()
+
+ output := catFile("/tmp/awesome.log") // cat /tmp/dat2
+ fmt.Print(output)
+}
+
+func catFile(file string) string {
+ cmd := exec.Command("cat", file)
+ cmdOutput := &bytes.Buffer{}
+ cmd.Stdout = cmdOutput
+ err := cmd.Run()
+ if err != nil {
+ log.Fatalf("cmd.Run() failed with %s\n", err)
+ }
+ return string(cmdOutput.Bytes())
+}
diff --git a/examples/showoff/main.go b/examples/showoff/main.go
index bccaf33..a84e4c7 100644
--- a/examples/showoff/main.go
+++ b/examples/showoff/main.go
@@ -2,9 +2,10 @@ package main
import (
"fmt"
+ "regexp"
+
"github.com/cyucelen/marker"
"github.com/fatih/color"
- "regexp"
)
var magentaFg = color.New(color.FgMagenta)
@@ -30,16 +31,16 @@ func main() {
r, _ := regexp.Compile("([a-z]?cream)")
markedWithRegexp := marker.Mark(rhyme, marker.MatchRegexp(r), whiteFg.Add(color.BgHiBlue))
- regexpExampleHeader := fmt.Sprintf("Mark Regexp \"%s\":\t\t\t\t", whiteFg.Add(color.BgHiBlue).Sprint("([a-z]?cream)"))
+ regexpExampleHeader := fmt.Sprintf("Mark Regexp \"%s\":\t\t\t", whiteFg.Add(color.BgHiBlue).Sprint("([a-z]?cream)"))
fmt.Println(regexpExampleHeader + markedWithRegexp)
b := &marker.MarkBuilder{}
markedWithBuilder := b.SetString(rhyme).
Mark(marker.MatchN("for ice", 1), redFg).
Mark(marker.MatchAll("all"), magentaFg).
- Mark(marker.MatchRegexp(r), redFg.Add(color.BgHiWhite)).
+ Mark(marker.MatchRegexp(r), blueFg).
Build()
- builderExampleHeader := fmt.Sprintf("Mark \"%s\", \"%s\", \"%s\" (w/ builder):\t",
- color.New(color.FgRed).Sprint("for ice"), magentaFg.Sprint("all"), redFg.Add(color.BgHiWhite).Sprint("([a-z]?cream)"))
+ builderExampleHeader := fmt.Sprintf("Mark \"%s\", \"%s\", \"%s\" :\t",
+ color.New(color.FgRed).Sprint("for ice"), magentaFg.Sprint("all"), blueFg.Sprint("([a-z]?cream)"))
fmt.Println(builderExampleHeader + markedWithBuilder)
}
diff --git a/image_generator/README.md b/image_generator/README.md
new file mode 100644
index 0000000..a8ebdc1
--- /dev/null
+++ b/image_generator/README.md
@@ -0,0 +1,40 @@
+
+# Terminal image generator
+
+`generate.py` runs all the `main.go` files under examples and converts terminal outputs to `html` and then `png`
+
+## Prerequisites
+
+* Go
+* Python3.7 (preferred)
+* Pip
+
+### terminal-to-html
+
+```
+$ cd ~/
+$ go get github.com/buildkite/terminal-to-html/cmd/terminal-to-html
+```
+
+### wkhtmltoimage
+
+#### Arch
+
+```
+$ yaourt wkhtmltopdf
+```
+
+#### Ubuntu
+
+```
+$ sudo apt-get update
+$ sudo apt-get install xvfb libfontconfig wkhtmltopdf
+```
+
+## Usage
+
+```
+$ python3.7 generate.py
+```
+
+After running the script, image files should be created under `assets/png`
\ No newline at end of file
diff --git a/image_generator/log.txt b/image_generator/log.txt
new file mode 100644
index 0000000..f61253f
--- /dev/null
+++ b/image_generator/log.txt
@@ -0,0 +1 @@
+[34m[INFO][0m [31mmarker[0m is working as expected
diff --git a/log.go b/log.go
new file mode 100644
index 0000000..0d4ea61
--- /dev/null
+++ b/log.go
@@ -0,0 +1,54 @@
+package marker
+
+import (
+ "io"
+ "os"
+
+ "github.com/fatih/color"
+)
+
+// WriteMarkerOption is functional option type for WriteMarker
+type WriteMarkerOption func(*WriteMarker)
+
+// MarkRule contains marking information to be applied on log stream
+type MarkRule struct {
+ Matcher MatcherFunc
+ Color *color.Color
+}
+
+// WriteMarker contains specified rules for applying them on output
+type WriteMarker struct {
+ rules []MarkRule
+ out io.Writer
+}
+
+// NewWriteMarker creates a Marker that writes out to the given io.Writer
+func NewWriteMarker(writer io.Writer) *WriteMarker {
+ logMarker := &WriteMarker{out: writer}
+ return logMarker
+}
+
+// NewStdoutMarker creates a WriteMarker with default out as os.Stdout
+func NewStdoutMarker() *WriteMarker {
+ return NewWriteMarker(os.Stdout)
+}
+
+// AddRule appends a rule to WriteMarker and returns itself
+func (s *WriteMarker) AddRule(rule MarkRule) *WriteMarker {
+ s.rules = append(s.rules, rule)
+ return s
+}
+
+// AddRules appends all rules from given slice to WriteMarker rules
+func (s *WriteMarker) AddRules(rules []MarkRule) {
+ s.rules = append(s.rules, rules...)
+}
+
+// Write marks the text with specified rules and writes the output to specifed out
+func (s WriteMarker) Write(p []byte) (n int, err error) {
+ marked := string(p)
+ for _, rule := range s.rules {
+ marked = Mark(marked, rule.Matcher, rule.Color)
+ }
+ return s.out.Write([]byte(marked))
+}
diff --git a/log_test.go b/log_test.go
new file mode 100644
index 0000000..aa8e535
--- /dev/null
+++ b/log_test.go
@@ -0,0 +1,61 @@
+package marker
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "testing"
+
+ "github.com/fatih/color"
+ "github.com/stretchr/testify/assert"
+)
+
+type MockLogOut struct {
+ actualLog string
+}
+
+func (m *MockLogOut) Write(p []byte) (n int, err error) {
+ m.actualLog = string(p)
+ return len(p), nil
+}
+
+func Test_New(t *testing.T) {
+ stdoutMarker := NewStdoutMarker()
+ assert.Equal(t, stdoutMarker.out, os.Stdout)
+
+ mockLogOut := &MockLogOut{}
+ writeMarker := NewWriteMarker(mockLogOut)
+ assert.Equal(t, writeMarker.out, mockLogOut)
+}
+
+func Test_Write(t *testing.T) {
+ redFg := color.New(color.FgRed)
+ redFg.EnableColor()
+ red := redFg.SprintFunc()
+ blueFg := color.New(color.FgBlue)
+ blueFg.EnableColor()
+ blue := blueFg.SprintFunc()
+
+ mockOut := &MockLogOut{}
+ writeMarker := NewWriteMarker(mockOut)
+
+ writeMarker.AddRule(MarkRule{MatchAll("skydome"), redFg}).AddRule(MarkRule{MatchAll("data"), redFg})
+
+ logger := log.New(writeMarker, "", 0)
+ logger.Print("best data company is skydome")
+
+ expectedLog := fmt.Sprintf("best %s company is %s\n", red("data"), red("skydome"))
+ assert.Equal(t, expectedLog, mockOut.actualLog)
+
+ // Testing the mark order here since we cannot assert function equality (https://golang.org/ref/spec#Comparison_operators)
+ newRules := []MarkRule{
+ {MatchAll("skydome"), blueFg}, // blue should override red because of order
+ {MatchAll("company"), redFg},
+ }
+ writeMarker.AddRules(newRules)
+
+ expectedLog = fmt.Sprintf("best %s %s is %s\n", red("data"), red("company"), red(blue("skydome")))
+ logger.Print("best data company is skydome")
+ assert.Equal(t, expectedLog, mockOut.actualLog)
+
+}