🖍️ Marker is the easiest way to match and mark strings for colorful terminal outputs!

Marker is the easiest way to match and mark strings for colorful terminal outputs.

marker

Marker is built for easily match and mark strings for colorful terminal outputs. You can match your strings with built-in matchers or easily implement a custom matcher for your usecase. Marker uses fatih/color for colorizing terminal output.

Installation

go get github.com/cyucelen/marker

Basic Usage

Marker has very simple and extensible way to get your strings colorful and brilliant!

Example

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)

Table of Contents


Mark Your Log Stream

You may want to instrument a logger such that any output coming from it is colorized in the expected manner. marker contains functionality which can be easily integrated with Golang's log or any interface that supports io.Writer.

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")

Custom 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.

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/awesome.log
fmt.Print(output)


Matchers

MatchAll

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

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

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

sentence := "I pull out things surrounded by abcWHOA COLORSdef"
markedSurrounded := marker.Mark(sentence, marker.MatchSurrounded("abc", "def"), color.New(color.FgMagenta))
fmt.Println(markedSurrounded)

MatchBracketSurrounded

sentence = "[INFO] This is what log lines look like"
markedSurrounded = marker.Mark(sentence, marker.MatchBracketSurrounded(), color.New(color.FgRed))
fmt.Println(markedSurrounded)

MatchParensSurrounded

sentence = "[ERROR] This is what (parens) lines look like"
markedSurrounded = marker.Mark(sentence, marker.MatchParensSurrounded(), color.New(color.FgBlue))
fmt.Println(markedSurrounded)

MatchTimestamp

MatchTimestamp can be used for matching the timestamps fits the layouts in Golang's time.

All possible formats can be found here.

  goodOldTimes := "2006-01-02T15:04:05Z07:00 [INFO] Loading King of Fighters '97 ROM"
  timestampMarked := marker.Mark(goodOldTimes, marker.MatchTimestamp(time.RFC3339), color.New(color.FgBlue))
  fmt.Println(timestampMarked)


Builder way

If you want to mark different patterns in the same string, marker builder is neater way to do this.

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()

fmt.Println(markedWithBuilder)


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. A Matcher is a simple closure that returns a MatcherFunc to be called by Mark function to get Match information to put colorized versions of patterns into template.

Lets write our own custom Matcher that matches first encounter of given pattern.

Example

  func MatchFirst(pattern string) marker.MatcherFunc {
    return func(str string) marker.Match {
      return marker.Match{
        // replace first matching pattern with %s
        Template: strings.Replace(str, pattern, "%s", 1),
        // patterns to be colorized by Mark, in order
        Patterns: []string{pattern},
      }
    }
  }

You can also check built-in matchers for inspiration.

Contribution

I would like to accept any contributions to make Marker better and feature rich. So feel free to contribute your features(i.e. more Matchers!), improvements and fixes.

Have fun!

