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 ¶
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 )
const BgLevel = 70
BgLevel is the colour value of R, G, or B when the colour is shown in the background.
Variables ¶
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.
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.
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") )
var DefaultColour = Blue
DefaultColour is the default colour if no colour is set via arguments.
Functions ¶
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) Read ¶
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 ¶
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 Exact ¶
type Exact struct {
// contains filtered or unexported fields
}
Exact looks for the exact word in the string.
type Finder ¶
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 ¶
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.
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.