// StdLenColorized returns the colorized standard length label for console // output using ANSI escape sequences. func (l Label) StdLenColorized() string { if l.level == LEVEL_PRINT { return l.StdLenName() } return rgbterm.String(l.StdLenName(), l.colorRGB[0], l.colorRGB[1], l.colorRGB[2]) }
func ExampleString() { var r, g, b uint8 // pick a color r, g, b = 252, 255, 43 // choose a word word := "=)" // colorize it! coloredWord := rgbterm.String(word, r, g, b) fmt.Println("Oh!", coloredWord, "hello!") // Output: // Oh! [38;5;165m=)[0;00m hello! }
var date = "Mon 20060102 15:04:05" var fprintOutputTests = []struct { template string prefix string level level dateFormat string flags int text string expect string expectErr bool }{ // Test with color prefix { template: logFmt, prefix: rgbterm.String("TEST>", 0, 255, 0), level: LEVEL_PRINT, dateFormat: date, flags: LstdFlags, text: "test number 1", // The %s format specifier is the placeholder for the date. expect: "%s \x1b[38;5;46mTEST>\x1b[0;00m test number 1", expectErr: false, }, // Test output with coloring turned off { template: logFmt, prefix: "TEST>", level: LEVEL_PRINT, dateFormat: date, flags: Ldate | Lprefix,
// Fprint is used by all of the logging functions to send output to the output // stream. // // flags sets the output flags to use when writing the output. // // logLevel is the level of the output. // // calldepth is the number of stack frames to skip when getting the file // name of original calling function for file name output. // // text is the string to append to the assembled log format output. If the text // is prefixed with newlines, they will be stripped out and placed in front of // the completed output (test with template applied) before writing it to the // stream. // // stream will be used as the output stream the text will be written to. If // stream is nil, the stream value contained in the logger object is used. // // Fprint returns the number of bytes written to the stream or an error. func (l *Logger) Fprint(flags int, logLevel level, calldepth int, text string, stream io.Writer) (n int, err error) { if (logLevel != LEVEL_PRINT && l.level != LEVEL_PRINT) && logLevel < l.level { return } // Check for string excludes if len(l.excludeStrings) > 0 { for _, val := range l.excludeStrings { if strings.Contains(text, val) { return } } } now := time.Now() var pgmC uintptr var file, fName string var line int var id string var indentCount int l.mu.Lock() defer l.mu.Unlock() if flags&(LlongFileName|LshortFileName|LfunctionName|Lid|Ltree) != 0 || len(l.excludeFuncNames) > 0 { // release lock while getting caller info - it's expensive. l.mu.Unlock() pgmC, file, line, _ = runtime.Caller(calldepth) if flags&Ltree != 0 { pc := make([]uintptr, 32) pcNum := runtime.Callers(4, pc) for i := 1; i < pcNum; i++ { pcFunc := runtime.FuncForPC(pc[i]) funcName := pcFunc.Name() if funcName == "runtime.goexit" { continue } indentCount += 1 } } if flags&Lid != 0 { fAtPC := runtime.FuncForPC(pgmC) fName = fAtPC.Name() var idNum int if _, ok := l.ids[fName]; ok { idNum = l.ids[fName] } else { l.ids[fName] = l.lastId idNum = l.lastId l.lastId += 1 } id = fmt.Sprintf("[%02.f]", float64(idNum)) } if flags&LshortFileName != 0 { short := file for i := len(file) - 1; i > 0; i-- { if file[i] == '/' { short = file[i+1:] break } } file = short } if flags&LfunctionName != 0 || len(l.excludeFuncNames) > 0 { fAtPC := runtime.FuncForPC(pgmC) fName = fAtPC.Name() for i := len(fName) - 1; i >= 0; i-- { if fName[i] == '.' { fName = fName[i+1:] break } } } l.mu.Lock() } // Check excludes and skip output if matches are found var iId int if flags&(Lid) != 0 { for _, eId := range l.excludeIDs { iId, _ = strconv.Atoi(id[1 : len(id)-1]) if iId == eId { return } } } // Check func name excludes and return if matches are found if len(fName) > 0 { for _, name := range l.excludeFuncNames { if strings.Contains(fName, name) { return } } } // Reset the buffer l.buf = l.buf[:0] trimText := strings.TrimLeft(text, "\n") trimedCount := len(text) - len(trimText) if trimedCount > 0 { l.buf = append(l.buf, trimText...) } else { l.buf = append(l.buf, text...) } var date string var prefix string if flags&Ldate != 0 { date = now.Format(l.dateFormat) } if flags&Lprefix != 0 { prefix = l.prefix } if flags&LlineNumber == 0 { line = 0 } if flags&(LshortFileName|LlongFileName) == 0 { file = "" } if flags&LfunctionName == 0 { fName = "" } var indent string if indentCount > 0 || flags&Lindent != 0 { for i := 0; i < indentCount+l.indent; i++ { for j := 0; j < l.tabStop; j++ { if flags&LshowIndent != 0 && j == l.tabStop-1 { indent += "|" } else if flags&LshowIndent != 0 { indent += "." } else { indent += " " } } } if len(indent) > 0 && string(indent[0]) != " " { indent = rgbterm.String(indent, defaultIndentColor[0], defaultIndentColor[1], defaultIndentColor[2]) } } var label string if flags&Llabel != 0 { if flags&Lcolor != 0 { label = logLevel.AnsiLabel() if flags&Ltree != 0 { label = logLevel.AnsiStdLenLabel() } } else { label = logLevel.Label() if flags&Ltree != 0 { label = logLevel.StdLenLabel() } } } f := &format{ Prefix: prefix, LogLabel: label, Date: date, FileName: file, FunctionName: fName, LineNumber: line, Indent: indent, Id: id, Text: string(l.buf), } var out bytes.Buffer var strippedText, finalText string err = l.template.Execute(&out, f) if err != nil { panic(err) } if flags&Lcolor == 0 { strippedText = stripAnsi(out.String()) } if trimedCount > 0 && flags&Lcolor == 0 { finalText = strings.Repeat("\n", trimedCount) + strippedText } else if trimedCount > 0 && flags&Lcolor != 0 { finalText = strings.Repeat("\n", trimedCount) + out.String() } else if flags&Lcolor == 0 { finalText = strippedText } else { finalText = out.String() } if stream == nil { n, err = l.Write([]byte(finalText)) } else { n, err = stream.Write([]byte(finalText)) } return }
// Colorized returns the colorized label for console output using ANSI escape // sequences. func (l Label) Colorized() string { if l.level == LEVEL_PRINT { return l.name } return rgbterm.String(l.name, l.colorRGB[0], l.colorRGB[1], l.colorRGB[2]) }
// at all. LEVEL_ERROR // LEVEL_CRITICAL messages are used when something is completely broken // and unrecoverable. Critical messages are usually followed by // os.Exit(). LEVEL_CRITICAL // LEVEL_PRINT shows output for the standard Print functions and above. LEVEL_PRINT ) var ( defaultDate = "Mon Jan 02 15:04:05 MST 2006" defaultPrefix = "::" defaultPrefixColor = rgbterm.String("::", 0, 255, 135) // Green defaultIndentColor = []uint8{0, 135, 175} // Grayish blue ) // Flags are used to control the formatting of the logging output. const ( // These flags define which text to prefix to each log entry generated // by the Logger. Bits or'ed together to control what's printed. Ldate = 1 << iota // Full file name and line number: /a/b/c/d.go:23 LlongFileName // Base file name and line number: d.go:23. overrides LshortFileName LshortFileName
import ( "fmt" "io/ioutil" "os" "sort" "strings" "github.com/aybabtme/rgbterm" "github.com/davecgh/go-spew/spew" "github.com/demizer/go-elog" "github.com/docopt/docopt-go" "gopkg.in/yaml.v2" ) var APP_NAME = rgbterm.String("progress-dump", 255, 255, 135) var APP_DESC = rgbterm.String("Dumps progress output", 0, 215, 95) var APP_USAGE = APP_NAME + " - " + APP_DESC + ` Usage: progress-dump [--progress-yml <PATH>] [-h | --help] Options: -h --help Show the help message. --progress-yml <PATH> The path to progress.yml [default: ../../progress.yml] --readme <PATH> The path to README.rst ` type Item struct { Item string Done string
// This code is MIT licensed. See the LICENSE file for more info. package log import ( "fmt" "testing" "github.com/aybabtme/rgbterm" ) var colorTests = []struct { escapeCodes string output string }{ {rgbterm.String("red foreground color", 255, 0, 0), "\x1b[38;5;196mred foreground color\x1b[0;00m"}, {rgbterm.String("green foreground color", 0, 255, 0), "\x1b[38;5;46mgreen foreground color\x1b[0;00m"}, {rgbterm.String("blue foreground color", 0, 0, 255), "\x1b[38;5;21mblue foreground color\x1b[0;00m"}, } func TestColors(t *testing.T) { for i, v := range colorTests { if out := v.escapeCodes; out != v.output { fmt.Println(v.escapeCodes) t.Errorf("Test Number: %d\nGot:\t%q\nExpect:\t%q\n", i, v.escapeCodes, v.output) } }