Owner
Çağatay Yücelen
Currently working on secret alien technology.
Çağatay Yücelen
Comments
  • [WIP] Log marker

    [WIP] Log marker

    It stands to reason that one of the strongest use cases would be for users to colorize their logs for easy reading.

    • [x] Build a abstraction structure upon Golang's logger to colorize. (We can experiment here!)
    • [x] Implement io.Writer
    • [x] Add Mark Rules (Mark Rule name can change)
      • [x] Builder way
      • [x] Passing Rule slice
    • [x] README documentation

    We can add further features to the checklist!

    Closes #17

  • Create logger functionality

    Create logger functionality

    [WIP]

    Thinking about this project, it stands to reason that one of the strongest use cases would be for users to colorize their logs for easy reading. With that in mind, the current setup where you create a builder, give it a string, then mark means that there is a decent amount of overhead to integrating it with a logging system.

    I was messing around with the testing framework and the fact that the testing instances have a .Log function got me thinking about wrapping marker in a similar way. There could be some CreateLogger which you could pass a builder to (or maybe it is the builder) which then logs in the colorized manner you specify.

  • Fix stamp overlap - MatchTimestamp

    Fix stamp overlap - MatchTimestamp

    Golang's regexp package, build under google's RE2 engine, doesn't support backtracking and look around assertions (https://github.com/golang/go/issues/18868). Since negative lookahead is the most straight forward solution, I've found this: https://github.com/dlclark/regexp2.

    The only downside of using regexp2 (other than adding one more dependency to the project) is that it doesn't have constant time guarantees like the built-in regexp package, but since it's only used to Timestamp matches, I don't see it being a problem.

    https://godoc.org/github.com/dlclark/regexp2 Ref #8

  • Generate images for readme

    Generate images for readme

    It doesn't work as intended, but maybe somebody know how to fix this.

    I made script that generates svg files and crop them. And it's works when I open image in browser! But when I try to include image in README.md it looks awful. I can not control it size, and worse - crop doesn't work. (look https://github.com/Darkclainer/marker/blob/generate_images_for_readme/assets/svg/showoff.svg)

    I tried to convert this svg files to png, but not inkspace nor cairosvg don't read this files correctly.

    Your ideas?

    Issue #18

  • Keeping in touch

    Keeping in touch

    Since past two weeks, I feel like we built an awesome synergy among us. I really enjoyed working with you guys, I believe you all valuable and we can learn a lot from each other!

    So, i want to discuss about using a platform -like Slack but without limitations- for keeping in touch. By this way, i think, we can develop marker better and faster! I believe communication channel matters for efficiency.

    Even we can build new fantastic projects as a team and welcome new comers to our culture we just started to built!

    Lets discuss if it is a good idea and which platform should we use.

  • Add script that generates images for readme

    Add script that generates images for readme

    Script helps to generate clean images from examples for README.md

    Second solution. This actually works, but somebody (who knows css) should clean template for more neat output.

    Issue #18

  • Find a standard way to create colorized terminal output pictures for README

    Find a standard way to create colorized terminal output pictures for README

    It is hard to keep the terminal pictures in README file tidy and in order with respect to size, font family, font color, background color, etc. Want to discuss for finding a standard way that can be used by everbody to create colorful terminal output pictures for our API examples in README file.

    There are some possible solutions that comes to my mind:

    • Online IDE outputs
    • Online Terminal Emulators (if there are any)
    • We can find a standard way to create SVGs.
    • https://terminal.sexy/ template
  • Matching days of the week

    Matching days of the week

    Added a new matcher api to match days of the week in a string. The string can have days starting with a uppercase (starting after a period) or completely lower case. A new test case has been added as well.

    Closes #11

  • Match invalid English words

    Match invalid English words

    Given a string we need to match all valid english words that does not have numericals in them. One use case that I can think of is this feature is useful in matching all misspelled english words. For example:

    "This word has a singel error" Ouput : singel

    "This word is not a word1" No words matched here

  • Closes #11: Added a Match builder called MatchDaysOfWeek.

    Closes #11: Added a Match builder called MatchDaysOfWeek.

    This is my take on Match Days of Week. If you like this, merge it but merge Srivats1991 first to give him credit for his work if he is doing Hacktoberfest. If you don't like this, deny it :)

    Also, if you need a visual representation of my regex: image

  • Match surrounded characters

    Match surrounded characters

    Oftentimes in log files, the beginning of the log has certain characters encasing it ex: [INFO]. Create a matcher which takes in surrounding characters and colorizes the encased letters, inclusive of the surrounding characters.

  • Bump pillow from 9.0.1 to 9.3.0 in /image_generator

    Bump pillow from 9.0.1 to 9.3.0 in /image_generator

    Bumps pillow from 9.0.1 to 9.3.0.

    Release notes

    Sourced from pillow's releases.

    9.3.0

    https://pillow.readthedocs.io/en/stable/releasenotes/9.3.0.html

    Changes

    ... (truncated)

    Changelog

    Sourced from pillow's changelog.

    9.3.0 (2022-10-29)

    • Limit SAMPLESPERPIXEL to avoid runtime DOS #6700 [wiredfool]

    • Initialize libtiff buffer when saving #6699 [radarhere]

    • Inline fname2char to fix memory leak #6329 [nulano]

    • Fix memory leaks related to text features #6330 [nulano]

    • Use double quotes for version check on old CPython on Windows #6695 [hugovk]

    • Remove backup implementation of Round for Windows platforms #6693 [cgohlke]

    • Fixed set_variation_by_name offset #6445 [radarhere]

    • Fix malloc in _imagingft.c:font_setvaraxes #6690 [cgohlke]

    • Release Python GIL when converting images using matrix operations #6418 [hmaarrfk]

    • Added ExifTags enums #6630 [radarhere]

    • Do not modify previous frame when calculating delta in PNG #6683 [radarhere]

    • Added support for reading BMP images with RLE4 compression #6674 [npjg, radarhere]

    • Decode JPEG compressed BLP1 data in original mode #6678 [radarhere]

    • Added GPS TIFF tag info #6661 [radarhere]

    • Added conversion between RGB/RGBA/RGBX and LAB #6647 [radarhere]

    • Do not attempt normalization if mode is already normal #6644 [radarhere]

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

  • MarkWriter implementation

    MarkWriter implementation

    This is branch of issue #17.

    Context

    I recap the idea. We want to make wrapper for io.Writer interface, that colorize its input. For example we want to colorize our log output. If we have this wrapper, we simply do:

    log.SetOutput(NewMarkWriter(os.stdout, rules))
    

    I've seen the PR #24 with implementation for such wrapper and I sure it works in that context (for Logger), but can have subtle bugs in others.

    Problem

    Writing in common can happen in parts. We can write on part of line, than - another. It's undefined how we use io.Writer and this is the reason, why it can not nicely live with Mark. Mark have some rules, even regex and etc. It need full text to work correctly. Imagine that we writer our line in io.Writer by single byte - Mark will not work. If we match word "sense", and write:

    MarkWriter.Write("se")
    MarkWriter.Write("nse")
    

    MarkWriter will not match "sense". I hope I made problem clear.

    It's not like we can do nothing to mitigate this issue, but the way that I see has its own drawbacks. We can buffer and collect our line of text in MarkWriter until we get some delimiter (newline makes sense). So

    MarkWriter.Write("se")
    MarkWriter.Write("nse")
    MarkWriter.Write(" blabla\n")
    

    now can mark "sense", but will write entire string in it's underlying io.Writer.

    And there is another thing - we should implement Close method, that will flush buffer and close underlying Writer (if it can be close of course).

  • Encapsulating the color library inside marker

    Encapsulating the color library inside marker

    Marker depends on fatih/color library to colorizing strings for terminal output. Encapsulating the colorizing behavior inside marker library to prevent multiple imports from user side can be beneficial. I want to discuss the implementation details of this encapsulation and if its overkill and comes with restrictions along with it or not.

  • Match time format

    Match time format

    Create a matcher which takes one of the time layouts of golang standard time library and matches them in given string.

    const (
    	ANSIC       = "Mon Jan _2 15:04:05 2006"
    	UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
    	RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
    	RFC822      = "02 Jan 06 15:04 MST"
    	RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
    	RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
    	RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
    	RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
    	RFC3339     = "2006-01-02T15:04:05Z07:00"
    	RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
    	Kitchen     = "3:04PM"
    	// Handy time stamps.
    	Stamp      = "Jan _2 15:04:05"
    	StampMilli = "Jan _2 15:04:05.000"
    	StampMicro = "Jan _2 15:04:05.000000"
    	StampNano  = "Jan _2 15:04:05.000000000"
    )
    

    An example:

    strWithTimestamp := "Current timestamp is 2019-10-07T23:45:05Z03:00"
    match := MatchTimestamp(time.RFC3339)(strWithTimestamp)
    // expected match => Match{Template: "Current timestamp is %s", Patterns: []string{"2019-10-07T23:45:05Z03:00"}}
    
    

    Distinct implementations can be written for each format. We can discuss to split the issue to fine grained pieces on the way with respect to complexity.

Related tags
espnwrapper to track real time scores for your fav match... in a terminal while working.
espnwrapper to track real time scores for your fav match... in a terminal while working.

An espncricinfo wrapper written in go to track scores in real time and in the cmd/cli you can find the Command Line Interface wrapped over this wrapper.

Mar 13, 2022
Limner colorizes and transforms CLI outputs.
Limner colorizes and transforms CLI outputs.

Limner Limner colorizes and transforms CLI outputs. Motivation When playing with kubectl, I sometimes found it hard to extract the information I neede

Dec 14, 2022
Go program that outputs a GIF with the lissajous figures using green and black

lissajousgb This is an exercise of the book The Go Programming Language, by Alan

Dec 18, 2021
simple clipboard copy for complex outputs
simple clipboard copy for complex outputs

Terminal Clipboard Different from others terminal's clipboard coppiers, this one can copy complex and interminables commands like tail -f or outputs t

Nov 5, 2021
A simple CLI tool that outputs the history of connections to Amazon EC2 instances using AWS Session Manager.

ssmh This is a simple CLI tool that outputs the history of connections to Amazon EC2 instances using AWS Session Manager. Installation brew install mi

Dec 10, 2021
A piece of software that shouldn't need to exist. Processes badly formatted outputs from Morgan Stanley Shareworks into usable CSV files.
A piece of software that shouldn't need to exist.  Processes badly formatted outputs from Morgan Stanley Shareworks into usable CSV files.

Shareworks-munger: A program to process Shareworks reports into Something Usable "Shareworks" is a product of Morgan Stanley which tracks certain kind

Jun 6, 2022
This package can parse date match expression, which used by ElasticSearch

datemath-parser this package is pure go package, this package can parse date match expression, which used by ElasticSearch. Date Math Definition you c

Jan 8, 2022
Json-match - Command line util for matching values in a JSON input

json-match Match JSON input by specifying key and value > json-match -json '{\"p

Jan 12, 2022
Small, fast library to create ANSI colored strings and codes. [go, golang]

ansi Package ansi is a small, fast library to create ANSI colored strings and codes. Install Get it go get -u github.com/mgutz/ansi Example import "gi

Dec 23, 2022
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.
Stonks is a terminal based stock visualizer and tracker that displays realtime stocks in graph format in a terminal.

Stonks is a terminal based stock visualizer and tracker. Installation Requirements: golang >= 1.13 Manual Clone the repo Run make && make install Pack

Dec 16, 2022
Library for easy named formatting strings

go-celsium Library for easy named formatting translations Documentation All translations with named parameters are stored in next format: Hello, {name

Apr 12, 2021
linenoise-classic is a command-line tool that generates strings of random characters that can be used as reasonably secure passwords.

linenoise-classic is a command-line tool that generates strings of random characters that can be used as reasonably secure passwords.

Aug 21, 2022
Go cmd utility that prints its command line arguments using strings.Join

Results This is an exercise of the book The Go Programming Language, by Alan A. A. Donovan and Brian Kernighan. Comparison between different versions

Dec 18, 2021
Zenstring - Randomly generated, friendly & zen strings for your app

zenstring Randomly generated, friendly & zen strings for your app. Started as a

Feb 3, 2022
Procmon is a Linux reimagining of the classic Procmon tool from the Sysinternals suite of tools for Windows. Procmon provides a convenient and efficient way for Linux developers to trace the syscall activity on the system.
Procmon is a Linux reimagining of the classic Procmon tool from the Sysinternals suite of tools for Windows. Procmon provides a convenient and efficient way for Linux developers to trace the syscall activity on the system.

Process Monitor for Linux (Preview) Process Monitor (Procmon) is a Linux reimagining of the classic Procmon tool from the Sysinternals suite of tools

Dec 29, 2022
A better way to clone, organize and manage multiple git repositories
A better way to clone, organize and manage multiple git repositories

git-get git-get is a better way to clone, organize and manage multiple git repositories. git-get Description Installation macOS Linux Windows Usage gi

Nov 16, 2022
🚀 goprobe is a promising command line tool for inspecting URLs with modern and user-friendly way.

goprobe Build go build -o ./bin/goprobe Example > goprobe https://github.com/gaitr/goprobe > cat links.txt | goprobe > echo "https://github.com/gaitr/

Oct 24, 2021
A simple way of sending messages from the CLI output to your Discord channel with webhook.
A simple way of sending messages from the CLI output to your Discord channel with webhook.

discat A simple way of sending messages from the CLI output to your Discord channel with webhook. Actually, this is a fork version of slackcat that I

Nov 15, 2022
A command tool to help user install oh-my-zsh plugins fast in a comfortable way

zshx A command tool to help user install oh-my-zsh plugins fast in a comfortable way. in other way, it is a zsh plugin package manager. How to use the

Feb 11, 2022