blush

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 22, 2022 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package blush reads from a given io.Reader line by line and looks for patterns.

Blush struct has a Reader property which can be Stdin in case of it being shell's pipe, or any type that implements io.ReadCloser. If NoCut is set to true, it will show all lines despite being not matched. You cannot call Read() and WriteTo() on the same object. Blush will return ErrReadWriteMix on the second consequent call. The first time Read/WriteTo is called, it will start a goroutine and reads up to LineCache lines from Reader. If the Read() is in use, it starts a goroutine that reads up to CharCache bytes from the line cache and fills up the given buffer.

The hex number should be in 3 or 6 part format (#aaaaaa or #aaa) and each part will be translated to a number value between 0 and 255 when creating the Colour instance. If any of hex parts are not between 00 and ff, it creates the DefaultColour value.

Important Notes

The Read() method could be slow in case of huge inspections. It is recommended to avoid it and use WriteTo() instead; io.Copy() can take care of that for you.

When WriteTo() is called with an unavailable or un-writeable writer, there will be no further checks until it tries to write into it. If the Write encounters any errors regarding writes, it will return the amount if writes and stops its search.

There always will be a newline after each read.

Index

Examples

Constants

View Source
const (
	// Separator string between name of the reader and the contents.
	Separator = ": "

	// DefaultLineCache is minimum lines to cache.
	DefaultLineCache = 50

	// DefaultCharCache is minimum characters to cache for each line. This is in
	// effect only if Read() function is used.
	DefaultCharCache = 1000
)
View Source
const BgLevel = 70

BgLevel is the colour value of R, G, or B when the colour is shown in the background.

Variables

View Source
var (
	NoRGB     = RGB{-1, -1, -1}
	FgRed     = RGB{255, 0, 0}
	FgBlue    = RGB{0, 0, 255}
	FgGreen   = RGB{0, 255, 0}
	FgBlack   = RGB{0, 0, 0}
	FgWhite   = RGB{255, 255, 255}
	FgCyan    = RGB{0, 255, 255}
	FgMagenta = RGB{255, 0, 255}
	FgYellow  = RGB{255, 255, 0}
	BgRed     = RGB{BgLevel, 0, 0}
	BgBlue    = RGB{0, 0, BgLevel}
	BgGreen   = RGB{0, BgLevel, 0}
	BgBlack   = RGB{0, 0, 0}
	BgWhite   = RGB{BgLevel, BgLevel, BgLevel}
	BgCyan    = RGB{0, BgLevel, BgLevel}
	BgMagenta = RGB{BgLevel, 0, BgLevel}
	BgYellow  = RGB{BgLevel, BgLevel, 0}
)

These are colour settings. NoRGB results in no colouring in the terminal.

View Source
var (
	NoColour = Colour{NoRGB, NoRGB}
	Red      = Colour{FgRed, NoRGB}
	Blue     = Colour{FgBlue, NoRGB}
	Green    = Colour{FgGreen, NoRGB}
	Black    = Colour{FgBlack, NoRGB}
	White    = Colour{FgWhite, NoRGB}
	Cyan     = Colour{FgCyan, NoRGB}
	Magenta  = Colour{FgMagenta, NoRGB}
	Yellow   = Colour{FgYellow, NoRGB}
)

Some stock colours. There will be no colouring when NoColour is used.

View Source
var (
	// ErrNoWriter is returned if a nil object is passed to the WriteTo method.
	ErrNoWriter = errors.New("no writer defined")

	// ErrNoFinder is returned if there is no finder passed to Blush.
	ErrNoFinder = errors.New("no finders defined")

	// ErrClosed is returned if the reader is closed and you try to read from
	// it.
	ErrClosed = errors.New("reader already closed")

	// ErrReadWriteMix is returned when the Read and WriteTo are called on the
	// same object.
	ErrReadWriteMix = errors.New("you cannot mix Read and WriteTo calls")
)
View Source
var DefaultColour = Blue

DefaultColour is the default colour if no colour is set via arguments.

Functions

func Colourise

func Colourise(input string, c Colour) string

Colourise wraps the input between colours.

Types

type Blush

type Blush struct {
	Finders      []Finder
	Reader       io.ReadCloser
	LineCache    uint
	CharCache    uint
	Drop         bool // do not cut out non-matched lines.
	WithFileName bool
	// contains filtered or unexported fields
}

Blush reads from reader and matches against all finders. If NoCut is true, any unmatched lines are printed as well. If WithFileName is true, blush will write the filename before it writes the output. Read and WriteTo will return ErrReadWriteMix if both Read and WriteTo are called on the same object. See package docs for more details. nolint:govet // we are expecting lots of these objects.

Example
package main

import (
	"bytes"
	"io"

	"github.com/arsham/blush/blush"
)

func main() {
	f := blush.NewExact("sword", blush.Red)
	r := bytes.NewBufferString("He who lives by the sword, will surely also die")
	b := &blush.Blush{
		Finders: []blush.Finder{f},
		Reader:  io.NopCloser(r),
	}
	b.Close()
}
Output:

func (*Blush) Close

func (b *Blush) Close() error

Close closes the reader and returns whatever error it returns.

func (*Blush) Read

func (b *Blush) Read(p []byte) (n int, err error)

Read creates a goroutine on first invocation to read from the underlying reader. It is considerably slower than WriteTo as it reads the bytes one by one in order to produce the results, therefore you should use WriteTo directly or use io.Copy() on blush.

Example
package main

import (
	"bytes"
	"io"

	"github.com/arsham/blush/blush"
)

func main() {
	var p []byte
	f := blush.NewExact("sin", blush.Red)
	r := bytes.NewBufferString("He who lives in sin, will surely live the lie")
	b := &blush.Blush{
		Finders: []blush.Finder{f},
		Reader:  io.NopCloser(r),
	}
	b.Read(p)
}
Output:

Example (InDetails)
package main

import (
	"bytes"
	"fmt"
	"io"

	"github.com/arsham/blush/blush"
)

func main() {
	f := blush.NewExact("sin", blush.Red)
	r := bytes.NewBufferString("He who lives in sin, will surely live the lie")
	b := &blush.Blush{
		Finders: []blush.Finder{f},
		Reader:  io.NopCloser(r),
	}
	expect := fmt.Sprintf("He who lives in %s, will surely live the lie", f)

	// you should account for the additional characters for colour formatting.
	length := r.Len() - len("sin") + len(f.String())
	p := make([]byte, length)
	n, err := b.Read(p)
	fmt.Println("n == len(p):", n == len(p))
	fmt.Println("err:", err)
	fmt.Println("p == expect:", string(p) == expect)
	// by the way
	fmt.Println(`f == "sin":`, f.String() == "sin")

}
Output:

n == len(p): true
err: <nil>
p == expect: true
f == "sin": false

func (*Blush) WriteTo

func (b *Blush) WriteTo(w io.Writer) (int64, error)

WriteTo writes matches to w. It returns an error if the writer is nil or there are not paths defined or there is no files found in the Reader.

Example
package main

import (
	"bytes"
	"fmt"
	"io"

	"github.com/arsham/blush/blush"
)

func main() {
	f := blush.NewExact("victor", blush.Red)
	r := bytes.NewBufferString("It is a shield of passion and strong will from this I am the victor instead of the kill\n")
	b := &blush.Blush{
		Finders: []blush.Finder{f},
		Reader:  io.NopCloser(r),
	}
	buf := new(bytes.Buffer)
	n, err := b.WriteTo(buf)

	expected := fmt.Sprintf("It is a shield of passion and strong will from this I am the %s instead of the kill\n", f)
	fmt.Println("err:", err)
	fmt.Println("n == len(expected):", int(n) == len(expected))
	fmt.Println("buf.String() == expected:", buf.String() == expected)

}
Output:

err: <nil>
n == len(expected): true
buf.String() == expected: true
Example (Copy)
package main

import (
	"bytes"
	"fmt"
	"io"

	"github.com/arsham/blush/blush"
)

func main() {
	f := blush.NewExact("you feel", blush.Cyan)
	r := bytes.NewBufferString("Savour what you feel and what you see\n")
	b := &blush.Blush{
		Finders: []blush.Finder{f},
		Reader:  io.NopCloser(r),
	}
	buf := new(bytes.Buffer)
	n, err := io.Copy(buf, b)

	expected := fmt.Sprintf("Savour what %s and what you see\n", f)
	fmt.Println("err:", err)
	fmt.Println("n == len(expected):", int(n) == len(expected))
	fmt.Println("buf.String() == expected:", buf.String() == expected)

}
Output:

err: <nil>
n == len(expected): true
buf.String() == expected: true
Example (MultiReader)
package main

import (
	"bytes"
	"io"

	"github.com/arsham/blush/blush"
)

func main() {
	mg := blush.NewExact("truth", blush.Magenta)
	g := blush.NewExact("Life", blush.Green)
	r1 := bytes.NewBufferString("Life is like a mystery with many clues, but with few answers\n")
	r2 := bytes.NewBufferString("To tell us what it is that we can do to look for messages that keep us from the truth\n")
	mr := io.MultiReader(r1, r2)

	b := &blush.Blush{
		Finders: []blush.Finder{mg, g},
		Reader:  io.NopCloser(mr),
	}
	buf := new(bytes.Buffer)
	b.WriteTo(buf)
}
Output:

Example (MultiReaderInDetails)
package main

import (
	"bytes"
	"fmt"
	"io"

	"github.com/arsham/blush/blush"
)

func main() {
	mg := blush.NewExact("truth", blush.Magenta)
	g := blush.NewExact("Life", blush.Green)
	r1 := bytes.NewBufferString("Life is like a mystery with many clues, but with few answers\n")
	r2 := bytes.NewBufferString("To tell us what it is that we can do to look for messages that keep us from the truth\n")
	mr := io.MultiReader(r1, r2)

	b := &blush.Blush{
		Finders: []blush.Finder{mg, g},
		Reader:  io.NopCloser(mr),
	}
	buf := new(bytes.Buffer)
	n, err := b.WriteTo(buf)

	line1 := fmt.Sprintf("%s is like a mystery with many clues, but with few answers\n", g)
	line2 := fmt.Sprintf("To tell us what it is that we can do to look for messages that keep us from the %s\n", mg)
	expected := line1 + line2
	fmt.Println("err:", err)
	fmt.Println("n == len(expected):", int(n) == len(expected))
	fmt.Println("buf.String() == expected:", buf.String() == expected)

}
Output:

err: <nil>
n == len(expected): true
buf.String() == expected: true

type Colour

type Colour struct {
	Foreground RGB
	Background RGB
}

Colour is a pair of RGB colours for foreground and background.

type Exact

type Exact struct {
	// contains filtered or unexported fields
}

Exact looks for the exact word in the string.

func NewExact

func NewExact(s string, c Colour) Exact

NewExact returns a new instance of the Exact.

func (Exact) Colour

func (e Exact) Colour() Colour

Colour returns the Colour property.

func (Exact) Find

func (e Exact) Find(input string) (string, bool)

Find looks for the exact string. Any strings it finds will be decorated with the given Colour.

func (Exact) String

func (e Exact) String() string

String will returned the colourised contents.

type Finder

type Finder interface {
	Find(string) (string, bool)
}

Finder finds texts based on a plain text or regexp logic. If it doesn't find any match, it will return an empty string. It might decorate the match with a given instruction.

func NewLocator

func NewLocator(colour, search string, insensitive bool) Finder

NewLocator returns a Rx object if search is a valid regexp, otherwise it returns Exact or Iexact. If insensitive is true, the match will be case insensitive. The colour argument can be in short form (b) or long form (blue). If it cannot find the colour, it will fall-back to DefaultColour. The colour also can be in hex format, which should be started with a pound sign (#666).

type Iexact

type Iexact struct {
	// contains filtered or unexported fields
}

Iexact is like Exact but case insensitive.

func NewIexact

func NewIexact(s string, c Colour) Iexact

NewIexact returns a new instance of the Iexact.

func (Iexact) Colour

func (i Iexact) Colour() Colour

Colour returns the Colour property.

func (Iexact) Find

func (i Iexact) Find(input string) (string, bool)

Find looks for the exact string. Any strings it finds will be decorated with the given Colour.

func (Iexact) String

func (i Iexact) String() string

String will returned the colourised contents.

type RGB

type RGB struct {
	R, G, B int
}

RGB represents colours that can be printed in terminals. R, G and B should be between 0 and 255.

type Rx

type Rx struct {
	*regexp.Regexp
	// contains filtered or unexported fields
}

Rx is the regexp implementation of the Locator.

func NewRx

func NewRx(r *regexp.Regexp, c Colour) Rx

NewRx returns a new instance of the Rx.

func (Rx) Colour

func (r Rx) Colour() Colour

Colour returns the Colour property.

func (Rx) Find

func (r Rx) Find(input string) (string, bool)

Find looks for the string matching `r` regular expression. Any strings it finds will be decorated with the given Colour.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL